Pull drm updates from Dave Airlie: "Highlights: - i915 has seen a lot of refactoring and uAPI cleanups due to a change in the upstream direction going forward This has all been audited with known userspace, but there may be some pitfalls that were missed. - i915 now uses common TTM to enable discrete memory on DG1/2 GPUs - i915 enables Jasper and Elkhart Lake by default and has preliminary XeHP/DG2 support - amdgpu adds support for Cyan Skillfish - lots of implicit fencing rules documented and fixed up in drivers - msm now uses the core scheduler - the irq midlayer has been removed for non-legacy drivers - the sysfb code now works on more than x86. Otherwise the usual smattering of stuff everywhere, panels, bridges, refactorings. Detailed summary: core: - extract i915 eDP backlight into core - DP aux bus support - drm_device.irq_enabled removed - port drivers to native irq interfaces - export gem shadow plane handling for vgem - print proper driver name in framebuffer registration - driver fixes for implicit fencing rules - ARM fixed rate compression modifier added - updated fb damage handling - rmfb ioctl logging/docs - drop drm_gem_object_put_locked - define DRM_FORMAT_MAX_PLANES - add gem fb vmap/vunmap helpers - add lockdep_assert(once) helpers - mark drm irq midlayer as legacy - use offset adjusted bo mapping conversion vgaarb: - cleanups fbdev: - extend efifb handling to all arches - div by 0 fixes for multiple drivers udmabuf: - add hugepage mapping support dma-buf: - non-dynamic exporter fixups - document implicit fencing rules amdgpu: - Initial Cyan Skillfish support - switch virtual DCE over to vkms based atomic - VCN/JPEG power down fixes - NAVI PCIE link handling fixes - AMD HDMI freesync fixes - Yellow Carp + Beige Goby fixes - Clockgating/S0ix/SMU/EEPROM fixes - embed hw fence in job - rework dma-resv handling - ensure eviction to system ram amdkfd: - uapi: SVM address range query added - sysfs leak fix - GPUVM TLB optimizations - vmfault/migration counters i915: - Enable JSL and EHL by default - preliminary XeHP/DG2 support - remove all CNL support (never shipped) - move to TTM for discrete memory support - allow mixed object mmap handling - GEM uAPI spring cleaning - add I915_MMAP_OBJECT_FIXED - reinstate ADL-P mmap ioctls - drop a bunch of unused by userspace features - disable and remove GPU relocations - revert some i915 misfeatures - major refactoring of GuC for Gen11+ - execbuffer object locking separate step - reject caching/set-domain on discrete - Enable pipe DMC loading on XE-LPD and ADL-P - add PSF GV point support - Refactor and fix DDI buffer translations - Clean up FBC CFB allocation code - Finish INTEL_GEN() and friends macro conversions nouveau: - add eDP backlight support - implicit fence fix msm: - a680/7c3 support - drm/scheduler conversion panfrost: - rework GPU reset virtio: - fix fencing for planes ast: - add detect support bochs: - move to tiny GPU driver vc4: - use hotplug irqs - HDMI codec support vmwgfx: - use internal vmware device headers ingenic: - demidlayering irq rcar-du: - shutdown fixes - convert to bridge connector helpers zynqmp-dsub: - misc fixes mgag200: - convert PLL handling to atomic mediatek: - MT8133 AAL support - gem mmap object support - MT8167 support etnaviv: - NXP Layerscape LS1028A SoC support - GEM mmap cleanups tegra: - new user API exynos: - missing unlock fix - build warning fix - use refcount_t" * tag 'drm-next-2021-08-31-1' of git://anongit.freedesktop.org/drm/drm: (1318 commits) drm/amd/display: Move AllowDRAMSelfRefreshOrDRAMClockChangeInVblank to bounding box drm/amd/display: Remove duplicate dml init drm/amd/display: Update bounding box states (v2) drm/amd/display: Update number of DCN3 clock states drm/amdgpu: disable GFX CGCG in aldebaran drm/amdgpu: Clear RAS interrupt status on aldebaran drm/amdgpu: Add support for RAS XGMI err query drm/amdkfd: Account for SH/SE count when setting up cu masks. drm/amdgpu: rename amdgpu_bo_get_preferred_pin_domain drm/amdgpu: drop redundant cancel_delayed_work_sync call drm/amdgpu: add missing cleanups for more ASICs on UVD/VCE suspend drm/amdgpu: add missing cleanups for Polaris12 UVD/VCE on suspend drm/amdkfd: map SVM range with correct access permission drm/amdkfd: check access permisson to restore retry fault drm/amdgpu: Update RAS XGMI Error Query drm/amdgpu: Add driver infrastructure for MCA RAS drm/amd/display: Add Logging for HDMI color depth information drm/amd/amdgpu: consolidate PSP TA init shared buf functions drm/amd/amdgpu: add name field back to ras_common_if drm/amdgpu: Fix build with missing pm_suspend_target_state module export ...
Unified · Split
| @@ -0,0 +1,24 @@ | ||
| 1 | +What: /sys/kernel/dmabuf/buffers | |
| 2 | +Date: May 2021 | |
| 3 | +KernelVersion: v5.13 | |
| 4 | +Contact: Hridya Valsaraju <hridya@google.com> | |
| 5 | +Description: The /sys/kernel/dmabuf/buffers directory contains a | |
| 6 | + snapshot of the internal state of every DMA-BUF. | |
| 7 | + /sys/kernel/dmabuf/buffers/<inode_number> will contain the | |
| 8 | + statistics for the DMA-BUF with the unique inode number | |
| 9 | + <inode_number> | |
| 10 | +Users: kernel memory tuning/debugging tools | |
| 11 | + | |
| 12 | +What: /sys/kernel/dmabuf/buffers/<inode_number>/exporter_name | |
| 13 | +Date: May 2021 | |
| 14 | +KernelVersion: v5.13 | |
| 15 | +Contact: Hridya Valsaraju <hridya@google.com> | |
| 16 | +Description: This file is read-only and contains the name of the exporter of | |
| 17 | + the DMA-BUF. | |
| 18 | + | |
| 19 | +What: /sys/kernel/dmabuf/buffers/<inode_number>/size | |
| 20 | +Date: May 2021 | |
| 21 | +KernelVersion: v5.13 | |
| 22 | +Contact: Hridya Valsaraju <hridya@google.com> | |
| 23 | +Description: This file is read-only and specifies the size of the DMA-BUF in | |
| 24 | + bytes. | |
| @@ -22,6 +22,9 @@ properties: · 21 unmodified lines | ||
| 22 | 22 | - ti,ths8134a |
| 23 | 23 | - ti,ths8134b |
| 24 | 24 | - const: ti,ths8134 |
| 25 | + - items: | |
| 26 | + - const: corpro,gm7123 | |
| 27 | + - const: adi,adv7123 | |
| 25 | 28 | - enum: |
| 26 | 29 | - adi,adv7123 |
| 27 | 30 | - dumb-vga-dac |
| @@ -70,6 +70,9 @@ properties: · 69 unmodified lines | ||
| 70 | 70 | const: 1 |
| 71 | 71 | description: See ../../pwm/pwm.yaml for description of the cell formats. |
| 72 | 72 | |
| 73 | + aux-bus: | |
| 74 | + $ref: /schemas/display/dp-aux-bus.yaml# | |
| 75 | + | |
| 73 | 76 | ports: |
| 74 | 77 | $ref: /schemas/graph.yaml#/properties/ports |
| 75 | 78 | |
| @@ -150,7 +153,6 @@ properties: · 74 unmodified lines | ||
| 150 | 153 | required: |
| 151 | 154 | - compatible |
| 152 | 155 | - reg |
| 153 | − - enable-gpios | |
| 154 | 156 | - vccio-supply |
| 155 | 157 | - vpll-supply |
| 156 | 158 | - vcca-supply |
| @@ -201,11 +203,26 @@ examples: · 44 unmodified lines | ||
| 201 | 203 | |
| 202 | 204 | port@1 { |
| 203 | 205 | reg = <1>; |
| 204 | − endpoint { | |
| 206 | + sn65dsi86_out: endpoint { | |
| 205 | 207 | remote-endpoint = <&panel_in_edp>; |
| 206 | 208 | }; |
| 207 | 209 | }; |
| 208 | 210 | }; |
| 211 | + | |
| 212 | + aux-bus { | |
| 213 | + panel { | |
| 214 | + compatible = "boe,nv133fhm-n62"; | |
| 215 | + power-supply = <&pp3300_dx_edp>; | |
| 216 | + backlight = <&backlight>; | |
| 217 | + hpd-gpios = <&sn65dsi86_bridge 2 GPIO_ACTIVE_HIGH>; | |
| 218 | + | |
| 219 | + port { | |
| 220 | + panel_in_edp: endpoint { | |
| 221 | + remote-endpoint = <&sn65dsi86_out>; | |
| 222 | + }; | |
| 223 | + }; | |
| 224 | + }; | |
| 225 | + }; | |
| 209 | 226 | }; |
| 210 | 227 | }; |
| 211 | 228 | - | |
| @@ -0,0 +1,37 @@ | ||
| 1 | +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) | |
| 2 | +%YAML 1.2 | |
| 3 | +--- | |
| 4 | +$id: http://devicetree.org/schemas/display/dp-aux-bus.yaml# | |
| 5 | +$schema: http://devicetree.org/meta-schemas/core.yaml# | |
| 6 | + | |
| 7 | +title: DisplayPort AUX bus | |
| 8 | + | |
| 9 | +maintainers: | |
| 10 | + - Douglas Anderson <dianders@chromium.org> | |
| 11 | + | |
| 12 | +description: | |
| 13 | + DisplayPort controllers provide a control channel to the sinks that | |
| 14 | + are hooked up to them. This is the DP AUX bus. Over the DP AUX bus | |
| 15 | + we can query properties about a sink and also configure it. In | |
| 16 | + particular, DP sinks support DDC over DP AUX which allows tunneling | |
| 17 | + a standard I2C DDC connection over the AUX channel. | |
| 18 | + | |
| 19 | + To model this relationship, DP sinks should be placed as children | |
| 20 | + of the DP controller under the "aux-bus" node. | |
| 21 | + | |
| 22 | + At the moment, this binding only handles the eDP case. It is | |
| 23 | + possible it will be extended in the future to handle the DP case. | |
| 24 | + For DP, presumably a connector would be listed under the DP AUX | |
| 25 | + bus instead of a panel. | |
| 26 | + | |
| 27 | +properties: | |
| 28 | + $nodename: | |
| 29 | + const: "aux-bus" | |
| 30 | + | |
| 31 | + panel: | |
| 32 | + $ref: panel/panel-common.yaml# | |
| 33 | + | |
| 34 | +additionalProperties: false | |
| 35 | + | |
| 36 | +required: | |
| 37 | + - panel | |
| @@ -7,7 +7,7 @@ channel output. · 6 unmodified lines | ||
| 7 | 7 | |
| 8 | 8 | Required properties: |
| 9 | 9 | - compatible: "mediatek,<chip>-dsi" |
| 10 | −- the supported chips are mt2701, mt7623, mt8173 and mt8183. | |
| 10 | +- the supported chips are mt2701, mt7623, mt8167, mt8173 and mt8183. | |
| 11 | 11 | - reg: Physical base address and length of the controller's registers |
| 12 | 12 | - interrupts: The interrupt signal from the function block. |
| 13 | 13 | - clocks: device clocks |
| @@ -64,6 +64,18 @@ properties: · 63 unmodified lines | ||
| 64 | 64 | Indicates if the DSI controller is driving a panel which needs |
| 65 | 65 | 2 DSI links. |
| 66 | 66 | |
| 67 | + assigned-clocks: | |
| 68 | + minItems: 2 | |
| 69 | + maxItems: 2 | |
| 70 | + description: | | |
| 71 | + Parents of "byte" and "pixel" for the given platform. | |
| 72 | + | |
| 73 | + assigned-clock-parents: | |
| 74 | + minItems: 2 | |
| 75 | + maxItems: 2 | |
| 76 | + description: | | |
| 77 | + The Byte clock and Pixel clock PLL outputs provided by a DSI PHY block. | |
| 78 | + | |
| 67 | 79 | power-domains: |
| 68 | 80 | maxItems: 1 |
| 69 | 81 | |
| @@ -119,6 +131,8 @@ required: · 49 unmodified lines | ||
| 119 | 131 | - clock-names |
| 120 | 132 | - phys |
| 121 | 133 | - phy-names |
| 134 | + - assigned-clocks | |
| 135 | + - assigned-clock-parents | |
| 122 | 136 | - power-domains |
| 123 | 137 | - operating-points-v2 |
| 124 | 138 | - ports |
| @@ -159,6 +173,9 @@ examples: · 34 unmodified lines | ||
| 159 | 173 | phys = <&dsi0_phy>; |
| 160 | 174 | phy-names = "dsi"; |
| 161 | 175 | |
| 176 | + assigned-clocks = <&dispcc DISP_CC_MDSS_BYTE0_CLK_SRC>, <&dispcc DISP_CC_MDSS_PCLK0_CLK_SRC>; | |
| 177 | + assigned-clock-parents = <&dsi_phy 0>, <&dsi_phy 1>; | |
| 178 | + | |
| 162 | 179 | power-domains = <&rpmhpd SC7180_CX>; |
| 163 | 180 | operating-points-v2 = <&dsi_opp_table>; |
| 164 | 181 | |
| @@ -0,0 +1,72 @@ | ||
| 1 | +# SPDX-License-Identifier: GPL-2.0-only or BSD-2-Clause | |
| 2 | +%YAML 1.2 | |
| 3 | +--- | |
| 4 | +$id: http://devicetree.org/schemas/display/msm/dsi-phy-7nm.yaml# | |
| 5 | +$schema: http://devicetree.org/meta-schemas/core.yaml# | |
| 6 | + | |
| 7 | +title: Qualcomm Display DSI 7nm PHY | |
| 8 | + | |
| 9 | +maintainers: | |
| 10 | + - Jonathan Marek <jonathan@marek.ca> | |
| 11 | + | |
| 12 | +allOf: | |
| 13 | + - $ref: dsi-phy-common.yaml# | |
| 14 | + | |
| 15 | +properties: | |
| 16 | + compatible: | |
| 17 | + oneOf: | |
| 18 | + - const: qcom,dsi-phy-7nm | |
| 19 | + - const: qcom,dsi-phy-7nm-8150 | |
| 20 | + - const: qcom,sc7280-dsi-phy-7nm | |
| 21 | + | |
| 22 | + reg: | |
| 23 | + items: | |
| 24 | + - description: dsi phy register set | |
| 25 | + - description: dsi phy lane register set | |
| 26 | + - description: dsi pll register set | |
| 27 | + | |
| 28 | + reg-names: | |
| 29 | + items: | |
| 30 | + - const: dsi_phy | |
| 31 | + - const: dsi_phy_lane | |
| 32 | + - const: dsi_pll | |
| 33 | + | |
| 34 | + vdds-supply: | |
| 35 | + description: | | |
| 36 | + Connected to VDD_A_DSI_PLL_0P9 pin (or VDDA_DSI{0,1}_PLL_0P9 for sm8150) | |
| 37 | + | |
| 38 | + phy-type: | |
| 39 | + description: D-PHY (default) or C-PHY mode | |
| 40 | + enum: [ 10, 11 ] | |
| 41 | + default: 10 | |
| 42 | + | |
| 43 | +required: | |
| 44 | + - compatible | |
| 45 | + - reg | |
| 46 | + - reg-names | |
| 47 | + - vdds-supply | |
| 48 | + | |
| 49 | +unevaluatedProperties: false | |
| 50 | + | |
| 51 | +examples: | |
| 52 | + - | | |
| 53 | + #include <dt-bindings/clock/qcom,dispcc-sm8250.h> | |
| 54 | + #include <dt-bindings/clock/qcom,rpmh.h> | |
| 55 | + | |
| 56 | + dsi-phy@ae94400 { | |
| 57 | + compatible = "qcom,dsi-phy-7nm"; | |
| 58 | + reg = <0x0ae94400 0x200>, | |
| 59 | + <0x0ae94600 0x280>, | |
| 60 | + <0x0ae94900 0x260>; | |
| 61 | + reg-names = "dsi_phy", | |
| 62 | + "dsi_phy_lane", | |
| 63 | + "dsi_pll"; | |
| 64 | + | |
| 65 | + #clock-cells = <1>; | |
| 66 | + #phy-cells = <0>; | |
| 67 | + | |
| 68 | + vdds-supply = <&vreg_l5a_0p88>; | |
| 69 | + clocks = <&dispcc DISP_CC_MDSS_AHB_CLK>, | |
| 70 | + <&rpmhcc RPMH_CXO_CLK>; | |
| 71 | + clock-names = "iface", "ref"; | |
| 72 | + }; | |
| @@ -0,0 +1,78 @@ | ||
| 1 | +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) | |
| 2 | +%YAML 1.2 | |
| 3 | +--- | |
| 4 | +$id: http://devicetree.org/schemas/display/panel/ilitek,ili9341.yaml# | |
| 5 | +$schema: http://devicetree.org/meta-schemas/core.yaml# | |
| 6 | + | |
| 7 | +title: Ilitek-9341 Display Panel | |
| 8 | + | |
| 9 | +maintainers: | |
| 10 | + - Dillon Min <dillon.minfei@gmail.com> | |
| 11 | + | |
| 12 | +description: | | |
| 13 | + Ilitek ILI9341 TFT panel driver with SPI control bus | |
| 14 | + This is a driver for 320x240 TFT panels, accepting a rgb input | |
| 15 | + streams with 16 bits or 18 bits. | |
| 16 | + | |
| 17 | +allOf: | |
| 18 | + - $ref: panel-common.yaml# | |
| 19 | + | |
| 20 | +properties: | |
| 21 | + compatible: | |
| 22 | + items: | |
| 23 | + - enum: | |
| 24 | + # ili9341 240*320 Color on stm32f429-disco board | |
| 25 | + - st,sf-tc240t-9370-t | |
| 26 | + - const: ilitek,ili9341 | |
| 27 | + | |
| 28 | + reg: true | |
| 29 | + | |
| 30 | + dc-gpios: | |
| 31 | + maxItems: 1 | |
| 32 | + description: Display data/command selection (D/CX) of this DBI panel | |
| 33 | + | |
| 34 | + spi-3wire: true | |
| 35 | + | |
| 36 | + spi-max-frequency: | |
| 37 | + const: 10000000 | |
| 38 | + | |
| 39 | + port: true | |
| 40 | + | |
| 41 | + vci-supply: | |
| 42 | + description: Analog voltage supply (2.5 .. 3.3V) | |
| 43 | + | |
| 44 | + vddi-supply: | |
| 45 | + description: Voltage supply for interface logic (1.65 .. 3.3 V) | |
| 46 | + | |
| 47 | + vddi-led-supply: | |
| 48 | + description: Voltage supply for the LED driver (1.65 .. 3.3 V) | |
| 49 | + | |
| 50 | +additionalProperties: false | |
| 51 | + | |
| 52 | +required: | |
| 53 | + - compatible | |
| 54 | + - reg | |
| 55 | + - dc-gpios | |
| 56 | + - port | |
| 57 | + | |
| 58 | +examples: | |
| 59 | + - |+ | |
| 60 | + spi { | |
| 61 | + #address-cells = <1>; | |
| 62 | + #size-cells = <0>; | |
| 63 | + panel: display@0 { | |
| 64 | + compatible = "st,sf-tc240t-9370-t", | |
| 65 | + "ilitek,ili9341"; | |
| 66 | + reg = <0>; | |
| 67 | + spi-3wire; | |
| 68 | + spi-max-frequency = <10000000>; | |
| 69 | + dc-gpios = <&gpiod 13 0>; | |
| 70 | + port { | |
| 71 | + panel_in: endpoint { | |
| 72 | + remote-endpoint = <&display_out>; | |
| 73 | + }; | |
| 74 | + }; | |
| 75 | + }; | |
| 76 | + }; | |
| 77 | +... | |
| 78 | + | |
| @@ -0,0 +1,62 @@ | ||
| 1 | +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) | |
| 2 | +%YAML 1.2 | |
| 3 | +--- | |
| 4 | +$id: http://devicetree.org/schemas/display/panel/innolux,ej030na.yaml# | |
| 5 | +$schema: http://devicetree.org/meta-schemas/core.yaml# | |
| 6 | + | |
| 7 | +title: Innolux EJ030NA 3.0" (320x480 pixels) 24-bit TFT LCD panel | |
| 8 | + | |
| 9 | +description: | | |
| 10 | + The panel must obey the rules for a SPI slave device as specified in | |
| 11 | + spi/spi-controller.yaml | |
| 12 | + | |
| 13 | +maintainers: | |
| 14 | + - Paul Cercueil <paul@crapouillou.net> | |
| 15 | + | |
| 16 | +allOf: | |
| 17 | + - $ref: panel-common.yaml# | |
| 18 | + | |
| 19 | +properties: | |
| 20 | + compatible: | |
| 21 | + const: innolux,ej030na | |
| 22 | + | |
| 23 | + backlight: true | |
| 24 | + port: true | |
| 25 | + power-supply: true | |
| 26 | + reg: true | |
| 27 | + reset-gpios: true | |
| 28 | + | |
| 29 | +required: | |
| 30 | + - compatible | |
| 31 | + - reg | |
| 32 | + - power-supply | |
| 33 | + - reset-gpios | |
| 34 | + | |
| 35 | +unevaluatedProperties: false | |
| 36 | + | |
| 37 | +examples: | |
| 38 | + - | | |
| 39 | + #include <dt-bindings/gpio/gpio.h> | |
| 40 | + | |
| 41 | + spi { | |
| 42 | + #address-cells = <1>; | |
| 43 | + #size-cells = <0>; | |
| 44 | + | |
| 45 | + panel@0 { | |
| 46 | + compatible = "innolux,ej030na"; | |
| 47 | + reg = <0>; | |
| 48 | + | |
| 49 | + spi-max-frequency = <10000000>; | |
| 50 | + | |
| 51 | + reset-gpios = <&gpe 4 GPIO_ACTIVE_LOW>; | |
| 52 | + power-supply = <&lcd_power>; | |
| 53 | + | |
| 54 | + backlight = <&backlight>; | |
| 55 | + | |
| 56 | + port { | |
| 57 | + panel_input: endpoint { | |
| 58 | + remote-endpoint = <&panel_output>; | |
| 59 | + }; | |
| 60 | + }; | |
| 61 | + }; | |
| 62 | + }; | |
| @@ -46,9 +46,13 @@ properties: · 45 unmodified lines | ||
| 46 | 46 | # AU Optronics Corporation 11.6" HD (1366x768) color TFT-LCD panel |
| 47 | 47 | - auo,b116xw03 |
| 48 | 48 | # AU Optronics Corporation 13.3" FHD (1920x1080) color TFT-LCD panel |
| 49 | + - auo,b133han05 | |
| 50 | + # AU Optronics Corporation 13.3" FHD (1920x1080) color TFT-LCD panel | |
| 49 | 51 | - auo,b133htn01 |
| 50 | 52 | # AU Optronics Corporation 13.3" WXGA (1366x768) TFT LCD panel |
| 51 | 53 | - auo,b133xtn01 |
| 54 | + # AU Optronics Corporation 14.0" FHD (1920x1080) color TFT-LCD panel | |
| 55 | + - auo,b140han06 | |
| 52 | 56 | # AU Optronics Corporation 7.0" FHD (800 x 480) TFT LCD panel |
| 53 | 57 | - auo,g070vvn01 |
| 54 | 58 | # AU Optronics Corporation 10.1" (1280x800) color TFT LCD panel |
| @@ -110,6 +114,9 @@ properties: · 55 unmodified lines | ||
| 110 | 114 | # Emerging Display Technology Corp. 5.7" VGA TFT LCD panel |
| 111 | 115 | - edt,et057090dhu |
| 112 | 116 | - edt,et070080dh6 |
| 117 | + # Emerging Display Technology Corp. 3.5" WVGA TFT LCD panel with | |
| 118 | + # capacitive multitouch | |
| 119 | + - edt,etm0350g0dh6 | |
| 113 | 120 | # Emerging Display Technology Corp. 480x272 TFT Display with capacitive touch |
| 114 | 121 | - edt,etm043080dh6gp |
| 115 | 122 | # Emerging Display Technology Corp. 480x272 TFT Display |
| @@ -128,6 +135,11 @@ properties: · 12 unmodified lines | ||
| 128 | 135 | # Emerging Display Technology Corp. WVGA TFT Display with capacitive touch |
| 129 | 136 | - edt,etm0700g0dh6 |
| 130 | 137 | - edt,etm0700g0edh6 |
| 138 | + # Emerging Display Technology Corp. 5.7" VGA TFT LCD panel with | |
| 139 | + # capacitive touch | |
| 140 | + - edt,etmv570g2dhu | |
| 141 | + # E Ink VB3300-KCA | |
| 142 | + - eink,vb3300-kca | |
| 131 | 143 | # Evervision Electronics Co. Ltd. VGG804821 5.0" WVGA TFT LCD Panel |
| 132 | 144 | - evervision,vgg804821 |
| 133 | 145 | # Foxlink Group 5" WVGA TFT LCD panel |
| @@ -202,8 +214,14 @@ properties: · 68 unmodified lines | ||
| 202 | 214 | - logictechno,lt161010-2nhr |
| 203 | 215 | # Logic Technologies LT170410-2WHC 10.1" 1280x800 IPS TFT Cap Touch Mod. |
| 204 | 216 | - logictechno,lt170410-2whc |
| 217 | + # Logic Technologies LTTD800x480 L2RT 7" 800x480 TFT Resistive Touch Module | |
| 218 | + - logictechno,lttd800480070-l2rt | |
| 219 | + # Logic Technologies LTTD800480070-L6WH-RT 7” 800x480 TFT Resistive Touch Module | |
| 220 | + - logictechno,lttd800480070-l6wh-rt | |
| 205 | 221 | # Mitsubishi "AA070MC01 7.0" WVGA TFT LCD panel |
| 206 | 222 | - mitsubishi,aa070mc01-ca1 |
| 223 | + # Multi-Inno Technology Co.,Ltd MI1010AIT-1CP 10.1" 1280x800 LVDS IPS Cap Touch Mod. | |
| 224 | + - multi-inno,mi1010ait-1cp | |
| 207 | 225 | # NEC LCD Technologies, Ltd. 12.1" WXGA (1280x800) LVDS TFT LCD panel |
| 208 | 226 | - nec,nl12880bc20-05 |
| 209 | 227 | # NEC LCD Technologies,Ltd. WQVGA TFT LCD panel |
| @@ -238,10 +256,14 @@ properties: · 28 unmodified lines | ||
| 238 | 256 | - powertip,ph800480t013-idf02 |
| 239 | 257 | # QiaoDian XianShi Corporation 4"3 TFT LCD panel |
| 240 | 258 | - qiaodian,qd43003c0-40 |
| 259 | + # Shenzhen QiShenglong Industrialist Co., Ltd. Gopher 2b 4.3" 480(RGB)x272 TFT LCD panel | |
| 260 | + - qishenglong,gopher2b-lcd | |
| 241 | 261 | # Rocktech Displays Ltd. RK101II01D-CT 10.1" TFT 1280x800 |
| 242 | 262 | - rocktech,rk101ii01d-ct |
| 243 | 263 | # Rocktech Display Ltd. RK070ER9427 800(RGB)x480 TFT LCD panel |
| 244 | 264 | - rocktech,rk070er9427 |
| 265 | + # Samsung 13.3" FHD (1920x1080 pixels) eDP AMOLED panel | |
| 266 | + - samsung,atna33xc20 | |
| 245 | 267 | # Samsung 12.2" (2560x1600 pixels) TFT LCD panel |
| 246 | 268 | - samsung,lsn122dl01-c01 |
| 247 | 269 | # Samsung Electronics 10.1" WSVGA TFT LCD panel |
| @@ -298,6 +320,8 @@ properties: · 50 unmodified lines | ||
| 298 | 320 | enable-gpios: true |
| 299 | 321 | port: true |
| 300 | 322 | power-supply: true |
| 323 | + no-hpd: true | |
| 324 | + hpd-gpios: true | |
| 301 | 325 | |
| 302 | 326 | additionalProperties: false |
| 303 | 327 | |
| @@ -0,0 +1,99 @@ | ||
| 1 | +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) | |
| 2 | +%YAML 1.2 | |
| 3 | +--- | |
| 4 | +$id: http://devicetree.org/schemas/display/panel/samsung,lms380kf01.yaml# | |
| 5 | +$schema: http://devicetree.org/meta-schemas/core.yaml# | |
| 6 | + | |
| 7 | +title: Samsung LMS380KF01 display panel | |
| 8 | + | |
| 9 | +description: The LMS380KF01 is a 480x800 DPI display panel from Samsung Mobile | |
| 10 | + Displays (SMD) utilizing the WideChips WS2401 display controller. It can be | |
| 11 | + used with internal or external backlight control. | |
| 12 | + The panel must obey the rules for a SPI slave device as specified in | |
| 13 | + spi/spi-controller.yaml | |
| 14 | + | |
| 15 | +maintainers: | |
| 16 | + - Linus Walleij <linus.walleij@linaro.org> | |
| 17 | + | |
| 18 | +allOf: | |
| 19 | + - $ref: panel-common.yaml# | |
| 20 | + | |
| 21 | +properties: | |
| 22 | + compatible: | |
| 23 | + const: samsung,lms380kf01 | |
| 24 | + | |
| 25 | + reg: true | |
| 26 | + | |
| 27 | + interrupts: | |
| 28 | + description: provides an optional ESD (electrostatic discharge) | |
| 29 | + interrupt that signals abnormalities in the display hardware. | |
| 30 | + This can also be raised for other reasons like erroneous | |
| 31 | + configuration. | |
| 32 | + maxItems: 1 | |
| 33 | + | |
| 34 | + reset-gpios: true | |
| 35 | + | |
| 36 | + vci-supply: | |
| 37 | + description: regulator that supplies the VCI analog voltage | |
| 38 | + usually around 3.0 V | |
| 39 | + | |
| 40 | + vccio-supply: | |
| 41 | + description: regulator that supplies the VCCIO voltage usually | |
| 42 | + around 1.8 V | |
| 43 | + | |
| 44 | + backlight: true | |
| 45 | + | |
| 46 | + spi-cpha: true | |
| 47 | + | |
| 48 | + spi-cpol: true | |
| 49 | + | |
| 50 | + spi-max-frequency: | |
| 51 | + maximum: 1200000 | |
| 52 | + | |
| 53 | + port: true | |
| 54 | + | |
| 55 | +required: | |
| 56 | + - compatible | |
| 57 | + - reg | |
| 58 | + - spi-cpha | |
| 59 | + - spi-cpol | |
| 60 | + - port | |
| 61 | + | |
| 62 | +additionalProperties: false | |
| 63 | + | |
| 64 | +examples: | |
| 65 | + - | | |
| 66 | + #include <dt-bindings/gpio/gpio.h> | |
| 67 | + #include <dt-bindings/interrupt-controller/irq.h> | |
| 68 | + | |
| 69 | + spi { | |
| 70 | + compatible = "spi-gpio"; | |
| 71 | + sck-gpios = <&gpio 0 GPIO_ACTIVE_HIGH>; | |
| 72 | + miso-gpios = <&gpio 1 GPIO_ACTIVE_HIGH>; | |
| 73 | + mosi-gpios = <&gpio 2 GPIO_ACTIVE_HIGH>; | |
| 74 | + cs-gpios = <&gpio 3 GPIO_ACTIVE_HIGH>; | |
| 75 | + num-chipselects = <1>; | |
| 76 | + #address-cells = <1>; | |
| 77 | + #size-cells = <0>; | |
| 78 | + | |
| 79 | + panel@0 { | |
| 80 | + compatible = "samsung,lms380kf01"; | |
| 81 | + spi-max-frequency = <1200000>; | |
| 82 | + spi-cpha; | |
| 83 | + spi-cpol; | |
| 84 | + reg = <0>; | |
| 85 | + vci-supply = <&lcd_3v0_reg>; | |
| 86 | + vccio-supply = <&lcd_1v8_reg>; | |
| 87 | + reset-gpios = <&gpio 4 GPIO_ACTIVE_LOW>; | |
| 88 | + interrupt-parent = <&gpio>; | |
| 89 | + interrupts = <5 IRQ_TYPE_EDGE_RISING>; | |
| 90 | + | |
| 91 | + port { | |
| 92 | + panel_in: endpoint { | |
| 93 | + remote-endpoint = <&display_out>; | |
| 94 | + }; | |
| 95 | + }; | |
| 96 | + }; | |
| 97 | + }; | |
| 98 | + | |
| 99 | +... | |
| @@ -33,8 +33,11 @@ properties: · 32 unmodified lines | ||
| 33 | 33 | |
| 34 | 34 | backlight: true |
| 35 | 35 | |
| 36 | + spi-cpha: true | |
| 37 | + | |
| 38 | + spi-cpol: true | |
| 39 | + | |
| 36 | 40 | spi-max-frequency: |
| 37 | − $ref: /schemas/types.yaml#/definitions/uint32 | |
| 38 | 41 | description: inherited as a SPI client node, the datasheet specifies |
| 39 | 42 | maximum 300 ns minimum cycle which gives around 3 MHz max frequency |
| 40 | 43 | maximum: 3000000 |
| @@ -44,6 +47,9 @@ properties: · 3 unmodified lines | ||
| 44 | 47 | required: |
| 45 | 48 | - compatible |
| 46 | 49 | - reg |
| 50 | + - spi-cpha | |
| 51 | + - spi-cpol | |
| 52 | + - port | |
| 47 | 53 | |
| 48 | 54 | additionalProperties: false |
| 49 | 55 | |
| @@ -52,15 +58,23 @@ examples: · 2 unmodified lines | ||
| 52 | 58 | #include <dt-bindings/gpio/gpio.h> |
| 53 | 59 | |
| 54 | 60 | spi { |
| 61 | + compatible = "spi-gpio"; | |
| 62 | + sck-gpios = <&gpio 0 GPIO_ACTIVE_HIGH>; | |
| 63 | + miso-gpios = <&gpio 1 GPIO_ACTIVE_HIGH>; | |
| 64 | + mosi-gpios = <&gpio 2 GPIO_ACTIVE_HIGH>; | |
| 65 | + cs-gpios = <&gpio 3 GPIO_ACTIVE_HIGH>; | |
| 66 | + num-chipselects = <1>; | |
| 55 | 67 | #address-cells = <1>; |
| 56 | 68 | #size-cells = <0>; |
| 57 | 69 | panel@0 { |
| 58 | 70 | compatible = "samsung,lms397kf04"; |
| 59 | 71 | spi-max-frequency = <3000000>; |
| 72 | + spi-cpha; | |
| 73 | + spi-cpol; | |
| 60 | 74 | reg = <0>; |
| 61 | 75 | vci-supply = <&lcd_3v0_reg>; |
| 62 | 76 | vccio-supply = <&lcd_1v8_reg>; |
| 63 | − reset-gpios = <&gpio 1 GPIO_ACTIVE_LOW>; | |
| 77 | + reset-gpios = <&gpio 4 GPIO_ACTIVE_LOW>; | |
| 64 | 78 | backlight = <&ktd259>; |
| 65 | 79 | |
| 66 | 80 | port { |
| @@ -23,6 +23,7 @@ Required properties: · 22 unmodified lines | ||
| 23 | 23 | Optional properties: |
| 24 | 24 | - phys: from general PHY binding: the phandle for the PHY device. |
| 25 | 25 | - phy-names: Should be "dphy" if phys references an external phy. |
| 26 | +- #phy-cells: Defined when used as ISP phy, should be 0. | |
| 26 | 27 | - power-domains: a phandle to mipi dsi power domain node. |
| 27 | 28 | - resets: list of phandle + reset specifier pairs, as described in [3]. |
| 28 | 29 | - reset-names: string reset name, must be "apb". |
| @@ -0,0 +1,208 @@ | ||
| 1 | +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) | |
| 2 | +%YAML 1.2 | |
| 3 | +--- | |
| 4 | +$id: http://devicetree.org/schemas/display/solomon,ssd1307fb.yaml# | |
| 5 | +$schema: http://devicetree.org/meta-schemas/core.yaml# | |
| 6 | + | |
| 7 | +title: Solomon SSD1307 OLED Controller Framebuffer | |
| 8 | + | |
| 9 | +maintainers: | |
| 10 | + - Maxime Ripard <mripard@kernel.org> | |
| 11 | + | |
| 12 | +properties: | |
| 13 | + compatible: | |
| 14 | + enum: | |
| 15 | + - solomon,ssd1305fb-i2c | |
| 16 | + - solomon,ssd1306fb-i2c | |
| 17 | + - solomon,ssd1307fb-i2c | |
| 18 | + - solomon,ssd1309fb-i2c | |
| 19 | + | |
| 20 | + reg: | |
| 21 | + maxItems: 1 | |
| 22 | + | |
| 23 | + pwms: | |
| 24 | + maxItems: 1 | |
| 25 | + | |
| 26 | + reset-gpios: | |
| 27 | + maxItems: 1 | |
| 28 | + | |
| 29 | + vbat-supply: | |
| 30 | + description: The supply for VBAT | |
| 31 | + | |
| 32 | + solomon,height: | |
| 33 | + $ref: /schemas/types.yaml#/definitions/uint32 | |
| 34 | + default: 16 | |
| 35 | + description: | |
| 36 | + Height in pixel of the screen driven by the controller | |
| 37 | + | |
| 38 | + solomon,width: | |
| 39 | + $ref: /schemas/types.yaml#/definitions/uint32 | |
| 40 | + default: 96 | |
| 41 | + description: | |
| 42 | + Width in pixel of the screen driven by the controller | |
| 43 | + | |
| 44 | + solomon,page-offset: | |
| 45 | + $ref: /schemas/types.yaml#/definitions/uint32 | |
| 46 | + default: 1 | |
| 47 | + description: | |
| 48 | + Offset of pages (band of 8 pixels) that the screen is mapped to | |
| 49 | + | |
| 50 | + solomon,segment-no-remap: | |
| 51 | + type: boolean | |
| 52 | + description: | |
| 53 | + Display needs normal (non-inverted) data column to segment mapping | |
| 54 | + | |
| 55 | + solomon,col-offset: | |
| 56 | + $ref: /schemas/types.yaml#/definitions/uint32 | |
| 57 | + default: 0 | |
| 58 | + description: | |
| 59 | + Offset of columns (COL/SEG) that the screen is mapped to | |
| 60 | + | |
| 61 | + solomon,com-seq: | |
| 62 | + type: boolean | |
| 63 | + description: | |
| 64 | + Display uses sequential COM pin configuration | |
| 65 | + | |
| 66 | + solomon,com-lrremap: | |
| 67 | + type: boolean | |
| 68 | + description: | |
| 69 | + Display uses left-right COM pin remap | |
| 70 | + | |
| 71 | + solomon,com-invdir: | |
| 72 | + type: boolean | |
| 73 | + description: | |
| 74 | + Display uses inverted COM pin scan direction | |
| 75 | + | |
| 76 | + solomon,com-offset: | |
| 77 | + $ref: /schemas/types.yaml#/definitions/uint32 | |
| 78 | + default: 0 | |
| 79 | + description: | |
| 80 | + Number of the COM pin wired to the first display line | |
| 81 | + | |
| 82 | + solomon,prechargep1: | |
| 83 | + $ref: /schemas/types.yaml#/definitions/uint32 | |
| 84 | + default: 2 | |
| 85 | + description: | |
| 86 | + Length of deselect period (phase 1) in clock cycles | |
| 87 | + | |
| 88 | + solomon,prechargep2: | |
| 89 | + $ref: /schemas/types.yaml#/definitions/uint32 | |
| 90 | + default: 2 | |
| 91 | + description: | |
| 92 | + Length of precharge period (phase 2) in clock cycles. This needs to be | |
| 93 | + the higher, the higher the capacitance of the OLED's pixels is. | |
| 94 | + | |
| 95 | + solomon,dclk-div: | |
| 96 | + $ref: /schemas/types.yaml#/definitions/uint32 | |
| 97 | + minimum: 1 | |
| 98 | + maximum: 16 | |
| 99 | + description: | |
| 100 | + Clock divisor. The default value is controller-dependent. | |
| 101 | + | |
| 102 | + solomon,dclk-frq: | |
| 103 | + $ref: /schemas/types.yaml#/definitions/uint32 | |
| 104 | + minimum: 0 | |
| 105 | + maximum: 15 | |
| 106 | + description: | |
| 107 | + Clock frequency, higher value means higher frequency. | |
| 108 | + The default value is controller-dependent. | |
| 109 | + | |
| 110 | + solomon,lookup-table: | |
| 111 | + $ref: /schemas/types.yaml#/definitions/uint8-array | |
| 112 | + maxItems: 4 | |
| 113 | + description: | |
| 114 | + 8 bit value array of current drive pulse widths for BANK0, and colors A, | |
| 115 | + B, and C. Each value in range of 31 to 63 for pulse widths of 32 to 64. | |
| 116 | + Color D is always width 64. | |
| 117 | + | |
| 118 | + solomon,area-color-enable: | |
| 119 | + type: boolean | |
| 120 | + description: | |
| 121 | + Display uses color mode | |
| 122 | + | |
| 123 | + solomon,low-power: | |
| 124 | + type: boolean | |
| 125 | + description: | |
| 126 | + Display runs in low power mode | |
| 127 | + | |
| 128 | +required: | |
| 129 | + - compatible | |
| 130 | + - reg | |
| 131 | + | |
| 132 | +allOf: | |
| 133 | + - if: | |
| 134 | + properties: | |
| 135 | + compatible: | |
| 136 | + contains: | |
| 137 | + const: solomon,ssd1305fb-i2c | |
| 138 | + then: | |
| 139 | + properties: | |
| 140 | + solomon,dclk-div: | |
| 141 | + default: 1 | |
| 142 | + solomon,dclk-frq: | |
| 143 | + default: 7 | |
| 144 | + | |
| 145 | + - if: | |
| 146 | + properties: | |
| 147 | + compatible: | |
| 148 | + contains: | |
| 149 | + const: solomon,ssd1306fb-i2c | |
| 150 | + then: | |
| 151 | + properties: | |
| 152 | + solomon,dclk-div: | |
| 153 | + default: 1 | |
| 154 | + solomon,dclk-frq: | |
| 155 | + default: 8 | |
| 156 | + | |
| 157 | + - if: | |
| 158 | + properties: | |
| 159 | + compatible: | |
| 160 | + contains: | |
| 161 | + const: solomon,ssd1307fb-i2c | |
| 162 | + then: | |
| 163 | + properties: | |
| 164 | + solomon,dclk-div: | |
| 165 | + default: 2 | |
| 166 | + solomon,dclk-frq: | |
| 167 | + default: 12 | |
| 168 | + required: | |
| 169 | + - pwms | |
| 170 | + | |
| 171 | + - if: | |
| 172 | + properties: | |
| 173 | + compatible: | |
| 174 | + contains: | |
| 175 | + const: solomon,ssd1309fb-i2c | |
| 176 | + then: | |
| 177 | + properties: | |
| 178 | + solomon,dclk-div: | |
| 179 | + default: 1 | |
| 180 | + solomon,dclk-frq: | |
| 181 | + default: 10 | |
| 182 | + | |
| 183 | +additionalProperties: false | |
| 184 | + | |
| 185 | +examples: | |
| 186 | + - | | |
| 187 | + i2c1 { | |
| 188 | + #address-cells = <1>; | |
| 189 | + #size-cells = <0>; | |
| 190 | + | |
| 191 | + ssd1307: oled@3c { | |
| 192 | + compatible = "solomon,ssd1307fb-i2c"; | |
| 193 | + reg = <0x3c>; | |
| 194 | + pwms = <&pwm 4 3000>; | |
| 195 | + reset-gpios = <&gpio2 7>; | |
| 196 | + }; | |
| 197 | + | |
| 198 | + ssd1306: oled@3d { | |
| 199 | + compatible = "solomon,ssd1306fb-i2c"; | |
| 200 | + reg = <0x3c>; | |
| 201 | + pwms = <&pwm 4 3000>; | |
| 202 | + reset-gpios = <&gpio2 7>; | |
| 203 | + solomon,com-lrremap; | |
| 204 | + solomon,com-invdir; | |
| 205 | + solomon,com-offset = <32>; | |
| 206 | + solomon,lookup-table = /bits/ 8 <0x3f 0x3f 0x3f 0x3f>; | |
| 207 | + }; | |
| 208 | + }; | |
| @@ -1,60 +0,0 @@ | ||
| 1 | −* Solomon SSD1307 Framebuffer Driver | |
| 2 | − | |
| 3 | −Required properties: | |
| 4 | − - compatible: Should be "solomon,<chip>fb-<bus>". The only supported bus for | |
| 5 | − now is i2c, and the supported chips are ssd1305, ssd1306, ssd1307 and | |
| 6 | − ssd1309. | |
| 7 | − - reg: Should contain address of the controller on the I2C bus. Most likely | |
| 8 | − 0x3c or 0x3d | |
| 9 | − - pwm: Should contain the pwm to use according to the OF device tree PWM | |
| 10 | − specification [0]. Only required for the ssd1307. | |
| 11 | − - solomon,height: Height in pixel of the screen driven by the controller | |
| 12 | − - solomon,width: Width in pixel of the screen driven by the controller | |
| 13 | − - solomon,page-offset: Offset of pages (band of 8 pixels) that the screen is | |
| 14 | − mapped to. | |
| 15 | − | |
| 16 | −Optional properties: | |
| 17 | − - reset-gpios: The GPIO used to reset the OLED display, if available. See | |
| 18 | − Documentation/devicetree/bindings/gpio/gpio.txt for details. | |
| 19 | − - vbat-supply: The supply for VBAT | |
| 20 | − - solomon,segment-no-remap: Display needs normal (non-inverted) data column | |
| 21 | − to segment mapping | |
| 22 | − - solomon,col-offset: Offset of columns (COL/SEG) that the screen is mapped to. | |
| 23 | − - solomon,com-seq: Display uses sequential COM pin configuration | |
| 24 | − - solomon,com-lrremap: Display uses left-right COM pin remap | |
| 25 | − - solomon,com-invdir: Display uses inverted COM pin scan direction | |
| 26 | − - solomon,com-offset: Number of the COM pin wired to the first display line | |
| 27 | − - solomon,prechargep1: Length of deselect period (phase 1) in clock cycles. | |
| 28 | − - solomon,prechargep2: Length of precharge period (phase 2) in clock cycles. | |
| 29 | − This needs to be the higher, the higher the capacitance | |
| 30 | − of the OLED's pixels is | |
| 31 | − - solomon,dclk-div: Clock divisor 1 to 16 | |
| 32 | − - solomon,dclk-frq: Clock frequency 0 to 15, higher value means higher | |
| 33 | − frequency | |
| 34 | − - solomon,lookup-table: 8 bit value array of current drive pulse widths for | |
| 35 | − BANK0, and colors A, B, and C. Each value in range | |
| 36 | − of 31 to 63 for pulse widths of 32 to 64. Color D | |
| 37 | − is always width 64. | |
| 38 | − - solomon,area-color-enable: Display uses color mode | |
| 39 | − - solomon,low-power. Display runs in low power mode | |
| 40 | − | |
| 41 | −[0]: Documentation/devicetree/bindings/pwm/pwm.txt | |
| 42 | − | |
| 43 | −Examples: | |
| 44 | −ssd1307: oled@3c { | |
| 45 | − compatible = "solomon,ssd1307fb-i2c"; | |
| 46 | − reg = <0x3c>; | |
| 47 | − pwms = <&pwm 4 3000>; | |
| 48 | − reset-gpios = <&gpio2 7>; | |
| 49 | −}; | |
| 50 | − | |
| 51 | −ssd1306: oled@3c { | |
| 52 | − compatible = "solomon,ssd1306fb-i2c"; | |
| 53 | − reg = <0x3c>; | |
| 54 | − pwms = <&pwm 4 3000>; | |
| 55 | − reset-gpios = <&gpio2 7>; | |
| 56 | − solomon,com-lrremap; | |
| 57 | − solomon,com-invdir; | |
| 58 | − solomon,com-offset = <32>; | |
| 59 | − solomon,lookup-table = /bits/ 8 <0x3f 0x3f 0x3f 0x3f>; | |
| 60 | −}; | |
| @@ -341,6 +341,8 @@ patternProperties: · 340 unmodified lines | ||
| 341 | 341 | description: eGalax_eMPIA Technology Inc |
| 342 | 342 | "^einfochips,.*": |
| 343 | 343 | description: Einfochips |
| 344 | + "^eink,.*": | |
| 345 | + description: E Ink Corporation | |
| 344 | 346 | "^elan,.*": |
| 345 | 347 | description: Elan Microelectronic Corp. |
| 346 | 348 | "^element14,.*": |
| @@ -938,6 +940,8 @@ patternProperties: · 591 unmodified lines | ||
| 938 | 940 | description: Chengdu Kaixuan Information Technology Co., Ltd. |
| 939 | 941 | "^qiaodian,.*": |
| 940 | 942 | description: QiaoDian XianShi Corporation |
| 943 | + "^qishenglong,.*": | |
| 944 | + description: Shenzhen QiShenglong Industrialist Co., Ltd. | |
| 941 | 945 | "^qnap,.*": |
| 942 | 946 | description: QNAP Systems, Inc. |
| 943 | 947 | "^radxa,.*": |
| @@ -88,6 +88,9 @@ consider though: · 87 unmodified lines | ||
| 88 | 88 | - The DMA buffer FD is also pollable, see `Implicit Fence Poll Support`_ below for |
| 89 | 89 | details. |
| 90 | 90 | |
| 91 | +- The DMA buffer FD also supports a few dma-buf-specific ioctls, see | |
| 92 | + `DMA Buffer ioctls`_ below for details. | |
| 93 | + | |
| 91 | 94 | Basic Operation and Device DMA Access |
| 92 | 95 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 93 | 96 | |
| @@ -106,6 +109,16 @@ Implicit Fence Poll Support · 12 unmodified lines | ||
| 106 | 109 | .. kernel-doc:: drivers/dma-buf/dma-buf.c |
| 107 | 110 | :doc: implicit fence polling |
| 108 | 111 | |
| 112 | +DMA-BUF statistics | |
| 113 | +~~~~~~~~~~~~~~~~~~ | |
| 114 | +.. kernel-doc:: drivers/dma-buf/dma-buf-sysfs-stats.c | |
| 115 | + :doc: overview | |
| 116 | + | |
| 117 | +DMA Buffer ioctls | |
| 118 | +~~~~~~~~~~~~~~~~~ | |
| 119 | + | |
| 120 | +.. kernel-doc:: include/uapi/linux/dma-buf.h | |
| 121 | + | |
| 109 | 122 | Kernel Functions and Structures Reference |
| 110 | 123 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 111 | 124 | |
| @@ -90,7 +90,7 @@ Bug reports · 89 unmodified lines | ||
| 90 | 90 | ----------- |
| 91 | 91 | |
| 92 | 92 | Thermal management on Nouveau is new and may not work on all cards. If you have |
| 93 | −inquiries, please ping mupuf on IRC (#nouveau, freenode). | |
| 93 | +inquiries, please ping mupuf on IRC (#nouveau, OFTC). | |
| 94 | 94 | |
| 95 | 95 | Bug reports should be filled on Freedesktop's bug tracker. Please follow |
| 96 | 96 | https://nouveau.freedesktop.org/wiki/Bugs |
| @@ -159,6 +159,8 @@ KMS Core Structures and Functions · 158 unmodified lines | ||
| 159 | 159 | .. kernel-doc:: drivers/gpu/drm/drm_mode_config.c |
| 160 | 160 | :export: |
| 161 | 161 | |
| 162 | +.. _kms_base_object_abstraction: | |
| 163 | + | |
| 162 | 164 | Modeset Base Object Abstraction |
| 163 | 165 | =============================== |
| 164 | 166 | |
| @@ -463,6 +465,35 @@ KMS Properties · 298 unmodified lines | ||
| 463 | 465 | This section of the documentation is primarily aimed at user-space developers. |
| 464 | 466 | For the driver APIs, see the other sections. |
| 465 | 467 | |
| 468 | +Requirements | |
| 469 | +------------ | |
| 470 | + | |
| 471 | +KMS drivers might need to add extra properties to support new features. Each | |
| 472 | +new property introduced in a driver needs to meet a few requirements, in | |
| 473 | +addition to the one mentioned above: | |
| 474 | + | |
| 475 | +* It must be standardized, documenting: | |
| 476 | + | |
| 477 | + * The full, exact, name string; | |
| 478 | + * If the property is an enum, all the valid value name strings; | |
| 479 | + * What values are accepted, and what these values mean; | |
| 480 | + * What the property does and how it can be used; | |
| 481 | + * How the property might interact with other, existing properties. | |
| 482 | + | |
| 483 | +* It must provide a generic helper in the core code to register that | |
| 484 | + property on the object it attaches to. | |
| 485 | + | |
| 486 | +* Its content must be decoded by the core and provided in the object's | |
| 487 | + associated state structure. That includes anything drivers might want | |
| 488 | + to precompute, like struct drm_clip_rect for planes. | |
| 489 | + | |
| 490 | +* Its initial state must match the behavior prior to the property | |
| 491 | + introduction. This might be a fixed value matching what the hardware | |
| 492 | + does, or it may be inherited from the state the firmware left the | |
| 493 | + system in during boot. | |
| 494 | + | |
| 495 | +* An IGT test must be submitted where reasonable. | |
| 496 | + | |
| 466 | 497 | Property Types and Blob Property Support |
| 467 | 498 | ---------------------------------------- |
| 468 | 499 | |
| @@ -508,8 +539,8 @@ Plane Composition Properties · 39 unmodified lines | ||
| 508 | 539 | Damage Tracking Properties |
| 509 | 540 | -------------------------- |
| 510 | 541 | |
| 511 | −.. kernel-doc:: drivers/gpu/drm/drm_damage_helper.c | |
| 512 | − :doc: overview | |
| 542 | +.. kernel-doc:: drivers/gpu/drm/drm_plane.c | |
| 543 | + :doc: damage tracking | |
| 513 | 544 | |
| 514 | 545 | Color Management Properties |
| 515 | 546 | --------------------------- |
| @@ -37,6 +37,15 @@ Primary Nodes, DRM Master and Authentication · 36 unmodified lines | ||
| 37 | 37 | .. kernel-doc:: include/drm/drm_auth.h |
| 38 | 38 | :internal: |
| 39 | 39 | |
| 40 | + | |
| 41 | +.. _drm_leasing: | |
| 42 | + | |
| 43 | +DRM Display Resource Leasing | |
| 44 | +============================ | |
| 45 | + | |
| 46 | +.. kernel-doc:: drivers/gpu/drm/drm_lease.c | |
| 47 | + :doc: drm leasing | |
| 48 | + | |
| 40 | 49 | Open-Source Userspace Requirements |
| 41 | 50 | ================================== |
| 42 | 51 | |
| @@ -457,6 +466,19 @@ Userspace API Structures · 414 unmodified lines | ||
| 457 | 466 | .. kernel-doc:: include/uapi/drm/drm_mode.h |
| 458 | 467 | :doc: overview |
| 459 | 468 | |
| 469 | +.. _crtc_index: | |
| 470 | + | |
| 471 | +CRTC index | |
| 472 | +---------- | |
| 473 | + | |
| 474 | +CRTC's have both an object ID and an index, and they are not the same thing. | |
| 475 | +The index is used in cases where a densely packed identifier for a CRTC is | |
| 476 | +needed, for instance a bitmask of CRTC's. The member possible_crtcs of struct | |
| 477 | +drm_mode_get_plane is an example. | |
| 478 | + | |
| 479 | +DRM_IOCTL_MODE_GETRESOURCES populates a structure with an array of CRTC ID's, | |
| 480 | +and the CRTC index is its position in this array. | |
| 481 | + | |
| 460 | 482 | .. kernel-doc:: include/uapi/drm/drm.h |
| 461 | 483 | :internal: |
| 462 | 484 | |
| @@ -422,9 +422,16 @@ Batchbuffer Parsing · 421 unmodified lines | ||
| 422 | 422 | User Batchbuffer Execution |
| 423 | 423 | -------------------------- |
| 424 | 424 | |
| 425 | +.. kernel-doc:: drivers/gpu/drm/i915/gem/i915_gem_context_types.h | |
| 426 | + | |
| 425 | 427 | .. kernel-doc:: drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c |
| 426 | 428 | :doc: User command execution |
| 427 | 429 | |
| 430 | +Scheduling | |
| 431 | +---------- | |
| 432 | +.. kernel-doc:: drivers/gpu/drm/i915/i915_scheduler_types.h | |
| 433 | + :functions: i915_sched_engine | |
| 434 | + | |
| 428 | 435 | Logical Rings, Logical Ring Contexts and Execlists |
| 429 | 436 | -------------------------------------------------- |
| 430 | 437 | |
| @@ -518,6 +525,14 @@ GuC-based command submission · 87 unmodified lines | ||
| 518 | 525 | .. kernel-doc:: drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c |
| 519 | 526 | :doc: GuC-based command submission |
| 520 | 527 | |
| 528 | +GuC ABI | |
| 529 | +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
| 530 | + | |
| 531 | +.. kernel-doc:: drivers/gpu/drm/i915/gt/uc/abi/guc_messages_abi.h | |
| 532 | +.. kernel-doc:: drivers/gpu/drm/i915/gt/uc/abi/guc_communication_mmio_abi.h | |
| 533 | +.. kernel-doc:: drivers/gpu/drm/i915/gt/uc/abi/guc_communication_ctb_abi.h | |
| 534 | +.. kernel-doc:: drivers/gpu/drm/i915/gt/uc/abi/guc_actions_abi.h | |
| 535 | + | |
| 521 | 536 | HuC |
| 522 | 537 | --- |
| 523 | 538 | .. kernel-doc:: drivers/gpu/drm/i915/gt/uc/intel_huc.c |
| @@ -0,0 +1,122 @@ | ||
| 1 | +/* SPDX-License-Identifier: MIT */ | |
| 2 | +/* | |
| 3 | + * Copyright © 2021 Intel Corporation | |
| 4 | + */ | |
| 5 | + | |
| 6 | +#define I915_CONTEXT_ENGINES_EXT_PARALLEL_SUBMIT 2 /* see i915_context_engines_parallel_submit */ | |
| 7 | + | |
| 8 | +/** | |
| 9 | + * struct drm_i915_context_engines_parallel_submit - Configure engine for | |
| 10 | + * parallel submission. | |
| 11 | + * | |
| 12 | + * Setup a slot in the context engine map to allow multiple BBs to be submitted | |
| 13 | + * in a single execbuf IOCTL. Those BBs will then be scheduled to run on the GPU | |
| 14 | + * in parallel. Multiple hardware contexts are created internally in the i915 | |
| 15 | + * run these BBs. Once a slot is configured for N BBs only N BBs can be | |
| 16 | + * submitted in each execbuf IOCTL and this is implicit behavior e.g. The user | |
| 17 | + * doesn't tell the execbuf IOCTL there are N BBs, the execbuf IOCTL knows how | |
| 18 | + * many BBs there are based on the slot's configuration. The N BBs are the last | |
| 19 | + * N buffer objects or first N if I915_EXEC_BATCH_FIRST is set. | |
| 20 | + * | |
| 21 | + * The default placement behavior is to create implicit bonds between each | |
| 22 | + * context if each context maps to more than 1 physical engine (e.g. context is | |
| 23 | + * a virtual engine). Also we only allow contexts of same engine class and these | |
| 24 | + * contexts must be in logically contiguous order. Examples of the placement | |
| 25 | + * behavior described below. Lastly, the default is to not allow BBs to | |
| 26 | + * preempted mid BB rather insert coordinated preemption on all hardware | |
| 27 | + * contexts between each set of BBs. Flags may be added in the future to change | |
| 28 | + * both of these default behaviors. | |
| 29 | + * | |
| 30 | + * Returns -EINVAL if hardware context placement configuration is invalid or if | |
| 31 | + * the placement configuration isn't supported on the platform / submission | |
| 32 | + * interface. | |
| 33 | + * Returns -ENODEV if extension isn't supported on the platform / submission | |
| 34 | + * interface. | |
| 35 | + * | |
| 36 | + * .. code-block:: none | |
| 37 | + * | |
| 38 | + * Example 1 pseudo code: | |
| 39 | + * CS[X] = generic engine of same class, logical instance X | |
| 40 | + * INVALID = I915_ENGINE_CLASS_INVALID, I915_ENGINE_CLASS_INVALID_NONE | |
| 41 | + * set_engines(INVALID) | |
| 42 | + * set_parallel(engine_index=0, width=2, num_siblings=1, | |
| 43 | + * engines=CS[0],CS[1]) | |
| 44 | + * | |
| 45 | + * Results in the following valid placement: | |
| 46 | + * CS[0], CS[1] | |
| 47 | + * | |
| 48 | + * Example 2 pseudo code: | |
| 49 | + * CS[X] = generic engine of same class, logical instance X | |
| 50 | + * INVALID = I915_ENGINE_CLASS_INVALID, I915_ENGINE_CLASS_INVALID_NONE | |
| 51 | + * set_engines(INVALID) | |
| 52 | + * set_parallel(engine_index=0, width=2, num_siblings=2, | |
| 53 | + * engines=CS[0],CS[2],CS[1],CS[3]) | |
| 54 | + * | |
| 55 | + * Results in the following valid placements: | |
| 56 | + * CS[0], CS[1] | |
| 57 | + * CS[2], CS[3] | |
| 58 | + * | |
| 59 | + * This can also be thought of as 2 virtual engines described by 2-D array | |
| 60 | + * in the engines the field with bonds placed between each index of the | |
| 61 | + * virtual engines. e.g. CS[0] is bonded to CS[1], CS[2] is bonded to | |
| 62 | + * CS[3]. | |
| 63 | + * VE[0] = CS[0], CS[2] | |
| 64 | + * VE[1] = CS[1], CS[3] | |
| 65 | + * | |
| 66 | + * Example 3 pseudo code: | |
| 67 | + * CS[X] = generic engine of same class, logical instance X | |
| 68 | + * INVALID = I915_ENGINE_CLASS_INVALID, I915_ENGINE_CLASS_INVALID_NONE | |
| 69 | + * set_engines(INVALID) | |
| 70 | + * set_parallel(engine_index=0, width=2, num_siblings=2, | |
| 71 | + * engines=CS[0],CS[1],CS[1],CS[3]) | |
| 72 | + * | |
| 73 | + * Results in the following valid and invalid placements: | |
| 74 | + * CS[0], CS[1] | |
| 75 | + * CS[1], CS[3] - Not logical contiguous, return -EINVAL | |
| 76 | + */ | |
| 77 | +struct drm_i915_context_engines_parallel_submit { | |
| 78 | + /** | |
| 79 | + * @base: base user extension. | |
| 80 | + */ | |
| 81 | + struct i915_user_extension base; | |
| 82 | + | |
| 83 | + /** | |
| 84 | + * @engine_index: slot for parallel engine | |
| 85 | + */ | |
| 86 | + __u16 engine_index; | |
| 87 | + | |
| 88 | + /** | |
| 89 | + * @width: number of contexts per parallel engine | |
| 90 | + */ | |
| 91 | + __u16 width; | |
| 92 | + | |
| 93 | + /** | |
| 94 | + * @num_siblings: number of siblings per context | |
| 95 | + */ | |
| 96 | + __u16 num_siblings; | |
| 97 | + | |
| 98 | + /** | |
| 99 | + * @mbz16: reserved for future use; must be zero | |
| 100 | + */ | |
| 101 | + __u16 mbz16; | |
| 102 | + | |
| 103 | + /** | |
| 104 | + * @flags: all undefined flags must be zero, currently not defined flags | |
| 105 | + */ | |
| 106 | + __u64 flags; | |
| 107 | + | |
| 108 | + /** | |
| 109 | + * @mbz64: reserved for future use; must be zero | |
| 110 | + */ | |
| 111 | + __u64 mbz64[3]; | |
| 112 | + | |
| 113 | + /** | |
| 114 | + * @engines: 2-d array of engine instances to configure parallel engine | |
| 115 | + * | |
| 116 | + * length = width (i) * num_siblings (j) | |
| 117 | + * index = j + i * num_siblings | |
| 118 | + */ | |
| 119 | + struct i915_engine_class_instance engines[0]; | |
| 120 | + | |
| 121 | +} __packed; | |
| 122 | + | |
| @@ -0,0 +1,148 @@ | ||
| 1 | +========================================= | |
| 2 | +I915 GuC Submission/DRM Scheduler Section | |
| 3 | +========================================= | |
| 4 | + | |
| 5 | +Upstream plan | |
| 6 | +============= | |
| 7 | +For upstream the overall plan for landing GuC submission and integrating the | |
| 8 | +i915 with the DRM scheduler is: | |
| 9 | + | |
| 10 | +* Merge basic GuC submission | |
| 11 | + * Basic submission support for all gen11+ platforms | |
| 12 | + * Not enabled by default on any current platforms but can be enabled via | |
| 13 | + modparam enable_guc | |
| 14 | + * Lots of rework will need to be done to integrate with DRM scheduler so | |
| 15 | + no need to nit pick everything in the code, it just should be | |
| 16 | + functional, no major coding style / layering errors, and not regress | |
| 17 | + execlists | |
| 18 | + * Update IGTs / selftests as needed to work with GuC submission | |
| 19 | + * Enable CI on supported platforms for a baseline | |
| 20 | + * Rework / get CI heathly for GuC submission in place as needed | |
| 21 | +* Merge new parallel submission uAPI | |
| 22 | + * Bonding uAPI completely incompatible with GuC submission, plus it has | |
| 23 | + severe design issues in general, which is why we want to retire it no | |
| 24 | + matter what | |
| 25 | + * New uAPI adds I915_CONTEXT_ENGINES_EXT_PARALLEL context setup step | |
| 26 | + which configures a slot with N contexts | |
| 27 | + * After I915_CONTEXT_ENGINES_EXT_PARALLEL a user can submit N batches to | |
| 28 | + a slot in a single execbuf IOCTL and the batches run on the GPU in | |
| 29 | + paralllel | |
| 30 | + * Initially only for GuC submission but execlists can be supported if | |
| 31 | + needed | |
| 32 | +* Convert the i915 to use the DRM scheduler | |
| 33 | + * GuC submission backend fully integrated with DRM scheduler | |
| 34 | + * All request queues removed from backend (e.g. all backpressure | |
| 35 | + handled in DRM scheduler) | |
| 36 | + * Resets / cancels hook in DRM scheduler | |
| 37 | + * Watchdog hooks into DRM scheduler | |
| 38 | + * Lots of complexity of the GuC backend can be pulled out once | |
| 39 | + integrated with DRM scheduler (e.g. state machine gets | |
| 40 | + simplier, locking gets simplier, etc...) | |
| 41 | + * Execlists backend will minimum required to hook in the DRM scheduler | |
| 42 | + * Legacy interface | |
| 43 | + * Features like timeslicing / preemption / virtual engines would | |
| 44 | + be difficult to integrate with the DRM scheduler and these | |
| 45 | + features are not required for GuC submission as the GuC does | |
| 46 | + these things for us | |
| 47 | + * ROI low on fully integrating into DRM scheduler | |
| 48 | + * Fully integrating would add lots of complexity to DRM | |
| 49 | + scheduler | |
| 50 | + * Port i915 priority inheritance / boosting feature in DRM scheduler | |
| 51 | + * Used for i915 page flip, may be useful to other DRM drivers as | |
| 52 | + well | |
| 53 | + * Will be an optional feature in the DRM scheduler | |
| 54 | + * Remove in-order completion assumptions from DRM scheduler | |
| 55 | + * Even when using the DRM scheduler the backends will handle | |
| 56 | + preemption, timeslicing, etc... so it is possible for jobs to | |
| 57 | + finish out of order | |
| 58 | + * Pull out i915 priority levels and use DRM priority levels | |
| 59 | + * Optimize DRM scheduler as needed | |
| 60 | + | |
| 61 | +TODOs for GuC submission upstream | |
| 62 | +================================= | |
| 63 | + | |
| 64 | +* Need an update to GuC firmware / i915 to enable error state capture | |
| 65 | +* Open source tool to decode GuC logs | |
| 66 | +* Public GuC spec | |
| 67 | + | |
| 68 | +New uAPI for basic GuC submission | |
| 69 | +================================= | |
| 70 | +No major changes are required to the uAPI for basic GuC submission. The only | |
| 71 | +change is a new scheduler attribute: I915_SCHEDULER_CAP_STATIC_PRIORITY_MAP. | |
| 72 | +This attribute indicates the 2k i915 user priority levels are statically mapped | |
| 73 | +into 3 levels as follows: | |
| 74 | + | |
| 75 | +* -1k to -1 Low priority | |
| 76 | +* 0 Medium priority | |
| 77 | +* 1 to 1k High priority | |
| 78 | + | |
| 79 | +This is needed because the GuC only has 4 priority bands. The highest priority | |
| 80 | +band is reserved with the kernel. This aligns with the DRM scheduler priority | |
| 81 | +levels too. | |
| 82 | + | |
| 83 | +Spec references: | |
| 84 | +---------------- | |
| 85 | +* https://www.khronos.org/registry/EGL/extensions/IMG/EGL_IMG_context_priority.txt | |
| 86 | +* https://www.khronos.org/registry/vulkan/specs/1.2-extensions/html/chap5.html#devsandqueues-priority | |
| 87 | +* https://spec.oneapi.com/level-zero/latest/core/api.html#ze-command-queue-priority-t | |
| 88 | + | |
| 89 | +New parallel submission uAPI | |
| 90 | +============================ | |
| 91 | +The existing bonding uAPI is completely broken with GuC submission because | |
| 92 | +whether a submission is a single context submit or parallel submit isn't known | |
| 93 | +until execbuf time activated via the I915_SUBMIT_FENCE. To submit multiple | |
| 94 | +contexts in parallel with the GuC the context must be explicitly registered with | |
| 95 | +N contexts and all N contexts must be submitted in a single command to the GuC. | |
| 96 | +The GuC interfaces do not support dynamically changing between N contexts as the | |
| 97 | +bonding uAPI does. Hence the need for a new parallel submission interface. Also | |
| 98 | +the legacy bonding uAPI is quite confusing and not intuitive at all. Furthermore | |
| 99 | +I915_SUBMIT_FENCE is by design a future fence, so not really something we should | |
| 100 | +continue to support. | |
| 101 | + | |
| 102 | +The new parallel submission uAPI consists of 3 parts: | |
| 103 | + | |
| 104 | +* Export engines logical mapping | |
| 105 | +* A 'set_parallel' extension to configure contexts for parallel | |
| 106 | + submission | |
| 107 | +* Extend execbuf2 IOCTL to support submitting N BBs in a single IOCTL | |
| 108 | + | |
| 109 | +Export engines logical mapping | |
| 110 | +------------------------------ | |
| 111 | +Certain use cases require BBs to be placed on engine instances in logical order | |
| 112 | +(e.g. split-frame on gen11+). The logical mapping of engine instances can change | |
| 113 | +based on fusing. Rather than making UMDs be aware of fusing, simply expose the | |
| 114 | +logical mapping with the existing query engine info IOCTL. Also the GuC | |
| 115 | +submission interface currently only supports submitting multiple contexts to | |
| 116 | +engines in logical order which is a new requirement compared to execlists. | |
| 117 | +Lastly, all current platforms have at most 2 engine instances and the logical | |
| 118 | +order is the same as uAPI order. This will change on platforms with more than 2 | |
| 119 | +engine instances. | |
| 120 | + | |
| 121 | +A single bit will be added to drm_i915_engine_info.flags indicating that the | |
| 122 | +logical instance has been returned and a new field, | |
| 123 | +drm_i915_engine_info.logical_instance, returns the logical instance. | |
| 124 | + | |
| 125 | +A 'set_parallel' extension to configure contexts for parallel submission | |
| 126 | +------------------------------------------------------------------------ | |
| 127 | +The 'set_parallel' extension configures a slot for parallel submission of N BBs. | |
| 128 | +It is a setup step that must be called before using any of the contexts. See | |
| 129 | +I915_CONTEXT_ENGINES_EXT_LOAD_BALANCE or I915_CONTEXT_ENGINES_EXT_BOND for | |
| 130 | +similar existing examples. Once a slot is configured for parallel submission the | |
| 131 | +execbuf2 IOCTL can be called submitting N BBs in a single IOCTL. Initially only | |
| 132 | +supports GuC submission. Execlists supports can be added later if needed. | |
| 133 | + | |
| 134 | +Add I915_CONTEXT_ENGINES_EXT_PARALLEL_SUBMIT and | |
| 135 | +drm_i915_context_engines_parallel_submit to the uAPI to implement this | |
| 136 | +extension. | |
| 137 | + | |
| 138 | +.. kernel-doc:: Documentation/gpu/rfc/i915_parallel_execbuf.h | |
| 139 | + :functions: drm_i915_context_engines_parallel_submit | |
| 140 | + | |
| 141 | +Extend execbuf2 IOCTL to support submitting N BBs in a single IOCTL | |
| 142 | +------------------------------------------------------------------- | |
| 143 | +Contexts that have been configured with the 'set_parallel' extension can only | |
| 144 | +submit N BBs in a single execbuf2 IOCTL. The BBs are either the last N objects | |
| 145 | +in the drm_i915_gem_exec_object2 list or the first N if I915_EXEC_BATCH_FIRST is | |
| 146 | +set. The number of BBs is implicit based on the slot submitted and how it has | |
| 147 | +been configured by 'set_parallel' or other extensions. No uAPI changes are | |
| 148 | +required to the execbuf2 IOCTL. | |
| @@ -19,3 +19,7 @@ host such documentation: · 18 unmodified lines | ||
| 19 | 19 | .. toctree:: |
| 20 | 20 | |
| 21 | 21 | i915_gem_lmem.rst |
| 22 | + | |
| 23 | +.. toctree:: | |
| 24 | + | |
| 25 | + i915_scheduler.rst | |
| @@ -98,9 +98,17 @@ with VKMS maintainers. · 97 unmodified lines | ||
| 98 | 98 | IGT better support |
| 99 | 99 | ------------------ |
| 100 | 100 | |
| 101 | −- Investigate: (1) test cases on kms_plane that are failing due to timeout on | |
| 102 | − capturing CRC; (2) when running kms_flip test cases in sequence, some | |
| 103 | − successful individual test cases are failing randomly. | |
| 101 | +Debugging: | |
| 102 | + | |
| 103 | +- kms_plane: some test cases are failing due to timeout on capturing CRC; | |
| 104 | + | |
| 105 | +- kms_flip: when running test cases in sequence, some successful individual | |
| 106 | + test cases are failing randomly; when individually, some successful test | |
| 107 | + cases display in the log the following error:: | |
| 108 | + | |
| 109 | + [drm:vkms_prepare_fb [vkms]] ERROR vmap failed: -4 | |
| 110 | + | |
| 111 | +Virtual hardware (vblank-less) mode: | |
| 104 | 112 | |
| 105 | 113 | - VKMS already has support for vblanks simulated via hrtimers, which can be |
| 106 | 114 | tested with kms_flip test; in some way, we can say that VKMS already mimics |
| @@ -116,7 +124,17 @@ Add Plane Features · 9 unmodified lines | ||
| 116 | 124 | |
| 117 | 125 | There's lots of plane features we could add support for: |
| 118 | 126 | |
| 119 | −- Real overlay planes, not just cursor. | |
| 127 | +- Multiple overlay planes. [Good to get started] | |
| 128 | + | |
| 129 | +- Clearing primary plane: clear primary plane before plane composition (at the | |
| 130 | + start) for correctness of pixel blend ops. It also guarantees alpha channel | |
| 131 | + is cleared in the target buffer for stable crc. [Good to get started] | |
| 132 | + | |
| 133 | +- ARGB format on primary plane: blend the primary plane into background with | |
| 134 | + translucent alpha. | |
| 135 | + | |
| 136 | +- Support when the primary plane isn't exactly matching the output size: blend | |
| 137 | + the primary plane into the black background. | |
| 120 | 138 | |
| 121 | 139 | - Full alpha blending on all planes. |
| 122 | 140 | |
| @@ -129,13 +147,8 @@ There's lots of plane features we could add support for: · 6 unmodified lines | ||
| 129 | 147 | cursor api). |
| 130 | 148 | |
| 131 | 149 | For all of these, we also want to review the igt test coverage and make sure |
| 132 | −all relevant igt testcases work on vkms. | |
| 133 | − | |
| 134 | −Prime Buffer Sharing | |
| 135 | −-------------------- | |
| 136 | − | |
| 137 | −- Syzbot report - WARNING in vkms_gem_free_object: | |
| 138 | − https://syzkaller.appspot.com/bug?extid=e7ad70d406e74d8fc9d0 | |
| 150 | +all relevant igt testcases work on vkms. They are good options for internship | |
| 151 | +project. | |
| 139 | 152 | |
| 140 | 153 | Runtime Configuration |
| 141 | 154 | --------------------- |
| @@ -153,7 +166,7 @@ module. Use/Test-cases: · 11 unmodified lines | ||
| 153 | 166 | the refresh rate. |
| 154 | 167 | |
| 155 | 168 | The currently proposed solution is to expose vkms configuration through |
| 156 | −configfs. All existing module options should be supported through configfs | |
| 169 | +configfs. All existing module options should be supported through configfs | |
| 157 | 170 | too. |
| 158 | 171 | |
| 159 | 172 | Writeback support |
| @@ -162,6 +175,7 @@ Writeback support · 2 unmodified lines | ||
| 162 | 175 | - The writeback and CRC capture operations share the use of composer_enabled |
| 163 | 176 | boolean to ensure vblanks. Probably, when these operations work together, |
| 164 | 177 | composer_enabled needs to refcounting the composer state to proper work. |
| 178 | + [Good to get started] | |
| 165 | 179 | |
| 166 | 180 | - Add support for cloned writeback outputs and related test cases using a |
| 167 | 181 | cloned output in the IGT kms_writeback. |
| @@ -1703,7 +1703,7 @@ L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) · 1702 unmodified lines | ||
| 1703 | 1703 | S: Maintained |
| 1704 | 1704 | W: https://asahilinux.org |
| 1705 | 1705 | B: https://github.com/AsahiLinux/linux/issues |
| 1706 | −C: irc://chat.freenode.net/asahi-dev | |
| 1706 | +C: irc://irc.oftc.net/asahi-dev | |
| 1707 | 1707 | T: git https://github.com/AsahiLinux/linux.git |
| 1708 | 1708 | F: Documentation/devicetree/bindings/arm/apple.yaml |
| 1709 | 1709 | F: Documentation/devicetree/bindings/interrupt-controller/apple,aic.yaml |
| @@ -5799,7 +5799,7 @@ M: Gerd Hoffmann <kraxel@redhat.com> · 4089 unmodified lines | ||
| 5799 | 5799 | L: virtualization@lists.linux-foundation.org |
| 5800 | 5800 | S: Maintained |
| 5801 | 5801 | T: git git://anongit.freedesktop.org/drm/drm-misc |
| 5802 | −F: drivers/gpu/drm/bochs/ | |
| 5802 | +F: drivers/gpu/drm/tiny/bochs.c | |
| 5803 | 5803 | |
| 5804 | 5804 | DRM DRIVER FOR BOE HIMAX8279D PANELS |
| 5805 | 5805 | M: Jerry Han <hanxu5@huaqin.corp-partner.google.com> |
| @@ -5984,6 +5984,13 @@ S: Maintained · 178 unmodified lines | ||
| 5984 | 5984 | F: Documentation/devicetree/bindings/display/panel/raydium,rm67191.yaml |
| 5985 | 5985 | F: drivers/gpu/drm/panel/panel-raydium-rm67191.c |
| 5986 | 5986 | |
| 5987 | +DRM DRIVER FOR SAMSUNG DB7430 PANELS | |
| 5988 | +M: Linus Walleij <linus.walleij@linaro.org> | |
| 5989 | +S: Maintained | |
| 5990 | +T: git git://anongit.freedesktop.org/drm/drm-misc | |
| 5991 | +F: Documentation/devicetree/bindings/display/panel/samsung,lms397kf04.yaml | |
| 5992 | +F: drivers/gpu/drm/panel/panel-samsung-db7430.c | |
| 5993 | + | |
| 5987 | 5994 | DRM DRIVER FOR SITRONIX ST7703 PANELS |
| 5988 | 5995 | M: Guido Günther <agx@sigxcpu.org> |
| 5989 | 5996 | R: Purism Kernel Team <kernel@puri.sm> |
| @@ -6082,21 +6089,27 @@ F: drivers/gpu/drm/vboxvideo/ · 92 unmodified lines | ||
| 6082 | 6089 | |
| 6083 | 6090 | DRM DRIVER FOR VMWARE VIRTUAL GPU |
| 6084 | 6091 | M: "VMware Graphics" <linux-graphics-maintainer@vmware.com> |
| 6085 | −M: Roland Scheidegger <sroland@vmware.com> | |
| 6086 | 6092 | M: Zack Rusin <zackr@vmware.com> |
| 6087 | 6093 | L: dri-devel@lists.freedesktop.org |
| 6088 | 6094 | S: Supported |
| 6089 | −T: git git://people.freedesktop.org/~sroland/linux | |
| 6095 | +T: git git://anongit.freedesktop.org/drm/drm-misc | |
| 6090 | 6096 | F: drivers/gpu/drm/vmwgfx/ |
| 6091 | 6097 | F: include/uapi/drm/vmwgfx_drm.h |
| 6092 | 6098 | |
| 6099 | +DRM DRIVER FOR WIDECHIPS WS2401 PANELS | |
| 6100 | +M: Linus Walleij <linus.walleij@linaro.org> | |
| 6101 | +S: Maintained | |
| 6102 | +T: git git://anongit.freedesktop.org/drm/drm-misc | |
| 6103 | +F: Documentation/devicetree/bindings/display/panel/samsung,lms380kf01.yaml | |
| 6104 | +F: drivers/gpu/drm/panel/panel-widechips-ws2401.c | |
| 6105 | + | |
| 6093 | 6106 | DRM DRIVERS |
| 6094 | 6107 | M: David Airlie <airlied@linux.ie> |
| 6095 | 6108 | M: Daniel Vetter <daniel@ffwll.ch> |
| 6096 | 6109 | L: dri-devel@lists.freedesktop.org |
| 6097 | 6110 | S: Maintained |
| 6098 | 6111 | B: https://gitlab.freedesktop.org/drm |
| 6099 | −C: irc://chat.freenode.net/dri-devel | |
| 6112 | +C: irc://irc.oftc.net/dri-devel | |
| 6100 | 6113 | T: git git://anongit.freedesktop.org/drm/drm |
| 6101 | 6114 | F: Documentation/devicetree/bindings/display/ |
| 6102 | 6115 | F: Documentation/devicetree/bindings/gpu/ |
| @@ -9288,7 +9301,7 @@ S: Supported · 3185 unmodified lines | ||
| 9288 | 9301 | W: https://01.org/linuxgraphics/ |
| 9289 | 9302 | Q: http://patchwork.freedesktop.org/project/intel-gfx/ |
| 9290 | 9303 | B: https://gitlab.freedesktop.org/drm/intel/-/wikis/How-to-file-i915-bugs |
| 9291 | −C: irc://chat.freenode.net/intel-gfx | |
| 9304 | +C: irc://irc.oftc.net/intel-gfx | |
| 9292 | 9305 | T: git git://anongit.freedesktop.org/drm-intel |
| 9293 | 9306 | F: Documentation/gpu/i915.rst |
| 9294 | 9307 | F: drivers/gpu/drm/i915/ |
| @@ -17,6 +17,7 @@ · 16 unmodified lines | ||
| 17 | 17 | |
| 18 | 18 | #ifdef CONFIG_EFI |
| 19 | 19 | void efi_init(void); |
| 20 | +extern void efifb_setup_from_dmi(struct screen_info *si, const char *opt); | |
| 20 | 21 | |
| 21 | 22 | int efi_create_mapping(struct mm_struct *mm, efi_memory_desc_t *md); |
| 22 | 23 | int efi_set_mapping_permissions(struct mm_struct *mm, efi_memory_desc_t *md); |
| @@ -52,10 +53,6 @@ void efi_virtmap_unload(void); · 29 unmodified lines | ||
| 52 | 53 | struct screen_info *alloc_screen_info(void); |
| 53 | 54 | void free_screen_info(struct screen_info *si); |
| 54 | 55 | |
| 55 | −static inline void efifb_setup_from_dmi(struct screen_info *si, const char *opt) | |
| 56 | −{ | |
| 57 | −} | |
| 58 | − | |
| 59 | 56 | /* |
| 60 | 57 | * A reasonable upper bound for the uncompressed kernel size is 32 MBytes, |
| 61 | 58 | * so we will reserve that amount of memory. We have no easy way to tell what |
| @@ -255,21 +255,6 @@ · 254 unmodified lines | ||
| 255 | 255 | #sound-dai-cells = <0>; |
| 256 | 256 | }; |
| 257 | 257 | |
| 258 | − panel: panel { | |
| 259 | − /* Compatible will be filled in per-board */ | |
| 260 | − power-supply = <&pp3300_dx_edp>; | |
| 261 | − backlight = <&backlight>; | |
| 262 | − hpd-gpios = <&sn65dsi86_bridge 2 GPIO_ACTIVE_HIGH>; | |
| 263 | − | |
| 264 | − ports { | |
| 265 | − port { | |
| 266 | − panel_in_edp: endpoint { | |
| 267 | − remote-endpoint = <&sn65dsi86_out>; | |
| 268 | − }; | |
| 269 | − }; | |
| 270 | − }; | |
| 271 | − }; | |
| 272 | − | |
| 273 | 258 | pwmleds { |
| 274 | 259 | compatible = "pwm-leds"; |
| 275 | 260 | keyboard_backlight: keyboard-backlight { |
| @@ -666,6 +651,21 @@ edp_brij_i2c: &i2c2 { · 390 unmodified lines | ||
| 666 | 651 | }; |
| 667 | 652 | }; |
| 668 | 653 | }; |
| 654 | + | |
| 655 | + aux-bus { | |
| 656 | + panel: panel { | |
| 657 | + /* Compatible will be filled in per-board */ | |
| 658 | + power-supply = <&pp3300_dx_edp>; | |
| 659 | + backlight = <&backlight>; | |
| 660 | + hpd-gpios = <&sn65dsi86_bridge 2 GPIO_ACTIVE_HIGH>; | |
| 661 | + | |
| 662 | + port { | |
| 663 | + panel_in_edp: endpoint { | |
| 664 | + remote-endpoint = <&sn65dsi86_out>; | |
| 665 | + }; | |
| 666 | + }; | |
| 667 | + }; | |
| 668 | + }; | |
| 669 | 669 | }; |
| 670 | 670 | }; |
| 671 | 671 | |
| @@ -14,6 +14,7 @@ · 13 unmodified lines | ||
| 14 | 14 | |
| 15 | 15 | #ifdef CONFIG_EFI |
| 16 | 16 | extern void efi_init(void); |
| 17 | +extern void efifb_setup_from_dmi(struct screen_info *si, const char *opt); | |
| 17 | 18 | #else |
| 18 | 19 | #define efi_init() |
| 19 | 20 | #endif |
| @@ -85,10 +86,6 @@ static inline void free_screen_info(struct screen_info *si) · 65 unmodified lines | ||
| 85 | 86 | { |
| 86 | 87 | } |
| 87 | 88 | |
| 88 | −static inline void efifb_setup_from_dmi(struct screen_info *si, const char *opt) | |
| 89 | −{ | |
| 90 | −} | |
| 91 | − | |
| 92 | 89 | #define EFI_ALLOC_ALIGN SZ_64K |
| 93 | 90 | |
| 94 | 91 | /* |
| @@ -13,6 +13,7 @@ · 12 unmodified lines | ||
| 13 | 13 | |
| 14 | 14 | #ifdef CONFIG_EFI |
| 15 | 15 | extern void efi_init(void); |
| 16 | +extern void efifb_setup_from_dmi(struct screen_info *si, const char *opt); | |
| 16 | 17 | #else |
| 17 | 18 | #define efi_init() |
| 18 | 19 | #endif |
| @@ -39,10 +40,6 @@ static inline void free_screen_info(struct screen_info *si) · 20 unmodified lines | ||
| 39 | 40 | { |
| 40 | 41 | } |
| 41 | 42 | |
| 42 | −static inline void efifb_setup_from_dmi(struct screen_info *si, const char *opt) | |
| 43 | −{ | |
| 44 | −} | |
| 45 | − | |
| 46 | 43 | void efi_virtmap_load(void); |
| 47 | 44 | void efi_virtmap_unload(void); |
| 48 | 45 | |
| @@ -2767,32 +2767,6 @@ config AMD_NB · 2766 unmodified lines | ||
| 2767 | 2767 | def_bool y |
| 2768 | 2768 | depends on CPU_SUP_AMD && PCI |
| 2769 | 2769 | |
| 2770 | −config X86_SYSFB | |
| 2771 | − bool "Mark VGA/VBE/EFI FB as generic system framebuffer" | |
| 2772 | − help | |
| 2773 | − Firmwares often provide initial graphics framebuffers so the BIOS, | |
| 2774 | − bootloader or kernel can show basic video-output during boot for | |
| 2775 | − user-guidance and debugging. Historically, x86 used the VESA BIOS | |
| 2776 | − Extensions and EFI-framebuffers for this, which are mostly limited | |
| 2777 | − to x86. | |
| 2778 | − This option, if enabled, marks VGA/VBE/EFI framebuffers as generic | |
| 2779 | − framebuffers so the new generic system-framebuffer drivers can be | |
| 2780 | − used on x86. If the framebuffer is not compatible with the generic | |
| 2781 | − modes, it is advertised as fallback platform framebuffer so legacy | |
| 2782 | − drivers like efifb, vesafb and uvesafb can pick it up. | |
| 2783 | − If this option is not selected, all system framebuffers are always | |
| 2784 | − marked as fallback platform framebuffers as usual. | |
| 2785 | − | |
| 2786 | − Note: Legacy fbdev drivers, including vesafb, efifb, uvesafb, will | |
| 2787 | − not be able to pick up generic system framebuffers if this option | |
| 2788 | − is selected. You are highly encouraged to enable simplefb as | |
| 2789 | − replacement if you select this option. simplefb can correctly deal | |
| 2790 | − with generic system framebuffers. But you should still keep vesafb | |
| 2791 | − and others enabled as fallback if a system framebuffer is | |
| 2792 | − incompatible with simplefb. | |
| 2793 | − | |
| 2794 | − If unsure, say Y. | |
| 2795 | − | |
| 2796 | 2770 | endmenu |
| 2797 | 2771 | |
| 2798 | 2772 | |
| @@ -136,9 +136,6 @@ obj-$(CONFIG_X86_CHECK_BIOS_CORRUPTION) += check.o · 135 unmodified lines | ||
| 136 | 136 | obj-$(CONFIG_SWIOTLB) += pci-swiotlb.o |
| 137 | 137 | obj-$(CONFIG_OF) += devicetree.o |
| 138 | 138 | obj-$(CONFIG_UPROBES) += uprobes.o |
| 139 | −obj-y += sysfb.o | |
| 140 | −obj-$(CONFIG_X86_SYSFB) += sysfb_simplefb.o | |
| 141 | −obj-$(CONFIG_EFI) += sysfb_efi.o | |
| 142 | 139 | |
| 143 | 140 | obj-$(CONFIG_PERF_EVENTS) += perf_regs.o |
| 144 | 141 | obj-$(CONFIG_TRACING) += tracepoint.o |
| @@ -72,6 +72,17 @@ menuconfig DMABUF_HEAPS · 71 unmodified lines | ||
| 72 | 72 | allows userspace to allocate dma-bufs that can be shared |
| 73 | 73 | between drivers. |
| 74 | 74 | |
| 75 | +menuconfig DMABUF_SYSFS_STATS | |
| 76 | + bool "DMA-BUF sysfs statistics" | |
| 77 | + select DMA_SHARED_BUFFER | |
| 78 | + help | |
| 79 | + Choose this option to enable DMA-BUF sysfs statistics | |
| 80 | + in location /sys/kernel/dmabuf/buffers. | |
| 81 | + | |
| 82 | + /sys/kernel/dmabuf/buffers/<inode_number> will contain | |
| 83 | + statistics for the DMA-BUF with the unique inode number | |
| 84 | + <inode_number>. | |
| 85 | + | |
| 75 | 86 | source "drivers/dma-buf/heaps/Kconfig" |
| 76 | 87 | |
| 77 | 88 | endmenu |
| @@ -6,6 +6,7 @@ obj-$(CONFIG_DMABUF_HEAPS) += heaps/ · 5 unmodified lines | ||
| 6 | 6 | obj-$(CONFIG_SYNC_FILE) += sync_file.o |
| 7 | 7 | obj-$(CONFIG_SW_SYNC) += sw_sync.o sync_debug.o |
| 8 | 8 | obj-$(CONFIG_UDMABUF) += udmabuf.o |
| 9 | +obj-$(CONFIG_DMABUF_SYSFS_STATS) += dma-buf-sysfs-stats.o | |
| 9 | 10 | |
| 10 | 11 | dmabuf_selftests-y := \ |
| 11 | 12 | selftest.o \ |
| @@ -0,0 +1,205 @@ | ||
| 1 | +// SPDX-License-Identifier: GPL-2.0-only | |
| 2 | +/* | |
| 3 | + * DMA-BUF sysfs statistics. | |
| 4 | + * | |
| 5 | + * Copyright (C) 2021 Google LLC. | |
| 6 | + */ | |
| 7 | + | |
| 8 | +#include <linux/dma-buf.h> | |
| 9 | +#include <linux/dma-resv.h> | |
| 10 | +#include <linux/kobject.h> | |
| 11 | +#include <linux/printk.h> | |
| 12 | +#include <linux/slab.h> | |
| 13 | +#include <linux/sysfs.h> | |
| 14 | + | |
| 15 | +#include "dma-buf-sysfs-stats.h" | |
| 16 | + | |
| 17 | +#define to_dma_buf_entry_from_kobj(x) container_of(x, struct dma_buf_sysfs_entry, kobj) | |
| 18 | + | |
| 19 | +/** | |
| 20 | + * DOC: overview | |
| 21 | + * | |
| 22 | + * ``/sys/kernel/debug/dma_buf/bufinfo`` provides an overview of every DMA-BUF | |
| 23 | + * in the system. However, since debugfs is not safe to be mounted in | |
| 24 | + * production, procfs and sysfs can be used to gather DMA-BUF statistics on | |
| 25 | + * production systems. | |
| 26 | + * | |
| 27 | + * The ``/proc/<pid>/fdinfo/<fd>`` files in procfs can be used to gather | |
| 28 | + * information about DMA-BUF fds. Detailed documentation about the interface | |
| 29 | + * is present in Documentation/filesystems/proc.rst. | |
| 30 | + * | |
| 31 | + * Unfortunately, the existing procfs interfaces can only provide information | |
| 32 | + * about the DMA-BUFs for which processes hold fds or have the buffers mmapped | |
| 33 | + * into their address space. This necessitated the creation of the DMA-BUF sysfs | |
| 34 | + * statistics interface to provide per-buffer information on production systems. | |
| 35 | + * | |
| 36 | + * The interface at ``/sys/kernel/dma-buf/buffers`` exposes information about | |
| 37 | + * every DMA-BUF when ``CONFIG_DMABUF_SYSFS_STATS`` is enabled. | |
| 38 | + * | |
| 39 | + * The following stats are exposed by the interface: | |
| 40 | + * | |
| 41 | + * * ``/sys/kernel/dmabuf/buffers/<inode_number>/exporter_name`` | |
| 42 | + * * ``/sys/kernel/dmabuf/buffers/<inode_number>/size`` | |
| 43 | + * | |
| 44 | + * The information in the interface can also be used to derive per-exporter | |
| 45 | + * statistics. The data from the interface can be gathered on error conditions | |
| 46 | + * or other important events to provide a snapshot of DMA-BUF usage. | |
| 47 | + * It can also be collected periodically by telemetry to monitor various metrics. | |
| 48 | + * | |
| 49 | + * Detailed documentation about the interface is present in | |
| 50 | + * Documentation/ABI/testing/sysfs-kernel-dmabuf-buffers. | |
| 51 | + */ | |
| 52 | + | |
| 53 | +struct dma_buf_stats_attribute { | |
| 54 | + struct attribute attr; | |
| 55 | + ssize_t (*show)(struct dma_buf *dmabuf, | |
| 56 | + struct dma_buf_stats_attribute *attr, char *buf); | |
| 57 | +}; | |
| 58 | +#define to_dma_buf_stats_attr(x) container_of(x, struct dma_buf_stats_attribute, attr) | |
| 59 | + | |
| 60 | +static ssize_t dma_buf_stats_attribute_show(struct kobject *kobj, | |
| 61 | + struct attribute *attr, | |
| 62 | + char *buf) | |
| 63 | +{ | |
| 64 | + struct dma_buf_stats_attribute *attribute; | |
| 65 | + struct dma_buf_sysfs_entry *sysfs_entry; | |
| 66 | + struct dma_buf *dmabuf; | |
| 67 | + | |
| 68 | + attribute = to_dma_buf_stats_attr(attr); | |
| 69 | + sysfs_entry = to_dma_buf_entry_from_kobj(kobj); | |
| 70 | + dmabuf = sysfs_entry->dmabuf; | |
| 71 | + | |
| 72 | + if (!dmabuf || !attribute->show) | |
| 73 | + return -EIO; | |
| 74 | + | |
| 75 | + return attribute->show(dmabuf, attribute, buf); | |
| 76 | +} | |
| 77 | + | |
| 78 | +static const struct sysfs_ops dma_buf_stats_sysfs_ops = { | |
| 79 | + .show = dma_buf_stats_attribute_show, | |
| 80 | +}; | |
| 81 | + | |
| 82 | +static ssize_t exporter_name_show(struct dma_buf *dmabuf, | |
| 83 | + struct dma_buf_stats_attribute *attr, | |
| 84 | + char *buf) | |
| 85 | +{ | |
| 86 | + return sysfs_emit(buf, "%s\n", dmabuf->exp_name); | |
| 87 | +} | |
| 88 | + | |
| 89 | +static ssize_t size_show(struct dma_buf *dmabuf, | |
| 90 | + struct dma_buf_stats_attribute *attr, | |
| 91 | + char *buf) | |
| 92 | +{ | |
| 93 | + return sysfs_emit(buf, "%zu\n", dmabuf->size); | |
| 94 | +} | |
| 95 | + | |
| 96 | +static struct dma_buf_stats_attribute exporter_name_attribute = | |
| 97 | + __ATTR_RO(exporter_name); | |
| 98 | +static struct dma_buf_stats_attribute size_attribute = __ATTR_RO(size); | |
| 99 | + | |
| 100 | +static struct attribute *dma_buf_stats_default_attrs[] = { | |
| 101 | + &exporter_name_attribute.attr, | |
| 102 | + &size_attribute.attr, | |
| 103 | + NULL, | |
| 104 | +}; | |
| 105 | +ATTRIBUTE_GROUPS(dma_buf_stats_default); | |
| 106 | + | |
| 107 | +static void dma_buf_sysfs_release(struct kobject *kobj) | |
| 108 | +{ | |
| 109 | + struct dma_buf_sysfs_entry *sysfs_entry; | |
| 110 | + | |
| 111 | + sysfs_entry = to_dma_buf_entry_from_kobj(kobj); | |
| 112 | + kfree(sysfs_entry); | |
| 113 | +} | |
| 114 | + | |
| 115 | +static struct kobj_type dma_buf_ktype = { | |
| 116 | + .sysfs_ops = &dma_buf_stats_sysfs_ops, | |
| 117 | + .release = dma_buf_sysfs_release, | |
| 118 | + .default_groups = dma_buf_stats_default_groups, | |
| 119 | +}; | |
| 120 | + | |
| 121 | +void dma_buf_stats_teardown(struct dma_buf *dmabuf) | |
| 122 | +{ | |
| 123 | + struct dma_buf_sysfs_entry *sysfs_entry; | |
| 124 | + | |
| 125 | + sysfs_entry = dmabuf->sysfs_entry; | |
| 126 | + if (!sysfs_entry) | |
| 127 | + return; | |
| 128 | + | |
| 129 | + kobject_del(&sysfs_entry->kobj); | |
| 130 | + kobject_put(&sysfs_entry->kobj); | |
| 131 | +} | |
| 132 | + | |
| 133 | + | |
| 134 | +/* Statistics files do not need to send uevents. */ | |
| 135 | +static int dmabuf_sysfs_uevent_filter(struct kset *kset, struct kobject *kobj) | |
| 136 | +{ | |
| 137 | + return 0; | |
| 138 | +} | |
| 139 | + | |
| 140 | +static const struct kset_uevent_ops dmabuf_sysfs_no_uevent_ops = { | |
| 141 | + .filter = dmabuf_sysfs_uevent_filter, | |
| 142 | +}; | |
| 143 | + | |
| 144 | +static struct kset *dma_buf_stats_kset; | |
| 145 | +static struct kset *dma_buf_per_buffer_stats_kset; | |
| 146 | +int dma_buf_init_sysfs_statistics(void) | |
| 147 | +{ | |
| 148 | + dma_buf_stats_kset = kset_create_and_add("dmabuf", | |
| 149 | + &dmabuf_sysfs_no_uevent_ops, | |
| 150 | + kernel_kobj); | |
| 151 | + if (!dma_buf_stats_kset) | |
| 152 | + return -ENOMEM; | |
| 153 | + | |
| 154 | + dma_buf_per_buffer_stats_kset = kset_create_and_add("buffers", | |
| 155 | + &dmabuf_sysfs_no_uevent_ops, | |
| 156 | + &dma_buf_stats_kset->kobj); | |
| 157 | + if (!dma_buf_per_buffer_stats_kset) { | |
| 158 | + kset_unregister(dma_buf_stats_kset); | |
| 159 | + return -ENOMEM; | |
| 160 | + } | |
| 161 | + | |
| 162 | + return 0; | |
| 163 | +} | |
| 164 | + | |
| 165 | +void dma_buf_uninit_sysfs_statistics(void) | |
| 166 | +{ | |
| 167 | + kset_unregister(dma_buf_per_buffer_stats_kset); | |
| 168 | + kset_unregister(dma_buf_stats_kset); | |
| 169 | +} | |
| 170 | + | |
| 171 | +int dma_buf_stats_setup(struct dma_buf *dmabuf) | |
| 172 | +{ | |
| 173 | + struct dma_buf_sysfs_entry *sysfs_entry; | |
| 174 | + int ret; | |
| 175 | + | |
| 176 | + if (!dmabuf || !dmabuf->file) | |
| 177 | + return -EINVAL; | |
| 178 | + | |
| 179 | + if (!dmabuf->exp_name) { | |
| 180 | + pr_err("exporter name must not be empty if stats needed\n"); | |
| 181 | + return -EINVAL; | |
| 182 | + } | |
| 183 | + | |
| 184 | + sysfs_entry = kzalloc(sizeof(struct dma_buf_sysfs_entry), GFP_KERNEL); | |
| 185 | + if (!sysfs_entry) | |
| 186 | + return -ENOMEM; | |
| 187 | + | |
| 188 | + sysfs_entry->kobj.kset = dma_buf_per_buffer_stats_kset; | |
| 189 | + sysfs_entry->dmabuf = dmabuf; | |
| 190 | + | |
| 191 | + dmabuf->sysfs_entry = sysfs_entry; | |
| 192 | + | |
| 193 | + /* create the directory for buffer stats */ | |
| 194 | + ret = kobject_init_and_add(&sysfs_entry->kobj, &dma_buf_ktype, NULL, | |
| 195 | + "%lu", file_inode(dmabuf->file)->i_ino); | |
| 196 | + if (ret) | |
| 197 | + goto err_sysfs_dmabuf; | |
| 198 | + | |
| 199 | + return 0; | |
| 200 | + | |
| 201 | +err_sysfs_dmabuf: | |
| 202 | + kobject_put(&sysfs_entry->kobj); | |
| 203 | + dmabuf->sysfs_entry = NULL; | |
| 204 | + return ret; | |
| 205 | +} | |
| @@ -0,0 +1,35 @@ | ||
| 1 | +/* SPDX-License-Identifier: GPL-2.0-only */ | |
| 2 | +/* | |
| 3 | + * DMA-BUF sysfs statistics. | |
| 4 | + * | |
| 5 | + * Copyright (C) 2021 Google LLC. | |
| 6 | + */ | |
| 7 | + | |
| 8 | +#ifndef _DMA_BUF_SYSFS_STATS_H | |
| 9 | +#define _DMA_BUF_SYSFS_STATS_H | |
| 10 | + | |
| 11 | +#ifdef CONFIG_DMABUF_SYSFS_STATS | |
| 12 | + | |
| 13 | +int dma_buf_init_sysfs_statistics(void); | |
| 14 | +void dma_buf_uninit_sysfs_statistics(void); | |
| 15 | + | |
| 16 | +int dma_buf_stats_setup(struct dma_buf *dmabuf); | |
| 17 | + | |
| 18 | +void dma_buf_stats_teardown(struct dma_buf *dmabuf); | |
| 19 | +#else | |
| 20 | + | |
| 21 | +static inline int dma_buf_init_sysfs_statistics(void) | |
| 22 | +{ | |
| 23 | + return 0; | |
| 24 | +} | |
| 25 | + | |
| 26 | +static inline void dma_buf_uninit_sysfs_statistics(void) {} | |
| 27 | + | |
| 28 | +static inline int dma_buf_stats_setup(struct dma_buf *dmabuf) | |
| 29 | +{ | |
| 30 | + return 0; | |
| 31 | +} | |
| 32 | + | |
| 33 | +static inline void dma_buf_stats_teardown(struct dma_buf *dmabuf) {} | |
| 34 | +#endif | |
| 35 | +#endif // _DMA_BUF_SYSFS_STATS_H | |
| @@ -29,6 +29,8 @@ · 28 unmodified lines | ||
| 29 | 29 | #include <uapi/linux/dma-buf.h> |
| 30 | 30 | #include <uapi/linux/magic.h> |
| 31 | 31 | |
| 32 | +#include "dma-buf-sysfs-stats.h" | |
| 33 | + | |
| 32 | 34 | static inline int is_dma_buf_file(struct file *); |
| 33 | 35 | |
| 34 | 36 | struct dma_buf_list { |
| @@ -74,6 +76,7 @@ static void dma_buf_release(struct dentry *dentry) · 39 unmodified lines | ||
| 74 | 76 | */ |
| 75 | 77 | BUG_ON(dmabuf->cb_shared.active || dmabuf->cb_excl.active); |
| 76 | 78 | |
| 79 | + dma_buf_stats_teardown(dmabuf); | |
| 77 | 80 | dmabuf->ops->release(dmabuf); |
| 78 | 81 | |
| 79 | 82 | if (dmabuf->resv == (struct dma_resv *)&dmabuf[1]) |
| @@ -580,6 +583,10 @@ struct dma_buf *dma_buf_export(const struct dma_buf_export_info *exp_info) · 500 unmodified lines | ||
| 580 | 583 | file->f_mode |= FMODE_LSEEK; |
| 581 | 584 | dmabuf->file = file; |
| 582 | 585 | |
| 586 | + ret = dma_buf_stats_setup(dmabuf); | |
| 587 | + if (ret) | |
| 588 | + goto err_sysfs; | |
| 589 | + | |
| 583 | 590 | mutex_init(&dmabuf->lock); |
| 584 | 591 | INIT_LIST_HEAD(&dmabuf->attachments); |
| 585 | 592 | |
| @@ -589,6 +596,14 @@ struct dma_buf *dma_buf_export(const struct dma_buf_export_info *exp_info) · 3 unmodified lines | ||
| 589 | 596 | |
| 590 | 597 | return dmabuf; |
| 591 | 598 | |
| 599 | +err_sysfs: | |
| 600 | + /* | |
| 601 | + * Set file->f_path.dentry->d_fsdata to NULL so that when | |
| 602 | + * dma_buf_release() gets invoked by dentry_ops, it exits | |
| 603 | + * early before calling the release() dma_buf op. | |
| 604 | + */ | |
| 605 | + file->f_path.dentry->d_fsdata = NULL; | |
| 606 | + fput(file); | |
| 592 | 607 | err_dmabuf: |
| 593 | 608 | kfree(dmabuf); |
| 594 | 609 | err_module: |
| @@ -926,6 +941,9 @@ EXPORT_SYMBOL_GPL(dma_buf_unpin); · 331 unmodified lines | ||
| 926 | 941 | * the underlying backing storage is pinned for as long as a mapping exists, |
| 927 | 942 | * therefore users/importers should not hold onto a mapping for undue amounts of |
| 928 | 943 | * time. |
| 944 | + * | |
| 945 | + * Important: Dynamic importers must wait for the exclusive fence of the struct | |
| 946 | + * dma_resv attached to the DMA-BUF first. | |
| 929 | 947 | */ |
| 930 | 948 | struct sg_table *dma_buf_map_attachment(struct dma_buf_attachment *attach, |
| 931 | 949 | enum dma_data_direction direction) |
| @@ -992,7 +1010,6 @@ struct sg_table *dma_buf_map_attachment(struct dma_buf_attachment *attach, · 60 unmodified lines | ||
| 992 | 1010 | } |
| 993 | 1011 | } |
| 994 | 1012 | #endif /* CONFIG_DMA_API_DEBUG */ |
| 995 | − | |
| 996 | 1013 | return sg_table; |
| 997 | 1014 | } |
| 998 | 1015 | EXPORT_SYMBOL_GPL(dma_buf_map_attachment); |
| @@ -1469,6 +1486,12 @@ static inline void dma_buf_uninit_debugfs(void) · 470 unmodified lines | ||
| 1469 | 1486 | |
| 1470 | 1487 | static int __init dma_buf_init(void) |
| 1471 | 1488 | { |
| 1489 | + int ret; | |
| 1490 | + | |
| 1491 | + ret = dma_buf_init_sysfs_statistics(); | |
| 1492 | + if (ret) | |
| 1493 | + return ret; | |
| 1494 | + | |
| 1472 | 1495 | dma_buf_mnt = kern_mount(&dma_buf_fs_type); |
| 1473 | 1496 | if (IS_ERR(dma_buf_mnt)) |
| 1474 | 1497 | return PTR_ERR(dma_buf_mnt); |
| @@ -1484,5 +1507,6 @@ static void __exit dma_buf_deinit(void) · 9 unmodified lines | ||
| 1484 | 1507 | { |
| 1485 | 1508 | dma_buf_uninit_debugfs(); |
| 1486 | 1509 | kern_unmount(dma_buf_mnt); |
| 1510 | + dma_buf_uninit_sysfs_statistics(); | |
| 1487 | 1511 | } |
| 1488 | 1512 | __exitcall(dma_buf_deinit); |
| @@ -137,6 +137,7 @@ static void dma_fence_chain_cb(struct dma_fence *f, struct dma_fence_cb *cb) · 136 unmodified lines | ||
| 137 | 137 | struct dma_fence_chain *chain; |
| 138 | 138 | |
| 139 | 139 | chain = container_of(cb, typeof(*chain), cb); |
| 140 | + init_irq_work(&chain->work, dma_fence_chain_irq_work); | |
| 140 | 141 | irq_work_queue(&chain->work); |
| 141 | 142 | dma_fence_put(f); |
| 142 | 143 | } |
| @@ -239,7 +240,6 @@ void dma_fence_chain_init(struct dma_fence_chain *chain, · 96 unmodified lines | ||
| 239 | 240 | rcu_assign_pointer(chain->prev, prev); |
| 240 | 241 | chain->fence = fence; |
| 241 | 242 | chain->prev_seqno = 0; |
| 242 | − init_irq_work(&chain->work, dma_fence_chain_irq_work); | |
| 243 | 243 | |
| 244 | 244 | /* Try to reuse the context of the previous chain node. */ |
| 245 | 245 | if (prev_chain && __dma_fence_is_later(seqno, prev->seqno, prev->ops)) { |
| @@ -615,25 +615,21 @@ static inline int dma_resv_test_signaled_single(struct dma_fence *passed_fence) · 614 unmodified lines | ||
| 615 | 615 | */ |
| 616 | 616 | bool dma_resv_test_signaled(struct dma_resv *obj, bool test_all) |
| 617 | 617 | { |
| 618 | − unsigned int seq, shared_count; | |
| 618 | + struct dma_fence *fence; | |
| 619 | + unsigned int seq; | |
| 619 | 620 | int ret; |
| 620 | 621 | |
| 621 | 622 | rcu_read_lock(); |
| 622 | 623 | retry: |
| 623 | 624 | ret = true; |
| 624 | − shared_count = 0; | |
| 625 | 625 | seq = read_seqcount_begin(&obj->seq); |
| 626 | 626 | |
| 627 | 627 | if (test_all) { |
| 628 | 628 | struct dma_resv_list *fobj = dma_resv_shared_list(obj); |
| 629 | − unsigned int i; | |
| 630 | − | |
| 631 | − if (fobj) | |
| 632 | − shared_count = fobj->shared_count; | |
| 629 | + unsigned int i, shared_count; | |
| 633 | 630 | |
| 631 | + shared_count = fobj ? fobj->shared_count : 0; | |
| 634 | 632 | for (i = 0; i < shared_count; ++i) { |
| 635 | − struct dma_fence *fence; | |
| 636 | − | |
| 637 | 633 | fence = rcu_dereference(fobj->shared[i]); |
| 638 | 634 | ret = dma_resv_test_signaled_single(fence); |
| 639 | 635 | if (ret < 0) |
| @@ -641,24 +637,19 @@ retry: · 1 unmodified line | ||
| 641 | 637 | else if (!ret) |
| 642 | 638 | break; |
| 643 | 639 | } |
| 644 | − | |
| 645 | − if (read_seqcount_retry(&obj->seq, seq)) | |
| 646 | − goto retry; | |
| 647 | 640 | } |
| 648 | 641 | |
| 649 | − if (!shared_count) { | |
| 650 | − struct dma_fence *fence_excl = dma_resv_excl_fence(obj); | |
| 651 | − | |
| 652 | − if (fence_excl) { | |
| 653 | − ret = dma_resv_test_signaled_single(fence_excl); | |
| 654 | − if (ret < 0) | |
| 655 | − goto retry; | |
| 642 | + fence = dma_resv_excl_fence(obj); | |
| 643 | + if (ret && fence) { | |
| 644 | + ret = dma_resv_test_signaled_single(fence); | |
| 645 | + if (ret < 0) | |
| 646 | + goto retry; | |
| 656 | 647 | |
| 657 | − if (read_seqcount_retry(&obj->seq, seq)) | |
| 658 | − goto retry; | |
| 659 | − } | |
| 660 | 648 | } |
| 661 | 649 | |
| 650 | + if (read_seqcount_retry(&obj->seq, seq)) | |
| 651 | + goto retry; | |
| 652 | + | |
| 662 | 653 | rcu_read_unlock(); |
| 663 | 654 | return ret; |
| 664 | 655 | } |
| @@ -58,28 +58,20 @@ static struct dma_fence *mock_fence(void) · 57 unmodified lines | ||
| 58 | 58 | return &f->base; |
| 59 | 59 | } |
| 60 | 60 | |
| 61 | −static inline struct mock_chain { | |
| 62 | − struct dma_fence_chain base; | |
| 63 | −} *to_mock_chain(struct dma_fence *f) { | |
| 64 | − return container_of(f, struct mock_chain, base.base); | |
| 65 | −} | |
| 66 | − | |
| 67 | 61 | static struct dma_fence *mock_chain(struct dma_fence *prev, |
| 68 | 62 | struct dma_fence *fence, |
| 69 | 63 | u64 seqno) |
| 70 | 64 | { |
| 71 | − struct mock_chain *f; | |
| 65 | + struct dma_fence_chain *f; | |
| 72 | 66 | |
| 73 | − f = kmalloc(sizeof(*f), GFP_KERNEL); | |
| 67 | + f = dma_fence_chain_alloc(); | |
| 74 | 68 | if (!f) |
| 75 | 69 | return NULL; |
| 76 | 70 | |
| 77 | − dma_fence_chain_init(&f->base, | |
| 78 | − dma_fence_get(prev), | |
| 79 | − dma_fence_get(fence), | |
| 71 | + dma_fence_chain_init(f, dma_fence_get(prev), dma_fence_get(fence), | |
| 80 | 72 | seqno); |
| 81 | 73 | |
| 82 | − return &f->base.base; | |
| 74 | + return &f->base; | |
| 83 | 75 | } |
| 84 | 76 | |
| 85 | 77 | static int sanitycheck(void *arg) |
| @@ -11,9 +11,15 @@ · 10 unmodified lines | ||
| 11 | 11 | #include <linux/shmem_fs.h> |
| 12 | 12 | #include <linux/slab.h> |
| 13 | 13 | #include <linux/udmabuf.h> |
| 14 | +#include <linux/hugetlb.h> | |
| 14 | 15 | |
| 15 | −static const u32 list_limit = 1024; /* udmabuf_create_list->count limit */ | |
| 16 | −static const size_t size_limit_mb = 64; /* total dmabuf size, in megabytes */ | |
| 16 | +static int list_limit = 1024; | |
| 17 | +module_param(list_limit, int, 0644); | |
| 18 | +MODULE_PARM_DESC(list_limit, "udmabuf_create_list->count limit. Default is 1024."); | |
| 19 | + | |
| 20 | +static int size_limit_mb = 64; | |
| 21 | +module_param(size_limit_mb, int, 0644); | |
| 22 | +MODULE_PARM_DESC(size_limit_mb, "Max size of a dmabuf, in megabytes. Default is 64."); | |
| 17 | 23 | |
| 18 | 24 | struct udmabuf { |
| 19 | 25 | pgoff_t pagecount; |
| @@ -160,10 +166,13 @@ static long udmabuf_create(struct miscdevice *device, · 140 unmodified lines | ||
| 160 | 166 | { |
| 161 | 167 | DEFINE_DMA_BUF_EXPORT_INFO(exp_info); |
| 162 | 168 | struct file *memfd = NULL; |
| 169 | + struct address_space *mapping = NULL; | |
| 163 | 170 | struct udmabuf *ubuf; |
| 164 | 171 | struct dma_buf *buf; |
| 165 | 172 | pgoff_t pgoff, pgcnt, pgidx, pgbuf = 0, pglimit; |
| 166 | − struct page *page; | |
| 173 | + struct page *page, *hpage = NULL; | |
| 174 | + pgoff_t subpgoff, maxsubpgs; | |
| 175 | + struct hstate *hpstate; | |
| 167 | 176 | int seals, ret = -EINVAL; |
| 168 | 177 | u32 i, flags; |
| 169 | 178 | |
| @@ -194,7 +203,8 @@ static long udmabuf_create(struct miscdevice *device, · 24 unmodified lines | ||
| 194 | 203 | memfd = fget(list[i].memfd); |
| 195 | 204 | if (!memfd) |
| 196 | 205 | goto err; |
| 197 | − if (!shmem_mapping(file_inode(memfd)->i_mapping)) | |
| 206 | + mapping = file_inode(memfd)->i_mapping; | |
| 207 | + if (!shmem_mapping(mapping) && !is_file_hugepages(memfd)) | |
| 198 | 208 | goto err; |
| 199 | 209 | seals = memfd_fcntl(memfd, F_GET_SEALS, 0); |
| 200 | 210 | if (seals == -EINVAL) |
| @@ -205,17 +215,48 @@ static long udmabuf_create(struct miscdevice *device, · 4 unmodified lines | ||
| 205 | 215 | goto err; |
| 206 | 216 | pgoff = list[i].offset >> PAGE_SHIFT; |
| 207 | 217 | pgcnt = list[i].size >> PAGE_SHIFT; |
| 218 | + if (is_file_hugepages(memfd)) { | |
| 219 | + hpstate = hstate_file(memfd); | |
| 220 | + pgoff = list[i].offset >> huge_page_shift(hpstate); | |
| 221 | + subpgoff = (list[i].offset & | |
| 222 | + ~huge_page_mask(hpstate)) >> PAGE_SHIFT; | |
| 223 | + maxsubpgs = huge_page_size(hpstate) >> PAGE_SHIFT; | |
| 224 | + } | |
| 208 | 225 | for (pgidx = 0; pgidx < pgcnt; pgidx++) { |
| 209 | − page = shmem_read_mapping_page( | |
| 210 | − file_inode(memfd)->i_mapping, pgoff + pgidx); | |
| 211 | − if (IS_ERR(page)) { | |
| 212 | − ret = PTR_ERR(page); | |
| 213 | − goto err; | |
| 226 | + if (is_file_hugepages(memfd)) { | |
| 227 | + if (!hpage) { | |
| 228 | + hpage = find_get_page_flags(mapping, pgoff, | |
| 229 | + FGP_ACCESSED); | |
| 230 | + if (!hpage) { | |
| 231 | + ret = -EINVAL; | |
| 232 | + goto err; | |
| 233 | + } | |
| 234 | + } | |
| 235 | + page = hpage + subpgoff; | |
| 236 | + get_page(page); | |
| 237 | + subpgoff++; | |
| 238 | + if (subpgoff == maxsubpgs) { | |
| 239 | + put_page(hpage); | |
| 240 | + hpage = NULL; | |
| 241 | + subpgoff = 0; | |
| 242 | + pgoff++; | |
| 243 | + } | |
| 244 | + } else { | |
| 245 | + page = shmem_read_mapping_page(mapping, | |
| 246 | + pgoff + pgidx); | |
| 247 | + if (IS_ERR(page)) { | |
| 248 | + ret = PTR_ERR(page); | |
| 249 | + goto err; | |
| 250 | + } | |
| 214 | 251 | } |
| 215 | 252 | ubuf->pages[pgbuf++] = page; |
| 216 | 253 | } |
| 217 | 254 | fput(memfd); |
| 218 | 255 | memfd = NULL; |
| 256 | + if (hpage) { | |
| 257 | + put_page(hpage); | |
| 258 | + hpage = NULL; | |
| 259 | + } | |
| 219 | 260 | } |
| 220 | 261 | |
| 221 | 262 | exp_info.ops = &udmabuf_ops; |
| @@ -251,6 +251,38 @@ config QCOM_SCM_DOWNLOAD_MODE_DEFAULT · 250 unmodified lines | ||
| 251 | 251 | |
| 252 | 252 | Say Y here to enable "download mode" by default. |
| 253 | 253 | |
| 254 | +config SYSFB | |
| 255 | + bool | |
| 256 | + default y | |
| 257 | + depends on X86 || EFI | |
| 258 | + | |
| 259 | +config SYSFB_SIMPLEFB | |
| 260 | + bool "Mark VGA/VBE/EFI FB as generic system framebuffer" | |
| 261 | + depends on SYSFB | |
| 262 | + help | |
| 263 | + Firmwares often provide initial graphics framebuffers so the BIOS, | |
| 264 | + bootloader or kernel can show basic video-output during boot for | |
| 265 | + user-guidance and debugging. Historically, x86 used the VESA BIOS | |
| 266 | + Extensions and EFI-framebuffers for this, which are mostly limited | |
| 267 | + to x86 BIOS or EFI systems. | |
| 268 | + This option, if enabled, marks VGA/VBE/EFI framebuffers as generic | |
| 269 | + framebuffers so the new generic system-framebuffer drivers can be | |
| 270 | + used instead. If the framebuffer is not compatible with the generic | |
| 271 | + modes, it is advertised as fallback platform framebuffer so legacy | |
| 272 | + drivers like efifb, vesafb and uvesafb can pick it up. | |
| 273 | + If this option is not selected, all system framebuffers are always | |
| 274 | + marked as fallback platform framebuffers as usual. | |
| 275 | + | |
| 276 | + Note: Legacy fbdev drivers, including vesafb, efifb, uvesafb, will | |
| 277 | + not be able to pick up generic system framebuffers if this option | |
| 278 | + is selected. You are highly encouraged to enable simplefb as | |
| 279 | + replacement if you select this option. simplefb can correctly deal | |
| 280 | + with generic system framebuffers. But you should still keep vesafb | |
| 281 | + and others enabled as fallback if a system framebuffer is | |
| 282 | + incompatible with simplefb. | |
| 283 | + | |
| 284 | + If unsure, say Y. | |
| 285 | + | |
| 254 | 286 | config TI_SCI_PROTOCOL |
| 255 | 287 | tristate "TI System Control Interface (TISCI) Message Protocol" |
| 256 | 288 | depends on TI_MESSAGE_MANAGER |
| @@ -18,6 +18,8 @@ obj-$(CONFIG_FIRMWARE_MEMMAP) += memmap.o · 17 unmodified lines | ||
| 18 | 18 | obj-$(CONFIG_RASPBERRYPI_FIRMWARE) += raspberrypi.o |
| 19 | 19 | obj-$(CONFIG_FW_CFG_SYSFS) += qemu_fw_cfg.o |
| 20 | 20 | obj-$(CONFIG_QCOM_SCM) += qcom_scm.o qcom_scm-smc.o qcom_scm-legacy.o |
| 21 | +obj-$(CONFIG_SYSFB) += sysfb.o | |
| 22 | +obj-$(CONFIG_SYSFB_SIMPLEFB) += sysfb_simplefb.o | |
| 21 | 23 | obj-$(CONFIG_TI_SCI_PROTOCOL) += ti_sci.o |
| 22 | 24 | obj-$(CONFIG_TRUSTED_FOUNDATIONS) += trusted_foundations.o |
| 23 | 25 | obj-$(CONFIG_TURRIS_MOX_RWTM) += turris-mox-rwtm.o |
| @@ -36,6 +36,8 @@ obj-$(CONFIG_LOAD_UEFI_KEYS) += mokvar-table.o · 35 unmodified lines | ||
| 36 | 36 | fake_map-y += fake_mem.o |
| 37 | 37 | fake_map-$(CONFIG_X86) += x86_fake_mem.o |
| 38 | 38 | |
| 39 | +obj-$(CONFIG_SYSFB) += sysfb_efi.o | |
| 40 | + | |
| 39 | 41 | arm-obj-$(CONFIG_EFI) := efi-init.o arm-runtime.o |
| 40 | 42 | obj-$(CONFIG_ARM) += $(arm-obj-y) |
| 41 | 43 | obj-$(CONFIG_ARM64) += $(arm-obj-y) |
| @@ -275,93 +275,3 @@ void __init efi_init(void) · 274 unmodified lines | ||
| 275 | 275 | } |
| 276 | 276 | #endif |
| 277 | 277 | } |
| 278 | − | |
| 279 | −static bool efifb_overlaps_pci_range(const struct of_pci_range *range) | |
| 280 | −{ | |
| 281 | − u64 fb_base = screen_info.lfb_base; | |
| 282 | − | |
| 283 | − if (screen_info.capabilities & VIDEO_CAPABILITY_64BIT_BASE) | |
| 284 | − fb_base |= (u64)(unsigned long)screen_info.ext_lfb_base << 32; | |
| 285 | − | |
| 286 | − return fb_base >= range->cpu_addr && | |
| 287 | − fb_base < (range->cpu_addr + range->size); | |
| 288 | −} | |
| 289 | − | |
| 290 | −static struct device_node *find_pci_overlap_node(void) | |
| 291 | −{ | |
| 292 | − struct device_node *np; | |
| 293 | − | |
| 294 | − for_each_node_by_type(np, "pci") { | |
| 295 | − struct of_pci_range_parser parser; | |
| 296 | − struct of_pci_range range; | |
| 297 | − int err; | |
| 298 | − | |
| 299 | − err = of_pci_range_parser_init(&parser, np); | |
| 300 | − if (err) { | |
| 301 | − pr_warn("of_pci_range_parser_init() failed: %d\n", err); | |
| 302 | − continue; | |
| 303 | − } | |
| 304 | − | |
| 305 | − for_each_of_pci_range(&parser, &range) | |
| 306 | − if (efifb_overlaps_pci_range(&range)) | |
| 307 | − return np; | |
| 308 | − } | |
| 309 | − return NULL; | |
| 310 | −} | |
| 311 | − | |
| 312 | −/* | |
| 313 | − * If the efifb framebuffer is backed by a PCI graphics controller, we have | |
| 314 | − * to ensure that this relation is expressed using a device link when | |
| 315 | − * running in DT mode, or the probe order may be reversed, resulting in a | |
| 316 | − * resource reservation conflict on the memory window that the efifb | |
| 317 | − * framebuffer steals from the PCIe host bridge. | |
| 318 | − */ | |
| 319 | −static int efifb_add_links(struct fwnode_handle *fwnode) | |
| 320 | −{ | |
| 321 | − struct device_node *sup_np; | |
| 322 | − | |
| 323 | − sup_np = find_pci_overlap_node(); | |
| 324 | − | |
| 325 | − /* | |
| 326 | − * If there's no PCI graphics controller backing the efifb, we are | |
| 327 | − * done here. | |
| 328 | − */ | |
| 329 | − if (!sup_np) | |
| 330 | − return 0; | |
| 331 | − | |
| 332 | − fwnode_link_add(fwnode, of_fwnode_handle(sup_np)); | |
| 333 | − of_node_put(sup_np); | |
| 334 | − | |
| 335 | − return 0; | |
| 336 | −} | |
| 337 | − | |
| 338 | −static const struct fwnode_operations efifb_fwnode_ops = { | |
| 339 | − .add_links = efifb_add_links, | |
| 340 | −}; | |
| 341 | − | |
| 342 | −static struct fwnode_handle efifb_fwnode; | |
| 343 | − | |
| 344 | −static int __init register_gop_device(void) | |
| 345 | −{ | |
| 346 | − struct platform_device *pd; | |
| 347 | − int err; | |
| 348 | − | |
| 349 | − if (screen_info.orig_video_isVGA != VIDEO_TYPE_EFI) | |
| 350 | − return 0; | |
| 351 | − | |
| 352 | − pd = platform_device_alloc("efi-framebuffer", 0); | |
| 353 | − if (!pd) | |
| 354 | − return -ENOMEM; | |
| 355 | − | |
| 356 | − if (IS_ENABLED(CONFIG_PCI)) { | |
| 357 | − fwnode_init(&efifb_fwnode, &efifb_fwnode_ops); | |
| 358 | − pd->dev.fwnode = &efifb_fwnode; | |
| 359 | − } | |
| 360 | − | |
| 361 | − err = platform_device_add_data(pd, &screen_info, sizeof(screen_info)); | |
| 362 | − if (err) | |
| 363 | − return err; | |
| 364 | − | |
| 365 | − return platform_device_add(pd); | |
| 366 | −} | |
| 367 | −subsys_initcall(register_gop_device); | |
| @@ -1,6 +1,6 @@ | ||
| 1 | 1 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 2 | 2 | /* |
| 3 | − * Generic System Framebuffers on x86 | |
| 3 | + * Generic System Framebuffers | |
| 4 | 4 | * Copyright (c) 2012-2013 David Herrmann <dh.herrmann@gmail.com> |
| 5 | 5 | * |
| 6 | 6 | * EFI Quirks Copyright (c) 2006 Edgar Hucek <gimli@dark-green.com> |
| @@ -19,12 +19,14 @@ · 12 unmodified lines | ||
| 19 | 19 | #include <linux/init.h> |
| 20 | 20 | #include <linux/kernel.h> |
| 21 | 21 | #include <linux/mm.h> |
| 22 | +#include <linux/of_address.h> | |
| 22 | 23 | #include <linux/pci.h> |
| 24 | +#include <linux/platform_device.h> | |
| 23 | 25 | #include <linux/screen_info.h> |
| 26 | +#include <linux/sysfb.h> | |
| 24 | 27 | #include <video/vga.h> |
| 25 | 28 | |
| 26 | 29 | #include <asm/efi.h> |
| 27 | −#include <asm/sysfb.h> | |
| 28 | 30 | |
| 29 | 31 | enum { |
| 30 | 32 | OVERRIDE_NONE = 0x0, |
| @@ -267,7 +269,73 @@ static const struct dmi_system_id efifb_dmi_swap_width_height[] __initconst = { · 236 unmodified lines | ||
| 267 | 269 | {}, |
| 268 | 270 | }; |
| 269 | 271 | |
| 270 | −__init void sysfb_apply_efi_quirks(void) | |
| 272 | +static bool efifb_overlaps_pci_range(const struct of_pci_range *range) | |
| 273 | +{ | |
| 274 | + u64 fb_base = screen_info.lfb_base; | |
| 275 | + | |
| 276 | + if (screen_info.capabilities & VIDEO_CAPABILITY_64BIT_BASE) | |
| 277 | + fb_base |= (u64)(unsigned long)screen_info.ext_lfb_base << 32; | |
| 278 | + | |
| 279 | + return fb_base >= range->cpu_addr && | |
| 280 | + fb_base < (range->cpu_addr + range->size); | |
| 281 | +} | |
| 282 | + | |
| 283 | +static struct device_node *find_pci_overlap_node(void) | |
| 284 | +{ | |
| 285 | + struct device_node *np; | |
| 286 | + | |
| 287 | + for_each_node_by_type(np, "pci") { | |
| 288 | + struct of_pci_range_parser parser; | |
| 289 | + struct of_pci_range range; | |
| 290 | + int err; | |
| 291 | + | |
| 292 | + err = of_pci_range_parser_init(&parser, np); | |
| 293 | + if (err) { | |
| 294 | + pr_warn("of_pci_range_parser_init() failed: %d\n", err); | |
| 295 | + continue; | |
| 296 | + } | |
| 297 | + | |
| 298 | + for_each_of_pci_range(&parser, &range) | |
| 299 | + if (efifb_overlaps_pci_range(&range)) | |
| 300 | + return np; | |
| 301 | + } | |
| 302 | + return NULL; | |
| 303 | +} | |
| 304 | + | |
| 305 | +/* | |
| 306 | + * If the efifb framebuffer is backed by a PCI graphics controller, we have | |
| 307 | + * to ensure that this relation is expressed using a device link when | |
| 308 | + * running in DT mode, or the probe order may be reversed, resulting in a | |
| 309 | + * resource reservation conflict on the memory window that the efifb | |
| 310 | + * framebuffer steals from the PCIe host bridge. | |
| 311 | + */ | |
| 312 | +static int efifb_add_links(struct fwnode_handle *fwnode) | |
| 313 | +{ | |
| 314 | + struct device_node *sup_np; | |
| 315 | + | |
| 316 | + sup_np = find_pci_overlap_node(); | |
| 317 | + | |
| 318 | + /* | |
| 319 | + * If there's no PCI graphics controller backing the efifb, we are | |
| 320 | + * done here. | |
| 321 | + */ | |
| 322 | + if (!sup_np) | |
| 323 | + return 0; | |
| 324 | + | |
| 325 | + fwnode_link_add(fwnode, of_fwnode_handle(sup_np)); | |
| 326 | + of_node_put(sup_np); | |
| 327 | + | |
| 328 | + return 0; | |
| 329 | +} | |
| 330 | + | |
| 331 | +static const struct fwnode_operations efifb_fwnode_ops = { | |
| 332 | + .add_links = efifb_add_links, | |
| 333 | +}; | |
| 334 | + | |
| 335 | +#ifdef CONFIG_EFI | |
| 336 | +static struct fwnode_handle efifb_fwnode; | |
| 337 | + | |
| 338 | +__init void sysfb_apply_efi_quirks(struct platform_device *pd) | |
| 271 | 339 | { |
| 272 | 340 | if (screen_info.orig_video_isVGA != VIDEO_TYPE_EFI || |
| 273 | 341 | !(screen_info.capabilities & VIDEO_CAPABILITY_SKIP_QUIRKS)) |
| @@ -281,4 +349,10 @@ __init void sysfb_apply_efi_quirks(void) · 7 unmodified lines | ||
| 281 | 349 | screen_info.lfb_height = temp; |
| 282 | 350 | screen_info.lfb_linelength = 4 * screen_info.lfb_width; |
| 283 | 351 | } |
| 352 | + | |
| 353 | + if (screen_info.orig_video_isVGA == VIDEO_TYPE_EFI && IS_ENABLED(CONFIG_PCI)) { | |
| 354 | + fwnode_init(&efifb_fwnode, &efifb_fwnode_ops); | |
| 355 | + pd->dev.fwnode = &efifb_fwnode; | |
| 356 | + } | |
| 284 | 357 | } |
| 358 | +#endif | |
| @@ -1,11 +1,11 @@ | ||
| 1 | 1 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 2 | 2 | /* |
| 3 | − * Generic System Framebuffers on x86 | |
| 3 | + * Generic System Framebuffers | |
| 4 | 4 | * Copyright (c) 2012-2013 David Herrmann <dh.herrmann@gmail.com> |
| 5 | 5 | */ |
| 6 | 6 | |
| 7 | 7 | /* |
| 8 | − * Simple-Framebuffer support for x86 systems | |
| 8 | + * Simple-Framebuffer support | |
| 9 | 9 | * Create a platform-device for any available boot framebuffer. The |
| 10 | 10 | * simple-framebuffer platform device is already available on DT systems, so |
| 11 | 11 | * this module parses the global "screen_info" object and creates a suitable |
| @@ -16,12 +16,12 @@ · 4 unmodified lines | ||
| 16 | 16 | * to pick these devices up without messing with simple-framebuffer drivers. |
| 17 | 17 | * The global "screen_info" is still valid at all times. |
| 18 | 18 | * |
| 19 | − * If CONFIG_X86_SYSFB is not selected, we never register "simple-framebuffer" | |
| 19 | + * If CONFIG_SYSFB_SIMPLEFB is not selected, never register "simple-framebuffer" | |
| 20 | 20 | * platform devices, but only use legacy framebuffer devices for |
| 21 | 21 | * backwards compatibility. |
| 22 | 22 | * |
| 23 | 23 | * TODO: We set the dev_id field of all platform-devices to 0. This allows |
| 24 | − * other x86 OF/DT parsers to create such devices, too. However, they must | |
| 24 | + * other OF/DT parsers to create such devices, too. However, they must | |
| 25 | 25 | * start at offset 1 for this to work. |
| 26 | 26 | */ |
| 27 | 27 | |
| @@ -32,7 +32,7 @@ · 4 unmodified lines | ||
| 32 | 32 | #include <linux/platform_data/simplefb.h> |
| 33 | 33 | #include <linux/platform_device.h> |
| 34 | 34 | #include <linux/screen_info.h> |
| 35 | −#include <asm/sysfb.h> | |
| 35 | +#include <linux/sysfb.h> | |
| 36 | 36 | |
| 37 | 37 | static __init int sysfb_init(void) |
| 38 | 38 | { |
| @@ -43,12 +43,10 @@ static __init int sysfb_init(void) · 4 unmodified lines | ||
| 43 | 43 | bool compatible; |
| 44 | 44 | int ret; |
| 45 | 45 | |
| 46 | − sysfb_apply_efi_quirks(); | |
| 47 | − | |
| 48 | 46 | /* try to create a simple-framebuffer device */ |
| 49 | − compatible = parse_mode(si, &mode); | |
| 47 | + compatible = sysfb_parse_mode(si, &mode); | |
| 50 | 48 | if (compatible) { |
| 51 | − ret = create_simplefb(si, &mode); | |
| 49 | + ret = sysfb_create_simplefb(si, &mode); | |
| 52 | 50 | if (!ret) |
| 53 | 51 | return 0; |
| 54 | 52 | } |
| @@ -61,9 +59,24 @@ static __init int sysfb_init(void) · 6 unmodified lines | ||
| 61 | 59 | else |
| 62 | 60 | name = "platform-framebuffer"; |
| 63 | 61 | |
| 64 | − pd = platform_device_register_resndata(NULL, name, 0, | |
| 65 | − NULL, 0, si, sizeof(*si)); | |
| 66 | − return PTR_ERR_OR_ZERO(pd); | |
| 62 | + pd = platform_device_alloc(name, 0); | |
| 63 | + if (!pd) | |
| 64 | + return -ENOMEM; | |
| 65 | + | |
| 66 | + sysfb_apply_efi_quirks(pd); | |
| 67 | + | |
| 68 | + ret = platform_device_add_data(pd, si, sizeof(*si)); | |
| 69 | + if (ret) | |
| 70 | + goto err; | |
| 71 | + | |
| 72 | + ret = platform_device_add(pd); | |
| 73 | + if (ret) | |
| 74 | + goto err; | |
| 75 | + | |
| 76 | + return 0; | |
| 77 | +err: | |
| 78 | + platform_device_put(pd); | |
| 79 | + return ret; | |
| 67 | 80 | } |
| 68 | 81 | |
| 69 | 82 | /* must execute after PCI subsystem for EFI quirks */ |
| @@ -1,6 +1,6 @@ | ||
| 1 | 1 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 2 | 2 | /* |
| 3 | − * Generic System Framebuffers on x86 | |
| 3 | + * Generic System Framebuffers | |
| 4 | 4 | * Copyright (c) 2012-2013 David Herrmann <dh.herrmann@gmail.com> |
| 5 | 5 | */ |
| 6 | 6 | |
| @@ -18,14 +18,14 @@ · 11 unmodified lines | ||
| 18 | 18 | #include <linux/platform_data/simplefb.h> |
| 19 | 19 | #include <linux/platform_device.h> |
| 20 | 20 | #include <linux/screen_info.h> |
| 21 | −#include <asm/sysfb.h> | |
| 21 | +#include <linux/sysfb.h> | |
| 22 | 22 | |
| 23 | 23 | static const char simplefb_resname[] = "BOOTFB"; |
| 24 | 24 | static const struct simplefb_format formats[] = SIMPLEFB_FORMATS; |
| 25 | 25 | |
| 26 | −/* try parsing x86 screen_info into a simple-framebuffer mode struct */ | |
| 27 | −__init bool parse_mode(const struct screen_info *si, | |
| 28 | − struct simplefb_platform_data *mode) | |
| 26 | +/* try parsing screen_info into a simple-framebuffer mode struct */ | |
| 27 | +__init bool sysfb_parse_mode(const struct screen_info *si, | |
| 28 | + struct simplefb_platform_data *mode) | |
| 29 | 29 | { |
| 30 | 30 | const struct simplefb_format *f; |
| 31 | 31 | __u8 type; |
| @@ -57,13 +57,14 @@ __init bool parse_mode(const struct screen_info *si, · 25 unmodified lines | ||
| 57 | 57 | return false; |
| 58 | 58 | } |
| 59 | 59 | |
| 60 | −__init int create_simplefb(const struct screen_info *si, | |
| 61 | − const struct simplefb_platform_data *mode) | |
| 60 | +__init int sysfb_create_simplefb(const struct screen_info *si, | |
| 61 | + const struct simplefb_platform_data *mode) | |
| 62 | 62 | { |
| 63 | 63 | struct platform_device *pd; |
| 64 | 64 | struct resource res; |
| 65 | 65 | u64 base, size; |
| 66 | 66 | u32 length; |
| 67 | + int ret; | |
| 67 | 68 | |
| 68 | 69 | /* |
| 69 | 70 | * If the 64BIT_BASE capability is set, ext_lfb_base will contain the |
| @@ -105,7 +106,19 @@ __init int create_simplefb(const struct screen_info *si, · 35 unmodified lines | ||
| 105 | 106 | if (res.end <= res.start) |
| 106 | 107 | return -EINVAL; |
| 107 | 108 | |
| 108 | − pd = platform_device_register_resndata(NULL, "simple-framebuffer", 0, | |
| 109 | − &res, 1, mode, sizeof(*mode)); | |
| 110 | − return PTR_ERR_OR_ZERO(pd); | |
| 109 | + pd = platform_device_alloc("simple-framebuffer", 0); | |
| 110 | + if (!pd) | |
| 111 | + return -ENOMEM; | |
| 112 | + | |
| 113 | + sysfb_apply_efi_quirks(pd); | |
| 114 | + | |
| 115 | + ret = platform_device_add_resources(pd, &res, 1); | |
| 116 | + if (ret) | |
| 117 | + return ret; | |
| 118 | + | |
| 119 | + ret = platform_device_add_data(pd, mode, sizeof(*mode)); | |
| 120 | + if (ret) | |
| 121 | + return ret; | |
| 122 | + | |
| 123 | + return platform_device_add(pd); | |
| 111 | 124 | } |
| @@ -35,6 +35,11 @@ config DRM_MIPI_DSI · 34 unmodified lines | ||
| 35 | 35 | bool |
| 36 | 36 | depends on DRM |
| 37 | 37 | |
| 38 | +config DRM_DP_AUX_BUS | |
| 39 | + tristate | |
| 40 | + depends on DRM | |
| 41 | + depends on OF | |
| 42 | + | |
| 38 | 43 | config DRM_DP_AUX_CHARDEV |
| 39 | 44 | bool "DRM DP AUX Interface" |
| 40 | 45 | depends on DRM |
| @@ -251,7 +256,6 @@ config DRM_AMDGPU · 210 unmodified lines | ||
| 251 | 256 | select HWMON |
| 252 | 257 | select BACKLIGHT_CLASS_DEVICE |
| 253 | 258 | select INTERVAL_TREE |
| 254 | − select CHASH | |
| 255 | 259 | help |
| 256 | 260 | Choose this option if you have a recent AMD Radeon graphics card. |
| 257 | 261 | |
| @@ -317,8 +321,6 @@ source "drivers/gpu/drm/tilcdc/Kconfig" · 59 unmodified lines | ||
| 317 | 321 | |
| 318 | 322 | source "drivers/gpu/drm/qxl/Kconfig" |
| 319 | 323 | |
| 320 | −source "drivers/gpu/drm/bochs/Kconfig" | |
| 321 | − | |
| 322 | 324 | source "drivers/gpu/drm/virtio/Kconfig" |
| 323 | 325 | |
| 324 | 326 | source "drivers/gpu/drm/msm/Kconfig" |
| @@ -33,6 +33,8 @@ drm-$(CONFIG_PCI) += drm_pci.o · 32 unmodified lines | ||
| 33 | 33 | drm-$(CONFIG_DEBUG_FS) += drm_debugfs.o drm_debugfs_crc.o |
| 34 | 34 | drm-$(CONFIG_DRM_LOAD_EDID_FIRMWARE) += drm_edid_load.o |
| 35 | 35 | |
| 36 | +obj-$(CONFIG_DRM_DP_AUX_BUS) += drm_dp_aux_bus.o | |
| 37 | + | |
| 36 | 38 | drm_vram_helper-y := drm_gem_vram_helper.o |
| 37 | 39 | obj-$(CONFIG_DRM_VRAM_HELPER) += drm_vram_helper.o |
| 38 | 40 | |
| @@ -96,7 +98,6 @@ obj-y += omapdrm/ · 57 unmodified lines | ||
| 96 | 98 | obj-$(CONFIG_DRM_SUN4I) += sun4i/ |
| 97 | 99 | obj-y += tilcdc/ |
| 98 | 100 | obj-$(CONFIG_DRM_QXL) += qxl/ |
| 99 | −obj-$(CONFIG_DRM_BOCHS) += bochs/ | |
| 100 | 101 | obj-$(CONFIG_DRM_VIRTIO_GPU) += virtio/ |
| 101 | 102 | obj-$(CONFIG_DRM_MSM) += msm/ |
| 102 | 103 | obj-$(CONFIG_DRM_TEGRA) += tegra/ |
| @@ -57,7 +57,8 @@ amdgpu-y += amdgpu_device.o amdgpu_kms.o \ · 56 unmodified lines | ||
| 57 | 57 | amdgpu_xgmi.o amdgpu_csa.o amdgpu_ras.o amdgpu_vm_cpu.o \ |
| 58 | 58 | amdgpu_vm_sdma.o amdgpu_discovery.o amdgpu_ras_eeprom.o amdgpu_nbio.o \ |
| 59 | 59 | amdgpu_umc.o smu_v11_0_i2c.o amdgpu_fru_eeprom.o amdgpu_rap.o \ |
| 60 | − amdgpu_fw_attestation.o amdgpu_securedisplay.o amdgpu_hdp.o | |
| 60 | + amdgpu_fw_attestation.o amdgpu_securedisplay.o amdgpu_hdp.o \ | |
| 61 | + amdgpu_eeprom.o amdgpu_mca.o | |
| 61 | 62 | |
| 62 | 63 | amdgpu-$(CONFIG_PROC_FS) += amdgpu_fdinfo.o |
| 63 | 64 | |
| @@ -75,7 +76,7 @@ amdgpu-y += \ · 11 unmodified lines | ||
| 75 | 76 | vega20_reg_init.o nbio_v7_4.o nbio_v2_3.o nv.o navi10_reg_init.o navi14_reg_init.o \ |
| 76 | 77 | arct_reg_init.o navi12_reg_init.o mxgpu_nv.o sienna_cichlid_reg_init.o vangogh_reg_init.o \ |
| 77 | 78 | nbio_v7_2.o dimgrey_cavefish_reg_init.o hdp_v4_0.o hdp_v5_0.o aldebaran_reg_init.o aldebaran.o \ |
| 78 | − beige_goby_reg_init.o yellow_carp_reg_init.o | |
| 79 | + beige_goby_reg_init.o yellow_carp_reg_init.o cyan_skillfish_reg_init.o | |
| 79 | 80 | |
| 80 | 81 | # add DF block |
| 81 | 82 | amdgpu-y += \ |
| @@ -111,6 +112,7 @@ amdgpu-y += \ · 29 unmodified lines | ||
| 111 | 112 | psp_v3_1.o \ |
| 112 | 113 | psp_v10_0.o \ |
| 113 | 114 | psp_v11_0.o \ |
| 115 | + psp_v11_0_8.o \ | |
| 114 | 116 | psp_v12_0.o \ |
| 115 | 117 | psp_v13_0.o |
| 116 | 118 | |
| @@ -118,7 +120,7 @@ amdgpu-y += \ · 1 unmodified line | ||
| 118 | 120 | amdgpu-y += \ |
| 119 | 121 | dce_v10_0.o \ |
| 120 | 122 | dce_v11_0.o \ |
| 121 | − dce_virtual.o | |
| 123 | + amdgpu_vkms.o | |
| 122 | 124 | |
| 123 | 125 | # add GFX block |
| 124 | 126 | amdgpu-y += \ |
| @@ -187,6 +189,10 @@ amdgpu-y += \ · 62 unmodified lines | ||
| 187 | 189 | amdgpu-y += \ |
| 188 | 190 | amdgpu_reset.o |
| 189 | 191 | |
| 192 | +# add MCA block | |
| 193 | +amdgpu-y += \ | |
| 194 | + mca_v3_0.o | |
| 195 | + | |
| 190 | 196 | # add amdkfd interfaces |
| 191 | 197 | amdgpu-y += amdgpu_amdkfd.o |
| 192 | 198 | |
| @@ -108,6 +108,7 @@ · 107 unmodified lines | ||
| 108 | 108 | #include "amdgpu_df.h" |
| 109 | 109 | #include "amdgpu_smuio.h" |
| 110 | 110 | #include "amdgpu_fdinfo.h" |
| 111 | +#include "amdgpu_mca.h" | |
| 111 | 112 | |
| 112 | 113 | #define MAX_GPU_INSTANCE 16 |
| 113 | 114 | |
| @@ -916,6 +917,7 @@ struct amdgpu_device { · 802 unmodified lines | ||
| 916 | 917 | |
| 917 | 918 | /* display */ |
| 918 | 919 | bool enable_virtual_display; |
| 920 | + struct amdgpu_vkms_output *amdgpu_vkms_output; | |
| 919 | 921 | struct amdgpu_mode_info mode_info; |
| 920 | 922 | /* For pre-DCE11. DCE11 and later are in "struct amdgpu_device->dm" */ |
| 921 | 923 | struct work_struct hotplug_work; |
| @@ -1008,6 +1010,9 @@ struct amdgpu_device { · 86 unmodified lines | ||
| 1008 | 1010 | /* df */ |
| 1009 | 1011 | struct amdgpu_df df; |
| 1010 | 1012 | |
| 1013 | + /* MCA */ | |
| 1014 | + struct amdgpu_mca mca; | |
| 1015 | + | |
| 1011 | 1016 | struct amdgpu_ip_block ip_blocks[AMDGPU_MAX_IP_NUM]; |
| 1012 | 1017 | uint32_t harvest_ip_mask; |
| 1013 | 1018 | int num_ip_blocks; |
| @@ -1108,8 +1113,13 @@ void amdgpu_device_fini_sw(struct amdgpu_device *adev); · 94 unmodified lines | ||
| 1108 | 1113 | |
| 1109 | 1114 | int amdgpu_gpu_wait_for_idle(struct amdgpu_device *adev); |
| 1110 | 1115 | |
| 1116 | +void amdgpu_device_mm_access(struct amdgpu_device *adev, loff_t pos, | |
| 1117 | + void *buf, size_t size, bool write); | |
| 1118 | +size_t amdgpu_device_aper_access(struct amdgpu_device *adev, loff_t pos, | |
| 1119 | + void *buf, size_t size, bool write); | |
| 1120 | + | |
| 1111 | 1121 | void amdgpu_device_vram_access(struct amdgpu_device *adev, loff_t pos, |
| 1112 | − uint32_t *buf, size_t size, bool write); | |
| 1122 | + void *buf, size_t size, bool write); | |
| 1113 | 1123 | uint32_t amdgpu_device_rreg(struct amdgpu_device *adev, |
| 1114 | 1124 | uint32_t reg, uint32_t acc_flags); |
| 1115 | 1125 | void amdgpu_device_wreg(struct amdgpu_device *adev, |
| @@ -1265,6 +1275,8 @@ int emu_soc_asic_init(struct amdgpu_device *adev); · 149 unmodified lines | ||
| 1265 | 1275 | |
| 1266 | 1276 | #define amdgpu_inc_vram_lost(adev) atomic_inc(&((adev)->vram_lost_counter)); |
| 1267 | 1277 | |
| 1278 | +#define MIN(X, Y) ((X) < (Y) ? (X) : (Y)) | |
| 1279 | + | |
| 1268 | 1280 | /* Common functions */ |
| 1269 | 1281 | bool amdgpu_device_has_job_running(struct amdgpu_device *adev); |
| 1270 | 1282 | bool amdgpu_device_should_recover_gpu(struct amdgpu_device *adev); |
| @@ -1385,12 +1397,12 @@ int amdgpu_acpi_smart_shift_update(struct drm_device *dev, enum amdgpu_ss ss_sta · 114 unmodified lines | ||
| 1385 | 1397 | int amdgpu_acpi_pcie_notify_device_ready(struct amdgpu_device *adev); |
| 1386 | 1398 | |
| 1387 | 1399 | void amdgpu_acpi_get_backlight_caps(struct amdgpu_dm_backlight_caps *caps); |
| 1388 | −bool amdgpu_acpi_is_s0ix_supported(struct amdgpu_device *adev); | |
| 1400 | +bool amdgpu_acpi_is_s0ix_active(struct amdgpu_device *adev); | |
| 1389 | 1401 | void amdgpu_acpi_detect(void); |
| 1390 | 1402 | #else |
| 1391 | 1403 | static inline int amdgpu_acpi_init(struct amdgpu_device *adev) { return 0; } |
| 1392 | 1404 | static inline void amdgpu_acpi_fini(struct amdgpu_device *adev) { } |
| 1393 | −static inline bool amdgpu_acpi_is_s0ix_supported(struct amdgpu_device *adev) { return false; } | |
| 1405 | +static inline bool amdgpu_acpi_is_s0ix_active(struct amdgpu_device *adev) { return false; } | |
| 1394 | 1406 | static inline void amdgpu_acpi_detect(void) { } |
| 1395 | 1407 | static inline bool amdgpu_acpi_is_power_shift_control_supported(void) { return false; } |
| 1396 | 1408 | static inline int amdgpu_acpi_power_shift_control(struct amdgpu_device *adev, |
| @@ -160,17 +160,28 @@ static int acp_poweron(struct generic_pm_domain *genpd) · 159 unmodified lines | ||
| 160 | 160 | return 0; |
| 161 | 161 | } |
| 162 | 162 | |
| 163 | −static struct device *get_mfd_cell_dev(const char *device_name, int r) | |
| 163 | +static int acp_genpd_add_device(struct device *dev, void *data) | |
| 164 | 164 | { |
| 165 | − char auto_dev_name[25]; | |
| 166 | − struct device *dev; | |
| 165 | + struct generic_pm_domain *gpd = data; | |
| 166 | + int ret; | |
| 167 | 167 | |
| 168 | − snprintf(auto_dev_name, sizeof(auto_dev_name), | |
| 169 | − "%s.%d.auto", device_name, r); | |
| 170 | − dev = bus_find_device_by_name(&platform_bus_type, NULL, auto_dev_name); | |
| 171 | − dev_info(dev, "device %s added to pm domain\n", auto_dev_name); | |
| 168 | + ret = pm_genpd_add_device(gpd, dev); | |
| 169 | + if (ret) | |
| 170 | + dev_err(dev, "Failed to add dev to genpd %d\n", ret); | |
| 172 | 171 | |
| 173 | − return dev; | |
| 172 | + return ret; | |
| 173 | +} | |
| 174 | + | |
| 175 | +static int acp_genpd_remove_device(struct device *dev, void *data) | |
| 176 | +{ | |
| 177 | + int ret; | |
| 178 | + | |
| 179 | + ret = pm_genpd_remove_device(dev); | |
| 180 | + if (ret) | |
| 181 | + dev_err(dev, "Failed to remove dev from genpd %d\n", ret); | |
| 182 | + | |
| 183 | + /* Continue to remove */ | |
| 184 | + return 0; | |
| 174 | 185 | } |
| 175 | 186 | |
| 176 | 187 | /** |
| @@ -181,11 +192,10 @@ static struct device *get_mfd_cell_dev(const char *device_name, int r) · 4 unmodified lines | ||
| 181 | 192 | */ |
| 182 | 193 | static int acp_hw_init(void *handle) |
| 183 | 194 | { |
| 184 | − int r, i; | |
| 195 | + int r; | |
| 185 | 196 | uint64_t acp_base; |
| 186 | 197 | u32 val = 0; |
| 187 | 198 | u32 count = 0; |
| 188 | − struct device *dev; | |
| 189 | 199 | struct i2s_platform_data *i2s_pdata = NULL; |
| 190 | 200 | |
| 191 | 201 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; |
| @@ -341,15 +351,10 @@ static int acp_hw_init(void *handle) · 149 unmodified lines | ||
| 341 | 351 | if (r) |
| 342 | 352 | goto failure; |
| 343 | 353 | |
| 344 | − for (i = 0; i < ACP_DEVS ; i++) { | |
| 345 | − dev = get_mfd_cell_dev(adev->acp.acp_cell[i].name, i); | |
| 346 | − r = pm_genpd_add_device(&adev->acp.acp_genpd->gpd, dev); | |
| 347 | − if (r) { | |
| 348 | − dev_err(dev, "Failed to add dev to genpd\n"); | |
| 349 | − goto failure; | |
| 350 | − } | |
| 351 | − } | |
| 352 | − | |
| 354 | + r = device_for_each_child(adev->acp.parent, &adev->acp.acp_genpd->gpd, | |
| 355 | + acp_genpd_add_device); | |
| 356 | + if (r) | |
| 357 | + goto failure; | |
| 353 | 358 | |
| 354 | 359 | /* Assert Soft reset of ACP */ |
| 355 | 360 | val = cgs_read_register(adev->acp.cgs_device, mmACP_SOFT_RESET); |
| @@ -410,10 +415,8 @@ failure: · 54 unmodified lines | ||
| 410 | 415 | */ |
| 411 | 416 | static int acp_hw_fini(void *handle) |
| 412 | 417 | { |
| 413 | − int i, ret; | |
| 414 | 418 | u32 val = 0; |
| 415 | 419 | u32 count = 0; |
| 416 | − struct device *dev; | |
| 417 | 420 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; |
| 418 | 421 | |
| 419 | 422 | /* return early if no ACP */ |
| @@ -458,13 +461,8 @@ static int acp_hw_fini(void *handle) · 38 unmodified lines | ||
| 458 | 461 | udelay(100); |
| 459 | 462 | } |
| 460 | 463 | |
| 461 | − for (i = 0; i < ACP_DEVS ; i++) { | |
| 462 | − dev = get_mfd_cell_dev(adev->acp.acp_cell[i].name, i); | |
| 463 | − ret = pm_genpd_remove_device(dev); | |
| 464 | − /* If removal fails, dont giveup and try rest */ | |
| 465 | − if (ret) | |
| 466 | − dev_err(dev, "remove dev from genpd failed\n"); | |
| 467 | − } | |
| 464 | + device_for_each_child(adev->acp.parent, NULL, | |
| 465 | + acp_genpd_remove_device); | |
| 468 | 466 | |
| 469 | 467 | mfd_remove_devices(adev->acp.parent); |
| 470 | 468 | kfree(adev->acp.acp_res); |
| @@ -854,8 +854,8 @@ int amdgpu_acpi_init(struct amdgpu_device *adev) · 853 unmodified lines | ||
| 854 | 854 | if (amdgpu_device_has_dc_support(adev)) { |
| 855 | 855 | #if defined(CONFIG_DRM_AMD_DC) |
| 856 | 856 | struct amdgpu_display_manager *dm = &adev->dm; |
| 857 | − if (dm->backlight_dev) | |
| 858 | − atif->bd = dm->backlight_dev; | |
| 857 | + if (dm->backlight_dev[0]) | |
| 858 | + atif->bd = dm->backlight_dev[0]; | |
| 859 | 859 | #endif |
| 860 | 860 | } else { |
| 861 | 861 | struct drm_encoder *tmp; |
| @@ -1032,13 +1032,13 @@ void amdgpu_acpi_detect(void) · 170 unmodified lines | ||
| 1032 | 1032 | } |
| 1033 | 1033 | |
| 1034 | 1034 | /** |
| 1035 | − * amdgpu_acpi_is_s0ix_supported | |
| 1035 | + * amdgpu_acpi_is_s0ix_active | |
| 1036 | 1036 | * |
| 1037 | 1037 | * @adev: amdgpu_device_pointer |
| 1038 | 1038 | * |
| 1039 | 1039 | * returns true if supported, false if not. |
| 1040 | 1040 | */ |
| 1041 | −bool amdgpu_acpi_is_s0ix_supported(struct amdgpu_device *adev) | |
| 1041 | +bool amdgpu_acpi_is_s0ix_active(struct amdgpu_device *adev) | |
| 1042 | 1042 | { |
| 1043 | 1043 | #if IS_ENABLED(CONFIG_AMD_PMC) && IS_ENABLED(CONFIG_SUSPEND) |
| 1044 | 1044 | if (acpi_gbl_FADT.flags & ACPI_FADT_LOW_POWER_S0) { |
| @@ -21,6 +21,7 @@ · 20 unmodified lines | ||
| 21 | 21 | */ |
| 22 | 22 | |
| 23 | 23 | #include "amdgpu_amdkfd.h" |
| 24 | +#include "amd_pcie.h" | |
| 24 | 25 | #include "amd_shared.h" |
| 25 | 26 | |
| 26 | 27 | #include "amdgpu.h" |
| @@ -553,6 +554,88 @@ uint8_t amdgpu_amdkfd_get_xgmi_hops_count(struct kgd_dev *dst, struct kgd_dev *s · 526 unmodified lines | ||
| 553 | 554 | return (uint8_t)ret; |
| 554 | 555 | } |
| 555 | 556 | |
| 557 | +int amdgpu_amdkfd_get_xgmi_bandwidth_mbytes(struct kgd_dev *dst, struct kgd_dev *src, bool is_min) | |
| 558 | +{ | |
| 559 | + struct amdgpu_device *adev = (struct amdgpu_device *)dst, *peer_adev; | |
| 560 | + int num_links; | |
| 561 | + | |
| 562 | + if (adev->asic_type != CHIP_ALDEBARAN) | |
| 563 | + return 0; | |
| 564 | + | |
| 565 | + if (src) | |
| 566 | + peer_adev = (struct amdgpu_device *)src; | |
| 567 | + | |
| 568 | + /* num links returns 0 for indirect peers since indirect route is unknown. */ | |
| 569 | + num_links = is_min ? 1 : amdgpu_xgmi_get_num_links(adev, peer_adev); | |
| 570 | + if (num_links < 0) { | |
| 571 | + DRM_ERROR("amdgpu: failed to get xgmi num links between node %d and %d. ret = %d\n", | |
| 572 | + adev->gmc.xgmi.physical_node_id, | |
| 573 | + peer_adev->gmc.xgmi.physical_node_id, num_links); | |
| 574 | + num_links = 0; | |
| 575 | + } | |
| 576 | + | |
| 577 | + /* Aldebaran xGMI DPM is defeatured so assume x16 x 25Gbps for bandwidth. */ | |
| 578 | + return (num_links * 16 * 25000)/BITS_PER_BYTE; | |
| 579 | +} | |
| 580 | + | |
| 581 | +int amdgpu_amdkfd_get_pcie_bandwidth_mbytes(struct kgd_dev *dev, bool is_min) | |
| 582 | +{ | |
| 583 | + struct amdgpu_device *adev = (struct amdgpu_device *)dev; | |
| 584 | + int num_lanes_shift = (is_min ? ffs(adev->pm.pcie_mlw_mask) : | |
| 585 | + fls(adev->pm.pcie_mlw_mask)) - 1; | |
| 586 | + int gen_speed_shift = (is_min ? ffs(adev->pm.pcie_gen_mask & | |
| 587 | + CAIL_PCIE_LINK_SPEED_SUPPORT_MASK) : | |
| 588 | + fls(adev->pm.pcie_gen_mask & | |
| 589 | + CAIL_PCIE_LINK_SPEED_SUPPORT_MASK)) - 1; | |
| 590 | + uint32_t num_lanes_mask = 1 << num_lanes_shift; | |
| 591 | + uint32_t gen_speed_mask = 1 << gen_speed_shift; | |
| 592 | + int num_lanes_factor = 0, gen_speed_mbits_factor = 0; | |
| 593 | + | |
| 594 | + switch (num_lanes_mask) { | |
| 595 | + case CAIL_PCIE_LINK_WIDTH_SUPPORT_X1: | |
| 596 | + num_lanes_factor = 1; | |
| 597 | + break; | |
| 598 | + case CAIL_PCIE_LINK_WIDTH_SUPPORT_X2: | |
| 599 | + num_lanes_factor = 2; | |
| 600 | + break; | |
| 601 | + case CAIL_PCIE_LINK_WIDTH_SUPPORT_X4: | |
| 602 | + num_lanes_factor = 4; | |
| 603 | + break; | |
| 604 | + case CAIL_PCIE_LINK_WIDTH_SUPPORT_X8: | |
| 605 | + num_lanes_factor = 8; | |
| 606 | + break; | |
| 607 | + case CAIL_PCIE_LINK_WIDTH_SUPPORT_X12: | |
| 608 | + num_lanes_factor = 12; | |
| 609 | + break; | |
| 610 | + case CAIL_PCIE_LINK_WIDTH_SUPPORT_X16: | |
| 611 | + num_lanes_factor = 16; | |
| 612 | + break; | |
| 613 | + case CAIL_PCIE_LINK_WIDTH_SUPPORT_X32: | |
| 614 | + num_lanes_factor = 32; | |
| 615 | + break; | |
| 616 | + } | |
| 617 | + | |
| 618 | + switch (gen_speed_mask) { | |
| 619 | + case CAIL_PCIE_LINK_SPEED_SUPPORT_GEN1: | |
| 620 | + gen_speed_mbits_factor = 2500; | |
| 621 | + break; | |
| 622 | + case CAIL_PCIE_LINK_SPEED_SUPPORT_GEN2: | |
| 623 | + gen_speed_mbits_factor = 5000; | |
| 624 | + break; | |
| 625 | + case CAIL_PCIE_LINK_SPEED_SUPPORT_GEN3: | |
| 626 | + gen_speed_mbits_factor = 8000; | |
| 627 | + break; | |
| 628 | + case CAIL_PCIE_LINK_SPEED_SUPPORT_GEN4: | |
| 629 | + gen_speed_mbits_factor = 16000; | |
| 630 | + break; | |
| 631 | + case CAIL_PCIE_LINK_SPEED_SUPPORT_GEN5: | |
| 632 | + gen_speed_mbits_factor = 32000; | |
| 633 | + break; | |
| 634 | + } | |
| 635 | + | |
| 636 | + return (num_lanes_factor * gen_speed_mbits_factor)/BITS_PER_BYTE; | |
| 637 | +} | |
| 638 | + | |
| 556 | 639 | uint64_t amdgpu_amdkfd_get_mmio_remap_phys_addr(struct kgd_dev *kgd) |
| 557 | 640 | { |
| 558 | 641 | struct amdgpu_device *adev = (struct amdgpu_device *)kgd; |
| @@ -631,7 +714,6 @@ int amdgpu_amdkfd_submit_ib(struct kgd_dev *kgd, enum kgd_engine_type engine, · 72 unmodified lines | ||
| 631 | 714 | ret = dma_fence_wait(f, false); |
| 632 | 715 | |
| 633 | 716 | err_ib_sched: |
| 634 | − dma_fence_put(f); | |
| 635 | 717 | amdgpu_job_free(job); |
| 636 | 718 | err: |
| 637 | 719 | return ret; |
| @@ -226,6 +226,8 @@ uint32_t amdgpu_amdkfd_get_num_gws(struct kgd_dev *kgd); · 225 unmodified lines | ||
| 226 | 226 | uint32_t amdgpu_amdkfd_get_asic_rev_id(struct kgd_dev *kgd); |
| 227 | 227 | int amdgpu_amdkfd_get_noretry(struct kgd_dev *kgd); |
| 228 | 228 | uint8_t amdgpu_amdkfd_get_xgmi_hops_count(struct kgd_dev *dst, struct kgd_dev *src); |
| 229 | +int amdgpu_amdkfd_get_xgmi_bandwidth_mbytes(struct kgd_dev *dst, struct kgd_dev *src, bool is_min); | |
| 230 | +int amdgpu_amdkfd_get_pcie_bandwidth_mbytes(struct kgd_dev *dev, bool is_min); | |
| 229 | 231 | |
| 230 | 232 | /* Read user wptr from a specified user address space with page fault |
| 231 | 233 | * disabled. The memory must be pinned and mapped to the hardware when |
| @@ -269,7 +271,7 @@ int amdgpu_amdkfd_gpuvm_free_memory_of_gpu( · 37 unmodified lines | ||
| 269 | 271 | struct kgd_dev *kgd, struct kgd_mem *mem, void *drm_priv, |
| 270 | 272 | uint64_t *size); |
| 271 | 273 | int amdgpu_amdkfd_gpuvm_map_memory_to_gpu( |
| 272 | − struct kgd_dev *kgd, struct kgd_mem *mem, void *drm_priv); | |
| 274 | + struct kgd_dev *kgd, struct kgd_mem *mem, void *drm_priv, bool *table_freed); | |
| 273 | 275 | int amdgpu_amdkfd_gpuvm_unmap_memory_from_gpu( |
| 274 | 276 | struct kgd_dev *kgd, struct kgd_mem *mem, void *drm_priv); |
| 275 | 277 | int amdgpu_amdkfd_gpuvm_sync_memory( |
| @@ -330,7 +332,7 @@ int kgd2kfd_pre_reset(struct kfd_dev *kfd); · 54 unmodified lines | ||
| 330 | 332 | int kgd2kfd_post_reset(struct kfd_dev *kfd); |
| 331 | 333 | void kgd2kfd_interrupt(struct kfd_dev *kfd, const void *ih_ring_entry); |
| 332 | 334 | void kgd2kfd_set_sram_ecc_flag(struct kfd_dev *kfd); |
| 333 | −void kgd2kfd_smi_event_throttle(struct kfd_dev *kfd, uint32_t throttle_bitmask); | |
| 335 | +void kgd2kfd_smi_event_throttle(struct kfd_dev *kfd, uint64_t throttle_bitmask); | |
| 334 | 336 | #else |
| 335 | 337 | static inline int kgd2kfd_init(void) |
| 336 | 338 | { |
| @@ -389,7 +391,7 @@ void kgd2kfd_set_sram_ecc_flag(struct kfd_dev *kfd) · 52 unmodified lines | ||
| 389 | 391 | } |
| 390 | 392 | |
| 391 | 393 | static inline |
| 392 | −void kgd2kfd_smi_event_throttle(struct kfd_dev *kfd, uint32_t throttle_bitmask) | |
| 394 | +void kgd2kfd_smi_event_throttle(struct kfd_dev *kfd, uint64_t throttle_bitmask) | |
| 393 | 395 | { |
| 394 | 396 | } |
| 395 | 397 | #endif |
| @@ -44,4 +44,5 @@ const struct kfd2kgd_calls aldebaran_kfd2kgd = { · 43 unmodified lines | ||
| 44 | 44 | .get_atc_vmid_pasid_mapping_info = |
| 45 | 45 | kgd_gfx_v9_get_atc_vmid_pasid_mapping_info, |
| 46 | 46 | .set_vm_context_page_table_base = kgd_gfx_v9_set_vm_context_page_table_base, |
| 47 | + .program_trap_handler_settings = kgd_gfx_v9_program_trap_handler_settings | |
| 47 | 48 | }; |
| @@ -305,5 +305,6 @@ const struct kfd2kgd_calls arcturus_kfd2kgd = { · 304 unmodified lines | ||
| 305 | 305 | kgd_gfx_v9_get_atc_vmid_pasid_mapping_info, |
| 306 | 306 | .set_vm_context_page_table_base = |
| 307 | 307 | kgd_gfx_v9_set_vm_context_page_table_base, |
| 308 | − .get_cu_occupancy = kgd_gfx_v9_get_cu_occupancy | |
| 308 | + .get_cu_occupancy = kgd_gfx_v9_get_cu_occupancy, | |
| 309 | + .program_trap_handler_settings = kgd_gfx_v9_program_trap_handler_settings | |
| 309 | 310 | }; |
| @@ -560,6 +560,9 @@ static int kgd_hqd_destroy(struct kgd_dev *kgd, void *mqd, · 559 unmodified lines | ||
| 560 | 560 | case KFD_PREEMPT_TYPE_WAVEFRONT_RESET: |
| 561 | 561 | type = RESET_WAVES; |
| 562 | 562 | break; |
| 563 | + case KFD_PREEMPT_TYPE_WAVEFRONT_SAVE: | |
| 564 | + type = SAVE_WAVES; | |
| 565 | + break; | |
| 563 | 566 | default: |
| 564 | 567 | type = DRAIN_PIPE; |
| 565 | 568 | break; |
| @@ -754,6 +757,33 @@ static void set_vm_context_page_table_base(struct kgd_dev *kgd, uint32_t vmid, · 188 unmodified lines | ||
| 754 | 757 | adev->gfxhub.funcs->setup_vm_pt_regs(adev, vmid, page_table_base); |
| 755 | 758 | } |
| 756 | 759 | |
| 760 | +static void program_trap_handler_settings(struct kgd_dev *kgd, | |
| 761 | + uint32_t vmid, uint64_t tba_addr, uint64_t tma_addr) | |
| 762 | +{ | |
| 763 | + struct amdgpu_device *adev = get_amdgpu_device(kgd); | |
| 764 | + | |
| 765 | + lock_srbm(kgd, 0, 0, 0, vmid); | |
| 766 | + | |
| 767 | + /* | |
| 768 | + * Program TBA registers | |
| 769 | + */ | |
| 770 | + WREG32(SOC15_REG_OFFSET(GC, 0, mmSQ_SHADER_TBA_LO), | |
| 771 | + lower_32_bits(tba_addr >> 8)); | |
| 772 | + WREG32(SOC15_REG_OFFSET(GC, 0, mmSQ_SHADER_TBA_HI), | |
| 773 | + upper_32_bits(tba_addr >> 8) | | |
| 774 | + (1 << SQ_SHADER_TBA_HI__TRAP_EN__SHIFT)); | |
| 775 | + | |
| 776 | + /* | |
| 777 | + * Program TMA registers | |
| 778 | + */ | |
| 779 | + WREG32(SOC15_REG_OFFSET(GC, 0, mmSQ_SHADER_TMA_LO), | |
| 780 | + lower_32_bits(tma_addr >> 8)); | |
| 781 | + WREG32(SOC15_REG_OFFSET(GC, 0, mmSQ_SHADER_TMA_HI), | |
| 782 | + upper_32_bits(tma_addr >> 8)); | |
| 783 | + | |
| 784 | + unlock_srbm(kgd); | |
| 785 | +} | |
| 786 | + | |
| 757 | 787 | const struct kfd2kgd_calls gfx_v10_kfd2kgd = { |
| 758 | 788 | .program_sh_mem_settings = kgd_program_sh_mem_settings, |
| 759 | 789 | .set_pasid_vmid_mapping = kgd_set_pasid_vmid_mapping, |
| @@ -774,4 +804,5 @@ const struct kfd2kgd_calls gfx_v10_kfd2kgd = { · 14 unmodified lines | ||
| 774 | 804 | .get_atc_vmid_pasid_mapping_info = |
| 775 | 805 | get_atc_vmid_pasid_mapping_info, |
| 776 | 806 | .set_vm_context_page_table_base = set_vm_context_page_table_base, |
| 807 | + .program_trap_handler_settings = program_trap_handler_settings, | |
| 777 | 808 | }; |
| @@ -537,6 +537,9 @@ static int hqd_destroy_v10_3(struct kgd_dev *kgd, void *mqd, · 536 unmodified lines | ||
| 537 | 537 | case KFD_PREEMPT_TYPE_WAVEFRONT_RESET: |
| 538 | 538 | type = RESET_WAVES; |
| 539 | 539 | break; |
| 540 | + case KFD_PREEMPT_TYPE_WAVEFRONT_SAVE: | |
| 541 | + type = SAVE_WAVES; | |
| 542 | + break; | |
| 540 | 543 | default: |
| 541 | 544 | type = DRAIN_PIPE; |
| 542 | 545 | break; |
| @@ -658,6 +661,33 @@ static void set_vm_context_page_table_base_v10_3(struct kgd_dev *kgd, uint32_t v · 115 unmodified lines | ||
| 658 | 661 | adev->gfxhub.funcs->setup_vm_pt_regs(adev, vmid, page_table_base); |
| 659 | 662 | } |
| 660 | 663 | |
| 664 | +static void program_trap_handler_settings_v10_3(struct kgd_dev *kgd, | |
| 665 | + uint32_t vmid, uint64_t tba_addr, uint64_t tma_addr) | |
| 666 | +{ | |
| 667 | + struct amdgpu_device *adev = get_amdgpu_device(kgd); | |
| 668 | + | |
| 669 | + lock_srbm(kgd, 0, 0, 0, vmid); | |
| 670 | + | |
| 671 | + /* | |
| 672 | + * Program TBA registers | |
| 673 | + */ | |
| 674 | + WREG32(SOC15_REG_OFFSET(GC, 0, mmSQ_SHADER_TBA_LO), | |
| 675 | + lower_32_bits(tba_addr >> 8)); | |
| 676 | + WREG32(SOC15_REG_OFFSET(GC, 0, mmSQ_SHADER_TBA_HI), | |
| 677 | + upper_32_bits(tba_addr >> 8) | | |
| 678 | + (1 << SQ_SHADER_TBA_HI__TRAP_EN__SHIFT)); | |
| 679 | + | |
| 680 | + /* | |
| 681 | + * Program TMA registers | |
| 682 | + */ | |
| 683 | + WREG32(SOC15_REG_OFFSET(GC, 0, mmSQ_SHADER_TMA_LO), | |
| 684 | + lower_32_bits(tma_addr >> 8)); | |
| 685 | + WREG32(SOC15_REG_OFFSET(GC, 0, mmSQ_SHADER_TMA_HI), | |
| 686 | + upper_32_bits(tma_addr >> 8)); | |
| 687 | + | |
| 688 | + unlock_srbm(kgd); | |
| 689 | +} | |
| 690 | + | |
| 661 | 691 | #if 0 |
| 662 | 692 | uint32_t enable_debug_trap_v10_3(struct kgd_dev *kgd, |
| 663 | 693 | uint32_t trap_debug_wave_launch_mode, |
| @@ -820,6 +850,7 @@ const struct kfd2kgd_calls gfx_v10_3_kfd2kgd = { · 156 unmodified lines | ||
| 820 | 850 | .address_watch_get_offset = address_watch_get_offset_v10_3, |
| 821 | 851 | .get_atc_vmid_pasid_mapping_info = NULL, |
| 822 | 852 | .set_vm_context_page_table_base = set_vm_context_page_table_base_v10_3, |
| 853 | + .program_trap_handler_settings = program_trap_handler_settings_v10_3, | |
| 823 | 854 | #if 0 |
| 824 | 855 | .enable_debug_trap = enable_debug_trap_v10_3, |
| 825 | 856 | .disable_debug_trap = disable_debug_trap_v10_3, |
| @@ -42,7 +42,8 @@ · 41 unmodified lines | ||
| 42 | 42 | enum hqd_dequeue_request_type { |
| 43 | 43 | NO_ACTION = 0, |
| 44 | 44 | DRAIN_PIPE, |
| 45 | − RESET_WAVES | |
| 45 | + RESET_WAVES, | |
| 46 | + SAVE_WAVES | |
| 46 | 47 | }; |
| 47 | 48 | |
| 48 | 49 | static inline struct amdgpu_device *get_amdgpu_device(struct kgd_dev *kgd) |
| @@ -566,6 +567,9 @@ int kgd_gfx_v9_hqd_destroy(struct kgd_dev *kgd, void *mqd, · 517 unmodified lines | ||
| 566 | 567 | case KFD_PREEMPT_TYPE_WAVEFRONT_RESET: |
| 567 | 568 | type = RESET_WAVES; |
| 568 | 569 | break; |
| 570 | + case KFD_PREEMPT_TYPE_WAVEFRONT_SAVE: | |
| 571 | + type = SAVE_WAVES; | |
| 572 | + break; | |
| 569 | 573 | default: |
| 570 | 574 | type = DRAIN_PIPE; |
| 571 | 575 | break; |
| @@ -878,6 +882,32 @@ void kgd_gfx_v9_get_cu_occupancy(struct kgd_dev *kgd, int pasid, · 306 unmodified lines | ||
| 878 | 882 | adev->gfx.cu_info.max_waves_per_simd; |
| 879 | 883 | } |
| 880 | 884 | |
| 885 | +void kgd_gfx_v9_program_trap_handler_settings(struct kgd_dev *kgd, | |
| 886 | + uint32_t vmid, uint64_t tba_addr, uint64_t tma_addr) | |
| 887 | +{ | |
| 888 | + struct amdgpu_device *adev = get_amdgpu_device(kgd); | |
| 889 | + | |
| 890 | + lock_srbm(kgd, 0, 0, 0, vmid); | |
| 891 | + | |
| 892 | + /* | |
| 893 | + * Program TBA registers | |
| 894 | + */ | |
| 895 | + WREG32(SOC15_REG_OFFSET(GC, 0, mmSQ_SHADER_TBA_LO), | |
| 896 | + lower_32_bits(tba_addr >> 8)); | |
| 897 | + WREG32(SOC15_REG_OFFSET(GC, 0, mmSQ_SHADER_TBA_HI), | |
| 898 | + upper_32_bits(tba_addr >> 8)); | |
| 899 | + | |
| 900 | + /* | |
| 901 | + * Program TMA registers | |
| 902 | + */ | |
| 903 | + WREG32(SOC15_REG_OFFSET(GC, 0, mmSQ_SHADER_TMA_LO), | |
| 904 | + lower_32_bits(tma_addr >> 8)); | |
| 905 | + WREG32(SOC15_REG_OFFSET(GC, 0, mmSQ_SHADER_TMA_HI), | |
| 906 | + upper_32_bits(tma_addr >> 8)); | |
| 907 | + | |
| 908 | + unlock_srbm(kgd); | |
| 909 | +} | |
| 910 | + | |
| 881 | 911 | const struct kfd2kgd_calls gfx_v9_kfd2kgd = { |
| 882 | 912 | .program_sh_mem_settings = kgd_gfx_v9_program_sh_mem_settings, |
| 883 | 913 | .set_pasid_vmid_mapping = kgd_gfx_v9_set_pasid_vmid_mapping, |
| @@ -899,4 +929,5 @@ const struct kfd2kgd_calls gfx_v9_kfd2kgd = { · 15 unmodified lines | ||
| 899 | 929 | kgd_gfx_v9_get_atc_vmid_pasid_mapping_info, |
| 900 | 930 | .set_vm_context_page_table_base = kgd_gfx_v9_set_vm_context_page_table_base, |
| 901 | 931 | .get_cu_occupancy = kgd_gfx_v9_get_cu_occupancy, |
| 932 | + .program_trap_handler_settings = kgd_gfx_v9_program_trap_handler_settings, | |
| 902 | 933 | }; |
| @@ -65,3 +65,5 @@ void kgd_gfx_v9_set_vm_context_page_table_base(struct kgd_dev *kgd, · 64 unmodified lines | ||
| 65 | 65 | uint32_t vmid, uint64_t page_table_base); |
| 66 | 66 | void kgd_gfx_v9_get_cu_occupancy(struct kgd_dev *kgd, int pasid, |
| 67 | 67 | int *pasid_wave_cnt, int *max_waves_per_cu); |
| 68 | +void kgd_gfx_v9_program_trap_handler_settings(struct kgd_dev *kgd, | |
| 69 | + uint32_t vmid, uint64_t tba_addr, uint64_t tma_addr); | |
| @@ -1057,7 +1057,8 @@ static void unmap_bo_from_gpuvm(struct kgd_mem *mem, · 1056 unmodified lines | ||
| 1057 | 1057 | |
| 1058 | 1058 | static int update_gpuvm_pte(struct kgd_mem *mem, |
| 1059 | 1059 | struct kfd_mem_attachment *entry, |
| 1060 | − struct amdgpu_sync *sync) | |
| 1060 | + struct amdgpu_sync *sync, | |
| 1061 | + bool *table_freed) | |
| 1061 | 1062 | { |
| 1062 | 1063 | struct amdgpu_bo_va *bo_va = entry->bo_va; |
| 1063 | 1064 | struct amdgpu_device *adev = entry->adev; |
| @@ -1068,7 +1069,7 @@ static int update_gpuvm_pte(struct kgd_mem *mem, · 4 unmodified lines | ||
| 1068 | 1069 | return ret; |
| 1069 | 1070 | |
| 1070 | 1071 | /* Update the page tables */ |
| 1071 | − ret = amdgpu_vm_bo_update(adev, bo_va, false); | |
| 1072 | + ret = amdgpu_vm_bo_update(adev, bo_va, false, table_freed); | |
| 1072 | 1073 | if (ret) { |
| 1073 | 1074 | pr_err("amdgpu_vm_bo_update failed\n"); |
| 1074 | 1075 | return ret; |
| @@ -1080,7 +1081,8 @@ static int update_gpuvm_pte(struct kgd_mem *mem, · 5 unmodified lines | ||
| 1080 | 1081 | static int map_bo_to_gpuvm(struct kgd_mem *mem, |
| 1081 | 1082 | struct kfd_mem_attachment *entry, |
| 1082 | 1083 | struct amdgpu_sync *sync, |
| 1083 | − bool no_update_pte) | |
| 1084 | + bool no_update_pte, | |
| 1085 | + bool *table_freed) | |
| 1084 | 1086 | { |
| 1085 | 1087 | int ret; |
| 1086 | 1088 | |
| @@ -1097,7 +1099,7 @@ static int map_bo_to_gpuvm(struct kgd_mem *mem, · 10 unmodified lines | ||
| 1097 | 1099 | if (no_update_pte) |
| 1098 | 1100 | return 0; |
| 1099 | 1101 | |
| 1100 | − ret = update_gpuvm_pte(mem, entry, sync); | |
| 1102 | + ret = update_gpuvm_pte(mem, entry, sync, table_freed); | |
| 1101 | 1103 | if (ret) { |
| 1102 | 1104 | pr_err("update_gpuvm_pte() failed\n"); |
| 1103 | 1105 | goto update_gpuvm_pte_failed; |
| @@ -1285,11 +1287,22 @@ int amdgpu_amdkfd_gpuvm_acquire_process_vm(struct kgd_dev *kgd, · 181 unmodified lines | ||
| 1285 | 1287 | if (avm->process_info) |
| 1286 | 1288 | return -EINVAL; |
| 1287 | 1289 | |
| 1290 | + /* Free the original amdgpu allocated pasid, | |
| 1291 | + * will be replaced with kfd allocated pasid. | |
| 1292 | + */ | |
| 1293 | + if (avm->pasid) { | |
| 1294 | + amdgpu_pasid_free(avm->pasid); | |
| 1295 | + amdgpu_vm_set_pasid(adev, avm, 0); | |
| 1296 | + } | |
| 1297 | + | |
| 1288 | 1298 | /* Convert VM into a compute VM */ |
| 1289 | − ret = amdgpu_vm_make_compute(adev, avm, pasid); | |
| 1299 | + ret = amdgpu_vm_make_compute(adev, avm); | |
| 1290 | 1300 | if (ret) |
| 1291 | 1301 | return ret; |
| 1292 | 1302 | |
| 1303 | + ret = amdgpu_vm_set_pasid(adev, avm, pasid); | |
| 1304 | + if (ret) | |
| 1305 | + return ret; | |
| 1293 | 1306 | /* Initialize KFD part of the VM and process info */ |
| 1294 | 1307 | ret = init_kfd_vm(avm, process_info, ef); |
| 1295 | 1308 | if (ret) |
| @@ -1594,7 +1607,8 @@ int amdgpu_amdkfd_gpuvm_free_memory_of_gpu( · 298 unmodified lines | ||
| 1594 | 1607 | } |
| 1595 | 1608 | |
| 1596 | 1609 | int amdgpu_amdkfd_gpuvm_map_memory_to_gpu( |
| 1597 | − struct kgd_dev *kgd, struct kgd_mem *mem, void *drm_priv) | |
| 1610 | + struct kgd_dev *kgd, struct kgd_mem *mem, | |
| 1611 | + void *drm_priv, bool *table_freed) | |
| 1598 | 1612 | { |
| 1599 | 1613 | struct amdgpu_device *adev = get_amdgpu_device(kgd); |
| 1600 | 1614 | struct amdgpu_vm *avm = drm_priv_to_vm(drm_priv); |
| @@ -1682,7 +1696,7 @@ int amdgpu_amdkfd_gpuvm_map_memory_to_gpu( · 81 unmodified lines | ||
| 1682 | 1696 | entry->va, entry->va + bo_size, entry); |
| 1683 | 1697 | |
| 1684 | 1698 | ret = map_bo_to_gpuvm(mem, entry, ctx.sync, |
| 1685 | − is_invalid_userptr); | |
| 1699 | + is_invalid_userptr, table_freed); | |
| 1686 | 1700 | if (ret) { |
| 1687 | 1701 | pr_err("Failed to map bo to gpuvm\n"); |
| 1688 | 1702 | goto out_unreserve; |
| @@ -1706,6 +1720,12 @@ int amdgpu_amdkfd_gpuvm_map_memory_to_gpu( · 17 unmodified lines | ||
| 1706 | 1720 | true); |
| 1707 | 1721 | ret = unreserve_bo_and_vms(&ctx, false, false); |
| 1708 | 1722 | |
| 1723 | + /* Only apply no TLB flush on Aldebaran to | |
| 1724 | + * workaround regressions on other Asics. | |
| 1725 | + */ | |
| 1726 | + if (table_freed && (adev->asic_type != CHIP_ALDEBARAN)) | |
| 1727 | + *table_freed = true; | |
| 1728 | + | |
| 1709 | 1729 | goto out; |
| 1710 | 1730 | |
| 1711 | 1731 | out_unreserve: |
| @@ -2132,7 +2152,7 @@ static int validate_invalid_user_pages(struct amdkfd_process_info *process_info) · 420 unmodified lines | ||
| 2132 | 2152 | continue; |
| 2133 | 2153 | |
| 2134 | 2154 | kfd_mem_dmaunmap_attachment(mem, attachment); |
| 2135 | − ret = update_gpuvm_pte(mem, attachment, &sync); | |
| 2155 | + ret = update_gpuvm_pte(mem, attachment, &sync, NULL); | |
| 2136 | 2156 | if (ret) { |
| 2137 | 2157 | pr_err("%s: update PTE failed\n", __func__); |
| 2138 | 2158 | /* make sure this gets validated again */ |
| @@ -2338,7 +2358,7 @@ int amdgpu_amdkfd_gpuvm_restore_process_bos(void *info, struct dma_fence **ef) · 199 unmodified lines | ||
| 2338 | 2358 | continue; |
| 2339 | 2359 | |
| 2340 | 2360 | kfd_mem_dmaunmap_attachment(mem, attachment); |
| 2341 | − ret = update_gpuvm_pte(mem, attachment, &sync_obj); | |
| 2361 | + ret = update_gpuvm_pte(mem, attachment, &sync_obj, NULL); | |
| 2342 | 2362 | if (ret) { |
| 2343 | 2363 | pr_debug("Memory eviction: update PTE failed. Try again\n"); |
| 2344 | 2364 | goto validate_map_fail; |
| @@ -34,6 +34,7 @@ struct amdgpu_fpriv; · 33 unmodified lines | ||
| 34 | 34 | struct amdgpu_bo_list_entry { |
| 35 | 35 | struct ttm_validate_buffer tv; |
| 36 | 36 | struct amdgpu_bo_va *bo_va; |
| 37 | + struct dma_fence_chain *chain; | |
| 37 | 38 | uint32_t priority; |
| 38 | 39 | struct page **user_pages; |
| 39 | 40 | bool user_invalidated; |
| @@ -572,6 +572,20 @@ static int amdgpu_cs_parser_bos(struct amdgpu_cs_parser *p, · 571 unmodified lines | ||
| 572 | 572 | goto out; |
| 573 | 573 | } |
| 574 | 574 | |
| 575 | + amdgpu_bo_list_for_each_entry(e, p->bo_list) { | |
| 576 | + struct amdgpu_bo *bo = ttm_to_amdgpu_bo(e->tv.bo); | |
| 577 | + | |
| 578 | + e->bo_va = amdgpu_vm_bo_find(vm, bo); | |
| 579 | + | |
| 580 | + if (bo->tbo.base.dma_buf && !amdgpu_bo_explicit_sync(bo)) { | |
| 581 | + e->chain = dma_fence_chain_alloc(); | |
| 582 | + if (!e->chain) { | |
| 583 | + r = -ENOMEM; | |
| 584 | + goto error_validate; | |
| 585 | + } | |
| 586 | + } | |
| 587 | + } | |
| 588 | + | |
| 575 | 589 | amdgpu_cs_get_threshold_for_moves(p->adev, &p->bytes_moved_threshold, |
| 576 | 590 | &p->bytes_moved_vis_threshold); |
| 577 | 591 | p->bytes_moved = 0; |
| @@ -599,15 +613,6 @@ static int amdgpu_cs_parser_bos(struct amdgpu_cs_parser *p, · 21 unmodified lines | ||
| 599 | 613 | gws = p->bo_list->gws_obj; |
| 600 | 614 | oa = p->bo_list->oa_obj; |
| 601 | 615 | |
| 602 | − amdgpu_bo_list_for_each_entry(e, p->bo_list) { | |
| 603 | − struct amdgpu_bo *bo = ttm_to_amdgpu_bo(e->tv.bo); | |
| 604 | − | |
| 605 | − /* Make sure we use the exclusive slot for shared BOs */ | |
| 606 | − if (bo->prime_shared_count) | |
| 607 | − e->tv.num_shared = 0; | |
| 608 | − e->bo_va = amdgpu_vm_bo_find(vm, bo); | |
| 609 | − } | |
| 610 | − | |
| 611 | 616 | if (gds) { |
| 612 | 617 | p->job->gds_base = amdgpu_bo_gpu_offset(gds) >> PAGE_SHIFT; |
| 613 | 618 | p->job->gds_size = amdgpu_bo_size(gds) >> PAGE_SHIFT; |
| @@ -629,8 +634,13 @@ static int amdgpu_cs_parser_bos(struct amdgpu_cs_parser *p, · 15 unmodified lines | ||
| 629 | 634 | } |
| 630 | 635 | |
| 631 | 636 | error_validate: |
| 632 | − if (r) | |
| 637 | + if (r) { | |
| 638 | + amdgpu_bo_list_for_each_entry(e, p->bo_list) { | |
| 639 | + dma_fence_chain_free(e->chain); | |
| 640 | + e->chain = NULL; | |
| 641 | + } | |
| 633 | 642 | ttm_eu_backoff_reservation(&p->ticket, &p->validated); |
| 643 | + } | |
| 634 | 644 | out: |
| 635 | 645 | return r; |
| 636 | 646 | } |
| @@ -670,9 +680,17 @@ static void amdgpu_cs_parser_fini(struct amdgpu_cs_parser *parser, int error, · 33 unmodified lines | ||
| 670 | 680 | { |
| 671 | 681 | unsigned i; |
| 672 | 682 | |
| 673 | − if (error && backoff) | |
| 683 | + if (error && backoff) { | |
| 684 | + struct amdgpu_bo_list_entry *e; | |
| 685 | + | |
| 686 | + amdgpu_bo_list_for_each_entry(e, parser->bo_list) { | |
| 687 | + dma_fence_chain_free(e->chain); | |
| 688 | + e->chain = NULL; | |
| 689 | + } | |
| 690 | + | |
| 674 | 691 | ttm_eu_backoff_reservation(&parser->ticket, |
| 675 | 692 | &parser->validated); |
| 693 | + } | |
| 676 | 694 | |
| 677 | 695 | for (i = 0; i < parser->num_post_deps; i++) { |
| 678 | 696 | drm_syncobj_put(parser->post_deps[i].syncobj); |
| @@ -781,7 +799,7 @@ static int amdgpu_cs_vm_handling(struct amdgpu_cs_parser *p) · 102 unmodified lines | ||
| 781 | 799 | if (r) |
| 782 | 800 | return r; |
| 783 | 801 | |
| 784 | − r = amdgpu_vm_bo_update(adev, fpriv->prt_va, false); | |
| 802 | + r = amdgpu_vm_bo_update(adev, fpriv->prt_va, false, NULL); | |
| 785 | 803 | if (r) |
| 786 | 804 | return r; |
| 787 | 805 | |
| @@ -792,7 +810,7 @@ static int amdgpu_cs_vm_handling(struct amdgpu_cs_parser *p) · 4 unmodified lines | ||
| 792 | 810 | if (amdgpu_mcbp || amdgpu_sriov_vf(adev)) { |
| 793 | 811 | bo_va = fpriv->csa_va; |
| 794 | 812 | BUG_ON(!bo_va); |
| 795 | − r = amdgpu_vm_bo_update(adev, bo_va, false); | |
| 813 | + r = amdgpu_vm_bo_update(adev, bo_va, false, NULL); | |
| 796 | 814 | if (r) |
| 797 | 815 | return r; |
| 798 | 816 | |
| @@ -811,7 +829,7 @@ static int amdgpu_cs_vm_handling(struct amdgpu_cs_parser *p) · 12 unmodified lines | ||
| 811 | 829 | if (bo_va == NULL) |
| 812 | 830 | continue; |
| 813 | 831 | |
| 814 | − r = amdgpu_vm_bo_update(adev, bo_va, false); | |
| 832 | + r = amdgpu_vm_bo_update(adev, bo_va, false, NULL); | |
| 815 | 833 | if (r) |
| 816 | 834 | return r; |
| 817 | 835 | |
| @@ -1109,7 +1127,7 @@ static int amdgpu_cs_process_syncobj_timeline_out_dep(struct amdgpu_cs_parser *p · 291 unmodified lines | ||
| 1109 | 1127 | |
| 1110 | 1128 | dep->chain = NULL; |
| 1111 | 1129 | if (syncobj_deps[i].point) { |
| 1112 | − dep->chain = kmalloc(sizeof(*dep->chain), GFP_KERNEL); | |
| 1130 | + dep->chain = dma_fence_chain_alloc(); | |
| 1113 | 1131 | if (!dep->chain) |
| 1114 | 1132 | return -ENOMEM; |
| 1115 | 1133 | } |
| @@ -1117,7 +1135,7 @@ static int amdgpu_cs_process_syncobj_timeline_out_dep(struct amdgpu_cs_parser *p · 1 unmodified line | ||
| 1117 | 1135 | dep->syncobj = drm_syncobj_find(p->filp, |
| 1118 | 1136 | syncobj_deps[i].handle); |
| 1119 | 1137 | if (!dep->syncobj) { |
| 1120 | − kfree(dep->chain); | |
| 1138 | + dma_fence_chain_free(dep->chain); | |
| 1121 | 1139 | return -EINVAL; |
| 1122 | 1140 | } |
| 1123 | 1141 | dep->point = syncobj_deps[i].point; |
| @@ -1245,6 +1263,28 @@ static int amdgpu_cs_submit(struct amdgpu_cs_parser *p, · 121 unmodified lines | ||
| 1245 | 1263 | |
| 1246 | 1264 | amdgpu_vm_move_to_lru_tail(p->adev, &fpriv->vm); |
| 1247 | 1265 | |
| 1266 | + amdgpu_bo_list_for_each_entry(e, p->bo_list) { | |
| 1267 | + struct dma_resv *resv = e->tv.bo->base.resv; | |
| 1268 | + struct dma_fence_chain *chain = e->chain; | |
| 1269 | + | |
| 1270 | + if (!chain) | |
| 1271 | + continue; | |
| 1272 | + | |
| 1273 | + /* | |
| 1274 | + * Work around dma_resv shortcommings by wrapping up the | |
| 1275 | + * submission in a dma_fence_chain and add it as exclusive | |
| 1276 | + * fence, but first add the submission as shared fence to make | |
| 1277 | + * sure that shared fences never signal before the exclusive | |
| 1278 | + * one. | |
| 1279 | + */ | |
| 1280 | + dma_fence_chain_init(chain, dma_resv_excl_fence(resv), | |
| 1281 | + dma_fence_get(p->fence), 1); | |
| 1282 | + | |
| 1283 | + dma_resv_add_shared_fence(resv, p->fence); | |
| 1284 | + rcu_assign_pointer(resv->fence_excl, &chain->base); | |
| 1285 | + e->chain = NULL; | |
| 1286 | + } | |
| 1287 | + | |
| 1248 | 1288 | ttm_eu_fence_buffer_objects(&p->ticket, &p->validated, p->fence); |
| 1249 | 1289 | mutex_unlock(&p->adev->notifier_lock); |
| 1250 | 1290 | |
| @@ -1414,7 +1414,7 @@ no_preempt: · 1413 unmodified lines | ||
| 1414 | 1414 | continue; |
| 1415 | 1415 | } |
| 1416 | 1416 | job = to_amdgpu_job(s_job); |
| 1417 | − if (preempted && job->fence == fence) | |
| 1417 | + if (preempted && (&job->hw_fence) == fence) | |
| 1418 | 1418 | /* mark the job as preempted */ |
| 1419 | 1419 | job->preemption_status |= AMDGPU_IB_PREEMPTED; |
| 1420 | 1420 | } |
| @@ -116,6 +116,7 @@ const char *amdgpu_asic_name[] = { · 115 unmodified lines | ||
| 116 | 116 | "RENOIR", |
| 117 | 117 | "ALDEBARAN", |
| 118 | 118 | "NAVI10", |
| 119 | + "CYAN_SKILLFISH", | |
| 119 | 120 | "NAVI14", |
| 120 | 121 | "NAVI12", |
| 121 | 122 | "SIENNA_CICHLID", |
| @@ -287,7 +288,7 @@ bool amdgpu_device_supports_smart_shift(struct drm_device *dev) · 165 unmodified lines | ||
| 287 | 288 | */ |
| 288 | 289 | |
| 289 | 290 | /** |
| 290 | − * amdgpu_device_vram_access - read/write a buffer in vram | |
| 291 | + * amdgpu_device_mm_access - access vram by MM_INDEX/MM_DATA | |
| 291 | 292 | * |
| 292 | 293 | * @adev: amdgpu_device pointer |
| 293 | 294 | * @pos: offset of the buffer in vram |
| @@ -295,22 +296,65 @@ bool amdgpu_device_supports_smart_shift(struct drm_device *dev) · 1 unmodified line | ||
| 295 | 296 | * @size: read/write size, sizeof(@buf) must > @size |
| 296 | 297 | * @write: true - write to vram, otherwise - read from vram |
| 297 | 298 | */ |
| 298 | −void amdgpu_device_vram_access(struct amdgpu_device *adev, loff_t pos, | |
| 299 | − uint32_t *buf, size_t size, bool write) | |
| 299 | +void amdgpu_device_mm_access(struct amdgpu_device *adev, loff_t pos, | |
| 300 | + void *buf, size_t size, bool write) | |
| 300 | 301 | { |
| 301 | 302 | unsigned long flags; |
| 302 | − uint32_t hi = ~0; | |
| 303 | + uint32_t hi = ~0, tmp = 0; | |
| 304 | + uint32_t *data = buf; | |
| 303 | 305 | uint64_t last; |
| 304 | 306 | int idx; |
| 305 | 307 | |
| 306 | 308 | if (!drm_dev_enter(&adev->ddev, &idx)) |
| 307 | 309 | return; |
| 308 | 310 | |
| 311 | + BUG_ON(!IS_ALIGNED(pos, 4) || !IS_ALIGNED(size, 4)); | |
| 312 | + | |
| 313 | + spin_lock_irqsave(&adev->mmio_idx_lock, flags); | |
| 314 | + for (last = pos + size; pos < last; pos += 4) { | |
| 315 | + tmp = pos >> 31; | |
| 316 | + | |
| 317 | + WREG32_NO_KIQ(mmMM_INDEX, ((uint32_t)pos) | 0x80000000); | |
| 318 | + if (tmp != hi) { | |
| 319 | + WREG32_NO_KIQ(mmMM_INDEX_HI, tmp); | |
| 320 | + hi = tmp; | |
| 321 | + } | |
| 322 | + if (write) | |
| 323 | + WREG32_NO_KIQ(mmMM_DATA, *data++); | |
| 324 | + else | |
| 325 | + *data++ = RREG32_NO_KIQ(mmMM_DATA); | |
| 326 | + } | |
| 327 | + | |
| 328 | + spin_unlock_irqrestore(&adev->mmio_idx_lock, flags); | |
| 329 | + drm_dev_exit(idx); | |
| 330 | +} | |
| 331 | + | |
| 332 | +/** | |
| 333 | + * amdgpu_device_vram_access - access vram by vram aperature | |
| 334 | + * | |
| 335 | + * @adev: amdgpu_device pointer | |
| 336 | + * @pos: offset of the buffer in vram | |
| 337 | + * @buf: virtual address of the buffer in system memory | |
| 338 | + * @size: read/write size, sizeof(@buf) must > @size | |
| 339 | + * @write: true - write to vram, otherwise - read from vram | |
| 340 | + * | |
| 341 | + * The return value means how many bytes have been transferred. | |
| 342 | + */ | |
| 343 | +size_t amdgpu_device_aper_access(struct amdgpu_device *adev, loff_t pos, | |
| 344 | + void *buf, size_t size, bool write) | |
| 345 | +{ | |
| 309 | 346 | #ifdef CONFIG_64BIT |
| 347 | + void __iomem *addr; | |
| 348 | + size_t count = 0; | |
| 349 | + uint64_t last; | |
| 350 | + | |
| 351 | + if (!adev->mman.aper_base_kaddr) | |
| 352 | + return 0; | |
| 353 | + | |
| 310 | 354 | last = min(pos + size, adev->gmc.visible_vram_size); |
| 311 | 355 | if (last > pos) { |
| 312 | − void __iomem *addr = adev->mman.aper_base_kaddr + pos; | |
| 313 | − size_t count = last - pos; | |
| 356 | + addr = adev->mman.aper_base_kaddr + pos; | |
| 357 | + count = last - pos; | |
| 314 | 358 | |
| 315 | 359 | if (write) { |
| 316 | 360 | memcpy_toio(addr, buf, count); |
| @@ -322,35 +366,37 @@ void amdgpu_device_vram_access(struct amdgpu_device *adev, loff_t pos, · 5 unmodified lines | ||
| 322 | 366 | memcpy_fromio(buf, addr, count); |
| 323 | 367 | } |
| 324 | 368 | |
| 325 | − if (count == size) | |
| 326 | − goto exit; | |
| 327 | − | |
| 328 | − pos += count; | |
| 329 | − buf += count / 4; | |
| 330 | − size -= count; | |
| 331 | 369 | } |
| 370 | + | |
| 371 | + return count; | |
| 372 | +#else | |
| 373 | + return 0; | |
| 332 | 374 | #endif |
| 375 | +} | |
| 333 | 376 | |
| 334 | − spin_lock_irqsave(&adev->mmio_idx_lock, flags); | |
| 335 | − for (last = pos + size; pos < last; pos += 4) { | |
| 336 | − uint32_t tmp = pos >> 31; | |
| 377 | +/** | |
| 378 | + * amdgpu_device_vram_access - read/write a buffer in vram | |
| 379 | + * | |
| 380 | + * @adev: amdgpu_device pointer | |
| 381 | + * @pos: offset of the buffer in vram | |
| 382 | + * @buf: virtual address of the buffer in system memory | |
| 383 | + * @size: read/write size, sizeof(@buf) must > @size | |
| 384 | + * @write: true - write to vram, otherwise - read from vram | |
| 385 | + */ | |
| 386 | +void amdgpu_device_vram_access(struct amdgpu_device *adev, loff_t pos, | |
| 387 | + void *buf, size_t size, bool write) | |
| 388 | +{ | |
| 389 | + size_t count; | |
| 337 | 390 | |
| 338 | − WREG32_NO_KIQ(mmMM_INDEX, ((uint32_t)pos) | 0x80000000); | |
| 339 | − if (tmp != hi) { | |
| 340 | − WREG32_NO_KIQ(mmMM_INDEX_HI, tmp); | |
| 341 | − hi = tmp; | |
| 342 | − } | |
| 343 | − if (write) | |
| 344 | − WREG32_NO_KIQ(mmMM_DATA, *buf++); | |
| 345 | − else | |
| 346 | − *buf++ = RREG32_NO_KIQ(mmMM_DATA); | |
| 391 | + /* try to using vram apreature to access vram first */ | |
| 392 | + count = amdgpu_device_aper_access(adev, pos, buf, size, write); | |
| 393 | + size -= count; | |
| 394 | + if (size) { | |
| 395 | + /* using MM to access rest vram */ | |
| 396 | + pos += count; | |
| 397 | + buf += count; | |
| 398 | + amdgpu_device_mm_access(adev, pos, buf, size, write); | |
| 347 | 399 | } |
| 348 | − spin_unlock_irqrestore(&adev->mmio_idx_lock, flags); | |
| 349 | − | |
| 350 | −#ifdef CONFIG_64BIT | |
| 351 | −exit: | |
| 352 | −#endif | |
| 353 | − drm_dev_exit(idx); | |
| 354 | 400 | } |
| 355 | 401 | |
| 356 | 402 | /* |
| @@ -518,7 +564,7 @@ void amdgpu_mm_wreg_mmio_rlc(struct amdgpu_device *adev, · 161 unmodified lines | ||
| 518 | 564 | adev->gfx.rlc.funcs && |
| 519 | 565 | adev->gfx.rlc.funcs->is_rlcg_access_range) { |
| 520 | 566 | if (adev->gfx.rlc.funcs->is_rlcg_access_range(adev, reg)) |
| 521 | − return adev->gfx.rlc.funcs->rlcg_wreg(adev, reg, v, 0, 0); | |
| 567 | + return adev->gfx.rlc.funcs->sriov_wreg(adev, reg, v, 0, 0); | |
| 522 | 568 | } else { |
| 523 | 569 | writel(v, ((void __iomem *)adev->rmmio) + (reg * 4)); |
| 524 | 570 | } |
| @@ -1266,15 +1312,16 @@ bool amdgpu_device_need_post(struct amdgpu_device *adev) · 741 unmodified lines | ||
| 1266 | 1312 | /** |
| 1267 | 1313 | * amdgpu_device_vga_set_decode - enable/disable vga decode |
| 1268 | 1314 | * |
| 1269 | − * @cookie: amdgpu_device pointer | |
| 1315 | + * @pdev: PCI device pointer | |
| 1270 | 1316 | * @state: enable/disable vga decode |
| 1271 | 1317 | * |
| 1272 | 1318 | * Enable/disable vga decode (all asics). |
| 1273 | 1319 | * Returns VGA resource flags. |
| 1274 | 1320 | */ |
| 1275 | −static unsigned int amdgpu_device_vga_set_decode(void *cookie, bool state) | |
| 1321 | +static unsigned int amdgpu_device_vga_set_decode(struct pci_dev *pdev, | |
| 1322 | + bool state) | |
| 1276 | 1323 | { |
| 1277 | − struct amdgpu_device *adev = cookie; | |
| 1324 | + struct amdgpu_device *adev = drm_to_adev(pci_get_drvdata(pdev)); | |
| 1278 | 1325 | amdgpu_asic_set_vga_state(adev, state); |
| 1279 | 1326 | if (state) |
| 1280 | 1327 | return VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM | |
| @@ -1394,6 +1441,10 @@ static int amdgpu_device_init_apu_flags(struct amdgpu_device *adev) · 113 unmodified lines | ||
| 1394 | 1441 | break; |
| 1395 | 1442 | case CHIP_YELLOW_CARP: |
| 1396 | 1443 | break; |
| 1444 | + case CHIP_CYAN_SKILLFISH: | |
| 1445 | + if (adev->pdev->device == 0x13FE) | |
| 1446 | + adev->apu_flags |= AMD_APU_IS_CYAN_SKILLFISH2; | |
| 1447 | + break; | |
| 1397 | 1448 | default: |
| 1398 | 1449 | return -EINVAL; |
| 1399 | 1450 | } |
| @@ -2100,6 +2151,7 @@ static int amdgpu_device_ip_early_init(struct amdgpu_device *adev) · 700 unmodified lines | ||
| 2100 | 2151 | case CHIP_BEIGE_GOBY: |
| 2101 | 2152 | case CHIP_VANGOGH: |
| 2102 | 2153 | case CHIP_YELLOW_CARP: |
| 2154 | + case CHIP_CYAN_SKILLFISH: | |
| 2103 | 2155 | if (adev->asic_type == CHIP_VANGOGH) |
| 2104 | 2156 | adev->family = AMDGPU_FAMILY_VGH; |
| 2105 | 2157 | else if (adev->asic_type == CHIP_YELLOW_CARP) |
| @@ -3594,9 +3646,9 @@ int amdgpu_device_init(struct amdgpu_device *adev, · 1488 unmodified lines | ||
| 3594 | 3646 | |
| 3595 | 3647 | fence_driver_init: |
| 3596 | 3648 | /* Fence driver */ |
| 3597 | − r = amdgpu_fence_driver_init(adev); | |
| 3649 | + r = amdgpu_fence_driver_sw_init(adev); | |
| 3598 | 3650 | if (r) { |
| 3599 | − dev_err(adev->dev, "amdgpu_fence_driver_init failed\n"); | |
| 3651 | + dev_err(adev->dev, "amdgpu_fence_driver_sw_init failed\n"); | |
| 3600 | 3652 | amdgpu_vf_error_put(adev, AMDGIM_ERROR_VF_FENCE_INIT_FAIL, 0, 0); |
| 3601 | 3653 | goto failed; |
| 3602 | 3654 | } |
| @@ -3623,6 +3675,8 @@ fence_driver_init: · 20 unmodified lines | ||
| 3623 | 3675 | goto release_ras_con; |
| 3624 | 3676 | } |
| 3625 | 3677 | |
| 3678 | + amdgpu_fence_driver_hw_init(adev); | |
| 3679 | + | |
| 3626 | 3680 | dev_info(adev->dev, |
| 3627 | 3681 | "SE %d, SH per SE %d, CU per SH %d, active_cu_number %d\n", |
| 3628 | 3682 | adev->gfx.config.max_shader_engines, |
| @@ -3714,7 +3768,7 @@ fence_driver_init: · 85 unmodified lines | ||
| 3714 | 3768 | /* this will fail for cards that aren't VGA class devices, just |
| 3715 | 3769 | * ignore it */ |
| 3716 | 3770 | if ((adev->pdev->class >> 8) == PCI_CLASS_DISPLAY_VGA) |
| 3717 | − vga_client_register(adev->pdev, adev, NULL, amdgpu_device_vga_set_decode); | |
| 3771 | + vga_client_register(adev->pdev, amdgpu_device_vga_set_decode); | |
| 3718 | 3772 | |
| 3719 | 3773 | if (amdgpu_device_supports_px(ddev)) { |
| 3720 | 3774 | px = true; |
| @@ -3771,7 +3825,10 @@ void amdgpu_device_fini_hw(struct amdgpu_device *adev) · 50 unmodified lines | ||
| 3771 | 3825 | { |
| 3772 | 3826 | dev_info(adev->dev, "amdgpu: finishing device.\n"); |
| 3773 | 3827 | flush_delayed_work(&adev->delayed_init_work); |
| 3774 | − ttm_bo_lock_delayed_workqueue(&adev->mman.bdev); | |
| 3828 | + if (adev->mman.initialized) { | |
| 3829 | + flush_delayed_work(&adev->mman.bdev.wq); | |
| 3830 | + ttm_bo_lock_delayed_workqueue(&adev->mman.bdev); | |
| 3831 | + } | |
| 3775 | 3832 | adev->shutdown = true; |
| 3776 | 3833 | |
| 3777 | 3834 | /* make sure IB test finished before entering exclusive mode |
| @@ -3790,7 +3847,7 @@ void amdgpu_device_fini_hw(struct amdgpu_device *adev) · 12 unmodified lines | ||
| 3790 | 3847 | else |
| 3791 | 3848 | drm_atomic_helper_shutdown(adev_to_drm(adev)); |
| 3792 | 3849 | } |
| 3793 | − amdgpu_fence_driver_fini_hw(adev); | |
| 3850 | + amdgpu_fence_driver_hw_fini(adev); | |
| 3794 | 3851 | |
| 3795 | 3852 | if (adev->pm_sysfs_en) |
| 3796 | 3853 | amdgpu_pm_sysfs_fini(adev); |
| @@ -3812,7 +3869,7 @@ void amdgpu_device_fini_hw(struct amdgpu_device *adev) · 15 unmodified lines | ||
| 3812 | 3869 | void amdgpu_device_fini_sw(struct amdgpu_device *adev) |
| 3813 | 3870 | { |
| 3814 | 3871 | amdgpu_device_ip_fini(adev); |
| 3815 | − amdgpu_fence_driver_fini_sw(adev); | |
| 3872 | + amdgpu_fence_driver_sw_fini(adev); | |
| 3816 | 3873 | release_firmware(adev->firmware.gpu_info_fw); |
| 3817 | 3874 | adev->firmware.gpu_info_fw = NULL; |
| 3818 | 3875 | adev->accel_working = false; |
| @@ -3833,7 +3890,7 @@ void amdgpu_device_fini_sw(struct amdgpu_device *adev) · 14 unmodified lines | ||
| 3833 | 3890 | vga_switcheroo_fini_domain_pm_ops(adev->dev); |
| 3834 | 3891 | } |
| 3835 | 3892 | if ((adev->pdev->class >> 8) == PCI_CLASS_DISPLAY_VGA) |
| 3836 | − vga_client_register(adev->pdev, NULL, NULL, NULL); | |
| 3893 | + vga_client_unregister(adev->pdev); | |
| 3837 | 3894 | |
| 3838 | 3895 | if (IS_ENABLED(CONFIG_PERF_EVENTS)) |
| 3839 | 3896 | amdgpu_pmu_fini(adev); |
| @@ -3887,7 +3944,7 @@ int amdgpu_device_suspend(struct drm_device *dev, bool fbcon) · 47 unmodified lines | ||
| 3887 | 3944 | /* evict vram memory */ |
| 3888 | 3945 | amdgpu_bo_evict_vram(adev); |
| 3889 | 3946 | |
| 3890 | − amdgpu_fence_driver_suspend(adev); | |
| 3947 | + amdgpu_fence_driver_hw_fini(adev); | |
| 3891 | 3948 | |
| 3892 | 3949 | amdgpu_device_ip_suspend_phase2(adev); |
| 3893 | 3950 | /* evict remaining vram memory |
| @@ -3932,8 +3989,7 @@ int amdgpu_device_resume(struct drm_device *dev, bool fbcon) · 38 unmodified lines | ||
| 3932 | 3989 | dev_err(adev->dev, "amdgpu_device_ip_resume failed (%d).\n", r); |
| 3933 | 3990 | return r; |
| 3934 | 3991 | } |
| 3935 | − amdgpu_fence_driver_resume(adev); | |
| 3936 | − | |
| 3992 | + amdgpu_fence_driver_hw_init(adev); | |
| 3937 | 3993 | |
| 3938 | 3994 | r = amdgpu_device_ip_late_init(adev); |
| 3939 | 3995 | if (r) |
| @@ -4394,7 +4450,7 @@ int amdgpu_device_mode1_reset(struct amdgpu_device *adev) · 454 unmodified lines | ||
| 4394 | 4450 | int amdgpu_device_pre_asic_reset(struct amdgpu_device *adev, |
| 4395 | 4451 | struct amdgpu_reset_context *reset_context) |
| 4396 | 4452 | { |
| 4397 | − int i, r = 0; | |
| 4453 | + int i, j, r = 0; | |
| 4398 | 4454 | struct amdgpu_job *job = NULL; |
| 4399 | 4455 | bool need_full_reset = |
| 4400 | 4456 | test_bit(AMDGPU_NEED_FULL_RESET, &reset_context->flags); |
| @@ -4418,11 +4474,22 @@ int amdgpu_device_pre_asic_reset(struct amdgpu_device *adev, · 17 unmodified lines | ||
| 4418 | 4474 | if (!ring || !ring->sched.thread) |
| 4419 | 4475 | continue; |
| 4420 | 4476 | |
| 4477 | + /*clear job fence from fence drv to avoid force_completion | |
| 4478 | + *leave NULL and vm flush fence in fence drv */ | |
| 4479 | + for (j = 0; j <= ring->fence_drv.num_fences_mask; j++) { | |
| 4480 | + struct dma_fence *old, **ptr; | |
| 4481 | + | |
| 4482 | + ptr = &ring->fence_drv.fences[j]; | |
| 4483 | + old = rcu_dereference_protected(*ptr, 1); | |
| 4484 | + if (old && test_bit(AMDGPU_FENCE_FLAG_EMBED_IN_JOB_BIT, &old->flags)) { | |
| 4485 | + RCU_INIT_POINTER(*ptr, NULL); | |
| 4486 | + } | |
| 4487 | + } | |
| 4421 | 4488 | /* after all hw jobs are reset, hw fence is meaningless, so force_completion */ |
| 4422 | 4489 | amdgpu_fence_driver_force_completion(ring); |
| 4423 | 4490 | } |
| 4424 | 4491 | |
| 4425 | − if(job) | |
| 4492 | + if (job && job->vm) | |
| 4426 | 4493 | drm_sched_increase_karma(&job->base); |
| 4427 | 4494 | |
| 4428 | 4495 | r = amdgpu_reset_prepare_hwcontext(adev, reset_context); |
| @@ -4886,7 +4953,7 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev, · 457 unmodified lines | ||
| 4886 | 4953 | DRM_INFO("Bailing on TDR for s_job:%llx, hive: %llx as another already in progress", |
| 4887 | 4954 | job ? job->base.id : -1, hive->hive_id); |
| 4888 | 4955 | amdgpu_put_xgmi_hive(hive); |
| 4889 | − if (job) | |
| 4956 | + if (job && job->vm) | |
| 4890 | 4957 | drm_sched_increase_karma(&job->base); |
| 4891 | 4958 | return 0; |
| 4892 | 4959 | } |
| @@ -4910,7 +4977,7 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev, · 17 unmodified lines | ||
| 4910 | 4977 | job ? job->base.id : -1); |
| 4911 | 4978 | |
| 4912 | 4979 | /* even we skipped this reset, still need to set the job to guilty */ |
| 4913 | − if (job) | |
| 4980 | + if (job && job->vm) | |
| 4914 | 4981 | drm_sched_increase_karma(&job->base); |
| 4915 | 4982 | goto skip_recovery; |
| 4916 | 4983 | } |
| @@ -5277,6 +5344,10 @@ int amdgpu_device_baco_exit(struct drm_device *dev) · 360 unmodified lines | ||
| 5277 | 5344 | adev->nbio.funcs->enable_doorbell_interrupt) |
| 5278 | 5345 | adev->nbio.funcs->enable_doorbell_interrupt(adev, true); |
| 5279 | 5346 | |
| 5347 | + if (amdgpu_passthrough(adev) && | |
| 5348 | + adev->nbio.funcs->clear_doorbell_interrupt) | |
| 5349 | + adev->nbio.funcs->clear_doorbell_interrupt(adev); | |
| 5350 | + | |
| 5280 | 5351 | return 0; |
| 5281 | 5352 | } |
| 5282 | 5353 | |
| @@ -42,48 +42,6 @@ · 41 unmodified lines | ||
| 42 | 42 | #include <linux/pci-p2pdma.h> |
| 43 | 43 | #include <linux/pm_runtime.h> |
| 44 | 44 | |
| 45 | −static int | |
| 46 | −__dma_resv_make_exclusive(struct dma_resv *obj) | |
| 47 | −{ | |
| 48 | − struct dma_fence **fences; | |
| 49 | − unsigned int count; | |
| 50 | − int r; | |
| 51 | − | |
| 52 | − if (!dma_resv_shared_list(obj)) /* no shared fences to convert */ | |
| 53 | − return 0; | |
| 54 | − | |
| 55 | − r = dma_resv_get_fences(obj, NULL, &count, &fences); | |
| 56 | − if (r) | |
| 57 | − return r; | |
| 58 | − | |
| 59 | − if (count == 0) { | |
| 60 | − /* Now that was unexpected. */ | |
| 61 | − } else if (count == 1) { | |
| 62 | − dma_resv_add_excl_fence(obj, fences[0]); | |
| 63 | − dma_fence_put(fences[0]); | |
| 64 | − kfree(fences); | |
| 65 | − } else { | |
| 66 | − struct dma_fence_array *array; | |
| 67 | − | |
| 68 | − array = dma_fence_array_create(count, fences, | |
| 69 | − dma_fence_context_alloc(1), 0, | |
| 70 | − false); | |
| 71 | − if (!array) | |
| 72 | − goto err_fences_put; | |
| 73 | − | |
| 74 | − dma_resv_add_excl_fence(obj, &array->base); | |
| 75 | − dma_fence_put(&array->base); | |
| 76 | − } | |
| 77 | − | |
| 78 | − return 0; | |
| 79 | − | |
| 80 | −err_fences_put: | |
| 81 | − while (count--) | |
| 82 | − dma_fence_put(fences[count]); | |
| 83 | − kfree(fences); | |
| 84 | − return -ENOMEM; | |
| 85 | −} | |
| 86 | − | |
| 87 | 45 | /** |
| 88 | 46 | * amdgpu_dma_buf_attach - &dma_buf_ops.attach implementation |
| 89 | 47 | * |
| @@ -110,24 +68,6 @@ static int amdgpu_dma_buf_attach(struct dma_buf *dmabuf, · 20 unmodified lines | ||
| 110 | 68 | if (r < 0) |
| 111 | 69 | goto out; |
| 112 | 70 | |
| 113 | − r = amdgpu_bo_reserve(bo, false); | |
| 114 | − if (unlikely(r != 0)) | |
| 115 | − goto out; | |
| 116 | − | |
| 117 | − /* | |
| 118 | − * We only create shared fences for internal use, but importers | |
| 119 | − * of the dmabuf rely on exclusive fences for implicitly | |
| 120 | − * tracking write hazards. As any of the current fences may | |
| 121 | − * correspond to a write, we need to convert all existing | |
| 122 | − * fences on the reservation object into a single exclusive | |
| 123 | − * fence. | |
| 124 | − */ | |
| 125 | − r = __dma_resv_make_exclusive(bo->tbo.base.resv); | |
| 126 | − if (r) | |
| 127 | − goto out; | |
| 128 | − | |
| 129 | − bo->prime_shared_count++; | |
| 130 | − amdgpu_bo_unreserve(bo); | |
| 131 | 71 | return 0; |
| 132 | 72 | |
| 133 | 73 | out: |
| @@ -150,9 +90,6 @@ static void amdgpu_dma_buf_detach(struct dma_buf *dmabuf, · 16 unmodified lines | ||
| 150 | 90 | struct amdgpu_bo *bo = gem_to_amdgpu_bo(obj); |
| 151 | 91 | struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev); |
| 152 | 92 | |
| 153 | − if (attach->dev->driver != adev->dev->driver && bo->prime_shared_count) | |
| 154 | − bo->prime_shared_count--; | |
| 155 | − | |
| 156 | 93 | pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); |
| 157 | 94 | pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); |
| 158 | 95 | } |
| @@ -418,8 +355,6 @@ amdgpu_dma_buf_create_obj(struct drm_device *dev, struct dma_buf *dma_buf) · 259 unmodified lines | ||
| 418 | 355 | bo = gem_to_amdgpu_bo(gobj); |
| 419 | 356 | bo->allowed_domains = AMDGPU_GEM_DOMAIN_GTT; |
| 420 | 357 | bo->preferred_domains = AMDGPU_GEM_DOMAIN_GTT; |
| 421 | − if (dma_buf->ops != &amdgpu_dmabuf_ops) | |
| 422 | − bo->prime_shared_count = 1; | |
| 423 | 358 | |
| 424 | 359 | dma_resv_unlock(resv); |
| 425 | 360 | return gobj; |
| @@ -870,11 +870,10 @@ MODULE_PARM_DESC(reset_method, "GPU reset method (-1 = auto (default), 0 = legac · 869 unmodified lines | ||
| 870 | 870 | module_param_named(reset_method, amdgpu_reset_method, int, 0444); |
| 871 | 871 | |
| 872 | 872 | /** |
| 873 | − * DOC: bad_page_threshold (int) | |
| 874 | − * Bad page threshold is to specify the threshold value of faulty pages | |
| 875 | − * detected by RAS ECC, that may result in GPU entering bad status if total | |
| 876 | − * faulty pages by ECC exceed threshold value and leave it for user's further | |
| 877 | − * check. | |
| 873 | + * DOC: bad_page_threshold (int) Bad page threshold is specifies the | |
| 874 | + * threshold value of faulty pages detected by RAS ECC, which may | |
| 875 | + * result in the GPU entering bad status when the number of total | |
| 876 | + * faulty pages by ECC exceeds the threshold value. | |
| 878 | 877 | */ |
| 879 | 878 | MODULE_PARM_DESC(bad_page_threshold, "Bad page threshold(-1 = auto(default value), 0 = disable bad page retirement)"); |
| 880 | 879 | module_param_named(bad_page_threshold, amdgpu_bad_page_threshold, int, 0444); |
| @@ -1213,6 +1212,9 @@ static const struct pci_device_id pciidlist[] = { · 332 unmodified lines | ||
| 1213 | 1212 | {0x1002, 0x740F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ALDEBARAN|AMD_EXP_HW_SUPPORT}, |
| 1214 | 1213 | {0x1002, 0x7410, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ALDEBARAN|AMD_EXP_HW_SUPPORT}, |
| 1215 | 1214 | |
| 1215 | + /* CYAN_SKILLFISH */ | |
| 1216 | + {0x1002, 0x13FE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CYAN_SKILLFISH|AMD_IS_APU}, | |
| 1217 | + | |
| 1216 | 1218 | /* BEIGE_GOBY */ |
| 1217 | 1219 | {0x1002, 0x7420, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BEIGE_GOBY}, |
| 1218 | 1220 | {0x1002, 0x7421, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BEIGE_GOBY}, |
| @@ -1236,7 +1238,7 @@ static int amdgpu_pci_probe(struct pci_dev *pdev, · 17 unmodified lines | ||
| 1236 | 1238 | int ret, retry = 0; |
| 1237 | 1239 | bool supports_atomic = false; |
| 1238 | 1240 | |
| 1239 | − if (!amdgpu_virtual_display && | |
| 1241 | + if (amdgpu_virtual_display || | |
| 1240 | 1242 | amdgpu_device_asic_has_dc_support(flags & AMD_ASIC_MASK)) |
| 1241 | 1243 | supports_atomic = true; |
| 1242 | 1244 | |
| @@ -1292,7 +1294,7 @@ static int amdgpu_pci_probe(struct pci_dev *pdev, · 49 unmodified lines | ||
| 1292 | 1294 | #endif |
| 1293 | 1295 | |
| 1294 | 1296 | /* Get rid of things like offb */ |
| 1295 | − ret = drm_aperture_remove_conflicting_pci_framebuffers(pdev, "amdgpudrmfb"); | |
| 1297 | + ret = drm_aperture_remove_conflicting_pci_framebuffers(pdev, &amdgpu_kms_driver); | |
| 1296 | 1298 | if (ret) |
| 1297 | 1299 | return ret; |
| 1298 | 1300 | |
| @@ -1474,7 +1476,7 @@ static int amdgpu_pmops_suspend(struct device *dev) · 175 unmodified lines | ||
| 1474 | 1476 | struct amdgpu_device *adev = drm_to_adev(drm_dev); |
| 1475 | 1477 | int r; |
| 1476 | 1478 | |
| 1477 | − if (amdgpu_acpi_is_s0ix_supported(adev)) | |
| 1479 | + if (amdgpu_acpi_is_s0ix_active(adev)) | |
| 1478 | 1480 | adev->in_s0ix = true; |
| 1479 | 1481 | adev->in_s3 = true; |
| 1480 | 1482 | r = amdgpu_device_suspend(drm_dev, true); |
| @@ -1490,7 +1492,7 @@ static int amdgpu_pmops_resume(struct device *dev) · 9 unmodified lines | ||
| 1490 | 1492 | int r; |
| 1491 | 1493 | |
| 1492 | 1494 | r = amdgpu_device_resume(drm_dev, true); |
| 1493 | − if (amdgpu_acpi_is_s0ix_supported(adev)) | |
| 1495 | + if (amdgpu_acpi_is_s0ix_active(adev)) | |
| 1494 | 1496 | adev->in_s0ix = false; |
| 1495 | 1497 | return r; |
| 1496 | 1498 | } |
| @@ -1784,7 +1786,6 @@ static const struct drm_driver amdgpu_kms_driver = { · 287 unmodified lines | ||
| 1784 | 1786 | .open = amdgpu_driver_open_kms, |
| 1785 | 1787 | .postclose = amdgpu_driver_postclose_kms, |
| 1786 | 1788 | .lastclose = amdgpu_driver_lastclose_kms, |
| 1787 | − .irq_handler = amdgpu_irq_handler, | |
| 1788 | 1789 | .ioctls = amdgpu_ioctls_kms, |
| 1789 | 1790 | .num_ioctls = ARRAY_SIZE(amdgpu_ioctls_kms), |
| 1790 | 1791 | .dumb_create = amdgpu_mode_dumb_create, |
| @@ -0,0 +1,239 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright 2021 Advanced Micro Devices, Inc. | |
| 3 | + * | |
| 4 | + * Permission is hereby granted, free of charge, to any person obtaining a | |
| 5 | + * copy of this software and associated documentation files (the "Software"), | |
| 6 | + * to deal in the Software without restriction, including without limitation | |
| 7 | + * the rights to use, copy, modify, merge, publish, distribute, sublicense, | |
| 8 | + * and/or sell copies of the Software, and to permit persons to whom the | |
| 9 | + * Software is furnished to do so, subject to the following conditions: | |
| 10 | + * | |
| 11 | + * The above copyright notice and this permission notice shall be included in | |
| 12 | + * all copies or substantial portions of the Software. | |
| 13 | + * | |
| 14 | + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
| 15 | + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
| 16 | + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |
| 17 | + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR | |
| 18 | + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | |
| 19 | + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | |
| 20 | + * OTHER DEALINGS IN THE SOFTWARE. | |
| 21 | + * | |
| 22 | + */ | |
| 23 | + | |
| 24 | +#include "amdgpu_eeprom.h" | |
| 25 | +#include "amdgpu.h" | |
| 26 | + | |
| 27 | +/* AT24CM02 and M24M02-R have a 256-byte write page size. | |
| 28 | + */ | |
| 29 | +#define EEPROM_PAGE_BITS 8 | |
| 30 | +#define EEPROM_PAGE_SIZE (1U << EEPROM_PAGE_BITS) | |
| 31 | +#define EEPROM_PAGE_MASK (EEPROM_PAGE_SIZE - 1) | |
| 32 | + | |
| 33 | +#define EEPROM_OFFSET_SIZE 2 | |
| 34 | + | |
| 35 | +/* EEPROM memory addresses are 19-bits long, which can | |
| 36 | + * be partitioned into 3, 8, 8 bits, for a total of 19. | |
| 37 | + * The upper 3 bits are sent as part of the 7-bit | |
| 38 | + * "Device Type Identifier"--an I2C concept, which for EEPROM devices | |
| 39 | + * is hard-coded as 1010b, indicating that it is an EEPROM | |
| 40 | + * device--this is the wire format, followed by the upper | |
| 41 | + * 3 bits of the 19-bit address, followed by the direction, | |
| 42 | + * followed by two bytes holding the rest of the 16-bits of | |
| 43 | + * the EEPROM memory address. The format on the wire for EEPROM | |
| 44 | + * devices is: 1010XYZD, A15:A8, A7:A0, | |
| 45 | + * Where D is the direction and sequenced out by the hardware. | |
| 46 | + * Bits XYZ are memory address bits 18, 17 and 16. | |
| 47 | + * These bits are compared to how pins 1-3 of the part are connected, | |
| 48 | + * depending on the size of the part, more on that later. | |
| 49 | + * | |
| 50 | + * Note that of this wire format, a client is in control | |
| 51 | + * of, and needs to specify only XYZ, A15:A8, A7:0, bits, | |
| 52 | + * which is exactly the EEPROM memory address, or offset, | |
| 53 | + * in order to address up to 8 EEPROM devices on the I2C bus. | |
| 54 | + * | |
| 55 | + * For instance, a 2-Mbit I2C EEPROM part, addresses all its bytes, | |
| 56 | + * using an 18-bit address, bit 17 to 0 and thus would use all but one bit of | |
| 57 | + * the 19 bits previously mentioned. The designer would then not connect | |
| 58 | + * pins 1 and 2, and pin 3 usually named "A_2" or "E2", would be connected to | |
| 59 | + * either Vcc or GND. This would allow for up to two 2-Mbit parts on | |
| 60 | + * the same bus, where one would be addressable with bit 18 as 1, and | |
| 61 | + * the other with bit 18 of the address as 0. | |
| 62 | + * | |
| 63 | + * For a 2-Mbit part, bit 18 is usually known as the "Chip Enable" or | |
| 64 | + * "Hardware Address Bit". This bit is compared to the load on pin 3 | |
| 65 | + * of the device, described above, and if there is a match, then this | |
| 66 | + * device responds to the command. This way, you can connect two | |
| 67 | + * 2-Mbit EEPROM devices on the same bus, but see one contiguous | |
| 68 | + * memory from 0 to 7FFFFh, where address 0 to 3FFFF is in the device | |
| 69 | + * whose pin 3 is connected to GND, and address 40000 to 7FFFFh is in | |
| 70 | + * the 2nd device, whose pin 3 is connected to Vcc. | |
| 71 | + * | |
| 72 | + * This addressing you encode in the 32-bit "eeprom_addr" below, | |
| 73 | + * namely the 19-bits "XYZ,A15:A0", as a single 19-bit address. For | |
| 74 | + * instance, eeprom_addr = 0x6DA01, is 110_1101_1010_0000_0001, where | |
| 75 | + * XYZ=110b, and A15:A0=DA01h. The XYZ bits become part of the device | |
| 76 | + * address, and the rest of the address bits are sent as the memory | |
| 77 | + * address bytes. | |
| 78 | + * | |
| 79 | + * That is, for an I2C EEPROM driver everything is controlled by | |
| 80 | + * the "eeprom_addr". | |
| 81 | + * | |
| 82 | + * P.S. If you need to write, lock and read the Identification Page, | |
| 83 | + * (M24M02-DR device only, which we do not use), change the "7" to | |
| 84 | + * "0xF" in the macro below, and let the client set bit 20 to 1 in | |
| 85 | + * "eeprom_addr", and set A10 to 0 to write into it, and A10 and A1 to | |
| 86 | + * 1 to lock it permanently. | |
| 87 | + */ | |
| 88 | +#define MAKE_I2C_ADDR(_aa) ((0xA << 3) | (((_aa) >> 16) & 7)) | |
| 89 | + | |
| 90 | +static int __amdgpu_eeprom_xfer(struct i2c_adapter *i2c_adap, u32 eeprom_addr, | |
| 91 | + u8 *eeprom_buf, u16 buf_size, bool read) | |
| 92 | +{ | |
| 93 | + u8 eeprom_offset_buf[EEPROM_OFFSET_SIZE]; | |
| 94 | + struct i2c_msg msgs[] = { | |
| 95 | + { | |
| 96 | + .flags = 0, | |
| 97 | + .len = EEPROM_OFFSET_SIZE, | |
| 98 | + .buf = eeprom_offset_buf, | |
| 99 | + }, | |
| 100 | + { | |
| 101 | + .flags = read ? I2C_M_RD : 0, | |
| 102 | + }, | |
| 103 | + }; | |
| 104 | + const u8 *p = eeprom_buf; | |
| 105 | + int r; | |
| 106 | + u16 len; | |
| 107 | + | |
| 108 | + for (r = 0; buf_size > 0; | |
| 109 | + buf_size -= len, eeprom_addr += len, eeprom_buf += len) { | |
| 110 | + /* Set the EEPROM address we want to write to/read from. | |
| 111 | + */ | |
| 112 | + msgs[0].addr = MAKE_I2C_ADDR(eeprom_addr); | |
| 113 | + msgs[1].addr = msgs[0].addr; | |
| 114 | + msgs[0].buf[0] = (eeprom_addr >> 8) & 0xff; | |
| 115 | + msgs[0].buf[1] = eeprom_addr & 0xff; | |
| 116 | + | |
| 117 | + if (!read) { | |
| 118 | + /* Write the maximum amount of data, without | |
| 119 | + * crossing the device's page boundary, as per | |
| 120 | + * its spec. Partial page writes are allowed, | |
| 121 | + * starting at any location within the page, | |
| 122 | + * so long as the page boundary isn't crossed | |
| 123 | + * over (actually the page pointer rolls | |
| 124 | + * over). | |
| 125 | + * | |
| 126 | + * As per the AT24CM02 EEPROM spec, after | |
| 127 | + * writing into a page, the I2C driver should | |
| 128 | + * terminate the transfer, i.e. in | |
| 129 | + * "i2c_transfer()" below, with a STOP | |
| 130 | + * condition, so that the self-timed write | |
| 131 | + * cycle begins. This is implied for the | |
| 132 | + * "i2c_transfer()" abstraction. | |
| 133 | + */ | |
| 134 | + len = min(EEPROM_PAGE_SIZE - (eeprom_addr & | |
| 135 | + EEPROM_PAGE_MASK), | |
| 136 | + (u32)buf_size); | |
| 137 | + } else { | |
| 138 | + /* Reading from the EEPROM has no limitation | |
| 139 | + * on the number of bytes read from the EEPROM | |
| 140 | + * device--they are simply sequenced out. | |
| 141 | + */ | |
| 142 | + len = buf_size; | |
| 143 | + } | |
| 144 | + msgs[1].len = len; | |
| 145 | + msgs[1].buf = eeprom_buf; | |
| 146 | + | |
| 147 | + /* This constitutes a START-STOP transaction. | |
| 148 | + */ | |
| 149 | + r = i2c_transfer(i2c_adap, msgs, ARRAY_SIZE(msgs)); | |
| 150 | + if (r != ARRAY_SIZE(msgs)) | |
| 151 | + break; | |
| 152 | + | |
| 153 | + if (!read) { | |
| 154 | + /* According to EEPROM specs the length of the | |
| 155 | + * self-writing cycle, tWR (tW), is 10 ms. | |
| 156 | + * | |
| 157 | + * TODO: Use polling on ACK, aka Acknowledge | |
| 158 | + * Polling, to minimize waiting for the | |
| 159 | + * internal write cycle to complete, as it is | |
| 160 | + * usually smaller than tWR (tW). | |
| 161 | + */ | |
| 162 | + msleep(10); | |
| 163 | + } | |
| 164 | + } | |
| 165 | + | |
| 166 | + return r < 0 ? r : eeprom_buf - p; | |
| 167 | +} | |
| 168 | + | |
| 169 | +/** | |
| 170 | + * amdgpu_eeprom_xfer -- Read/write from/to an I2C EEPROM device | |
| 171 | + * @i2c_adap: pointer to the I2C adapter to use | |
| 172 | + * @eeprom_addr: EEPROM address from which to read/write | |
| 173 | + * @eeprom_buf: pointer to data buffer to read into/write from | |
| 174 | + * @buf_size: the size of @eeprom_buf | |
| 175 | + * @read: True if reading from the EEPROM, false if writing | |
| 176 | + * | |
| 177 | + * Returns the number of bytes read/written; -errno on error. | |
| 178 | + */ | |
| 179 | +static int amdgpu_eeprom_xfer(struct i2c_adapter *i2c_adap, u32 eeprom_addr, | |
| 180 | + u8 *eeprom_buf, u16 buf_size, bool read) | |
| 181 | +{ | |
| 182 | + const struct i2c_adapter_quirks *quirks = i2c_adap->quirks; | |
| 183 | + u16 limit; | |
| 184 | + | |
| 185 | + if (!quirks) | |
| 186 | + limit = 0; | |
| 187 | + else if (read) | |
| 188 | + limit = quirks->max_read_len; | |
| 189 | + else | |
| 190 | + limit = quirks->max_write_len; | |
| 191 | + | |
| 192 | + if (limit == 0) { | |
| 193 | + return __amdgpu_eeprom_xfer(i2c_adap, eeprom_addr, | |
| 194 | + eeprom_buf, buf_size, read); | |
| 195 | + } else if (limit <= EEPROM_OFFSET_SIZE) { | |
| 196 | + dev_err_ratelimited(&i2c_adap->dev, | |
| 197 | + "maddr:0x%04X size:0x%02X:quirk max_%s_len must be > %d", | |
| 198 | + eeprom_addr, buf_size, | |
| 199 | + read ? "read" : "write", EEPROM_OFFSET_SIZE); | |
| 200 | + return -EINVAL; | |
| 201 | + } else { | |
| 202 | + u16 ps; /* Partial size */ | |
| 203 | + int res = 0, r; | |
| 204 | + | |
| 205 | + /* The "limit" includes all data bytes sent/received, | |
| 206 | + * which would include the EEPROM_OFFSET_SIZE bytes. | |
| 207 | + * Account for them here. | |
| 208 | + */ | |
| 209 | + limit -= EEPROM_OFFSET_SIZE; | |
| 210 | + for ( ; buf_size > 0; | |
| 211 | + buf_size -= ps, eeprom_addr += ps, eeprom_buf += ps) { | |
| 212 | + ps = min(limit, buf_size); | |
| 213 | + | |
| 214 | + r = __amdgpu_eeprom_xfer(i2c_adap, eeprom_addr, | |
| 215 | + eeprom_buf, ps, read); | |
| 216 | + if (r < 0) | |
| 217 | + return r; | |
| 218 | + res += r; | |
| 219 | + } | |
| 220 | + | |
| 221 | + return res; | |
| 222 | + } | |
| 223 | +} | |
| 224 | + | |
| 225 | +int amdgpu_eeprom_read(struct i2c_adapter *i2c_adap, | |
| 226 | + u32 eeprom_addr, u8 *eeprom_buf, | |
| 227 | + u16 bytes) | |
| 228 | +{ | |
| 229 | + return amdgpu_eeprom_xfer(i2c_adap, eeprom_addr, eeprom_buf, bytes, | |
| 230 | + true); | |
| 231 | +} | |
| 232 | + | |
| 233 | +int amdgpu_eeprom_write(struct i2c_adapter *i2c_adap, | |
| 234 | + u32 eeprom_addr, u8 *eeprom_buf, | |
| 235 | + u16 bytes) | |
| 236 | +{ | |
| 237 | + return amdgpu_eeprom_xfer(i2c_adap, eeprom_addr, eeprom_buf, bytes, | |
| 238 | + false); | |
| 239 | +} | |
| @@ -0,0 +1,37 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright 2021 Advanced Micro Devices, Inc. | |
| 3 | + * | |
| 4 | + * Permission is hereby granted, free of charge, to any person obtaining a | |
| 5 | + * copy of this software and associated documentation files (the "Software"), | |
| 6 | + * to deal in the Software without restriction, including without limitation | |
| 7 | + * the rights to use, copy, modify, merge, publish, distribute, sublicense, | |
| 8 | + * and/or sell copies of the Software, and to permit persons to whom the | |
| 9 | + * Software is furnished to do so, subject to the following conditions: | |
| 10 | + * | |
| 11 | + * The above copyright notice and this permission notice shall be included in | |
| 12 | + * all copies or substantial portions of the Software. | |
| 13 | + * | |
| 14 | + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
| 15 | + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
| 16 | + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |
| 17 | + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR | |
| 18 | + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | |
| 19 | + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | |
| 20 | + * OTHER DEALINGS IN THE SOFTWARE. | |
| 21 | + * | |
| 22 | + */ | |
| 23 | + | |
| 24 | +#ifndef _AMDGPU_EEPROM_H | |
| 25 | +#define _AMDGPU_EEPROM_H | |
| 26 | + | |
| 27 | +#include <linux/i2c.h> | |
| 28 | + | |
| 29 | +int amdgpu_eeprom_read(struct i2c_adapter *i2c_adap, | |
| 30 | + u32 eeprom_addr, u8 *eeprom_buf, | |
| 31 | + u16 bytes); | |
| 32 | + | |
| 33 | +int amdgpu_eeprom_write(struct i2c_adapter *i2c_adap, | |
| 34 | + u32 eeprom_addr, u8 *eeprom_buf, | |
| 35 | + u16 bytes); | |
| 36 | + | |
| 37 | +#endif | |
| @@ -273,9 +273,6 @@ static int amdgpufb_create(struct drm_fb_helper *helper, · 272 unmodified lines | ||
| 273 | 273 | return 0; |
| 274 | 274 | |
| 275 | 275 | out: |
| 276 | − if (abo) { | |
| 277 | − | |
| 278 | − } | |
| 279 | 276 | if (fb && ret) { |
| 280 | 277 | drm_gem_object_put(gobj); |
| 281 | 278 | drm_framebuffer_unregister_private(fb); |
| @@ -344,7 +341,7 @@ int amdgpu_fbdev_init(struct amdgpu_device *adev) · 62 unmodified lines | ||
| 344 | 341 | } |
| 345 | 342 | |
| 346 | 343 | /* disable all the possible outputs/crtcs before entering KMS mode */ |
| 347 | − if (!amdgpu_device_has_dc_support(adev)) | |
| 344 | + if (!amdgpu_device_has_dc_support(adev) && !amdgpu_virtual_display) | |
| 348 | 345 | drm_helper_disable_unused_functions(adev_to_drm(adev)); |
| 349 | 346 | |
| 350 | 347 | drm_fb_helper_initial_config(&rfbdev->helper, bpp_sel); |
| @@ -129,30 +129,50 @@ static u32 amdgpu_fence_read(struct amdgpu_ring *ring) · 128 unmodified lines | ||
| 129 | 129 | * |
| 130 | 130 | * @ring: ring the fence is associated with |
| 131 | 131 | * @f: resulting fence object |
| 132 | + * @job: job the fence is embedded in | |
| 132 | 133 | * @flags: flags to pass into the subordinate .emit_fence() call |
| 133 | 134 | * |
| 134 | 135 | * Emits a fence command on the requested ring (all asics). |
| 135 | 136 | * Returns 0 on success, -ENOMEM on failure. |
| 136 | 137 | */ |
| 137 | −int amdgpu_fence_emit(struct amdgpu_ring *ring, struct dma_fence **f, | |
| 138 | +int amdgpu_fence_emit(struct amdgpu_ring *ring, struct dma_fence **f, struct amdgpu_job *job, | |
| 138 | 139 | unsigned flags) |
| 139 | 140 | { |
| 140 | 141 | struct amdgpu_device *adev = ring->adev; |
| 141 | − struct amdgpu_fence *fence; | |
| 142 | + struct dma_fence *fence; | |
| 143 | + struct amdgpu_fence *am_fence; | |
| 142 | 144 | struct dma_fence __rcu **ptr; |
| 143 | 145 | uint32_t seq; |
| 144 | 146 | int r; |
| 145 | 147 | |
| 146 | − fence = kmem_cache_alloc(amdgpu_fence_slab, GFP_KERNEL); | |
| 147 | − if (fence == NULL) | |
| 148 | − return -ENOMEM; | |
| 148 | + if (job == NULL) { | |
| 149 | + /* create a sperate hw fence */ | |
| 150 | + am_fence = kmem_cache_alloc(amdgpu_fence_slab, GFP_ATOMIC); | |
| 151 | + if (am_fence == NULL) | |
| 152 | + return -ENOMEM; | |
| 153 | + fence = &am_fence->base; | |
| 154 | + am_fence->ring = ring; | |
| 155 | + } else { | |
| 156 | + /* take use of job-embedded fence */ | |
| 157 | + fence = &job->hw_fence; | |
| 158 | + } | |
| 149 | 159 | |
| 150 | 160 | seq = ++ring->fence_drv.sync_seq; |
| 151 | − fence->ring = ring; | |
| 152 | − dma_fence_init(&fence->base, &amdgpu_fence_ops, | |
| 153 | − &ring->fence_drv.lock, | |
| 154 | − adev->fence_context + ring->idx, | |
| 155 | − seq); | |
| 161 | + if (job != NULL && job->job_run_counter) { | |
| 162 | + /* reinit seq for resubmitted jobs */ | |
| 163 | + fence->seqno = seq; | |
| 164 | + } else { | |
| 165 | + dma_fence_init(fence, &amdgpu_fence_ops, | |
| 166 | + &ring->fence_drv.lock, | |
| 167 | + adev->fence_context + ring->idx, | |
| 168 | + seq); | |
| 169 | + } | |
| 170 | + | |
| 171 | + if (job != NULL) { | |
| 172 | + /* mark this fence has a parent job */ | |
| 173 | + set_bit(AMDGPU_FENCE_FLAG_EMBED_IN_JOB_BIT, &fence->flags); | |
| 174 | + } | |
| 175 | + | |
| 156 | 176 | amdgpu_ring_emit_fence(ring, ring->fence_drv.gpu_addr, |
| 157 | 177 | seq, flags | AMDGPU_FENCE_FLAG_INT); |
| 158 | 178 | pm_runtime_get_noresume(adev_to_drm(adev)->dev); |
| @@ -175,9 +195,9 @@ int amdgpu_fence_emit(struct amdgpu_ring *ring, struct dma_fence **f, · 16 unmodified lines | ||
| 175 | 195 | /* This function can't be called concurrently anyway, otherwise |
| 176 | 196 | * emitting the fence would mess up the hardware ring buffer. |
| 177 | 197 | */ |
| 178 | − rcu_assign_pointer(*ptr, dma_fence_get(&fence->base)); | |
| 198 | + rcu_assign_pointer(*ptr, dma_fence_get(fence)); | |
| 179 | 199 | |
| 180 | − *f = &fence->base; | |
| 200 | + *f = fence; | |
| 181 | 201 | |
| 182 | 202 | return 0; |
| 183 | 203 | } |
| @@ -417,9 +437,6 @@ int amdgpu_fence_driver_start_ring(struct amdgpu_ring *ring, · 233 unmodified lines | ||
| 417 | 437 | } |
| 418 | 438 | amdgpu_fence_write(ring, atomic_read(&ring->fence_drv.last_seq)); |
| 419 | 439 | |
| 420 | − if (irq_src) | |
| 421 | − amdgpu_irq_get(adev, irq_src, irq_type); | |
| 422 | − | |
| 423 | 440 | ring->fence_drv.irq_src = irq_src; |
| 424 | 441 | ring->fence_drv.irq_type = irq_type; |
| 425 | 442 | ring->fence_drv.initialized = true; |
| @@ -490,7 +507,7 @@ int amdgpu_fence_driver_init_ring(struct amdgpu_ring *ring, · 64 unmodified lines | ||
| 490 | 507 | |
| 491 | 508 | r = drm_sched_init(&ring->sched, &amdgpu_sched_ops, |
| 492 | 509 | num_hw_submission, amdgpu_job_hang_limit, |
| 493 | − timeout, sched_score, ring->name); | |
| 510 | + timeout, NULL, sched_score, ring->name); | |
| 494 | 511 | if (r) { |
| 495 | 512 | DRM_ERROR("Failed to create scheduler on ring %s.\n", |
| 496 | 513 | ring->name); |
| @@ -501,7 +518,7 @@ int amdgpu_fence_driver_init_ring(struct amdgpu_ring *ring, · 4 unmodified lines | ||
| 501 | 518 | } |
| 502 | 519 | |
| 503 | 520 | /** |
| 504 | − * amdgpu_fence_driver_init - init the fence driver | |
| 521 | + * amdgpu_fence_driver_sw_init - init the fence driver | |
| 505 | 522 | * for all possible rings. |
| 506 | 523 | * |
| 507 | 524 | * @adev: amdgpu device pointer |
| @@ -512,20 +529,20 @@ int amdgpu_fence_driver_init_ring(struct amdgpu_ring *ring, · 4 unmodified lines | ||
| 512 | 529 | * amdgpu_fence_driver_start_ring(). |
| 513 | 530 | * Returns 0 for success. |
| 514 | 531 | */ |
| 515 | −int amdgpu_fence_driver_init(struct amdgpu_device *adev) | |
| 532 | +int amdgpu_fence_driver_sw_init(struct amdgpu_device *adev) | |
| 516 | 533 | { |
| 517 | 534 | return 0; |
| 518 | 535 | } |
| 519 | 536 | |
| 520 | 537 | /** |
| 521 | − * amdgpu_fence_driver_fini - tear down the fence driver | |
| 538 | + * amdgpu_fence_driver_hw_fini - tear down the fence driver | |
| 522 | 539 | * for all possible rings. |
| 523 | 540 | * |
| 524 | 541 | * @adev: amdgpu device pointer |
| 525 | 542 | * |
| 526 | 543 | * Tear down the fence driver for all possible rings (all asics). |
| 527 | 544 | */ |
| 528 | −void amdgpu_fence_driver_fini_hw(struct amdgpu_device *adev) | |
| 545 | +void amdgpu_fence_driver_hw_fini(struct amdgpu_device *adev) | |
| 529 | 546 | { |
| 530 | 547 | int i, r; |
| 531 | 548 | |
| @@ -534,8 +551,7 @@ void amdgpu_fence_driver_fini_hw(struct amdgpu_device *adev) · 2 unmodified lines | ||
| 534 | 551 | |
| 535 | 552 | if (!ring || !ring->fence_drv.initialized) |
| 536 | 553 | continue; |
| 537 | − if (!ring->no_scheduler) | |
| 538 | − drm_sched_fini(&ring->sched); | |
| 554 | + | |
| 539 | 555 | /* You can't wait for HW to signal if it's gone */ |
| 540 | 556 | if (!drm_dev_is_unplugged(&adev->ddev)) |
| 541 | 557 | r = amdgpu_fence_wait_empty(ring); |
| @@ -553,7 +569,7 @@ void amdgpu_fence_driver_fini_hw(struct amdgpu_device *adev) · 11 unmodified lines | ||
| 553 | 569 | } |
| 554 | 570 | } |
| 555 | 571 | |
| 556 | −void amdgpu_fence_driver_fini_sw(struct amdgpu_device *adev) | |
| 572 | +void amdgpu_fence_driver_sw_fini(struct amdgpu_device *adev) | |
| 557 | 573 | { |
| 558 | 574 | unsigned int i, j; |
| 559 | 575 | |
| @@ -563,6 +579,9 @@ void amdgpu_fence_driver_fini_sw(struct amdgpu_device *adev) · 3 unmodified lines | ||
| 563 | 579 | if (!ring || !ring->fence_drv.initialized) |
| 564 | 580 | continue; |
| 565 | 581 | |
| 582 | + if (!ring->no_scheduler) | |
| 583 | + drm_sched_fini(&ring->sched); | |
| 584 | + | |
| 566 | 585 | for (j = 0; j <= ring->fence_drv.num_fences_mask; ++j) |
| 567 | 586 | dma_fence_put(ring->fence_drv.fences[j]); |
| 568 | 587 | kfree(ring->fence_drv.fences); |
| @@ -572,49 +591,18 @@ void amdgpu_fence_driver_fini_sw(struct amdgpu_device *adev) · 3 unmodified lines | ||
| 572 | 591 | } |
| 573 | 592 | |
| 574 | 593 | /** |
| 575 | − * amdgpu_fence_driver_suspend - suspend the fence driver | |
| 576 | − * for all possible rings. | |
| 577 | − * | |
| 578 | − * @adev: amdgpu device pointer | |
| 579 | − * | |
| 580 | − * Suspend the fence driver for all possible rings (all asics). | |
| 581 | − */ | |
| 582 | −void amdgpu_fence_driver_suspend(struct amdgpu_device *adev) | |
| 583 | −{ | |
| 584 | − int i, r; | |
| 585 | − | |
| 586 | − for (i = 0; i < AMDGPU_MAX_RINGS; i++) { | |
| 587 | − struct amdgpu_ring *ring = adev->rings[i]; | |
| 588 | − if (!ring || !ring->fence_drv.initialized) | |
| 589 | − continue; | |
| 590 | − | |
| 591 | − /* wait for gpu to finish processing current batch */ | |
| 592 | − r = amdgpu_fence_wait_empty(ring); | |
| 593 | − if (r) { | |
| 594 | − /* delay GPU reset to resume */ | |
| 595 | − amdgpu_fence_driver_force_completion(ring); | |
| 596 | − } | |
| 597 | − | |
| 598 | − /* disable the interrupt */ | |
| 599 | − if (ring->fence_drv.irq_src) | |
| 600 | − amdgpu_irq_put(adev, ring->fence_drv.irq_src, | |
| 601 | − ring->fence_drv.irq_type); | |
| 602 | − } | |
| 603 | −} | |
| 604 | − | |
| 605 | −/** | |
| 606 | − * amdgpu_fence_driver_resume - resume the fence driver | |
| 594 | + * amdgpu_fence_driver_hw_init - enable the fence driver | |
| 607 | 595 | * for all possible rings. |
| 608 | 596 | * |
| 609 | 597 | * @adev: amdgpu device pointer |
| 610 | 598 | * |
| 611 | − * Resume the fence driver for all possible rings (all asics). | |
| 599 | + * Enable the fence driver for all possible rings (all asics). | |
| 612 | 600 | * Not all asics have all rings, so each asic will only |
| 613 | 601 | * start the fence driver on the rings it has using |
| 614 | 602 | * amdgpu_fence_driver_start_ring(). |
| 615 | 603 | * Returns 0 for success. |
| 616 | 604 | */ |
| 617 | −void amdgpu_fence_driver_resume(struct amdgpu_device *adev) | |
| 605 | +void amdgpu_fence_driver_hw_init(struct amdgpu_device *adev) | |
| 618 | 606 | { |
| 619 | 607 | int i; |
| 620 | 608 | |
| @@ -653,8 +641,16 @@ static const char *amdgpu_fence_get_driver_name(struct dma_fence *fence) · 32 unmodified lines | ||
| 653 | 641 | |
| 654 | 642 | static const char *amdgpu_fence_get_timeline_name(struct dma_fence *f) |
| 655 | 643 | { |
| 656 | − struct amdgpu_fence *fence = to_amdgpu_fence(f); | |
| 657 | − return (const char *)fence->ring->name; | |
| 644 | + struct amdgpu_ring *ring; | |
| 645 | + | |
| 646 | + if (test_bit(AMDGPU_FENCE_FLAG_EMBED_IN_JOB_BIT, &f->flags)) { | |
| 647 | + struct amdgpu_job *job = container_of(f, struct amdgpu_job, hw_fence); | |
| 648 | + | |
| 649 | + ring = to_amdgpu_ring(job->base.sched); | |
| 650 | + } else { | |
| 651 | + ring = to_amdgpu_fence(f)->ring; | |
| 652 | + } | |
| 653 | + return (const char *)ring->name; | |
| 658 | 654 | } |
| 659 | 655 | |
| 660 | 656 | /** |
| @@ -667,13 +663,20 @@ static const char *amdgpu_fence_get_timeline_name(struct dma_fence *f) · 6 unmodified lines | ||
| 667 | 663 | */ |
| 668 | 664 | static bool amdgpu_fence_enable_signaling(struct dma_fence *f) |
| 669 | 665 | { |
| 670 | − struct amdgpu_fence *fence = to_amdgpu_fence(f); | |
| 671 | − struct amdgpu_ring *ring = fence->ring; | |
| 666 | + struct amdgpu_ring *ring; | |
| 667 | + | |
| 668 | + if (test_bit(AMDGPU_FENCE_FLAG_EMBED_IN_JOB_BIT, &f->flags)) { | |
| 669 | + struct amdgpu_job *job = container_of(f, struct amdgpu_job, hw_fence); | |
| 670 | + | |
| 671 | + ring = to_amdgpu_ring(job->base.sched); | |
| 672 | + } else { | |
| 673 | + ring = to_amdgpu_fence(f)->ring; | |
| 674 | + } | |
| 672 | 675 | |
| 673 | 676 | if (!timer_pending(&ring->fence_drv.fallback_timer)) |
| 674 | 677 | amdgpu_fence_schedule_fallback(ring); |
| 675 | 678 | |
| 676 | − DMA_FENCE_TRACE(&fence->base, "armed on ring %i!\n", ring->idx); | |
| 679 | + DMA_FENCE_TRACE(f, "armed on ring %i!\n", ring->idx); | |
| 677 | 680 | |
| 678 | 681 | return true; |
| 679 | 682 | } |
| @@ -688,8 +691,20 @@ static bool amdgpu_fence_enable_signaling(struct dma_fence *f) · 8 unmodified lines | ||
| 688 | 691 | static void amdgpu_fence_free(struct rcu_head *rcu) |
| 689 | 692 | { |
| 690 | 693 | struct dma_fence *f = container_of(rcu, struct dma_fence, rcu); |
| 691 | − struct amdgpu_fence *fence = to_amdgpu_fence(f); | |
| 692 | − kmem_cache_free(amdgpu_fence_slab, fence); | |
| 694 | + | |
| 695 | + if (test_bit(AMDGPU_FENCE_FLAG_EMBED_IN_JOB_BIT, &f->flags)) { | |
| 696 | + /* free job if fence has a parent job */ | |
| 697 | + struct amdgpu_job *job; | |
| 698 | + | |
| 699 | + job = container_of(f, struct amdgpu_job, hw_fence); | |
| 700 | + kfree(job); | |
| 701 | + } else { | |
| 702 | + /* free fence_slab if it's separated fence*/ | |
| 703 | + struct amdgpu_fence *fence; | |
| 704 | + | |
| 705 | + fence = to_amdgpu_fence(f); | |
| 706 | + kmem_cache_free(amdgpu_fence_slab, fence); | |
| 707 | + } | |
| 693 | 708 | } |
| 694 | 709 | |
| 695 | 710 | /** |
| @@ -712,6 +727,7 @@ static const struct dma_fence_ops amdgpu_fence_ops = { · 16 unmodified lines | ||
| 712 | 727 | .release = amdgpu_fence_release, |
| 713 | 728 | }; |
| 714 | 729 | |
| 730 | + | |
| 715 | 731 | /* |
| 716 | 732 | * Fence debugfs |
| 717 | 733 | */ |
| @@ -27,10 +27,10 @@ · 26 unmodified lines | ||
| 27 | 27 | #include "smu_v11_0_i2c.h" |
| 28 | 28 | #include "atom.h" |
| 29 | 29 | #include "amdgpu_fru_eeprom.h" |
| 30 | +#include "amdgpu_eeprom.h" | |
| 30 | 31 | |
| 31 | −#define I2C_PRODUCT_INFO_ADDR 0xAC | |
| 32 | −#define I2C_PRODUCT_INFO_ADDR_SIZE 0x2 | |
| 33 | −#define I2C_PRODUCT_INFO_OFFSET 0xC0 | |
| 32 | +#define FRU_EEPROM_MADDR 0x60000 | |
| 33 | +#define I2C_PRODUCT_INFO_OFFSET 0xC0 | |
| 34 | 34 | |
| 35 | 35 | static bool is_fru_eeprom_supported(struct amdgpu_device *adev) |
| 36 | 36 | { |
| @@ -62,19 +62,11 @@ static bool is_fru_eeprom_supported(struct amdgpu_device *adev) · 25 unmodified lines | ||
| 62 | 62 | } |
| 63 | 63 | |
| 64 | 64 | static int amdgpu_fru_read_eeprom(struct amdgpu_device *adev, uint32_t addrptr, |
| 65 | − unsigned char *buff) | |
| 65 | + unsigned char *buff) | |
| 66 | 66 | { |
| 67 | 67 | int ret, size; |
| 68 | − struct i2c_msg msg = { | |
| 69 | − .addr = I2C_PRODUCT_INFO_ADDR, | |
| 70 | − .flags = I2C_M_RD, | |
| 71 | − .buf = buff, | |
| 72 | − }; | |
| 73 | − buff[0] = 0; | |
| 74 | − buff[1] = addrptr; | |
| 75 | − msg.len = I2C_PRODUCT_INFO_ADDR_SIZE + 1; | |
| 76 | − ret = i2c_transfer(&adev->pm.smu_i2c, &msg, 1); | |
| 77 | 68 | |
| 69 | + ret = amdgpu_eeprom_read(&adev->pm.smu_i2c, addrptr, buff, 1); | |
| 78 | 70 | if (ret < 1) { |
| 79 | 71 | DRM_WARN("FRU: Failed to get size field"); |
| 80 | 72 | return ret; |
| @@ -83,13 +75,9 @@ static int amdgpu_fru_read_eeprom(struct amdgpu_device *adev, uint32_t addrptr, · 2 unmodified lines | ||
| 83 | 75 | /* The size returned by the i2c requires subtraction of 0xC0 since the |
| 84 | 76 | * size apparently always reports as 0xC0+actual size. |
| 85 | 77 | */ |
| 86 | − size = buff[2] - I2C_PRODUCT_INFO_OFFSET; | |
| 87 | − /* Add 1 since address field was 1 byte */ | |
| 88 | − buff[1] = addrptr + 1; | |
| 89 | − | |
| 90 | − msg.len = I2C_PRODUCT_INFO_ADDR_SIZE + size; | |
| 91 | − ret = i2c_transfer(&adev->pm.smu_i2c, &msg, 1); | |
| 78 | + size = buff[0] - I2C_PRODUCT_INFO_OFFSET; | |
| 92 | 79 | |
| 80 | + ret = amdgpu_eeprom_read(&adev->pm.smu_i2c, addrptr + 1, buff, size); | |
| 93 | 81 | if (ret < 1) { |
| 94 | 82 | DRM_WARN("FRU: Failed to get data field"); |
| 95 | 83 | return ret; |
| @@ -101,8 +89,8 @@ static int amdgpu_fru_read_eeprom(struct amdgpu_device *adev, uint32_t addrptr, · 5 unmodified lines | ||
| 101 | 89 | int amdgpu_fru_get_product_info(struct amdgpu_device *adev) |
| 102 | 90 | { |
| 103 | 91 | unsigned char buff[34]; |
| 104 | − int addrptr, size; | |
| 105 | − int len; | |
| 92 | + u32 addrptr; | |
| 93 | + int size, len; | |
| 106 | 94 | |
| 107 | 95 | if (!is_fru_eeprom_supported(adev)) |
| 108 | 96 | return 0; |
| @@ -125,7 +113,7 @@ int amdgpu_fru_get_product_info(struct amdgpu_device *adev) · 16 unmodified lines | ||
| 125 | 113 | * Bytes 8-a are all 1-byte and refer to the size of the entire struct, |
| 126 | 114 | * and the language field, so just start from 0xb, manufacturer size |
| 127 | 115 | */ |
| 128 | − addrptr = 0xb; | |
| 116 | + addrptr = FRU_EEPROM_MADDR + 0xb; | |
| 129 | 117 | size = amdgpu_fru_read_eeprom(adev, addrptr, buff); |
| 130 | 118 | if (size < 1) { |
| 131 | 119 | DRM_ERROR("Failed to read FRU Manufacturer, ret:%d", size); |
| @@ -76,7 +76,7 @@ static int amdgpu_gart_dummy_page_init(struct amdgpu_device *adev) · 75 unmodified lines | ||
| 76 | 76 | if (adev->dummy_page_addr) |
| 77 | 77 | return 0; |
| 78 | 78 | adev->dummy_page_addr = dma_map_page(&adev->pdev->dev, dummy_page, 0, |
| 79 | − PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); | |
| 79 | + PAGE_SIZE, DMA_BIDIRECTIONAL); | |
| 80 | 80 | if (dma_mapping_error(&adev->pdev->dev, adev->dummy_page_addr)) { |
| 81 | 81 | dev_err(&adev->pdev->dev, "Failed to DMA MAP the dummy page\n"); |
| 82 | 82 | adev->dummy_page_addr = 0; |
| @@ -96,8 +96,8 @@ void amdgpu_gart_dummy_page_fini(struct amdgpu_device *adev) · 13 unmodified lines | ||
| 96 | 96 | { |
| 97 | 97 | if (!adev->dummy_page_addr) |
| 98 | 98 | return; |
| 99 | − pci_unmap_page(adev->pdev, adev->dummy_page_addr, | |
| 100 | − PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); | |
| 99 | + dma_unmap_page(&adev->pdev->dev, adev->dummy_page_addr, PAGE_SIZE, | |
| 100 | + DMA_BIDIRECTIONAL); | |
| 101 | 101 | adev->dummy_page_addr = 0; |
| 102 | 102 | } |
| 103 | 103 | |
| @@ -621,7 +621,7 @@ static void amdgpu_gem_va_update_vm(struct amdgpu_device *adev, · 620 unmodified lines | ||
| 621 | 621 | |
| 622 | 622 | if (operation == AMDGPU_VA_OP_MAP || |
| 623 | 623 | operation == AMDGPU_VA_OP_REPLACE) { |
| 624 | − r = amdgpu_vm_bo_update(adev, bo_va, false); | |
| 624 | + r = amdgpu_vm_bo_update(adev, bo_va, false, NULL); | |
| 625 | 625 | if (r) |
| 626 | 626 | goto error; |
| 627 | 627 | } |
| @@ -838,7 +838,8 @@ int amdgpu_gem_op_ioctl(struct drm_device *dev, void *data, · 210 unmodified lines | ||
| 838 | 838 | break; |
| 839 | 839 | } |
| 840 | 840 | case AMDGPU_GEM_OP_SET_PLACEMENT: |
| 841 | − if (robj->prime_shared_count && (args->value & AMDGPU_GEM_DOMAIN_VRAM)) { | |
| 841 | + if (robj->tbo.base.import_attach && | |
| 842 | + args->value & AMDGPU_GEM_DOMAIN_VRAM) { | |
| 842 | 843 | r = -EINVAL; |
| 843 | 844 | amdgpu_bo_unreserve(robj); |
| 844 | 845 | break; |
| @@ -903,7 +904,7 @@ int amdgpu_mode_dumb_create(struct drm_file *file_priv, · 58 unmodified lines | ||
| 903 | 904 | DIV_ROUND_UP(args->bpp, 8), 0); |
| 904 | 905 | args->size = (u64)args->pitch * args->height; |
| 905 | 906 | args->size = ALIGN(args->size, PAGE_SIZE); |
| 906 | − domain = amdgpu_bo_get_preferred_pin_domain(adev, | |
| 907 | + domain = amdgpu_bo_get_preferred_domain(adev, | |
| 907 | 908 | amdgpu_display_supported_domains(adev, flags)); |
| 908 | 909 | r = amdgpu_gem_object_create(adev, args->size, 0, domain, flags, |
| 909 | 910 | ttm_bo_type_device, NULL, &gobj); |
| @@ -629,7 +629,6 @@ int amdgpu_gfx_ras_late_init(struct amdgpu_device *adev) · 628 unmodified lines | ||
| 629 | 629 | adev->gfx.ras_if->block = AMDGPU_RAS_BLOCK__GFX; |
| 630 | 630 | adev->gfx.ras_if->type = AMDGPU_RAS_ERROR__MULTI_UNCORRECTABLE; |
| 631 | 631 | adev->gfx.ras_if->sub_block_index = 0; |
| 632 | − strcpy(adev->gfx.ras_if->name, "gfx"); | |
| 633 | 632 | } |
| 634 | 633 | fs_info.head = ih_info.head = *adev->gfx.ras_if; |
| 635 | 634 | r = amdgpu_ras_late_init(adev, adev->gfx.ras_if, |
| @@ -471,6 +471,27 @@ int amdgpu_gmc_ras_late_init(struct amdgpu_device *adev) · 470 unmodified lines | ||
| 471 | 471 | return r; |
| 472 | 472 | } |
| 473 | 473 | |
| 474 | + if (adev->mca.mp0.ras_funcs && | |
| 475 | + adev->mca.mp0.ras_funcs->ras_late_init) { | |
| 476 | + r = adev->mca.mp0.ras_funcs->ras_late_init(adev); | |
| 477 | + if (r) | |
| 478 | + return r; | |
| 479 | + } | |
| 480 | + | |
| 481 | + if (adev->mca.mp1.ras_funcs && | |
| 482 | + adev->mca.mp1.ras_funcs->ras_late_init) { | |
| 483 | + r = adev->mca.mp1.ras_funcs->ras_late_init(adev); | |
| 484 | + if (r) | |
| 485 | + return r; | |
| 486 | + } | |
| 487 | + | |
| 488 | + if (adev->mca.mpio.ras_funcs && | |
| 489 | + adev->mca.mpio.ras_funcs->ras_late_init) { | |
| 490 | + r = adev->mca.mpio.ras_funcs->ras_late_init(adev); | |
| 491 | + if (r) | |
| 492 | + return r; | |
| 493 | + } | |
| 494 | + | |
| 474 | 495 | return 0; |
| 475 | 496 | } |
| 476 | 497 | |
| @@ -132,14 +132,11 @@ static int amdgpu_gtt_mgr_new(struct ttm_resource_manager *man, · 131 unmodified lines | ||
| 132 | 132 | struct amdgpu_gtt_node *node; |
| 133 | 133 | int r; |
| 134 | 134 | |
| 135 | − spin_lock(&mgr->lock); | |
| 136 | − if (tbo->resource && tbo->resource->mem_type != TTM_PL_TT && | |
| 137 | − atomic64_read(&mgr->available) < num_pages) { | |
| 138 | − spin_unlock(&mgr->lock); | |
| 135 | + if (!(place->flags & TTM_PL_FLAG_TEMPORARY) && | |
| 136 | + atomic64_add_return(num_pages, &mgr->used) > man->size) { | |
| 137 | + atomic64_sub(num_pages, &mgr->used); | |
| 139 | 138 | return -ENOSPC; |
| 140 | 139 | } |
| 141 | − atomic64_sub(num_pages, &mgr->available); | |
| 142 | − spin_unlock(&mgr->lock); | |
| 143 | 140 | |
| 144 | 141 | node = kzalloc(struct_size(node, base.mm_nodes, 1), GFP_KERNEL); |
| 145 | 142 | if (!node) { |
| @@ -175,7 +172,8 @@ err_free: · 29 unmodified lines | ||
| 175 | 172 | kfree(node); |
| 176 | 173 | |
| 177 | 174 | err_out: |
| 178 | − atomic64_add(num_pages, &mgr->available); | |
| 175 | + if (!(place->flags & TTM_PL_FLAG_TEMPORARY)) | |
| 176 | + atomic64_sub(num_pages, &mgr->used); | |
| 179 | 177 | |
| 180 | 178 | return r; |
| 181 | 179 | } |
| @@ -198,7 +196,9 @@ static void amdgpu_gtt_mgr_del(struct ttm_resource_manager *man, · 16 unmodified lines | ||
| 198 | 196 | if (drm_mm_node_allocated(&node->base.mm_nodes[0])) |
| 199 | 197 | drm_mm_remove_node(&node->base.mm_nodes[0]); |
| 200 | 198 | spin_unlock(&mgr->lock); |
| 201 | − atomic64_add(res->num_pages, &mgr->available); | |
| 199 | + | |
| 200 | + if (!(res->placement & TTM_PL_FLAG_TEMPORARY)) | |
| 201 | + atomic64_sub(res->num_pages, &mgr->used); | |
| 202 | 202 | |
| 203 | 203 | kfree(node); |
| 204 | 204 | } |
| @@ -213,9 +213,8 @@ static void amdgpu_gtt_mgr_del(struct ttm_resource_manager *man, · 8 unmodified lines | ||
| 213 | 213 | uint64_t amdgpu_gtt_mgr_usage(struct ttm_resource_manager *man) |
| 214 | 214 | { |
| 215 | 215 | struct amdgpu_gtt_mgr *mgr = to_gtt_mgr(man); |
| 216 | − s64 result = man->size - atomic64_read(&mgr->available); | |
| 217 | 216 | |
| 218 | − return (result > 0 ? result : 0) * PAGE_SIZE; | |
| 217 | + return atomic64_read(&mgr->used) * PAGE_SIZE; | |
| 219 | 218 | } |
| 220 | 219 | |
| 221 | 220 | /** |
| @@ -265,9 +264,8 @@ static void amdgpu_gtt_mgr_debug(struct ttm_resource_manager *man, · 43 unmodified lines | ||
| 265 | 264 | drm_mm_print(&mgr->mm, printer); |
| 266 | 265 | spin_unlock(&mgr->lock); |
| 267 | 266 | |
| 268 | − drm_printf(printer, "man size:%llu pages, gtt available:%lld pages, usage:%lluMB\n", | |
| 269 | − man->size, (u64)atomic64_read(&mgr->available), | |
| 270 | − amdgpu_gtt_mgr_usage(man) >> 20); | |
| 267 | + drm_printf(printer, "man size:%llu pages, gtt used:%llu pages\n", | |
| 268 | + man->size, atomic64_read(&mgr->used)); | |
| 271 | 269 | } |
| 272 | 270 | |
| 273 | 271 | static const struct ttm_resource_manager_func amdgpu_gtt_mgr_func = { |
| @@ -299,7 +297,7 @@ int amdgpu_gtt_mgr_init(struct amdgpu_device *adev, uint64_t gtt_size) · 25 unmodified lines | ||
| 299 | 297 | size = (adev->gmc.gart_size >> PAGE_SHIFT) - start; |
| 300 | 298 | drm_mm_init(&mgr->mm, start, size); |
| 301 | 299 | spin_lock_init(&mgr->lock); |
| 302 | − atomic64_set(&mgr->available, gtt_size >> PAGE_SHIFT); | |
| 300 | + atomic64_set(&mgr->used, 0); | |
| 303 | 301 | |
| 304 | 302 | ttm_set_driver_manager(&adev->mman.bdev, TTM_PL_TT, &mgr->manager); |
| 305 | 303 | ttm_resource_manager_set_used(man, true); |
| @@ -41,7 +41,6 @@ int amdgpu_hdp_ras_late_init(struct amdgpu_device *adev) · 40 unmodified lines | ||
| 41 | 41 | adev->hdp.ras_if->block = AMDGPU_RAS_BLOCK__HDP; |
| 42 | 42 | adev->hdp.ras_if->type = AMDGPU_RAS_ERROR__MULTI_UNCORRECTABLE; |
| 43 | 43 | adev->hdp.ras_if->sub_block_index = 0; |
| 44 | − strcpy(adev->hdp.ras_if->name, "hdp"); | |
| 45 | 44 | } |
| 46 | 45 | ih_info.head = fs_info.head = *adev->hdp.ras_if; |
| 47 | 46 | r = amdgpu_ras_late_init(adev, adev->hdp.ras_if, |
| @@ -339,7 +339,7 @@ static void amdgpu_i2c_put_byte(struct amdgpu_i2c_chan *i2c_bus, · 338 unmodified lines | ||
| 339 | 339 | void |
| 340 | 340 | amdgpu_i2c_router_select_ddc_port(const struct amdgpu_connector *amdgpu_connector) |
| 341 | 341 | { |
| 342 | − u8 val; | |
| 342 | + u8 val = 0; | |
| 343 | 343 | |
| 344 | 344 | if (!amdgpu_connector->router.ddc_valid) |
| 345 | 345 | return; |
| @@ -262,7 +262,7 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned num_ibs, · 261 unmodified lines | ||
| 262 | 262 | fence_flags | AMDGPU_FENCE_FLAG_64BIT); |
| 263 | 263 | } |
| 264 | 264 | |
| 265 | − r = amdgpu_fence_emit(ring, f, fence_flags); | |
| 265 | + r = amdgpu_fence_emit(ring, f, job, fence_flags); | |
| 266 | 266 | if (r) { |
| 267 | 267 | dev_err(adev->dev, "failed to emit fence (%d)\n", r); |
| 268 | 268 | if (job && job->vmid) |
| @@ -46,7 +46,6 @@ · 45 unmodified lines | ||
| 46 | 46 | #include <linux/pci.h> |
| 47 | 47 | |
| 48 | 48 | #include <drm/drm_crtc_helper.h> |
| 49 | −#include <drm/drm_irq.h> | |
| 50 | 49 | #include <drm/drm_vblank.h> |
| 51 | 50 | #include <drm/amdgpu_drm.h> |
| 52 | 51 | #include <drm/drm_drv.h> |
| @@ -184,7 +183,7 @@ void amdgpu_irq_disable_all(struct amdgpu_device *adev) · 131 unmodified lines | ||
| 184 | 183 | * Returns: |
| 185 | 184 | * result of handling the IRQ, as defined by &irqreturn_t |
| 186 | 185 | */ |
| 187 | −irqreturn_t amdgpu_irq_handler(int irq, void *arg) | |
| 186 | +static irqreturn_t amdgpu_irq_handler(int irq, void *arg) | |
| 188 | 187 | { |
| 189 | 188 | struct drm_device *dev = (struct drm_device *) arg; |
| 190 | 189 | struct amdgpu_device *adev = drm_to_adev(dev); |
| @@ -307,6 +306,7 @@ static void amdgpu_restore_msix(struct amdgpu_device *adev) · 116 unmodified lines | ||
| 307 | 306 | int amdgpu_irq_init(struct amdgpu_device *adev) |
| 308 | 307 | { |
| 309 | 308 | int r = 0; |
| 309 | + unsigned int irq; | |
| 310 | 310 | |
| 311 | 311 | spin_lock_init(&adev->irq.lock); |
| 312 | 312 | |
| @@ -349,15 +349,22 @@ int amdgpu_irq_init(struct amdgpu_device *adev) · 36 unmodified lines | ||
| 349 | 349 | INIT_WORK(&adev->irq.ih2_work, amdgpu_irq_handle_ih2); |
| 350 | 350 | INIT_WORK(&adev->irq.ih_soft_work, amdgpu_irq_handle_ih_soft); |
| 351 | 351 | |
| 352 | − adev->irq.installed = true; | |
| 353 | − /* Use vector 0 for MSI-X */ | |
| 354 | − r = drm_irq_install(adev_to_drm(adev), pci_irq_vector(adev->pdev, 0)); | |
| 352 | + /* Use vector 0 for MSI-X. */ | |
| 353 | + r = pci_irq_vector(adev->pdev, 0); | |
| 354 | + if (r < 0) | |
| 355 | + return r; | |
| 356 | + irq = r; | |
| 357 | + | |
| 358 | + /* PCI devices require shared interrupts. */ | |
| 359 | + r = request_irq(irq, amdgpu_irq_handler, IRQF_SHARED, adev_to_drm(adev)->driver->name, | |
| 360 | + adev_to_drm(adev)); | |
| 355 | 361 | if (r) { |
| 356 | − adev->irq.installed = false; | |
| 357 | 362 | if (!amdgpu_device_has_dc_support(adev)) |
| 358 | 363 | flush_work(&adev->hotplug_work); |
| 359 | 364 | return r; |
| 360 | 365 | } |
| 366 | + adev->irq.installed = true; | |
| 367 | + adev->irq.irq = irq; | |
| 361 | 368 | adev_to_drm(adev)->max_vblank_count = 0x00ffffff; |
| 362 | 369 | |
| 363 | 370 | DRM_DEBUG("amdgpu: irq initialized.\n"); |
| @@ -368,7 +375,7 @@ int amdgpu_irq_init(struct amdgpu_device *adev) · 4 unmodified lines | ||
| 368 | 375 | void amdgpu_irq_fini_hw(struct amdgpu_device *adev) |
| 369 | 376 | { |
| 370 | 377 | if (adev->irq.installed) { |
| 371 | − drm_irq_uninstall(&adev->ddev); | |
| 378 | + free_irq(adev->irq.irq, adev_to_drm(adev)); | |
| 372 | 379 | adev->irq.installed = false; |
| 373 | 380 | if (adev->irq.msi_enabled) |
| 374 | 381 | pci_free_irq_vectors(adev->pdev); |
| @@ -584,7 +591,7 @@ void amdgpu_irq_gpu_reset_resume_helper(struct amdgpu_device *adev) · 209 unmodified lines | ||
| 584 | 591 | { |
| 585 | 592 | int i, j, k; |
| 586 | 593 | |
| 587 | − if (amdgpu_sriov_vf(adev)) | |
| 594 | + if (amdgpu_sriov_vf(adev) || amdgpu_passthrough(adev)) | |
| 588 | 595 | amdgpu_restore_msix(adev); |
| 589 | 596 | |
| 590 | 597 | for (i = 0; i < AMDGPU_IRQ_CLIENTID_MAX; ++i) { |
| @@ -617,7 +624,7 @@ void amdgpu_irq_gpu_reset_resume_helper(struct amdgpu_device *adev) · 26 unmodified lines | ||
| 617 | 624 | int amdgpu_irq_get(struct amdgpu_device *adev, struct amdgpu_irq_src *src, |
| 618 | 625 | unsigned type) |
| 619 | 626 | { |
| 620 | − if (!adev_to_drm(adev)->irq_enabled) | |
| 627 | + if (!adev->irq.installed) | |
| 621 | 628 | return -ENOENT; |
| 622 | 629 | |
| 623 | 630 | if (type >= src->num_types) |
| @@ -647,7 +654,7 @@ int amdgpu_irq_get(struct amdgpu_device *adev, struct amdgpu_irq_src *src, · 23 unmodified lines | ||
| 647 | 654 | int amdgpu_irq_put(struct amdgpu_device *adev, struct amdgpu_irq_src *src, |
| 648 | 655 | unsigned type) |
| 649 | 656 | { |
| 650 | − if (!adev_to_drm(adev)->irq_enabled) | |
| 657 | + if (!adev->irq.installed) | |
| 651 | 658 | return -ENOENT; |
| 652 | 659 | |
| 653 | 660 | if (type >= src->num_types) |
| @@ -678,7 +685,7 @@ int amdgpu_irq_put(struct amdgpu_device *adev, struct amdgpu_irq_src *src, · 24 unmodified lines | ||
| 678 | 685 | bool amdgpu_irq_enabled(struct amdgpu_device *adev, struct amdgpu_irq_src *src, |
| 679 | 686 | unsigned type) |
| 680 | 687 | { |
| 681 | − if (!adev_to_drm(adev)->irq_enabled) | |
| 688 | + if (!adev->irq.installed) | |
| 682 | 689 | return false; |
| 683 | 690 | |
| 684 | 691 | if (type >= src->num_types) |
| @@ -80,6 +80,7 @@ struct amdgpu_irq_src_funcs { · 79 unmodified lines | ||
| 80 | 80 | |
| 81 | 81 | struct amdgpu_irq { |
| 82 | 82 | bool installed; |
| 83 | + unsigned int irq; | |
| 83 | 84 | spinlock_t lock; |
| 84 | 85 | /* interrupt sources */ |
| 85 | 86 | struct amdgpu_irq_client client[AMDGPU_IRQ_CLIENTID_MAX]; |
| @@ -100,7 +101,6 @@ struct amdgpu_irq { · 14 unmodified lines | ||
| 100 | 101 | }; |
| 101 | 102 | |
| 102 | 103 | void amdgpu_irq_disable_all(struct amdgpu_device *adev); |
| 103 | −irqreturn_t amdgpu_irq_handler(int irq, void *arg); | |
| 104 | 104 | |
| 105 | 105 | int amdgpu_irq_init(struct amdgpu_device *adev); |
| 106 | 106 | void amdgpu_irq_fini_sw(struct amdgpu_device *adev); |
| @@ -127,11 +127,16 @@ void amdgpu_job_free_resources(struct amdgpu_job *job) · 126 unmodified lines | ||
| 127 | 127 | { |
| 128 | 128 | struct amdgpu_ring *ring = to_amdgpu_ring(job->base.sched); |
| 129 | 129 | struct dma_fence *f; |
| 130 | + struct dma_fence *hw_fence; | |
| 130 | 131 | unsigned i; |
| 131 | 132 | |
| 132 | − /* use sched fence if available */ | |
| 133 | − f = job->base.s_fence ? &job->base.s_fence->finished : job->fence; | |
| 133 | + if (job->hw_fence.ops == NULL) | |
| 134 | + hw_fence = job->external_hw_fence; | |
| 135 | + else | |
| 136 | + hw_fence = &job->hw_fence; | |
| 134 | 137 | |
| 138 | + /* use sched fence if available */ | |
| 139 | + f = job->base.s_fence ? &job->base.s_fence->finished : hw_fence; | |
| 135 | 140 | for (i = 0; i < job->num_ibs; ++i) |
| 136 | 141 | amdgpu_ib_free(ring->adev, &job->ibs[i], f); |
| 137 | 142 | } |
| @@ -142,20 +147,27 @@ static void amdgpu_job_free_cb(struct drm_sched_job *s_job) · 4 unmodified lines | ||
| 142 | 147 | |
| 143 | 148 | drm_sched_job_cleanup(s_job); |
| 144 | 149 | |
| 145 | − dma_fence_put(job->fence); | |
| 146 | 150 | amdgpu_sync_free(&job->sync); |
| 147 | 151 | amdgpu_sync_free(&job->sched_sync); |
| 148 | − kfree(job); | |
| 152 | + | |
| 153 | + /* only put the hw fence if has embedded fence */ | |
| 154 | + if (job->hw_fence.ops != NULL) | |
| 155 | + dma_fence_put(&job->hw_fence); | |
| 156 | + else | |
| 157 | + kfree(job); | |
| 149 | 158 | } |
| 150 | 159 | |
| 151 | 160 | void amdgpu_job_free(struct amdgpu_job *job) |
| 152 | 161 | { |
| 153 | 162 | amdgpu_job_free_resources(job); |
| 154 | − | |
| 155 | − dma_fence_put(job->fence); | |
| 156 | 163 | amdgpu_sync_free(&job->sync); |
| 157 | 164 | amdgpu_sync_free(&job->sched_sync); |
| 158 | − kfree(job); | |
| 165 | + | |
| 166 | + /* only put the hw fence if has embedded fence */ | |
| 167 | + if (job->hw_fence.ops != NULL) | |
| 168 | + dma_fence_put(&job->hw_fence); | |
| 169 | + else | |
| 170 | + kfree(job); | |
| 159 | 171 | } |
| 160 | 172 | |
| 161 | 173 | int amdgpu_job_submit(struct amdgpu_job *job, struct drm_sched_entity *entity, |
| @@ -184,11 +196,14 @@ int amdgpu_job_submit_direct(struct amdgpu_job *job, struct amdgpu_ring *ring, · 22 unmodified lines | ||
| 184 | 196 | |
| 185 | 197 | job->base.sched = &ring->sched; |
| 186 | 198 | r = amdgpu_ib_schedule(ring, job->num_ibs, job->ibs, NULL, fence); |
| 187 | − job->fence = dma_fence_get(*fence); | |
| 199 | + /* record external_hw_fence for direct submit */ | |
| 200 | + job->external_hw_fence = dma_fence_get(*fence); | |
| 188 | 201 | if (r) |
| 189 | 202 | return r; |
| 190 | 203 | |
| 191 | 204 | amdgpu_job_free(job); |
| 205 | + dma_fence_put(*fence); | |
| 206 | + | |
| 192 | 207 | return 0; |
| 193 | 208 | } |
| 194 | 209 | |
| @@ -246,10 +261,12 @@ static struct dma_fence *amdgpu_job_run(struct drm_sched_job *sched_job) · 51 unmodified lines | ||
| 246 | 261 | if (r) |
| 247 | 262 | DRM_ERROR("Error scheduling IBs (%d)\n", r); |
| 248 | 263 | } |
| 249 | − /* if gpu reset, hw fence will be replaced here */ | |
| 250 | − dma_fence_put(job->fence); | |
| 251 | − job->fence = dma_fence_get(fence); | |
| 252 | 264 | |
| 265 | + if (!job->job_run_counter) | |
| 266 | + dma_fence_get(fence); | |
| 267 | + else if (finished->error < 0) | |
| 268 | + dma_fence_put(&job->hw_fence); | |
| 269 | + job->job_run_counter++; | |
| 253 | 270 | amdgpu_job_free_resources(job); |
| 254 | 271 | |
| 255 | 272 | fence = r ? ERR_PTR(r) : fence; |
| @@ -46,7 +46,8 @@ struct amdgpu_job { · 45 unmodified lines | ||
| 46 | 46 | struct amdgpu_sync sync; |
| 47 | 47 | struct amdgpu_sync sched_sync; |
| 48 | 48 | struct amdgpu_ib *ibs; |
| 49 | − struct dma_fence *fence; /* the hw fence */ | |
| 49 | + struct dma_fence hw_fence; | |
| 50 | + struct dma_fence *external_hw_fence; | |
| 50 | 51 | uint32_t preamble_status; |
| 51 | 52 | uint32_t preemption_status; |
| 52 | 53 | uint32_t num_ibs; |
| @@ -62,6 +63,9 @@ struct amdgpu_job { · 9 unmodified lines | ||
| 62 | 63 | /* user fence handling */ |
| 63 | 64 | uint64_t uf_addr; |
| 64 | 65 | uint64_t uf_sequence; |
| 66 | + | |
| 67 | + /* job_run_counter >= 1 means a resubmit job */ | |
| 68 | + uint32_t job_run_counter; | |
| 65 | 69 | }; |
| 66 | 70 | |
| 67 | 71 | int amdgpu_job_alloc(struct amdgpu_device *adev, unsigned num_ibs, |
| @@ -47,8 +47,6 @@ int amdgpu_jpeg_sw_fini(struct amdgpu_device *adev) · 46 unmodified lines | ||
| 47 | 47 | { |
| 48 | 48 | int i; |
| 49 | 49 | |
| 50 | − cancel_delayed_work_sync(&adev->jpeg.idle_work); | |
| 51 | − | |
| 52 | 50 | for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) { |
| 53 | 51 | if (adev->jpeg.harvest_config & (1 << i)) |
| 54 | 52 | continue; |
| @@ -341,27 +341,27 @@ static int amdgpu_firmware_info(struct drm_amdgpu_info_firmware *fw_info, · 340 unmodified lines | ||
| 341 | 341 | switch (query_fw->index) { |
| 342 | 342 | case TA_FW_TYPE_PSP_XGMI: |
| 343 | 343 | fw_info->ver = adev->psp.ta_fw_version; |
| 344 | − fw_info->feature = adev->psp.ta_xgmi_ucode_version; | |
| 344 | + fw_info->feature = adev->psp.xgmi.feature_version; | |
| 345 | 345 | break; |
| 346 | 346 | case TA_FW_TYPE_PSP_RAS: |
| 347 | 347 | fw_info->ver = adev->psp.ta_fw_version; |
| 348 | − fw_info->feature = adev->psp.ta_ras_ucode_version; | |
| 348 | + fw_info->feature = adev->psp.ras.feature_version; | |
| 349 | 349 | break; |
| 350 | 350 | case TA_FW_TYPE_PSP_HDCP: |
| 351 | 351 | fw_info->ver = adev->psp.ta_fw_version; |
| 352 | − fw_info->feature = adev->psp.ta_hdcp_ucode_version; | |
| 352 | + fw_info->feature = adev->psp.hdcp.feature_version; | |
| 353 | 353 | break; |
| 354 | 354 | case TA_FW_TYPE_PSP_DTM: |
| 355 | 355 | fw_info->ver = adev->psp.ta_fw_version; |
| 356 | − fw_info->feature = adev->psp.ta_dtm_ucode_version; | |
| 356 | + fw_info->feature = adev->psp.dtm.feature_version; | |
| 357 | 357 | break; |
| 358 | 358 | case TA_FW_TYPE_PSP_RAP: |
| 359 | 359 | fw_info->ver = adev->psp.ta_fw_version; |
| 360 | − fw_info->feature = adev->psp.ta_rap_ucode_version; | |
| 360 | + fw_info->feature = adev->psp.rap.feature_version; | |
| 361 | 361 | break; |
| 362 | 362 | case TA_FW_TYPE_PSP_SECUREDISPLAY: |
| 363 | 363 | fw_info->ver = adev->psp.ta_fw_version; |
| 364 | − fw_info->feature = adev->psp.ta_securedisplay_ucode_version; | |
| 364 | + fw_info->feature = adev->psp.securedisplay.feature_version; | |
| 365 | 365 | break; |
| 366 | 366 | default: |
| 367 | 367 | return -EINVAL; |
| @@ -374,12 +374,12 @@ static int amdgpu_firmware_info(struct drm_amdgpu_info_firmware *fw_info, · 6 unmodified lines | ||
| 374 | 374 | fw_info->feature = adev->sdma.instance[query_fw->index].feature_version; |
| 375 | 375 | break; |
| 376 | 376 | case AMDGPU_INFO_FW_SOS: |
| 377 | − fw_info->ver = adev->psp.sos_fw_version; | |
| 378 | − fw_info->feature = adev->psp.sos_feature_version; | |
| 377 | + fw_info->ver = adev->psp.sos.fw_version; | |
| 378 | + fw_info->feature = adev->psp.sos.feature_version; | |
| 379 | 379 | break; |
| 380 | 380 | case AMDGPU_INFO_FW_ASD: |
| 381 | − fw_info->ver = adev->psp.asd_fw_version; | |
| 382 | − fw_info->feature = adev->psp.asd_feature_version; | |
| 381 | + fw_info->ver = adev->psp.asd.fw_version; | |
| 382 | + fw_info->feature = adev->psp.asd.feature_version; | |
| 383 | 383 | break; |
| 384 | 384 | case AMDGPU_INFO_FW_DMCU: |
| 385 | 385 | fw_info->ver = adev->dm.dmcu_fw_version; |
| @@ -390,8 +390,8 @@ static int amdgpu_firmware_info(struct drm_amdgpu_info_firmware *fw_info, · 4 unmodified lines | ||
| 390 | 390 | fw_info->feature = 0; |
| 391 | 391 | break; |
| 392 | 392 | case AMDGPU_INFO_FW_TOC: |
| 393 | − fw_info->ver = adev->psp.toc_fw_version; | |
| 394 | − fw_info->feature = adev->psp.toc_feature_version; | |
| 393 | + fw_info->ver = adev->psp.toc.fw_version; | |
| 394 | + fw_info->feature = adev->psp.toc.feature_version; | |
| 395 | 395 | break; |
| 396 | 396 | default: |
| 397 | 397 | return -EINVAL; |
| @@ -1179,10 +1179,14 @@ int amdgpu_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv) · 781 unmodified lines | ||
| 1179 | 1179 | pasid = 0; |
| 1180 | 1180 | } |
| 1181 | 1181 | |
| 1182 | − r = amdgpu_vm_init(adev, &fpriv->vm, pasid); | |
| 1182 | + r = amdgpu_vm_init(adev, &fpriv->vm); | |
| 1183 | 1183 | if (r) |
| 1184 | 1184 | goto error_pasid; |
| 1185 | 1185 | |
| 1186 | + r = amdgpu_vm_set_pasid(adev, &fpriv->vm, pasid); | |
| 1187 | + if (r) | |
| 1188 | + goto error_vm; | |
| 1189 | + | |
| 1186 | 1190 | fpriv->prt_va = amdgpu_vm_bo_add(adev, &fpriv->vm, NULL); |
| 1187 | 1191 | if (!fpriv->prt_va) { |
| 1188 | 1192 | r = -ENOMEM; |
| @@ -1210,8 +1214,10 @@ error_vm: · 21 unmodified lines | ||
| 1210 | 1214 | amdgpu_vm_fini(adev, &fpriv->vm); |
| 1211 | 1215 | |
| 1212 | 1216 | error_pasid: |
| 1213 | − if (pasid) | |
| 1217 | + if (pasid) { | |
| 1214 | 1218 | amdgpu_pasid_free(pasid); |
| 1219 | + amdgpu_vm_set_pasid(adev, &fpriv->vm, 0); | |
| 1220 | + } | |
| 1215 | 1221 | |
| 1216 | 1222 | kfree(fpriv); |
| 1217 | 1223 | |
| @@ -0,0 +1,117 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright 2021 Advanced Micro Devices, Inc. | |
| 3 | + * | |
| 4 | + * Permission is hereby granted, free of charge, to any person obtaining a | |
| 5 | + * copy of this software and associated documentation files (the "Software"), | |
| 6 | + * to deal in the Software without restriction, including without limitation | |
| 7 | + * the rights to use, copy, modify, merge, publish, distribute, sublicense, | |
| 8 | + * and/or sell copies of the Software, and to permit persons to whom the | |
| 9 | + * Software is furnished to do so, subject to the following conditions: | |
| 10 | + * | |
| 11 | + * The above copyright notice and this permission notice shall be included in | |
| 12 | + * all copies or substantial portions of the Software. | |
| 13 | + * | |
| 14 | + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
| 15 | + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
| 16 | + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |
| 17 | + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR | |
| 18 | + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | |
| 19 | + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | |
| 20 | + * OTHER DEALINGS IN THE SOFTWARE. | |
| 21 | + * | |
| 22 | + */ | |
| 23 | +#include "amdgpu_ras.h" | |
| 24 | +#include "amdgpu.h" | |
| 25 | +#include "amdgpu_mca.h" | |
| 26 | + | |
| 27 | +#include "umc/umc_6_7_0_offset.h" | |
| 28 | +#include "umc/umc_6_7_0_sh_mask.h" | |
| 29 | + | |
| 30 | +void amdgpu_mca_query_correctable_error_count(struct amdgpu_device *adev, | |
| 31 | + uint64_t mc_status_addr, | |
| 32 | + unsigned long *error_count) | |
| 33 | +{ | |
| 34 | + uint64_t mc_status = RREG64_PCIE(mc_status_addr * 4); | |
| 35 | + | |
| 36 | + if (REG_GET_FIELD(mc_status, MCA_UMC_UMC0_MCUMC_STATUST0, Val) == 1 && | |
| 37 | + REG_GET_FIELD(mc_status, MCA_UMC_UMC0_MCUMC_STATUST0, CECC) == 1) | |
| 38 | + *error_count += 1; | |
| 39 | +} | |
| 40 | + | |
| 41 | +void amdgpu_mca_query_uncorrectable_error_count(struct amdgpu_device *adev, | |
| 42 | + uint64_t mc_status_addr, | |
| 43 | + unsigned long *error_count) | |
| 44 | +{ | |
| 45 | + uint64_t mc_status = RREG64_PCIE(mc_status_addr * 4); | |
| 46 | + | |
| 47 | + if ((REG_GET_FIELD(mc_status, MCA_UMC_UMC0_MCUMC_STATUST0, Val) == 1) && | |
| 48 | + (REG_GET_FIELD(mc_status, MCA_UMC_UMC0_MCUMC_STATUST0, Deferred) == 1 || | |
| 49 | + REG_GET_FIELD(mc_status, MCA_UMC_UMC0_MCUMC_STATUST0, UECC) == 1 || | |
| 50 | + REG_GET_FIELD(mc_status, MCA_UMC_UMC0_MCUMC_STATUST0, PCC) == 1 || | |
| 51 | + REG_GET_FIELD(mc_status, MCA_UMC_UMC0_MCUMC_STATUST0, UC) == 1 || | |
| 52 | + REG_GET_FIELD(mc_status, MCA_UMC_UMC0_MCUMC_STATUST0, TCC) == 1)) | |
| 53 | + *error_count += 1; | |
| 54 | +} | |
| 55 | + | |
| 56 | +void amdgpu_mca_reset_error_count(struct amdgpu_device *adev, | |
| 57 | + uint64_t mc_status_addr) | |
| 58 | +{ | |
| 59 | + WREG64_PCIE(mc_status_addr * 4, 0x0ULL); | |
| 60 | +} | |
| 61 | + | |
| 62 | +void amdgpu_mca_query_ras_error_count(struct amdgpu_device *adev, | |
| 63 | + uint64_t mc_status_addr, | |
| 64 | + void *ras_error_status) | |
| 65 | +{ | |
| 66 | + struct ras_err_data *err_data = (struct ras_err_data *)ras_error_status; | |
| 67 | + | |
| 68 | + amdgpu_mca_query_correctable_error_count(adev, mc_status_addr, &(err_data->ce_count)); | |
| 69 | + amdgpu_mca_query_uncorrectable_error_count(adev, mc_status_addr, &(err_data->ue_count)); | |
| 70 | + | |
| 71 | + amdgpu_mca_reset_error_count(adev, mc_status_addr); | |
| 72 | +} | |
| 73 | + | |
| 74 | +int amdgpu_mca_ras_late_init(struct amdgpu_device *adev, | |
| 75 | + struct amdgpu_mca_ras *mca_dev) | |
| 76 | +{ | |
| 77 | + int r; | |
| 78 | + struct ras_ih_if ih_info = { | |
| 79 | + .cb = NULL, | |
| 80 | + }; | |
| 81 | + struct ras_fs_if fs_info = { | |
| 82 | + .sysfs_name = mca_dev->ras_funcs->sysfs_name, | |
| 83 | + }; | |
| 84 | + | |
| 85 | + if (!mca_dev->ras_if) { | |
| 86 | + mca_dev->ras_if = kmalloc(sizeof(struct ras_common_if), GFP_KERNEL); | |
| 87 | + if (!mca_dev->ras_if) | |
| 88 | + return -ENOMEM; | |
| 89 | + mca_dev->ras_if->block = mca_dev->ras_funcs->ras_block; | |
| 90 | + mca_dev->ras_if->type = AMDGPU_RAS_ERROR__MULTI_UNCORRECTABLE; | |
| 91 | + mca_dev->ras_if->sub_block_index = 0; | |
| 92 | + } | |
| 93 | + ih_info.head = fs_info.head = *mca_dev->ras_if; | |
| 94 | + r = amdgpu_ras_late_init(adev, mca_dev->ras_if, | |
| 95 | + &fs_info, &ih_info); | |
| 96 | + if (r || !amdgpu_ras_is_supported(adev, mca_dev->ras_if->block)) { | |
| 97 | + kfree(mca_dev->ras_if); | |
| 98 | + mca_dev->ras_if = NULL; | |
| 99 | + } | |
| 100 | + | |
| 101 | + return r; | |
| 102 | +} | |
| 103 | + | |
| 104 | +void amdgpu_mca_ras_fini(struct amdgpu_device *adev, | |
| 105 | + struct amdgpu_mca_ras *mca_dev) | |
| 106 | +{ | |
| 107 | + struct ras_ih_if ih_info = { | |
| 108 | + .cb = NULL, | |
| 109 | + }; | |
| 110 | + | |
| 111 | + if (!mca_dev->ras_if) | |
| 112 | + return; | |
| 113 | + | |
| 114 | + amdgpu_ras_late_fini(adev, mca_dev->ras_if, &ih_info); | |
| 115 | + kfree(mca_dev->ras_if); | |
| 116 | + mca_dev->ras_if = NULL; | |
| 117 | +} | |
| @@ -0,0 +1,72 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright (C) 2021 Advanced Micro Devices, Inc. | |
| 3 | + * | |
| 4 | + * Permission is hereby granted, free of charge, to any person obtaining a | |
| 5 | + * copy of this software and associated documentation files (the "Software"), | |
| 6 | + * to deal in the Software without restriction, including without limitation | |
| 7 | + * the rights to use, copy, modify, merge, publish, distribute, sublicense, | |
| 8 | + * and/or sell copies of the Software, and to permit persons to whom the | |
| 9 | + * Software is furnished to do so, subject to the following conditions: | |
| 10 | + * | |
| 11 | + * The above copyright notice and this permission notice shall be included | |
| 12 | + * in all copies or substantial portions of the Software. | |
| 13 | + * | |
| 14 | + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | |
| 15 | + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
| 16 | + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |
| 17 | + * THE COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN | |
| 18 | + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | |
| 19 | + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |
| 20 | + */ | |
| 21 | +#ifndef __AMDGPU_MCA_H__ | |
| 22 | +#define __AMDGPU_MCA_H__ | |
| 23 | + | |
| 24 | +struct amdgpu_mca_ras_funcs { | |
| 25 | + int (*ras_late_init)(struct amdgpu_device *adev); | |
| 26 | + void (*ras_fini)(struct amdgpu_device *adev); | |
| 27 | + void (*query_ras_error_count)(struct amdgpu_device *adev, | |
| 28 | + void *ras_error_status); | |
| 29 | + void (*query_ras_error_address)(struct amdgpu_device *adev, | |
| 30 | + void *ras_error_status); | |
| 31 | + uint32_t ras_block; | |
| 32 | + const char* sysfs_name; | |
| 33 | +}; | |
| 34 | + | |
| 35 | +struct amdgpu_mca_ras { | |
| 36 | + struct ras_common_if *ras_if; | |
| 37 | + const struct amdgpu_mca_ras_funcs *ras_funcs; | |
| 38 | +}; | |
| 39 | + | |
| 40 | +struct amdgpu_mca_funcs { | |
| 41 | + void (*init)(struct amdgpu_device *adev); | |
| 42 | +}; | |
| 43 | + | |
| 44 | +struct amdgpu_mca { | |
| 45 | + const struct amdgpu_mca_funcs *funcs; | |
| 46 | + struct amdgpu_mca_ras mp0; | |
| 47 | + struct amdgpu_mca_ras mp1; | |
| 48 | + struct amdgpu_mca_ras mpio; | |
| 49 | +}; | |
| 50 | + | |
| 51 | +void amdgpu_mca_query_correctable_error_count(struct amdgpu_device *adev, | |
| 52 | + uint64_t mc_status_addr, | |
| 53 | + unsigned long *error_count); | |
| 54 | + | |
| 55 | +void amdgpu_mca_query_uncorrectable_error_count(struct amdgpu_device *adev, | |
| 56 | + uint64_t mc_status_addr, | |
| 57 | + unsigned long *error_count); | |
| 58 | + | |
| 59 | +void amdgpu_mca_reset_error_count(struct amdgpu_device *adev, | |
| 60 | + uint64_t mc_status_addr); | |
| 61 | + | |
| 62 | +void amdgpu_mca_query_ras_error_count(struct amdgpu_device *adev, | |
| 63 | + uint64_t mc_status_addr, | |
| 64 | + void *ras_error_status); | |
| 65 | + | |
| 66 | +int amdgpu_mca_ras_late_init(struct amdgpu_device *adev, | |
| 67 | + struct amdgpu_mca_ras *mca_dev); | |
| 68 | + | |
| 69 | +void amdgpu_mca_ras_fini(struct amdgpu_device *adev, | |
| 70 | + struct amdgpu_mca_ras *mca_dev); | |
| 71 | + | |
| 72 | +#endif | |
| @@ -41,7 +41,6 @@ int amdgpu_mmhub_ras_late_init(struct amdgpu_device *adev) · 40 unmodified lines | ||
| 41 | 41 | adev->mmhub.ras_if->block = AMDGPU_RAS_BLOCK__MMHUB; |
| 42 | 42 | adev->mmhub.ras_if->type = AMDGPU_RAS_ERROR__MULTI_UNCORRECTABLE; |
| 43 | 43 | adev->mmhub.ras_if->sub_block_index = 0; |
| 44 | − strcpy(adev->mmhub.ras_if->name, "mmhub"); | |
| 45 | 44 | } |
| 46 | 45 | ih_info.head = fs_info.head = *adev->mmhub.ras_if; |
| 47 | 46 | r = amdgpu_ras_late_init(adev, adev->mmhub.ras_if, |
| @@ -39,7 +39,6 @@ int amdgpu_nbio_ras_late_init(struct amdgpu_device *adev) · 38 unmodified lines | ||
| 39 | 39 | adev->nbio.ras_if->block = AMDGPU_RAS_BLOCK__PCIE_BIF; |
| 40 | 40 | adev->nbio.ras_if->type = AMDGPU_RAS_ERROR__MULTI_UNCORRECTABLE; |
| 41 | 41 | adev->nbio.ras_if->sub_block_index = 0; |
| 42 | − strcpy(adev->nbio.ras_if->name, "pcie_bif"); | |
| 43 | 42 | } |
| 44 | 43 | ih_info.head = fs_info.head = *adev->nbio.ras_if; |
| 45 | 44 | r = amdgpu_ras_late_init(adev, adev->nbio.ras_if, |
| @@ -95,6 +95,7 @@ struct amdgpu_nbio_funcs { · 94 unmodified lines | ||
| 95 | 95 | void (*program_aspm)(struct amdgpu_device *adev); |
| 96 | 96 | void (*apply_lc_spc_mode_wa)(struct amdgpu_device *adev); |
| 97 | 97 | void (*apply_l1_link_width_reconfig_wa)(struct amdgpu_device *adev); |
| 98 | + void (*clear_doorbell_interrupt)(struct amdgpu_device *adev); | |
| 98 | 99 | }; |
| 99 | 100 | |
| 100 | 101 | struct amdgpu_nbio { |
| @@ -196,7 +196,7 @@ void amdgpu_bo_placement_from_domain(struct amdgpu_bo *abo, u32 domain) · 195 unmodified lines | ||
| 196 | 196 | c++; |
| 197 | 197 | } |
| 198 | 198 | |
| 199 | − BUG_ON(c >= AMDGPU_BO_MAX_PLACEMENTS); | |
| 199 | + BUG_ON(c > AMDGPU_BO_MAX_PLACEMENTS); | |
| 200 | 200 | |
| 201 | 201 | placement->num_placement = c; |
| 202 | 202 | placement->placement = places; |
| @@ -731,7 +731,7 @@ retry: · 528 unmodified lines | ||
| 731 | 731 | /** |
| 732 | 732 | * amdgpu_bo_add_to_shadow_list - add a BO to the shadow list |
| 733 | 733 | * |
| 734 | − * @bo: BO that will be inserted into the shadow list | |
| 734 | + * @vmbo: BO that will be inserted into the shadow list | |
| 735 | 735 | * |
| 736 | 736 | * Insert a BO to the shadow list. |
| 737 | 737 | */ |
| @@ -913,7 +913,7 @@ int amdgpu_bo_pin_restricted(struct amdgpu_bo *bo, u32 domain, · 175 unmodified lines | ||
| 913 | 913 | return -EINVAL; |
| 914 | 914 | |
| 915 | 915 | /* A shared bo cannot be migrated to VRAM */ |
| 916 | − if (bo->prime_shared_count || bo->tbo.base.import_attach) { | |
| 916 | + if (bo->tbo.base.import_attach) { | |
| 917 | 917 | if (domain & AMDGPU_GEM_DOMAIN_GTT) |
| 918 | 918 | domain = AMDGPU_GEM_DOMAIN_GTT; |
| 919 | 919 | else |
| @@ -947,7 +947,7 @@ int amdgpu_bo_pin_restricted(struct amdgpu_bo *bo, u32 domain, · 27 unmodified lines | ||
| 947 | 947 | /* This assumes only APU display buffers are pinned with (VRAM|GTT). |
| 948 | 948 | * See function amdgpu_display_supported_domains() |
| 949 | 949 | */ |
| 950 | − domain = amdgpu_bo_get_preferred_pin_domain(adev, domain); | |
| 950 | + domain = amdgpu_bo_get_preferred_domain(adev, domain); | |
| 951 | 951 | |
| 952 | 952 | if (bo->tbo.base.import_attach) |
| 953 | 953 | dma_buf_pin(bo->tbo.base.import_attach); |
| @@ -1518,14 +1518,14 @@ u64 amdgpu_bo_gpu_offset_no_check(struct amdgpu_bo *bo) · 564 unmodified lines | ||
| 1518 | 1518 | } |
| 1519 | 1519 | |
| 1520 | 1520 | /** |
| 1521 | − * amdgpu_bo_get_preferred_pin_domain - get preferred domain for scanout | |
| 1521 | + * amdgpu_bo_get_preferred_domain - get preferred domain | |
| 1522 | 1522 | * @adev: amdgpu device object |
| 1523 | 1523 | * @domain: allowed :ref:`memory domains <amdgpu_memory_domains>` |
| 1524 | 1524 | * |
| 1525 | 1525 | * Returns: |
| 1526 | − * Which of the allowed domains is preferred for pinning the BO for scanout. | |
| 1526 | + * Which of the allowed domains is preferred for allocating the BO. | |
| 1527 | 1527 | */ |
| 1528 | −uint32_t amdgpu_bo_get_preferred_pin_domain(struct amdgpu_device *adev, | |
| 1528 | +uint32_t amdgpu_bo_get_preferred_domain(struct amdgpu_device *adev, | |
| 1529 | 1529 | uint32_t domain) |
| 1530 | 1530 | { |
| 1531 | 1531 | if (domain == (AMDGPU_GEM_DOMAIN_VRAM | AMDGPU_GEM_DOMAIN_GTT)) { |
| @@ -100,7 +100,6 @@ struct amdgpu_bo { · 99 unmodified lines | ||
| 100 | 100 | struct ttm_buffer_object tbo; |
| 101 | 101 | struct ttm_bo_kmap_obj kmap; |
| 102 | 102 | u64 flags; |
| 103 | − unsigned prime_shared_count; | |
| 104 | 103 | /* per VM structure for page tables and with virtual addresses */ |
| 105 | 104 | struct amdgpu_vm_bo_base *vm_bo; |
| 106 | 105 | /* Constant after initialization */ |
| @@ -334,7 +333,7 @@ void amdgpu_bo_get_memory(struct amdgpu_bo *bo, uint64_t *vram_mem, · 227 unmodified lines | ||
| 334 | 333 | void amdgpu_bo_add_to_shadow_list(struct amdgpu_bo_vm *vmbo); |
| 335 | 334 | int amdgpu_bo_restore_shadow(struct amdgpu_bo *shadow, |
| 336 | 335 | struct dma_fence **fence); |
| 337 | −uint32_t amdgpu_bo_get_preferred_pin_domain(struct amdgpu_device *adev, | |
| 336 | +uint32_t amdgpu_bo_get_preferred_domain(struct amdgpu_device *adev, | |
| 338 | 337 | uint32_t domain); |
| 339 | 338 | |
| 340 | 339 | /* |
| @@ -80,12 +80,17 @@ static void amdgpu_pll_reduce_ratio(unsigned *nom, unsigned *den, · 79 unmodified lines | ||
| 80 | 80 | * Calculate feedback and reference divider for a given post divider. Makes |
| 81 | 81 | * sure we stay within the limits. |
| 82 | 82 | */ |
| 83 | −static void amdgpu_pll_get_fb_ref_div(unsigned nom, unsigned den, unsigned post_div, | |
| 84 | − unsigned fb_div_max, unsigned ref_div_max, | |
| 85 | − unsigned *fb_div, unsigned *ref_div) | |
| 83 | +static void amdgpu_pll_get_fb_ref_div(struct amdgpu_device *adev, unsigned int nom, | |
| 84 | + unsigned int den, unsigned int post_div, | |
| 85 | + unsigned int fb_div_max, unsigned int ref_div_max, | |
| 86 | + unsigned int *fb_div, unsigned int *ref_div) | |
| 86 | 87 | { |
| 88 | + | |
| 87 | 89 | /* limit reference * post divider to a maximum */ |
| 88 | − ref_div_max = min(128 / post_div, ref_div_max); | |
| 90 | + if (adev->family == AMDGPU_FAMILY_SI) | |
| 91 | + ref_div_max = min(100 / post_div, ref_div_max); | |
| 92 | + else | |
| 93 | + ref_div_max = min(128 / post_div, ref_div_max); | |
| 89 | 94 | |
| 90 | 95 | /* get matching reference and feedback divider */ |
| 91 | 96 | *ref_div = min(max(DIV_ROUND_CLOSEST(den, post_div), 1u), ref_div_max); |
| @@ -112,7 +117,8 @@ static void amdgpu_pll_get_fb_ref_div(unsigned nom, unsigned den, unsigned post_ · 20 unmodified lines | ||
| 112 | 117 | * Try to calculate the PLL parameters to generate the given frequency: |
| 113 | 118 | * dot_clock = (ref_freq * feedback_div) / (ref_div * post_div) |
| 114 | 119 | */ |
| 115 | −void amdgpu_pll_compute(struct amdgpu_pll *pll, | |
| 120 | +void amdgpu_pll_compute(struct amdgpu_device *adev, | |
| 121 | + struct amdgpu_pll *pll, | |
| 116 | 122 | u32 freq, |
| 117 | 123 | u32 *dot_clock_p, |
| 118 | 124 | u32 *fb_div_p, |
| @@ -199,7 +205,7 @@ void amdgpu_pll_compute(struct amdgpu_pll *pll, · 80 unmodified lines | ||
| 199 | 205 | |
| 200 | 206 | for (post_div = post_div_min; post_div <= post_div_max; ++post_div) { |
| 201 | 207 | unsigned diff; |
| 202 | − amdgpu_pll_get_fb_ref_div(nom, den, post_div, fb_div_max, | |
| 208 | + amdgpu_pll_get_fb_ref_div(adev, nom, den, post_div, fb_div_max, | |
| 203 | 209 | ref_div_max, &fb_div, &ref_div); |
| 204 | 210 | diff = abs(target_clock - (pll->reference_freq * fb_div) / |
| 205 | 211 | (ref_div * post_div)); |
| @@ -214,7 +220,7 @@ void amdgpu_pll_compute(struct amdgpu_pll *pll, · 8 unmodified lines | ||
| 214 | 220 | post_div = post_div_best; |
| 215 | 221 | |
| 216 | 222 | /* get the feedback and reference divider for the optimal value */ |
| 217 | − amdgpu_pll_get_fb_ref_div(nom, den, post_div, fb_div_max, ref_div_max, | |
| 223 | + amdgpu_pll_get_fb_ref_div(adev, nom, den, post_div, fb_div_max, ref_div_max, | |
| 218 | 224 | &fb_div, &ref_div); |
| 219 | 225 | |
| 220 | 226 | /* reduce the numbers to a simpler ratio once more */ |
| @@ -24,7 +24,8 @@ · 23 unmodified lines | ||
| 24 | 24 | #ifndef __AMDGPU_PLL_H__ |
| 25 | 25 | #define __AMDGPU_PLL_H__ |
| 26 | 26 | |
| 27 | −void amdgpu_pll_compute(struct amdgpu_pll *pll, | |
| 27 | +void amdgpu_pll_compute(struct amdgpu_device *adev, | |
| 28 | + struct amdgpu_pll *pll, | |
| 28 | 29 | u32 freq, |
| 29 | 30 | u32 *dot_clock_p, |
| 30 | 31 | u32 *fb_div_p, |
| @@ -24,16 +24,17 @@ · 23 unmodified lines | ||
| 24 | 24 | */ |
| 25 | 25 | |
| 26 | 26 | #include <linux/firmware.h> |
| 27 | −#include <linux/dma-mapping.h> | |
| 28 | 27 | #include <drm/drm_drv.h> |
| 29 | 28 | |
| 30 | 29 | #include "amdgpu.h" |
| 31 | 30 | #include "amdgpu_psp.h" |
| 32 | 31 | #include "amdgpu_ucode.h" |
| 32 | +#include "amdgpu_xgmi.h" | |
| 33 | 33 | #include "soc15_common.h" |
| 34 | 34 | #include "psp_v3_1.h" |
| 35 | 35 | #include "psp_v10_0.h" |
| 36 | 36 | #include "psp_v11_0.h" |
| 37 | +#include "psp_v11_0_8.h" | |
| 37 | 38 | #include "psp_v12_0.h" |
| 38 | 39 | #include "psp_v13_0.h" |
| 39 | 40 | |
| @@ -41,8 +42,6 @@ · 1 unmodified line | ||
| 41 | 42 | #include "amdgpu_securedisplay.h" |
| 42 | 43 | #include "amdgpu_atomfirmware.h" |
| 43 | 44 | |
| 44 | −#include <drm/drm_drv.h> | |
| 45 | − | |
| 46 | 45 | static int psp_sysfs_init(struct amdgpu_device *adev); |
| 47 | 46 | static void psp_sysfs_fini(struct amdgpu_device *adev); |
| 48 | 47 | |
| @@ -122,6 +121,12 @@ static int psp_early_init(void *handle) · 73 unmodified lines | ||
| 122 | 121 | psp_v13_0_set_psp_funcs(psp); |
| 123 | 122 | psp->autoload_supported = true; |
| 124 | 123 | break; |
| 124 | + case CHIP_CYAN_SKILLFISH: | |
| 125 | + if (adev->apu_flags & AMD_APU_IS_CYAN_SKILLFISH2) { | |
| 126 | + psp_v11_0_8_set_psp_funcs(psp); | |
| 127 | + psp->autoload_supported = false; | |
| 128 | + } | |
| 129 | + break; | |
| 125 | 130 | default: |
| 126 | 131 | return -EINVAL; |
| 127 | 132 | } |
| @@ -247,6 +252,12 @@ static int psp_sw_init(void *handle) · 119 unmodified lines | ||
| 247 | 252 | struct psp_runtime_boot_cfg_entry boot_cfg_entry; |
| 248 | 253 | struct psp_memory_training_context *mem_training_ctx = &psp->mem_train_ctx; |
| 249 | 254 | |
| 255 | + psp->cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL); | |
| 256 | + if (!psp->cmd) { | |
| 257 | + DRM_ERROR("Failed to allocate memory to command buffer!\n"); | |
| 258 | + ret = -ENOMEM; | |
| 259 | + } | |
| 260 | + | |
| 250 | 261 | if (!amdgpu_sriov_vf(adev)) { |
| 251 | 262 | ret = psp_init_microcode(psp); |
| 252 | 263 | if (ret) { |
| @@ -309,25 +320,30 @@ static int psp_sw_init(void *handle) · 56 unmodified lines | ||
| 309 | 320 | static int psp_sw_fini(void *handle) |
| 310 | 321 | { |
| 311 | 322 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; |
| 323 | + struct psp_context *psp = &adev->psp; | |
| 324 | + struct psp_gfx_cmd_resp *cmd = psp->cmd; | |
| 312 | 325 | |
| 313 | − psp_memory_training_fini(&adev->psp); | |
| 314 | − if (adev->psp.sos_fw) { | |
| 315 | − release_firmware(adev->psp.sos_fw); | |
| 316 | − adev->psp.sos_fw = NULL; | |
| 326 | + psp_memory_training_fini(psp); | |
| 327 | + if (psp->sos_fw) { | |
| 328 | + release_firmware(psp->sos_fw); | |
| 329 | + psp->sos_fw = NULL; | |
| 317 | 330 | } |
| 318 | − if (adev->psp.asd_fw) { | |
| 319 | − release_firmware(adev->psp.asd_fw); | |
| 320 | − adev->psp.asd_fw = NULL; | |
| 331 | + if (psp->asd_fw) { | |
| 332 | + release_firmware(psp->asd_fw); | |
| 333 | + psp->asd_fw = NULL; | |
| 321 | 334 | } |
| 322 | − if (adev->psp.ta_fw) { | |
| 323 | − release_firmware(adev->psp.ta_fw); | |
| 324 | − adev->psp.ta_fw = NULL; | |
| 335 | + if (psp->ta_fw) { | |
| 336 | + release_firmware(psp->ta_fw); | |
| 337 | + psp->ta_fw = NULL; | |
| 325 | 338 | } |
| 326 | 339 | |
| 327 | 340 | if (adev->asic_type == CHIP_NAVI10 || |
| 328 | 341 | adev->asic_type == CHIP_SIENNA_CICHLID) |
| 329 | 342 | psp_sysfs_fini(adev); |
| 330 | 343 | |
| 344 | + kfree(cmd); | |
| 345 | + cmd = NULL; | |
| 346 | + | |
| 331 | 347 | return 0; |
| 332 | 348 | } |
| 333 | 349 | |
| @@ -356,6 +372,44 @@ int psp_wait_for(struct psp_context *psp, uint32_t reg_index, · 22 unmodified lines | ||
| 356 | 372 | return -ETIME; |
| 357 | 373 | } |
| 358 | 374 | |
| 375 | +static const char *psp_gfx_cmd_name(enum psp_gfx_cmd_id cmd_id) | |
| 376 | +{ | |
| 377 | + switch (cmd_id) { | |
| 378 | + case GFX_CMD_ID_LOAD_TA: | |
| 379 | + return "LOAD_TA"; | |
| 380 | + case GFX_CMD_ID_UNLOAD_TA: | |
| 381 | + return "UNLOAD_TA"; | |
| 382 | + case GFX_CMD_ID_INVOKE_CMD: | |
| 383 | + return "INVOKE_CMD"; | |
| 384 | + case GFX_CMD_ID_LOAD_ASD: | |
| 385 | + return "LOAD_ASD"; | |
| 386 | + case GFX_CMD_ID_SETUP_TMR: | |
| 387 | + return "SETUP_TMR"; | |
| 388 | + case GFX_CMD_ID_LOAD_IP_FW: | |
| 389 | + return "LOAD_IP_FW"; | |
| 390 | + case GFX_CMD_ID_DESTROY_TMR: | |
| 391 | + return "DESTROY_TMR"; | |
| 392 | + case GFX_CMD_ID_SAVE_RESTORE: | |
| 393 | + return "SAVE_RESTORE_IP_FW"; | |
| 394 | + case GFX_CMD_ID_SETUP_VMR: | |
| 395 | + return "SETUP_VMR"; | |
| 396 | + case GFX_CMD_ID_DESTROY_VMR: | |
| 397 | + return "DESTROY_VMR"; | |
| 398 | + case GFX_CMD_ID_PROG_REG: | |
| 399 | + return "PROG_REG"; | |
| 400 | + case GFX_CMD_ID_GET_FW_ATTESTATION: | |
| 401 | + return "GET_FW_ATTESTATION"; | |
| 402 | + case GFX_CMD_ID_LOAD_TOC: | |
| 403 | + return "ID_LOAD_TOC"; | |
| 404 | + case GFX_CMD_ID_AUTOLOAD_RLC: | |
| 405 | + return "AUTOLOAD_RLC"; | |
| 406 | + case GFX_CMD_ID_BOOT_CFG: | |
| 407 | + return "BOOT_CFG"; | |
| 408 | + default: | |
| 409 | + return "UNKNOWN CMD"; | |
| 410 | + } | |
| 411 | +} | |
| 412 | + | |
| 359 | 413 | static int |
| 360 | 414 | psp_cmd_submit_buf(struct psp_context *psp, |
| 361 | 415 | struct amdgpu_firmware_info *ucode, |
| @@ -373,8 +427,6 @@ psp_cmd_submit_buf(struct psp_context *psp, · 11 unmodified lines | ||
| 373 | 427 | if (!drm_dev_enter(&psp->adev->ddev, &idx)) |
| 374 | 428 | return 0; |
| 375 | 429 | |
| 376 | − mutex_lock(&psp->mutex); | |
| 377 | − | |
| 378 | 430 | memset(psp->cmd_buf_mem, 0, PSP_CMD_BUFFER_SIZE); |
| 379 | 431 | |
| 380 | 432 | memcpy(psp->cmd_buf_mem, cmd, sizeof(struct psp_gfx_cmd_resp)); |
| @@ -417,10 +469,10 @@ psp_cmd_submit_buf(struct psp_context *psp, · 36 unmodified lines | ||
| 417 | 469 | */ |
| 418 | 470 | if (!skip_unsupport && (psp->cmd_buf_mem->resp.status || !timeout) && !ras_intr) { |
| 419 | 471 | if (ucode) |
| 420 | − DRM_WARN("failed to load ucode id (%d) ", | |
| 421 | − ucode->ucode_id); | |
| 422 | − DRM_WARN("psp command (0x%X) failed and response status is (0x%X)\n", | |
| 423 | − psp->cmd_buf_mem->cmd_id, | |
| 472 | + DRM_WARN("failed to load ucode (%s) ", | |
| 473 | + amdgpu_ucode_name(ucode->ucode_id)); | |
| 474 | + DRM_WARN("psp gfx command (%s) failed and response status is (0x%X)\n", | |
| 475 | + psp_gfx_cmd_name(psp->cmd_buf_mem->cmd_id), | |
| 424 | 476 | psp->cmd_buf_mem->resp.status); |
| 425 | 477 | if (!timeout) { |
| 426 | 478 | ret = -EINVAL; |
| @@ -434,11 +486,26 @@ psp_cmd_submit_buf(struct psp_context *psp, · 7 unmodified lines | ||
| 434 | 486 | } |
| 435 | 487 | |
| 436 | 488 | exit: |
| 437 | − mutex_unlock(&psp->mutex); | |
| 438 | 489 | drm_dev_exit(idx); |
| 439 | 490 | return ret; |
| 440 | 491 | } |
| 441 | 492 | |
| 493 | +static struct psp_gfx_cmd_resp *acquire_psp_cmd_buf(struct psp_context *psp) | |
| 494 | +{ | |
| 495 | + struct psp_gfx_cmd_resp *cmd = psp->cmd; | |
| 496 | + | |
| 497 | + mutex_lock(&psp->mutex); | |
| 498 | + | |
| 499 | + memset(cmd, 0, sizeof(struct psp_gfx_cmd_resp)); | |
| 500 | + | |
| 501 | + return cmd; | |
| 502 | +} | |
| 503 | + | |
| 504 | +void release_psp_cmd_buf(struct psp_context *psp) | |
| 505 | +{ | |
| 506 | + mutex_unlock(&psp->mutex); | |
| 507 | +} | |
| 508 | + | |
| 442 | 509 | static void psp_prep_tmr_cmd_buf(struct psp_context *psp, |
| 443 | 510 | struct psp_gfx_cmd_resp *cmd, |
| 444 | 511 | uint64_t tmr_mc, struct amdgpu_bo *tmr_bo) |
| @@ -473,21 +540,20 @@ static int psp_load_toc(struct psp_context *psp, · 28 unmodified lines | ||
| 473 | 540 | uint32_t *tmr_size) |
| 474 | 541 | { |
| 475 | 542 | int ret; |
| 476 | − struct psp_gfx_cmd_resp *cmd; | |
| 543 | + struct psp_gfx_cmd_resp *cmd = acquire_psp_cmd_buf(psp); | |
| 477 | 544 | |
| 478 | − cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL); | |
| 479 | − if (!cmd) | |
| 480 | − return -ENOMEM; | |
| 481 | 545 | /* Copy toc to psp firmware private buffer */ |
| 482 | − psp_copy_fw(psp, psp->toc_start_addr, psp->toc_bin_size); | |
| 546 | + psp_copy_fw(psp, psp->toc.start_addr, psp->toc.size_bytes); | |
| 483 | 547 | |
| 484 | − psp_prep_load_toc_cmd_buf(cmd, psp->fw_pri_mc_addr, psp->toc_bin_size); | |
| 548 | + psp_prep_load_toc_cmd_buf(cmd, psp->fw_pri_mc_addr, psp->toc.size_bytes); | |
| 485 | 549 | |
| 486 | 550 | ret = psp_cmd_submit_buf(psp, NULL, cmd, |
| 487 | 551 | psp->fence_buf_mc_addr); |
| 488 | 552 | if (!ret) |
| 489 | 553 | *tmr_size = psp->cmd_buf_mem->resp.tmr_size; |
| 490 | − kfree(cmd); | |
| 554 | + | |
| 555 | + release_psp_cmd_buf(psp); | |
| 556 | + | |
| 491 | 557 | return ret; |
| 492 | 558 | } |
| 493 | 559 | |
| @@ -511,8 +577,8 @@ static int psp_tmr_init(struct psp_context *psp) · 17 unmodified lines | ||
| 511 | 577 | /* For ASICs support RLC autoload, psp will parse the toc |
| 512 | 578 | * and calculate the total size of TMR needed */ |
| 513 | 579 | if (!amdgpu_sriov_vf(psp->adev) && |
| 514 | − psp->toc_start_addr && | |
| 515 | − psp->toc_bin_size && | |
| 580 | + psp->toc.start_addr && | |
| 581 | + psp->toc.size_bytes && | |
| 516 | 582 | psp->fw_pri_buf) { |
| 517 | 583 | ret = psp_load_toc(psp, &tmr_size); |
| 518 | 584 | if (ret) { |
| @@ -552,9 +618,7 @@ static int psp_tmr_load(struct psp_context *psp) · 33 unmodified lines | ||
| 552 | 618 | if (amdgpu_sriov_vf(psp->adev) && psp_skip_tmr(psp)) |
| 553 | 619 | return 0; |
| 554 | 620 | |
| 555 | − cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL); | |
| 556 | − if (!cmd) | |
| 557 | − return -ENOMEM; | |
| 621 | + cmd = acquire_psp_cmd_buf(psp); | |
| 558 | 622 | |
| 559 | 623 | psp_prep_tmr_cmd_buf(psp, cmd, psp->tmr_mc_addr, psp->tmr_bo); |
| 560 | 624 | DRM_INFO("reserve 0x%lx from 0x%llx for PSP TMR\n", |
| @@ -563,13 +627,13 @@ static int psp_tmr_load(struct psp_context *psp) · 2 unmodified lines | ||
| 563 | 627 | ret = psp_cmd_submit_buf(psp, NULL, cmd, |
| 564 | 628 | psp->fence_buf_mc_addr); |
| 565 | 629 | |
| 566 | − kfree(cmd); | |
| 630 | + release_psp_cmd_buf(psp); | |
| 567 | 631 | |
| 568 | 632 | return ret; |
| 569 | 633 | } |
| 570 | 634 | |
| 571 | 635 | static void psp_prep_tmr_unload_cmd_buf(struct psp_context *psp, |
| 572 | − struct psp_gfx_cmd_resp *cmd) | |
| 636 | + struct psp_gfx_cmd_resp *cmd) | |
| 573 | 637 | { |
| 574 | 638 | if (amdgpu_sriov_vf(psp->adev)) |
| 575 | 639 | cmd->cmd_id = GFX_CMD_ID_DESTROY_VMR; |
| @@ -580,11 +644,7 @@ static void psp_prep_tmr_unload_cmd_buf(struct psp_context *psp, · 4 unmodified lines | ||
| 580 | 644 | static int psp_tmr_unload(struct psp_context *psp) |
| 581 | 645 | { |
| 582 | 646 | int ret; |
| 583 | − struct psp_gfx_cmd_resp *cmd; | |
| 584 | − | |
| 585 | − cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL); | |
| 586 | − if (!cmd) | |
| 587 | − return -ENOMEM; | |
| 647 | + struct psp_gfx_cmd_resp *cmd = acquire_psp_cmd_buf(psp); | |
| 588 | 648 | |
| 589 | 649 | psp_prep_tmr_unload_cmd_buf(psp, cmd); |
| 590 | 650 | DRM_INFO("free PSP TMR buffer\n"); |
| @@ -592,7 +652,7 @@ static int psp_tmr_unload(struct psp_context *psp) · 1 unmodified line | ||
| 592 | 652 | ret = psp_cmd_submit_buf(psp, NULL, cmd, |
| 593 | 653 | psp->fence_buf_mc_addr); |
| 594 | 654 | |
| 595 | − kfree(cmd); | |
| 655 | + release_psp_cmd_buf(psp); | |
| 596 | 656 | |
| 597 | 657 | return ret; |
| 598 | 658 | } |
| @@ -626,9 +686,7 @@ int psp_get_fw_attestation_records_addr(struct psp_context *psp, · 27 unmodified lines | ||
| 626 | 686 | if (amdgpu_sriov_vf(psp->adev)) |
| 627 | 687 | return 0; |
| 628 | 688 | |
| 629 | − cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL); | |
| 630 | − if (!cmd) | |
| 631 | − return -ENOMEM; | |
| 689 | + cmd = acquire_psp_cmd_buf(psp); | |
| 632 | 690 | |
| 633 | 691 | cmd->cmd_id = GFX_CMD_ID_GET_FW_ATTESTATION; |
| 634 | 692 | |
| @@ -640,7 +698,7 @@ int psp_get_fw_attestation_records_addr(struct psp_context *psp, · 5 unmodified lines | ||
| 640 | 698 | ((uint64_t)cmd->resp.uresp.fwar_db_info.fwar_db_addr_hi << 32); |
| 641 | 699 | } |
| 642 | 700 | |
| 643 | − kfree(cmd); | |
| 701 | + release_psp_cmd_buf(psp); | |
| 644 | 702 | |
| 645 | 703 | return ret; |
| 646 | 704 | } |
| @@ -648,13 +706,13 @@ int psp_get_fw_attestation_records_addr(struct psp_context *psp, · 1 unmodified line | ||
| 648 | 706 | static int psp_boot_config_get(struct amdgpu_device *adev, uint32_t *boot_cfg) |
| 649 | 707 | { |
| 650 | 708 | struct psp_context *psp = &adev->psp; |
| 651 | − struct psp_gfx_cmd_resp *cmd = psp->cmd; | |
| 709 | + struct psp_gfx_cmd_resp *cmd; | |
| 652 | 710 | int ret; |
| 653 | 711 | |
| 654 | 712 | if (amdgpu_sriov_vf(adev)) |
| 655 | 713 | return 0; |
| 656 | 714 | |
| 657 | − memset(cmd, 0, sizeof(struct psp_gfx_cmd_resp)); | |
| 715 | + cmd = acquire_psp_cmd_buf(psp); | |
| 658 | 716 | |
| 659 | 717 | cmd->cmd_id = GFX_CMD_ID_BOOT_CFG; |
| 660 | 718 | cmd->cmd.boot_cfg.sub_cmd = BOOTCFG_CMD_GET; |
| @@ -665,47 +723,59 @@ static int psp_boot_config_get(struct amdgpu_device *adev, uint32_t *boot_cfg) · 4 unmodified lines | ||
| 665 | 723 | (cmd->resp.uresp.boot_cfg.boot_cfg & BOOT_CONFIG_GECC) ? 1 : 0; |
| 666 | 724 | } |
| 667 | 725 | |
| 726 | + release_psp_cmd_buf(psp); | |
| 727 | + | |
| 668 | 728 | return ret; |
| 669 | 729 | } |
| 670 | 730 | |
| 671 | 731 | static int psp_boot_config_set(struct amdgpu_device *adev, uint32_t boot_cfg) |
| 672 | 732 | { |
| 733 | + int ret; | |
| 673 | 734 | struct psp_context *psp = &adev->psp; |
| 674 | − struct psp_gfx_cmd_resp *cmd = psp->cmd; | |
| 735 | + struct psp_gfx_cmd_resp *cmd; | |
| 675 | 736 | |
| 676 | 737 | if (amdgpu_sriov_vf(adev)) |
| 677 | 738 | return 0; |
| 678 | 739 | |
| 679 | − memset(cmd, 0, sizeof(struct psp_gfx_cmd_resp)); | |
| 740 | + cmd = acquire_psp_cmd_buf(psp); | |
| 680 | 741 | |
| 681 | 742 | cmd->cmd_id = GFX_CMD_ID_BOOT_CFG; |
| 682 | 743 | cmd->cmd.boot_cfg.sub_cmd = BOOTCFG_CMD_SET; |
| 683 | 744 | cmd->cmd.boot_cfg.boot_config = boot_cfg; |
| 684 | 745 | cmd->cmd.boot_cfg.boot_config_valid = boot_cfg; |
| 685 | 746 | |
| 686 | − return psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr); | |
| 747 | + ret = psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr); | |
| 748 | + | |
| 749 | + release_psp_cmd_buf(psp); | |
| 750 | + | |
| 751 | + return ret; | |
| 687 | 752 | } |
| 688 | 753 | |
| 689 | 754 | static int psp_rl_load(struct amdgpu_device *adev) |
| 690 | 755 | { |
| 756 | + int ret; | |
| 691 | 757 | struct psp_context *psp = &adev->psp; |
| 692 | − struct psp_gfx_cmd_resp *cmd = psp->cmd; | |
| 758 | + struct psp_gfx_cmd_resp *cmd; | |
| 693 | 759 | |
| 694 | − if (psp->rl_bin_size == 0) | |
| 760 | + if (!is_psp_fw_valid(psp->rl)) | |
| 695 | 761 | return 0; |
| 696 | 762 | |
| 697 | − memset(psp->fw_pri_buf, 0, PSP_1_MEG); | |
| 698 | − memcpy(psp->fw_pri_buf, psp->rl_start_addr, psp->rl_bin_size); | |
| 763 | + cmd = acquire_psp_cmd_buf(psp); | |
| 699 | 764 | |
| 700 | − memset(cmd, 0, sizeof(struct psp_gfx_cmd_resp)); | |
| 765 | + memset(psp->fw_pri_buf, 0, PSP_1_MEG); | |
| 766 | + memcpy(psp->fw_pri_buf, psp->rl.start_addr, psp->rl.size_bytes); | |
| 701 | 767 | |
| 702 | 768 | cmd->cmd_id = GFX_CMD_ID_LOAD_IP_FW; |
| 703 | 769 | cmd->cmd.cmd_load_ip_fw.fw_phy_addr_lo = lower_32_bits(psp->fw_pri_mc_addr); |
| 704 | 770 | cmd->cmd.cmd_load_ip_fw.fw_phy_addr_hi = upper_32_bits(psp->fw_pri_mc_addr); |
| 705 | − cmd->cmd.cmd_load_ip_fw.fw_size = psp->rl_bin_size; | |
| 771 | + cmd->cmd.cmd_load_ip_fw.fw_size = psp->rl.size_bytes; | |
| 706 | 772 | cmd->cmd.cmd_load_ip_fw.fw_type = GFX_FW_TYPE_REG_LIST; |
| 707 | 773 | |
| 708 | − return psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr); | |
| 774 | + ret = psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr); | |
| 775 | + | |
| 776 | + release_psp_cmd_buf(psp); | |
| 777 | + | |
| 778 | + return ret; | |
| 709 | 779 | } |
| 710 | 780 | |
| 711 | 781 | static void psp_prep_asd_load_cmd_buf(struct psp_gfx_cmd_resp *cmd, |
| @@ -730,17 +800,15 @@ static int psp_asd_load(struct psp_context *psp) · 18 unmodified lines | ||
| 730 | 800 | * add workaround to bypass it for sriov now. |
| 731 | 801 | * TODO: add version check to make it common |
| 732 | 802 | */ |
| 733 | − if (amdgpu_sriov_vf(psp->adev) || !psp->asd_ucode_size) | |
| 803 | + if (amdgpu_sriov_vf(psp->adev) || !psp->asd.size_bytes) | |
| 734 | 804 | return 0; |
| 735 | 805 | |
| 736 | − cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL); | |
| 737 | − if (!cmd) | |
| 738 | − return -ENOMEM; | |
| 806 | + cmd = acquire_psp_cmd_buf(psp); | |
| 739 | 807 | |
| 740 | − psp_copy_fw(psp, psp->asd_start_addr, psp->asd_ucode_size); | |
| 808 | + psp_copy_fw(psp, psp->asd.start_addr, psp->asd.size_bytes); | |
| 741 | 809 | |
| 742 | 810 | psp_prep_asd_load_cmd_buf(cmd, psp->fw_pri_mc_addr, |
| 743 | − psp->asd_ucode_size); | |
| 811 | + psp->asd.size_bytes); | |
| 744 | 812 | |
| 745 | 813 | ret = psp_cmd_submit_buf(psp, NULL, cmd, |
| 746 | 814 | psp->fence_buf_mc_addr); |
| @@ -749,7 +817,7 @@ static int psp_asd_load(struct psp_context *psp) · 2 unmodified lines | ||
| 749 | 817 | psp->asd_context.session_id = cmd->resp.session_id; |
| 750 | 818 | } |
| 751 | 819 | |
| 752 | − kfree(cmd); | |
| 820 | + release_psp_cmd_buf(psp); | |
| 753 | 821 | |
| 754 | 822 | return ret; |
| 755 | 823 | } |
| @@ -772,9 +840,7 @@ static int psp_asd_unload(struct psp_context *psp) · 16 unmodified lines | ||
| 772 | 840 | if (!psp->asd_context.asd_initialized) |
| 773 | 841 | return 0; |
| 774 | 842 | |
| 775 | − cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL); | |
| 776 | − if (!cmd) | |
| 777 | − return -ENOMEM; | |
| 843 | + cmd = acquire_psp_cmd_buf(psp); | |
| 778 | 844 | |
| 779 | 845 | psp_prep_ta_unload_cmd_buf(cmd, psp->asd_context.session_id); |
| 780 | 846 | |
| @@ -783,7 +849,7 @@ static int psp_asd_unload(struct psp_context *psp) · 2 unmodified lines | ||
| 783 | 849 | if (!ret) |
| 784 | 850 | psp->asd_context.asd_initialized = false; |
| 785 | 851 | |
| 786 | − kfree(cmd); | |
| 852 | + release_psp_cmd_buf(psp); | |
| 787 | 853 | |
| 788 | 854 | return ret; |
| 789 | 855 | } |
| @@ -799,22 +865,21 @@ static void psp_prep_reg_prog_cmd_buf(struct psp_gfx_cmd_resp *cmd, · 9 unmodified lines | ||
| 799 | 865 | int psp_reg_program(struct psp_context *psp, enum psp_reg_prog_id reg, |
| 800 | 866 | uint32_t value) |
| 801 | 867 | { |
| 802 | − struct psp_gfx_cmd_resp *cmd = NULL; | |
| 868 | + struct psp_gfx_cmd_resp *cmd; | |
| 803 | 869 | int ret = 0; |
| 804 | 870 | |
| 805 | 871 | if (reg >= PSP_REG_LAST) |
| 806 | 872 | return -EINVAL; |
| 807 | 873 | |
| 808 | − cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL); | |
| 809 | − if (!cmd) | |
| 810 | − return -ENOMEM; | |
| 874 | + cmd = acquire_psp_cmd_buf(psp); | |
| 811 | 875 | |
| 812 | 876 | psp_prep_reg_prog_cmd_buf(cmd, reg, value); |
| 813 | 877 | ret = psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr); |
| 814 | 878 | if (ret) |
| 815 | 879 | DRM_ERROR("PSP failed to program reg id %d", reg); |
| 816 | 880 | |
| 817 | − kfree(cmd); | |
| 881 | + release_psp_cmd_buf(psp); | |
| 882 | + | |
| 818 | 883 | return ret; |
| 819 | 884 | } |
| 820 | 885 | |
| @@ -834,23 +899,37 @@ static void psp_prep_ta_load_cmd_buf(struct psp_gfx_cmd_resp *cmd, · 13 unmodified lines | ||
| 834 | 899 | cmd->cmd.cmd_load_ta.cmd_buf_len = ta_shared_size; |
| 835 | 900 | } |
| 836 | 901 | |
| 837 | −static int psp_xgmi_init_shared_buf(struct psp_context *psp) | |
| 902 | +static int psp_ta_init_shared_buf(struct psp_context *psp, | |
| 903 | + struct ta_mem_context *mem_ctx, | |
| 904 | + uint32_t shared_mem_size) | |
| 838 | 905 | { |
| 839 | 906 | int ret; |
| 840 | 907 | |
| 841 | 908 | /* |
| 842 | − * Allocate 16k memory aligned to 4k from Frame Buffer (local | |
| 843 | − * physical) for xgmi ta <-> Driver | |
| 844 | − */ | |
| 845 | − ret = amdgpu_bo_create_kernel(psp->adev, PSP_XGMI_SHARED_MEM_SIZE, | |
| 846 | − PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM, | |
| 847 | − &psp->xgmi_context.xgmi_shared_bo, | |
| 848 | − &psp->xgmi_context.xgmi_shared_mc_addr, | |
| 849 | − &psp->xgmi_context.xgmi_shared_buf); | |
| 909 | + * Allocate 16k memory aligned to 4k from Frame Buffer (local | |
| 910 | + * physical) for ta to host memory | |
| 911 | + */ | |
| 912 | + ret = amdgpu_bo_create_kernel(psp->adev, shared_mem_size, PAGE_SIZE, | |
| 913 | + AMDGPU_GEM_DOMAIN_VRAM, | |
| 914 | + &mem_ctx->shared_bo, | |
| 915 | + &mem_ctx->shared_mc_addr, | |
| 916 | + &mem_ctx->shared_buf); | |
| 850 | 917 | |
| 851 | 918 | return ret; |
| 852 | 919 | } |
| 853 | 920 | |
| 921 | +static void psp_ta_free_shared_buf(struct ta_mem_context *mem_ctx) | |
| 922 | +{ | |
| 923 | + amdgpu_bo_free_kernel(&mem_ctx->shared_bo, &mem_ctx->shared_mc_addr, | |
| 924 | + &mem_ctx->shared_buf); | |
| 925 | +} | |
| 926 | + | |
| 927 | +static int psp_xgmi_init_shared_buf(struct psp_context *psp) | |
| 928 | +{ | |
| 929 | + return psp_ta_init_shared_buf(psp, &psp->xgmi_context.context.mem_context, | |
| 930 | + PSP_XGMI_SHARED_MEM_SIZE); | |
| 931 | +} | |
| 932 | + | |
| 854 | 933 | static void psp_prep_ta_invoke_cmd_buf(struct psp_gfx_cmd_resp *cmd, |
| 855 | 934 | uint32_t ta_cmd_id, |
| 856 | 935 | uint32_t session_id) |
| @@ -865,18 +944,14 @@ static int psp_ta_invoke(struct psp_context *psp, · 8 unmodified lines | ||
| 865 | 944 | uint32_t session_id) |
| 866 | 945 | { |
| 867 | 946 | int ret; |
| 868 | − struct psp_gfx_cmd_resp *cmd; | |
| 869 | − | |
| 870 | − cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL); | |
| 871 | − if (!cmd) | |
| 872 | − return -ENOMEM; | |
| 947 | + struct psp_gfx_cmd_resp *cmd = acquire_psp_cmd_buf(psp); | |
| 873 | 948 | |
| 874 | 949 | psp_prep_ta_invoke_cmd_buf(cmd, ta_cmd_id, session_id); |
| 875 | 950 | |
| 876 | 951 | ret = psp_cmd_submit_buf(psp, NULL, cmd, |
| 877 | 952 | psp->fence_buf_mc_addr); |
| 878 | 953 | |
| 879 | − kfree(cmd); | |
| 954 | + release_psp_cmd_buf(psp); | |
| 880 | 955 | |
| 881 | 956 | return ret; |
| 882 | 957 | } |
| @@ -890,27 +965,25 @@ static int psp_xgmi_load(struct psp_context *psp) · 7 unmodified lines | ||
| 890 | 965 | * TODO: bypass the loading in sriov for now |
| 891 | 966 | */ |
| 892 | 967 | |
| 893 | − cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL); | |
| 894 | − if (!cmd) | |
| 895 | − return -ENOMEM; | |
| 968 | + cmd = acquire_psp_cmd_buf(psp); | |
| 896 | 969 | |
| 897 | − psp_copy_fw(psp, psp->ta_xgmi_start_addr, psp->ta_xgmi_ucode_size); | |
| 970 | + psp_copy_fw(psp, psp->xgmi.start_addr, psp->xgmi.size_bytes); | |
| 898 | 971 | |
| 899 | 972 | psp_prep_ta_load_cmd_buf(cmd, |
| 900 | 973 | psp->fw_pri_mc_addr, |
| 901 | − psp->ta_xgmi_ucode_size, | |
| 902 | − psp->xgmi_context.xgmi_shared_mc_addr, | |
| 974 | + psp->xgmi.size_bytes, | |
| 975 | + psp->xgmi_context.context.mem_context.shared_mc_addr, | |
| 903 | 976 | PSP_XGMI_SHARED_MEM_SIZE); |
| 904 | 977 | |
| 905 | 978 | ret = psp_cmd_submit_buf(psp, NULL, cmd, |
| 906 | 979 | psp->fence_buf_mc_addr); |
| 907 | 980 | |
| 908 | 981 | if (!ret) { |
| 909 | − psp->xgmi_context.initialized = 1; | |
| 910 | − psp->xgmi_context.session_id = cmd->resp.session_id; | |
| 982 | + psp->xgmi_context.context.initialized = true; | |
| 983 | + psp->xgmi_context.context.session_id = cmd->resp.session_id; | |
| 911 | 984 | } |
| 912 | 985 | |
| 913 | − kfree(cmd); | |
| 986 | + release_psp_cmd_buf(psp); | |
| 914 | 987 | |
| 915 | 988 | return ret; |
| 916 | 989 | } |
| @@ -930,57 +1003,56 @@ static int psp_xgmi_unload(struct psp_context *psp) · 13 unmodified lines | ||
| 930 | 1003 | * TODO: bypass the unloading in sriov for now |
| 931 | 1004 | */ |
| 932 | 1005 | |
| 933 | − cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL); | |
| 934 | − if (!cmd) | |
| 935 | − return -ENOMEM; | |
| 1006 | + cmd = acquire_psp_cmd_buf(psp); | |
| 936 | 1007 | |
| 937 | − psp_prep_ta_unload_cmd_buf(cmd, psp->xgmi_context.session_id); | |
| 1008 | + psp_prep_ta_unload_cmd_buf(cmd, psp->xgmi_context.context.session_id); | |
| 938 | 1009 | |
| 939 | 1010 | ret = psp_cmd_submit_buf(psp, NULL, cmd, |
| 940 | 1011 | psp->fence_buf_mc_addr); |
| 941 | 1012 | |
| 942 | − kfree(cmd); | |
| 1013 | + release_psp_cmd_buf(psp); | |
| 943 | 1014 | |
| 944 | 1015 | return ret; |
| 945 | 1016 | } |
| 946 | 1017 | |
| 947 | 1018 | int psp_xgmi_invoke(struct psp_context *psp, uint32_t ta_cmd_id) |
| 948 | 1019 | { |
| 949 | − return psp_ta_invoke(psp, ta_cmd_id, psp->xgmi_context.session_id); | |
| 1020 | + return psp_ta_invoke(psp, ta_cmd_id, psp->xgmi_context.context.session_id); | |
| 950 | 1021 | } |
| 951 | 1022 | |
| 952 | 1023 | int psp_xgmi_terminate(struct psp_context *psp) |
| 953 | 1024 | { |
| 954 | 1025 | int ret; |
| 955 | 1026 | |
| 956 | − if (!psp->xgmi_context.initialized) | |
| 1027 | + if (!psp->xgmi_context.context.initialized) | |
| 957 | 1028 | return 0; |
| 958 | 1029 | |
| 959 | 1030 | ret = psp_xgmi_unload(psp); |
| 960 | 1031 | if (ret) |
| 961 | 1032 | return ret; |
| 962 | 1033 | |
| 963 | − psp->xgmi_context.initialized = 0; | |
| 1034 | + psp->xgmi_context.context.initialized = false; | |
| 964 | 1035 | |
| 965 | 1036 | /* free xgmi shared memory */ |
| 966 | − amdgpu_bo_free_kernel(&psp->xgmi_context.xgmi_shared_bo, | |
| 967 | − &psp->xgmi_context.xgmi_shared_mc_addr, | |
| 968 | − &psp->xgmi_context.xgmi_shared_buf); | |
| 1037 | + psp_ta_free_shared_buf(&psp->xgmi_context.context.mem_context); | |
| 969 | 1038 | |
| 970 | 1039 | return 0; |
| 971 | 1040 | } |
| 972 | 1041 | |
| 973 | −int psp_xgmi_initialize(struct psp_context *psp) | |
| 1042 | +int psp_xgmi_initialize(struct psp_context *psp, bool set_extended_data, bool load_ta) | |
| 974 | 1043 | { |
| 975 | 1044 | struct ta_xgmi_shared_memory *xgmi_cmd; |
| 976 | 1045 | int ret; |
| 977 | 1046 | |
| 978 | − if (!psp->adev->psp.ta_fw || | |
| 979 | − !psp->adev->psp.ta_xgmi_ucode_size || | |
| 980 | − !psp->adev->psp.ta_xgmi_start_addr) | |
| 1047 | + if (!psp->ta_fw || | |
| 1048 | + !psp->xgmi.size_bytes || | |
| 1049 | + !psp->xgmi.start_addr) | |
| 981 | 1050 | return -ENOENT; |
| 982 | 1051 | |
| 983 | − if (!psp->xgmi_context.initialized) { | |
| 1052 | + if (!load_ta) | |
| 1053 | + goto invoke; | |
| 1054 | + | |
| 1055 | + if (!psp->xgmi_context.context.initialized) { | |
| 984 | 1056 | ret = psp_xgmi_init_shared_buf(psp); |
| 985 | 1057 | if (ret) |
| 986 | 1058 | return ret; |
| @@ -991,9 +1063,11 @@ int psp_xgmi_initialize(struct psp_context *psp) · 4 unmodified lines | ||
| 991 | 1063 | if (ret) |
| 992 | 1064 | return ret; |
| 993 | 1065 | |
| 1066 | +invoke: | |
| 994 | 1067 | /* Initialize XGMI session */ |
| 995 | − xgmi_cmd = (struct ta_xgmi_shared_memory *)(psp->xgmi_context.xgmi_shared_buf); | |
| 1068 | + xgmi_cmd = (struct ta_xgmi_shared_memory *)(psp->xgmi_context.context.mem_context.shared_buf); | |
| 996 | 1069 | memset(xgmi_cmd, 0, sizeof(struct ta_xgmi_shared_memory)); |
| 1070 | + xgmi_cmd->flag_extend_link_record = set_extended_data; | |
| 997 | 1071 | xgmi_cmd->cmd_id = TA_COMMAND_XGMI__INITIALIZE; |
| 998 | 1072 | |
| 999 | 1073 | ret = psp_xgmi_invoke(psp, xgmi_cmd->cmd_id); |
| @@ -1006,7 +1080,7 @@ int psp_xgmi_get_hive_id(struct psp_context *psp, uint64_t *hive_id) · 6 unmodified lines | ||
| 1006 | 1080 | struct ta_xgmi_shared_memory *xgmi_cmd; |
| 1007 | 1081 | int ret; |
| 1008 | 1082 | |
| 1009 | − xgmi_cmd = (struct ta_xgmi_shared_memory *)psp->xgmi_context.xgmi_shared_buf; | |
| 1083 | + xgmi_cmd = (struct ta_xgmi_shared_memory *)psp->xgmi_context.context.mem_context.shared_buf; | |
| 1010 | 1084 | memset(xgmi_cmd, 0, sizeof(struct ta_xgmi_shared_memory)); |
| 1011 | 1085 | |
| 1012 | 1086 | xgmi_cmd->cmd_id = TA_COMMAND_XGMI__GET_HIVE_ID; |
| @@ -1026,7 +1100,7 @@ int psp_xgmi_get_node_id(struct psp_context *psp, uint64_t *node_id) · 13 unmodified lines | ||
| 1026 | 1100 | struct ta_xgmi_shared_memory *xgmi_cmd; |
| 1027 | 1101 | int ret; |
| 1028 | 1102 | |
| 1029 | − xgmi_cmd = (struct ta_xgmi_shared_memory *)psp->xgmi_context.xgmi_shared_buf; | |
| 1103 | + xgmi_cmd = (struct ta_xgmi_shared_memory *)psp->xgmi_context.context.mem_context.shared_buf; | |
| 1030 | 1104 | memset(xgmi_cmd, 0, sizeof(struct ta_xgmi_shared_memory)); |
| 1031 | 1105 | |
| 1032 | 1106 | xgmi_cmd->cmd_id = TA_COMMAND_XGMI__GET_NODE_ID; |
| @@ -1041,9 +1115,62 @@ int psp_xgmi_get_node_id(struct psp_context *psp, uint64_t *node_id) · 8 unmodified lines | ||
| 1041 | 1115 | return 0; |
| 1042 | 1116 | } |
| 1043 | 1117 | |
| 1118 | +static bool psp_xgmi_peer_link_info_supported(struct psp_context *psp) | |
| 1119 | +{ | |
| 1120 | + return psp->adev->asic_type == CHIP_ALDEBARAN && | |
| 1121 | + psp->xgmi.feature_version >= 0x2000000b; | |
| 1122 | +} | |
| 1123 | + | |
| 1124 | +/* | |
| 1125 | + * Chips that support extended topology information require the driver to | |
| 1126 | + * reflect topology information in the opposite direction. This is | |
| 1127 | + * because the TA has already exceeded its link record limit and if the | |
| 1128 | + * TA holds bi-directional information, the driver would have to do | |
| 1129 | + * multiple fetches instead of just two. | |
| 1130 | + */ | |
| 1131 | +static void psp_xgmi_reflect_topology_info(struct psp_context *psp, | |
| 1132 | + struct psp_xgmi_node_info node_info) | |
| 1133 | +{ | |
| 1134 | + struct amdgpu_device *mirror_adev; | |
| 1135 | + struct amdgpu_hive_info *hive; | |
| 1136 | + uint64_t src_node_id = psp->adev->gmc.xgmi.node_id; | |
| 1137 | + uint64_t dst_node_id = node_info.node_id; | |
| 1138 | + uint8_t dst_num_hops = node_info.num_hops; | |
| 1139 | + uint8_t dst_num_links = node_info.num_links; | |
| 1140 | + | |
| 1141 | + hive = amdgpu_get_xgmi_hive(psp->adev); | |
| 1142 | + list_for_each_entry(mirror_adev, &hive->device_list, gmc.xgmi.head) { | |
| 1143 | + struct psp_xgmi_topology_info *mirror_top_info; | |
| 1144 | + int j; | |
| 1145 | + | |
| 1146 | + if (mirror_adev->gmc.xgmi.node_id != dst_node_id) | |
| 1147 | + continue; | |
| 1148 | + | |
| 1149 | + mirror_top_info = &mirror_adev->psp.xgmi_context.top_info; | |
| 1150 | + for (j = 0; j < mirror_top_info->num_nodes; j++) { | |
| 1151 | + if (mirror_top_info->nodes[j].node_id != src_node_id) | |
| 1152 | + continue; | |
| 1153 | + | |
| 1154 | + mirror_top_info->nodes[j].num_hops = dst_num_hops; | |
| 1155 | + /* | |
| 1156 | + * prevent 0 num_links value re-reflection since reflection | |
| 1157 | + * criteria is based on num_hops (direct or indirect). | |
| 1158 | + * | |
| 1159 | + */ | |
| 1160 | + if (dst_num_links) | |
| 1161 | + mirror_top_info->nodes[j].num_links = dst_num_links; | |
| 1162 | + | |
| 1163 | + break; | |
| 1164 | + } | |
| 1165 | + | |
| 1166 | + break; | |
| 1167 | + } | |
| 1168 | +} | |
| 1169 | + | |
| 1044 | 1170 | int psp_xgmi_get_topology_info(struct psp_context *psp, |
| 1045 | 1171 | int number_devices, |
| 1046 | − struct psp_xgmi_topology_info *topology) | |
| 1172 | + struct psp_xgmi_topology_info *topology, | |
| 1173 | + bool get_extended_data) | |
| 1047 | 1174 | { |
| 1048 | 1175 | struct ta_xgmi_shared_memory *xgmi_cmd; |
| 1049 | 1176 | struct ta_xgmi_cmd_get_topology_info_input *topology_info_input; |
| @@ -1054,8 +1181,9 @@ int psp_xgmi_get_topology_info(struct psp_context *psp, · 4 unmodified lines | ||
| 1054 | 1181 | if (!topology || topology->num_nodes > TA_XGMI__MAX_CONNECTED_NODES) |
| 1055 | 1182 | return -EINVAL; |
| 1056 | 1183 | |
| 1057 | − xgmi_cmd = (struct ta_xgmi_shared_memory *)psp->xgmi_context.xgmi_shared_buf; | |
| 1184 | + xgmi_cmd = (struct ta_xgmi_shared_memory *)psp->xgmi_context.context.mem_context.shared_buf; | |
| 1058 | 1185 | memset(xgmi_cmd, 0, sizeof(struct ta_xgmi_shared_memory)); |
| 1186 | + xgmi_cmd->flag_extend_link_record = get_extended_data; | |
| 1059 | 1187 | |
| 1060 | 1188 | /* Fill in the shared memory with topology information as input */ |
| 1061 | 1189 | topology_info_input = &xgmi_cmd->xgmi_in_message.get_topology_info; |
| @@ -1078,10 +1206,45 @@ int psp_xgmi_get_topology_info(struct psp_context *psp, · 16 unmodified lines | ||
| 1078 | 1206 | topology_info_output = &xgmi_cmd->xgmi_out_message.get_topology_info; |
| 1079 | 1207 | topology->num_nodes = xgmi_cmd->xgmi_out_message.get_topology_info.num_nodes; |
| 1080 | 1208 | for (i = 0; i < topology->num_nodes; i++) { |
| 1081 | − topology->nodes[i].node_id = topology_info_output->nodes[i].node_id; | |
| 1082 | − topology->nodes[i].num_hops = topology_info_output->nodes[i].num_hops; | |
| 1083 | − topology->nodes[i].is_sharing_enabled = topology_info_output->nodes[i].is_sharing_enabled; | |
| 1084 | − topology->nodes[i].sdma_engine = topology_info_output->nodes[i].sdma_engine; | |
| 1209 | + /* extended data will either be 0 or equal to non-extended data */ | |
| 1210 | + if (topology_info_output->nodes[i].num_hops) | |
| 1211 | + topology->nodes[i].num_hops = topology_info_output->nodes[i].num_hops; | |
| 1212 | + | |
| 1213 | + /* non-extended data gets everything here so no need to update */ | |
| 1214 | + if (!get_extended_data) { | |
| 1215 | + topology->nodes[i].node_id = topology_info_output->nodes[i].node_id; | |
| 1216 | + topology->nodes[i].is_sharing_enabled = | |
| 1217 | + topology_info_output->nodes[i].is_sharing_enabled; | |
| 1218 | + topology->nodes[i].sdma_engine = | |
| 1219 | + topology_info_output->nodes[i].sdma_engine; | |
| 1220 | + } | |
| 1221 | + | |
| 1222 | + } | |
| 1223 | + | |
| 1224 | + /* Invoke xgmi ta again to get the link information */ | |
| 1225 | + if (psp_xgmi_peer_link_info_supported(psp)) { | |
| 1226 | + struct ta_xgmi_cmd_get_peer_link_info_output *link_info_output; | |
| 1227 | + | |
| 1228 | + xgmi_cmd->cmd_id = TA_COMMAND_XGMI__GET_PEER_LINKS; | |
| 1229 | + | |
| 1230 | + ret = psp_xgmi_invoke(psp, TA_COMMAND_XGMI__GET_PEER_LINKS); | |
| 1231 | + | |
| 1232 | + if (ret) | |
| 1233 | + return ret; | |
| 1234 | + | |
| 1235 | + link_info_output = &xgmi_cmd->xgmi_out_message.get_link_info; | |
| 1236 | + for (i = 0; i < topology->num_nodes; i++) { | |
| 1237 | + /* accumulate num_links on extended data */ | |
| 1238 | + topology->nodes[i].num_links = get_extended_data ? | |
| 1239 | + topology->nodes[i].num_links + | |
| 1240 | + link_info_output->nodes[i].num_links : | |
| 1241 | + link_info_output->nodes[i].num_links; | |
| 1242 | + | |
| 1243 | + /* reflect the topology information for bi-directionality */ | |
| 1244 | + if (psp->xgmi_context.supports_extended_data && | |
| 1245 | + get_extended_data && topology->nodes[i].num_hops) | |
| 1246 | + psp_xgmi_reflect_topology_info(psp, topology->nodes[i]); | |
| 1247 | + } | |
| 1085 | 1248 | } |
| 1086 | 1249 | |
| 1087 | 1250 | return 0; |
| @@ -1098,7 +1261,7 @@ int psp_xgmi_set_topology_info(struct psp_context *psp, · 10 unmodified lines | ||
| 1098 | 1261 | if (!topology || topology->num_nodes > TA_XGMI__MAX_CONNECTED_NODES) |
| 1099 | 1262 | return -EINVAL; |
| 1100 | 1263 | |
| 1101 | − xgmi_cmd = (struct ta_xgmi_shared_memory *)psp->xgmi_context.xgmi_shared_buf; | |
| 1264 | + xgmi_cmd = (struct ta_xgmi_shared_memory *)psp->xgmi_context.context.mem_context.shared_buf; | |
| 1102 | 1265 | memset(xgmi_cmd, 0, sizeof(struct ta_xgmi_shared_memory)); |
| 1103 | 1266 | |
| 1104 | 1267 | topology_info_input = &xgmi_cmd->xgmi_in_message.get_topology_info; |
| @@ -1119,19 +1282,8 @@ int psp_xgmi_set_topology_info(struct psp_context *psp, · 14 unmodified lines | ||
| 1119 | 1282 | // ras begin |
| 1120 | 1283 | static int psp_ras_init_shared_buf(struct psp_context *psp) |
| 1121 | 1284 | { |
| 1122 | − int ret; | |
| 1123 | − | |
| 1124 | − /* | |
| 1125 | − * Allocate 16k memory aligned to 4k from Frame Buffer (local | |
| 1126 | − * physical) for ras ta <-> Driver | |
| 1127 | − */ | |
| 1128 | − ret = amdgpu_bo_create_kernel(psp->adev, PSP_RAS_SHARED_MEM_SIZE, | |
| 1129 | − PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM, | |
| 1130 | − &psp->ras.ras_shared_bo, | |
| 1131 | − &psp->ras.ras_shared_mc_addr, | |
| 1132 | − &psp->ras.ras_shared_buf); | |
| 1133 | − | |
| 1134 | − return ret; | |
| 1285 | + return psp_ta_init_shared_buf(psp, &psp->ras_context.context.mem_context, | |
| 1286 | + PSP_RAS_SHARED_MEM_SIZE); | |
| 1135 | 1287 | } |
| 1136 | 1288 | |
| 1137 | 1289 | static int psp_ras_load(struct psp_context *psp) |
| @@ -1146,42 +1298,40 @@ static int psp_ras_load(struct psp_context *psp) · 8 unmodified lines | ||
| 1146 | 1298 | if (amdgpu_sriov_vf(psp->adev)) |
| 1147 | 1299 | return 0; |
| 1148 | 1300 | |
| 1149 | − cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL); | |
| 1150 | − if (!cmd) | |
| 1151 | − return -ENOMEM; | |
| 1152 | − | |
| 1153 | − psp_copy_fw(psp, psp->ta_ras_start_addr, psp->ta_ras_ucode_size); | |
| 1301 | + psp_copy_fw(psp, psp->ras.start_addr, psp->ras.size_bytes); | |
| 1154 | 1302 | |
| 1155 | − ras_cmd = (struct ta_ras_shared_memory *)psp->ras.ras_shared_buf; | |
| 1303 | + ras_cmd = (struct ta_ras_shared_memory *)psp->ras_context.context.mem_context.shared_buf; | |
| 1156 | 1304 | |
| 1157 | 1305 | if (psp->adev->gmc.xgmi.connected_to_cpu) |
| 1158 | 1306 | ras_cmd->ras_in_message.init_flags.poison_mode_en = 1; |
| 1159 | 1307 | else |
| 1160 | 1308 | ras_cmd->ras_in_message.init_flags.dgpu_mode = 1; |
| 1161 | 1309 | |
| 1310 | + cmd = acquire_psp_cmd_buf(psp); | |
| 1311 | + | |
| 1162 | 1312 | psp_prep_ta_load_cmd_buf(cmd, |
| 1163 | 1313 | psp->fw_pri_mc_addr, |
| 1164 | − psp->ta_ras_ucode_size, | |
| 1165 | − psp->ras.ras_shared_mc_addr, | |
| 1314 | + psp->ras.size_bytes, | |
| 1315 | + psp->ras_context.context.mem_context.shared_mc_addr, | |
| 1166 | 1316 | PSP_RAS_SHARED_MEM_SIZE); |
| 1167 | 1317 | |
| 1168 | 1318 | ret = psp_cmd_submit_buf(psp, NULL, cmd, |
| 1169 | 1319 | psp->fence_buf_mc_addr); |
| 1170 | 1320 | |
| 1171 | 1321 | if (!ret) { |
| 1172 | − psp->ras.session_id = cmd->resp.session_id; | |
| 1322 | + psp->ras_context.context.session_id = cmd->resp.session_id; | |
| 1173 | 1323 | |
| 1174 | 1324 | if (!ras_cmd->ras_status) |
| 1175 | − psp->ras.ras_initialized = true; | |
| 1325 | + psp->ras_context.context.initialized = true; | |
| 1176 | 1326 | else |
| 1177 | 1327 | dev_warn(psp->adev->dev, "RAS Init Status: 0x%X\n", ras_cmd->ras_status); |
| 1178 | 1328 | } |
| 1179 | 1329 | |
| 1330 | + release_psp_cmd_buf(psp); | |
| 1331 | + | |
| 1180 | 1332 | if (ret || ras_cmd->ras_status) |
| 1181 | 1333 | amdgpu_ras_fini(psp->adev); |
| 1182 | 1334 | |
| 1183 | − kfree(cmd); | |
| 1184 | − | |
| 1185 | 1335 | return ret; |
| 1186 | 1336 | } |
| 1187 | 1337 | |
| @@ -1196,16 +1346,14 @@ static int psp_ras_unload(struct psp_context *psp) · 8 unmodified lines | ||
| 1196 | 1346 | if (amdgpu_sriov_vf(psp->adev)) |
| 1197 | 1347 | return 0; |
| 1198 | 1348 | |
| 1199 | − cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL); | |
| 1200 | − if (!cmd) | |
| 1201 | − return -ENOMEM; | |
| 1349 | + cmd = acquire_psp_cmd_buf(psp); | |
| 1202 | 1350 | |
| 1203 | − psp_prep_ta_unload_cmd_buf(cmd, psp->ras.session_id); | |
| 1351 | + psp_prep_ta_unload_cmd_buf(cmd, psp->ras_context.context.session_id); | |
| 1204 | 1352 | |
| 1205 | 1353 | ret = psp_cmd_submit_buf(psp, NULL, cmd, |
| 1206 | 1354 | psp->fence_buf_mc_addr); |
| 1207 | 1355 | |
| 1208 | − kfree(cmd); | |
| 1356 | + release_psp_cmd_buf(psp); | |
| 1209 | 1357 | |
| 1210 | 1358 | return ret; |
| 1211 | 1359 | } |
| @@ -1215,7 +1363,7 @@ int psp_ras_invoke(struct psp_context *psp, uint32_t ta_cmd_id) · 3 unmodified lines | ||
| 1215 | 1363 | struct ta_ras_shared_memory *ras_cmd; |
| 1216 | 1364 | int ret; |
| 1217 | 1365 | |
| 1218 | − ras_cmd = (struct ta_ras_shared_memory *)psp->ras.ras_shared_buf; | |
| 1366 | + ras_cmd = (struct ta_ras_shared_memory *)psp->ras_context.context.mem_context.shared_buf; | |
| 1219 | 1367 | |
| 1220 | 1368 | /* |
| 1221 | 1369 | * TODO: bypass the loading in sriov for now |
| @@ -1223,7 +1371,7 @@ int psp_ras_invoke(struct psp_context *psp, uint32_t ta_cmd_id) · 1 unmodified line | ||
| 1223 | 1371 | if (amdgpu_sriov_vf(psp->adev)) |
| 1224 | 1372 | return 0; |
| 1225 | 1373 | |
| 1226 | − ret = psp_ta_invoke(psp, ta_cmd_id, psp->ras.session_id); | |
| 1374 | + ret = psp_ta_invoke(psp, ta_cmd_id, psp->ras_context.context.session_id); | |
| 1227 | 1375 | |
| 1228 | 1376 | if (amdgpu_ras_intr_triggered()) |
| 1229 | 1377 | return ret; |
| @@ -1279,10 +1427,10 @@ int psp_ras_enable_features(struct psp_context *psp, · 49 unmodified lines | ||
| 1279 | 1427 | struct ta_ras_shared_memory *ras_cmd; |
| 1280 | 1428 | int ret; |
| 1281 | 1429 | |
| 1282 | − if (!psp->ras.ras_initialized) | |
| 1430 | + if (!psp->ras_context.context.initialized) | |
| 1283 | 1431 | return -EINVAL; |
| 1284 | 1432 | |
| 1285 | − ras_cmd = (struct ta_ras_shared_memory *)psp->ras.ras_shared_buf; | |
| 1433 | + ras_cmd = (struct ta_ras_shared_memory *)psp->ras_context.context.mem_context.shared_buf; | |
| 1286 | 1434 | memset(ras_cmd, 0, sizeof(struct ta_ras_shared_memory)); |
| 1287 | 1435 | |
| 1288 | 1436 | if (enable) |
| @@ -1309,19 +1457,17 @@ static int psp_ras_terminate(struct psp_context *psp) · 20 unmodified lines | ||
| 1309 | 1457 | if (amdgpu_sriov_vf(psp->adev)) |
| 1310 | 1458 | return 0; |
| 1311 | 1459 | |
| 1312 | − if (!psp->ras.ras_initialized) | |
| 1460 | + if (!psp->ras_context.context.initialized) | |
| 1313 | 1461 | return 0; |
| 1314 | 1462 | |
| 1315 | 1463 | ret = psp_ras_unload(psp); |
| 1316 | 1464 | if (ret) |
| 1317 | 1465 | return ret; |
| 1318 | 1466 | |
| 1319 | − psp->ras.ras_initialized = false; | |
| 1467 | + psp->ras_context.context.initialized = false; | |
| 1320 | 1468 | |
| 1321 | 1469 | /* free ras shared memory */ |
| 1322 | − amdgpu_bo_free_kernel(&psp->ras.ras_shared_bo, | |
| 1323 | − &psp->ras.ras_shared_mc_addr, | |
| 1324 | − &psp->ras.ras_shared_buf); | |
| 1470 | + psp_ta_free_shared_buf(&psp->ras_context.context.mem_context); | |
| 1325 | 1471 | |
| 1326 | 1472 | return 0; |
| 1327 | 1473 | } |
| @@ -1338,8 +1484,8 @@ static int psp_ras_initialize(struct psp_context *psp) · 10 unmodified lines | ||
| 1338 | 1484 | if (amdgpu_sriov_vf(adev)) |
| 1339 | 1485 | return 0; |
| 1340 | 1486 | |
| 1341 | − if (!adev->psp.ta_ras_ucode_size || | |
| 1342 | − !adev->psp.ta_ras_start_addr) { | |
| 1487 | + if (!adev->psp.ras.size_bytes || | |
| 1488 | + !adev->psp.ras.start_addr) { | |
| 1343 | 1489 | dev_info(adev->dev, "RAS: optional ras ta ucode is not available\n"); |
| 1344 | 1490 | return 0; |
| 1345 | 1491 | } |
| @@ -1385,7 +1531,7 @@ static int psp_ras_initialize(struct psp_context *psp) · 39 unmodified lines | ||
| 1385 | 1531 | } |
| 1386 | 1532 | } |
| 1387 | 1533 | |
| 1388 | − if (!psp->ras.ras_initialized) { | |
| 1534 | + if (!psp->ras_context.context.initialized) { | |
| 1389 | 1535 | ret = psp_ras_init_shared_buf(psp); |
| 1390 | 1536 | if (ret) |
| 1391 | 1537 | return ret; |
| @@ -1404,10 +1550,10 @@ int psp_ras_trigger_error(struct psp_context *psp, · 12 unmodified lines | ||
| 1404 | 1550 | struct ta_ras_shared_memory *ras_cmd; |
| 1405 | 1551 | int ret; |
| 1406 | 1552 | |
| 1407 | − if (!psp->ras.ras_initialized) | |
| 1553 | + if (!psp->ras_context.context.initialized) | |
| 1408 | 1554 | return -EINVAL; |
| 1409 | 1555 | |
| 1410 | − ras_cmd = (struct ta_ras_shared_memory *)psp->ras.ras_shared_buf; | |
| 1556 | + ras_cmd = (struct ta_ras_shared_memory *)psp->ras_context.context.mem_context.shared_buf; | |
| 1411 | 1557 | memset(ras_cmd, 0, sizeof(struct ta_ras_shared_memory)); |
| 1412 | 1558 | |
| 1413 | 1559 | ras_cmd->cmd_id = TA_RAS_COMMAND__TRIGGER_ERROR; |
| @@ -1429,19 +1575,8 @@ int psp_ras_trigger_error(struct psp_context *psp, · 15 unmodified lines | ||
| 1429 | 1575 | // HDCP start |
| 1430 | 1576 | static int psp_hdcp_init_shared_buf(struct psp_context *psp) |
| 1431 | 1577 | { |
| 1432 | − int ret; | |
| 1433 | − | |
| 1434 | − /* | |
| 1435 | − * Allocate 16k memory aligned to 4k from Frame Buffer (local | |
| 1436 | − * physical) for hdcp ta <-> Driver | |
| 1437 | − */ | |
| 1438 | − ret = amdgpu_bo_create_kernel(psp->adev, PSP_HDCP_SHARED_MEM_SIZE, | |
| 1439 | − PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM, | |
| 1440 | − &psp->hdcp_context.hdcp_shared_bo, | |
| 1441 | − &psp->hdcp_context.hdcp_shared_mc_addr, | |
| 1442 | − &psp->hdcp_context.hdcp_shared_buf); | |
| 1443 | − | |
| 1444 | − return ret; | |
| 1578 | + return psp_ta_init_shared_buf(psp, &psp->hdcp_context.context.mem_context, | |
| 1579 | + PSP_HDCP_SHARED_MEM_SIZE); | |
| 1445 | 1580 | } |
| 1446 | 1581 | |
| 1447 | 1582 | static int psp_hdcp_load(struct psp_context *psp) |
| @@ -1455,28 +1590,26 @@ static int psp_hdcp_load(struct psp_context *psp) · 7 unmodified lines | ||
| 1455 | 1590 | if (amdgpu_sriov_vf(psp->adev)) |
| 1456 | 1591 | return 0; |
| 1457 | 1592 | |
| 1458 | − cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL); | |
| 1459 | − if (!cmd) | |
| 1460 | − return -ENOMEM; | |
| 1593 | + psp_copy_fw(psp, psp->hdcp.start_addr, | |
| 1594 | + psp->hdcp.size_bytes); | |
| 1461 | 1595 | |
| 1462 | − psp_copy_fw(psp, psp->ta_hdcp_start_addr, | |
| 1463 | − psp->ta_hdcp_ucode_size); | |
| 1596 | + cmd = acquire_psp_cmd_buf(psp); | |
| 1464 | 1597 | |
| 1465 | 1598 | psp_prep_ta_load_cmd_buf(cmd, |
| 1466 | 1599 | psp->fw_pri_mc_addr, |
| 1467 | − psp->ta_hdcp_ucode_size, | |
| 1468 | − psp->hdcp_context.hdcp_shared_mc_addr, | |
| 1600 | + psp->hdcp.size_bytes, | |
| 1601 | + psp->hdcp_context.context.mem_context.shared_mc_addr, | |
| 1469 | 1602 | PSP_HDCP_SHARED_MEM_SIZE); |
| 1470 | 1603 | |
| 1471 | 1604 | ret = psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr); |
| 1472 | 1605 | |
| 1473 | 1606 | if (!ret) { |
| 1474 | − psp->hdcp_context.hdcp_initialized = true; | |
| 1475 | − psp->hdcp_context.session_id = cmd->resp.session_id; | |
| 1607 | + psp->hdcp_context.context.initialized = true; | |
| 1608 | + psp->hdcp_context.context.session_id = cmd->resp.session_id; | |
| 1476 | 1609 | mutex_init(&psp->hdcp_context.mutex); |
| 1477 | 1610 | } |
| 1478 | 1611 | |
| 1479 | − kfree(cmd); | |
| 1612 | + release_psp_cmd_buf(psp); | |
| 1480 | 1613 | |
| 1481 | 1614 | return ret; |
| 1482 | 1615 | } |
| @@ -1490,13 +1623,13 @@ static int psp_hdcp_initialize(struct psp_context *psp) · 7 unmodified lines | ||
| 1490 | 1623 | if (amdgpu_sriov_vf(psp->adev)) |
| 1491 | 1624 | return 0; |
| 1492 | 1625 | |
| 1493 | − if (!psp->adev->psp.ta_hdcp_ucode_size || | |
| 1494 | − !psp->adev->psp.ta_hdcp_start_addr) { | |
| 1626 | + if (!psp->hdcp.size_bytes || | |
| 1627 | + !psp->hdcp.start_addr) { | |
| 1495 | 1628 | dev_info(psp->adev->dev, "HDCP: optional hdcp ta ucode is not available\n"); |
| 1496 | 1629 | return 0; |
| 1497 | 1630 | } |
| 1498 | 1631 | |
| 1499 | − if (!psp->hdcp_context.hdcp_initialized) { | |
| 1632 | + if (!psp->hdcp_context.context.initialized) { | |
| 1500 | 1633 | ret = psp_hdcp_init_shared_buf(psp); |
| 1501 | 1634 | if (ret) |
| 1502 | 1635 | return ret; |
| @@ -1520,15 +1653,13 @@ static int psp_hdcp_unload(struct psp_context *psp) · 17 unmodified lines | ||
| 1520 | 1653 | if (amdgpu_sriov_vf(psp->adev)) |
| 1521 | 1654 | return 0; |
| 1522 | 1655 | |
| 1523 | − cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL); | |
| 1524 | − if (!cmd) | |
| 1525 | − return -ENOMEM; | |
| 1656 | + cmd = acquire_psp_cmd_buf(psp); | |
| 1526 | 1657 | |
| 1527 | − psp_prep_ta_unload_cmd_buf(cmd, psp->hdcp_context.session_id); | |
| 1658 | + psp_prep_ta_unload_cmd_buf(cmd, psp->hdcp_context.context.session_id); | |
| 1528 | 1659 | |
| 1529 | 1660 | ret = psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr); |
| 1530 | 1661 | |
| 1531 | − kfree(cmd); | |
| 1662 | + release_psp_cmd_buf(psp); | |
| 1532 | 1663 | |
| 1533 | 1664 | return ret; |
| 1534 | 1665 | } |
| @@ -1541,7 +1672,7 @@ int psp_hdcp_invoke(struct psp_context *psp, uint32_t ta_cmd_id) · 6 unmodified lines | ||
| 1541 | 1672 | if (amdgpu_sriov_vf(psp->adev)) |
| 1542 | 1673 | return 0; |
| 1543 | 1674 | |
| 1544 | − return psp_ta_invoke(psp, ta_cmd_id, psp->hdcp_context.session_id); | |
| 1675 | + return psp_ta_invoke(psp, ta_cmd_id, psp->hdcp_context.context.session_id); | |
| 1545 | 1676 | } |
| 1546 | 1677 | |
| 1547 | 1678 | static int psp_hdcp_terminate(struct psp_context *psp) |
| @@ -1554,8 +1685,8 @@ static int psp_hdcp_terminate(struct psp_context *psp) · 6 unmodified lines | ||
| 1554 | 1685 | if (amdgpu_sriov_vf(psp->adev)) |
| 1555 | 1686 | return 0; |
| 1556 | 1687 | |
| 1557 | − if (!psp->hdcp_context.hdcp_initialized) { | |
| 1558 | − if (psp->hdcp_context.hdcp_shared_buf) | |
| 1688 | + if (!psp->hdcp_context.context.initialized) { | |
| 1689 | + if (psp->hdcp_context.context.mem_context.shared_buf) | |
| 1559 | 1690 | goto out; |
| 1560 | 1691 | else |
| 1561 | 1692 | return 0; |
| @@ -1565,13 +1696,11 @@ static int psp_hdcp_terminate(struct psp_context *psp) · 3 unmodified lines | ||
| 1565 | 1696 | if (ret) |
| 1566 | 1697 | return ret; |
| 1567 | 1698 | |
| 1568 | − psp->hdcp_context.hdcp_initialized = false; | |
| 1699 | + psp->hdcp_context.context.initialized = false; | |
| 1569 | 1700 | |
| 1570 | 1701 | out: |
| 1571 | 1702 | /* free hdcp shared memory */ |
| 1572 | − amdgpu_bo_free_kernel(&psp->hdcp_context.hdcp_shared_bo, | |
| 1573 | − &psp->hdcp_context.hdcp_shared_mc_addr, | |
| 1574 | − &psp->hdcp_context.hdcp_shared_buf); | |
| 1703 | + psp_ta_free_shared_buf(&psp->hdcp_context.context.mem_context); | |
| 1575 | 1704 | |
| 1576 | 1705 | return 0; |
| 1577 | 1706 | } |
| @@ -1580,19 +1709,8 @@ out: · 2 unmodified lines | ||
| 1580 | 1709 | // DTM start |
| 1581 | 1710 | static int psp_dtm_init_shared_buf(struct psp_context *psp) |
| 1582 | 1711 | { |
| 1583 | − int ret; | |
| 1584 | − | |
| 1585 | − /* | |
| 1586 | − * Allocate 16k memory aligned to 4k from Frame Buffer (local | |
| 1587 | − * physical) for dtm ta <-> Driver | |
| 1588 | − */ | |
| 1589 | − ret = amdgpu_bo_create_kernel(psp->adev, PSP_DTM_SHARED_MEM_SIZE, | |
| 1590 | − PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM, | |
| 1591 | − &psp->dtm_context.dtm_shared_bo, | |
| 1592 | − &psp->dtm_context.dtm_shared_mc_addr, | |
| 1593 | − &psp->dtm_context.dtm_shared_buf); | |
| 1594 | − | |
| 1595 | − return ret; | |
| 1712 | + return psp_ta_init_shared_buf(psp, &psp->dtm_context.context.mem_context, | |
| 1713 | + PSP_DTM_SHARED_MEM_SIZE); | |
| 1596 | 1714 | } |
| 1597 | 1715 | |
| 1598 | 1716 | static int psp_dtm_load(struct psp_context *psp) |
| @@ -1606,27 +1724,25 @@ static int psp_dtm_load(struct psp_context *psp) · 7 unmodified lines | ||
| 1606 | 1724 | if (amdgpu_sriov_vf(psp->adev)) |
| 1607 | 1725 | return 0; |
| 1608 | 1726 | |
| 1609 | − cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL); | |
| 1610 | − if (!cmd) | |
| 1611 | − return -ENOMEM; | |
| 1727 | + psp_copy_fw(psp, psp->dtm.start_addr, psp->dtm.size_bytes); | |
| 1612 | 1728 | |
| 1613 | − psp_copy_fw(psp, psp->ta_dtm_start_addr, psp->ta_dtm_ucode_size); | |
| 1729 | + cmd = acquire_psp_cmd_buf(psp); | |
| 1614 | 1730 | |
| 1615 | 1731 | psp_prep_ta_load_cmd_buf(cmd, |
| 1616 | 1732 | psp->fw_pri_mc_addr, |
| 1617 | − psp->ta_dtm_ucode_size, | |
| 1618 | − psp->dtm_context.dtm_shared_mc_addr, | |
| 1733 | + psp->dtm.size_bytes, | |
| 1734 | + psp->dtm_context.context.mem_context.shared_mc_addr, | |
| 1619 | 1735 | PSP_DTM_SHARED_MEM_SIZE); |
| 1620 | 1736 | |
| 1621 | 1737 | ret = psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr); |
| 1622 | 1738 | |
| 1623 | 1739 | if (!ret) { |
| 1624 | − psp->dtm_context.dtm_initialized = true; | |
| 1625 | − psp->dtm_context.session_id = cmd->resp.session_id; | |
| 1740 | + psp->dtm_context.context.initialized = true; | |
| 1741 | + psp->dtm_context.context.session_id = cmd->resp.session_id; | |
| 1626 | 1742 | mutex_init(&psp->dtm_context.mutex); |
| 1627 | 1743 | } |
| 1628 | 1744 | |
| 1629 | − kfree(cmd); | |
| 1745 | + release_psp_cmd_buf(psp); | |
| 1630 | 1746 | |
| 1631 | 1747 | return ret; |
| 1632 | 1748 | } |
| @@ -1641,13 +1757,13 @@ static int psp_dtm_initialize(struct psp_context *psp) · 8 unmodified lines | ||
| 1641 | 1757 | if (amdgpu_sriov_vf(psp->adev)) |
| 1642 | 1758 | return 0; |
| 1643 | 1759 | |
| 1644 | − if (!psp->adev->psp.ta_dtm_ucode_size || | |
| 1645 | − !psp->adev->psp.ta_dtm_start_addr) { | |
| 1760 | + if (!psp->dtm.size_bytes || | |
| 1761 | + !psp->dtm.start_addr) { | |
| 1646 | 1762 | dev_info(psp->adev->dev, "DTM: optional dtm ta ucode is not available\n"); |
| 1647 | 1763 | return 0; |
| 1648 | 1764 | } |
| 1649 | 1765 | |
| 1650 | − if (!psp->dtm_context.dtm_initialized) { | |
| 1766 | + if (!psp->dtm_context.context.initialized) { | |
| 1651 | 1767 | ret = psp_dtm_init_shared_buf(psp); |
| 1652 | 1768 | if (ret) |
| 1653 | 1769 | return ret; |
| @@ -1671,15 +1787,13 @@ static int psp_dtm_unload(struct psp_context *psp) · 17 unmodified lines | ||
| 1671 | 1787 | if (amdgpu_sriov_vf(psp->adev)) |
| 1672 | 1788 | return 0; |
| 1673 | 1789 | |
| 1674 | − cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL); | |
| 1675 | − if (!cmd) | |
| 1676 | − return -ENOMEM; | |
| 1790 | + cmd = acquire_psp_cmd_buf(psp); | |
| 1677 | 1791 | |
| 1678 | − psp_prep_ta_unload_cmd_buf(cmd, psp->dtm_context.session_id); | |
| 1792 | + psp_prep_ta_unload_cmd_buf(cmd, psp->dtm_context.context.session_id); | |
| 1679 | 1793 | |
| 1680 | 1794 | ret = psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr); |
| 1681 | 1795 | |
| 1682 | − kfree(cmd); | |
| 1796 | + release_psp_cmd_buf(psp); | |
| 1683 | 1797 | |
| 1684 | 1798 | return ret; |
| 1685 | 1799 | } |
| @@ -1692,7 +1806,7 @@ int psp_dtm_invoke(struct psp_context *psp, uint32_t ta_cmd_id) · 6 unmodified lines | ||
| 1692 | 1806 | if (amdgpu_sriov_vf(psp->adev)) |
| 1693 | 1807 | return 0; |
| 1694 | 1808 | |
| 1695 | − return psp_ta_invoke(psp, ta_cmd_id, psp->dtm_context.session_id); | |
| 1809 | + return psp_ta_invoke(psp, ta_cmd_id, psp->dtm_context.context.session_id); | |
| 1696 | 1810 | } |
| 1697 | 1811 | |
| 1698 | 1812 | static int psp_dtm_terminate(struct psp_context *psp) |
| @@ -1705,8 +1819,8 @@ static int psp_dtm_terminate(struct psp_context *psp) · 6 unmodified lines | ||
| 1705 | 1819 | if (amdgpu_sriov_vf(psp->adev)) |
| 1706 | 1820 | return 0; |
| 1707 | 1821 | |
| 1708 | − if (!psp->dtm_context.dtm_initialized) { | |
| 1709 | − if (psp->dtm_context.dtm_shared_buf) | |
| 1822 | + if (!psp->dtm_context.context.initialized) { | |
| 1823 | + if (psp->dtm_context.context.mem_context.shared_buf) | |
| 1710 | 1824 | goto out; |
| 1711 | 1825 | else |
| 1712 | 1826 | return 0; |
| @@ -1716,13 +1830,11 @@ static int psp_dtm_terminate(struct psp_context *psp) · 3 unmodified lines | ||
| 1716 | 1830 | if (ret) |
| 1717 | 1831 | return ret; |
| 1718 | 1832 | |
| 1719 | − psp->dtm_context.dtm_initialized = false; | |
| 1833 | + psp->dtm_context.context.initialized = false; | |
| 1720 | 1834 | |
| 1721 | 1835 | out: |
| 1722 | − /* free hdcp shared memory */ | |
| 1723 | − amdgpu_bo_free_kernel(&psp->dtm_context.dtm_shared_bo, | |
| 1724 | − &psp->dtm_context.dtm_shared_mc_addr, | |
| 1725 | − &psp->dtm_context.dtm_shared_buf); | |
| 1836 | + /* free dtm shared memory */ | |
| 1837 | + psp_ta_free_shared_buf(&psp->dtm_context.context.mem_context); | |
| 1726 | 1838 | |
| 1727 | 1839 | return 0; |
| 1728 | 1840 | } |
| @@ -1731,19 +1843,8 @@ out: · 2 unmodified lines | ||
| 1731 | 1843 | // RAP start |
| 1732 | 1844 | static int psp_rap_init_shared_buf(struct psp_context *psp) |
| 1733 | 1845 | { |
| 1734 | − int ret; | |
| 1735 | − | |
| 1736 | − /* | |
| 1737 | − * Allocate 16k memory aligned to 4k from Frame Buffer (local | |
| 1738 | − * physical) for rap ta <-> Driver | |
| 1739 | − */ | |
| 1740 | − ret = amdgpu_bo_create_kernel(psp->adev, PSP_RAP_SHARED_MEM_SIZE, | |
| 1741 | − PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM, | |
| 1742 | − &psp->rap_context.rap_shared_bo, | |
| 1743 | − &psp->rap_context.rap_shared_mc_addr, | |
| 1744 | − &psp->rap_context.rap_shared_buf); | |
| 1745 | − | |
| 1746 | − return ret; | |
| 1846 | + return psp_ta_init_shared_buf(psp, &psp->rap_context.context.mem_context, | |
| 1847 | + PSP_RAP_SHARED_MEM_SIZE); | |
| 1747 | 1848 | } |
| 1748 | 1849 | |
| 1749 | 1850 | static int psp_rap_load(struct psp_context *psp) |
| @@ -1751,27 +1852,25 @@ static int psp_rap_load(struct psp_context *psp) · 1 unmodified line | ||
| 1751 | 1852 | int ret; |
| 1752 | 1853 | struct psp_gfx_cmd_resp *cmd; |
| 1753 | 1854 | |
| 1754 | − cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL); | |
| 1755 | − if (!cmd) | |
| 1756 | − return -ENOMEM; | |
| 1855 | + psp_copy_fw(psp, psp->rap.start_addr, psp->rap.size_bytes); | |
| 1757 | 1856 | |
| 1758 | − psp_copy_fw(psp, psp->ta_rap_start_addr, psp->ta_rap_ucode_size); | |
| 1857 | + cmd = acquire_psp_cmd_buf(psp); | |
| 1759 | 1858 | |
| 1760 | 1859 | psp_prep_ta_load_cmd_buf(cmd, |
| 1761 | 1860 | psp->fw_pri_mc_addr, |
| 1762 | − psp->ta_rap_ucode_size, | |
| 1763 | − psp->rap_context.rap_shared_mc_addr, | |
| 1861 | + psp->rap.size_bytes, | |
| 1862 | + psp->rap_context.context.mem_context.shared_mc_addr, | |
| 1764 | 1863 | PSP_RAP_SHARED_MEM_SIZE); |
| 1765 | 1864 | |
| 1766 | 1865 | ret = psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr); |
| 1767 | 1866 | |
| 1768 | 1867 | if (!ret) { |
| 1769 | − psp->rap_context.rap_initialized = true; | |
| 1770 | − psp->rap_context.session_id = cmd->resp.session_id; | |
| 1868 | + psp->rap_context.context.initialized = true; | |
| 1869 | + psp->rap_context.context.session_id = cmd->resp.session_id; | |
| 1771 | 1870 | mutex_init(&psp->rap_context.mutex); |
| 1772 | 1871 | } |
| 1773 | 1872 | |
| 1774 | − kfree(cmd); | |
| 1873 | + release_psp_cmd_buf(psp); | |
| 1775 | 1874 | |
| 1776 | 1875 | return ret; |
| 1777 | 1876 | } |
| @@ -1779,17 +1878,13 @@ static int psp_rap_load(struct psp_context *psp) · 1 unmodified line | ||
| 1779 | 1878 | static int psp_rap_unload(struct psp_context *psp) |
| 1780 | 1879 | { |
| 1781 | 1880 | int ret; |
| 1782 | − struct psp_gfx_cmd_resp *cmd; | |
| 1881 | + struct psp_gfx_cmd_resp *cmd = acquire_psp_cmd_buf(psp); | |
| 1783 | 1882 | |
| 1784 | − cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL); | |
| 1785 | − if (!cmd) | |
| 1786 | − return -ENOMEM; | |
| 1787 | − | |
| 1788 | − psp_prep_ta_unload_cmd_buf(cmd, psp->rap_context.session_id); | |
| 1883 | + psp_prep_ta_unload_cmd_buf(cmd, psp->rap_context.context.session_id); | |
| 1789 | 1884 | |
| 1790 | 1885 | ret = psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr); |
| 1791 | 1886 | |
| 1792 | − kfree(cmd); | |
| 1887 | + release_psp_cmd_buf(psp); | |
| 1793 | 1888 | |
| 1794 | 1889 | return ret; |
| 1795 | 1890 | } |
| @@ -1805,13 +1900,13 @@ static int psp_rap_initialize(struct psp_context *psp) · 9 unmodified lines | ||
| 1805 | 1900 | if (amdgpu_sriov_vf(psp->adev)) |
| 1806 | 1901 | return 0; |
| 1807 | 1902 | |
| 1808 | − if (!psp->adev->psp.ta_rap_ucode_size || | |
| 1809 | − !psp->adev->psp.ta_rap_start_addr) { | |
| 1903 | + if (!psp->rap.size_bytes || | |
| 1904 | + !psp->rap.start_addr) { | |
| 1810 | 1905 | dev_info(psp->adev->dev, "RAP: optional rap ta ucode is not available\n"); |
| 1811 | 1906 | return 0; |
| 1812 | 1907 | } |
| 1813 | 1908 | |
| 1814 | − if (!psp->rap_context.rap_initialized) { | |
| 1909 | + if (!psp->rap_context.context.initialized) { | |
| 1815 | 1910 | ret = psp_rap_init_shared_buf(psp); |
| 1816 | 1911 | if (ret) |
| 1817 | 1912 | return ret; |
| @@ -1825,11 +1920,9 @@ static int psp_rap_initialize(struct psp_context *psp) · 7 unmodified lines | ||
| 1825 | 1920 | if (ret || status != TA_RAP_STATUS__SUCCESS) { |
| 1826 | 1921 | psp_rap_unload(psp); |
| 1827 | 1922 | |
| 1828 | − amdgpu_bo_free_kernel(&psp->rap_context.rap_shared_bo, | |
| 1829 | − &psp->rap_context.rap_shared_mc_addr, | |
| 1830 | − &psp->rap_context.rap_shared_buf); | |
| 1923 | + psp_ta_free_shared_buf(&psp->rap_context.context.mem_context); | |
| 1831 | 1924 | |
| 1832 | − psp->rap_context.rap_initialized = false; | |
| 1925 | + psp->rap_context.context.initialized = false; | |
| 1833 | 1926 | |
| 1834 | 1927 | dev_warn(psp->adev->dev, "RAP TA initialize fail (%d) status %d.\n", |
| 1835 | 1928 | ret, status); |
| @@ -1844,17 +1937,15 @@ static int psp_rap_terminate(struct psp_context *psp) · 8 unmodified lines | ||
| 1844 | 1937 | { |
| 1845 | 1938 | int ret; |
| 1846 | 1939 | |
| 1847 | − if (!psp->rap_context.rap_initialized) | |
| 1940 | + if (!psp->rap_context.context.initialized) | |
| 1848 | 1941 | return 0; |
| 1849 | 1942 | |
| 1850 | 1943 | ret = psp_rap_unload(psp); |
| 1851 | 1944 | |
| 1852 | − psp->rap_context.rap_initialized = false; | |
| 1945 | + psp->rap_context.context.initialized = false; | |
| 1853 | 1946 | |
| 1854 | 1947 | /* free rap shared memory */ |
| 1855 | − amdgpu_bo_free_kernel(&psp->rap_context.rap_shared_bo, | |
| 1856 | − &psp->rap_context.rap_shared_mc_addr, | |
| 1857 | − &psp->rap_context.rap_shared_buf); | |
| 1948 | + psp_ta_free_shared_buf(&psp->rap_context.context.mem_context); | |
| 1858 | 1949 | |
| 1859 | 1950 | return ret; |
| 1860 | 1951 | } |
| @@ -1864,7 +1955,7 @@ int psp_rap_invoke(struct psp_context *psp, uint32_t ta_cmd_id, enum ta_rap_stat · 3 unmodified lines | ||
| 1864 | 1955 | struct ta_rap_shared_memory *rap_cmd; |
| 1865 | 1956 | int ret = 0; |
| 1866 | 1957 | |
| 1867 | − if (!psp->rap_context.rap_initialized) | |
| 1958 | + if (!psp->rap_context.context.initialized) | |
| 1868 | 1959 | return 0; |
| 1869 | 1960 | |
| 1870 | 1961 | if (ta_cmd_id != TA_CMD_RAP__INITIALIZE && |
| @@ -1874,13 +1965,13 @@ int psp_rap_invoke(struct psp_context *psp, uint32_t ta_cmd_id, enum ta_rap_stat · 3 unmodified lines | ||
| 1874 | 1965 | mutex_lock(&psp->rap_context.mutex); |
| 1875 | 1966 | |
| 1876 | 1967 | rap_cmd = (struct ta_rap_shared_memory *) |
| 1877 | − psp->rap_context.rap_shared_buf; | |
| 1968 | + psp->rap_context.context.mem_context.shared_buf; | |
| 1878 | 1969 | memset(rap_cmd, 0, sizeof(struct ta_rap_shared_memory)); |
| 1879 | 1970 | |
| 1880 | 1971 | rap_cmd->cmd_id = ta_cmd_id; |
| 1881 | 1972 | rap_cmd->validation_method_id = METHOD_A; |
| 1882 | 1973 | |
| 1883 | − ret = psp_ta_invoke(psp, rap_cmd->cmd_id, psp->rap_context.session_id); | |
| 1974 | + ret = psp_ta_invoke(psp, rap_cmd->cmd_id, psp->rap_context.context.session_id); | |
| 1884 | 1975 | if (ret) |
| 1885 | 1976 | goto out_unlock; |
| 1886 | 1977 | |
| @@ -1897,67 +1988,48 @@ out_unlock: · 10 unmodified lines | ||
| 1897 | 1988 | /* securedisplay start */ |
| 1898 | 1989 | static int psp_securedisplay_init_shared_buf(struct psp_context *psp) |
| 1899 | 1990 | { |
| 1900 | − int ret; | |
| 1901 | − | |
| 1902 | − /* | |
| 1903 | − * Allocate 16k memory aligned to 4k from Frame Buffer (local | |
| 1904 | − * physical) for sa ta <-> Driver | |
| 1905 | − */ | |
| 1906 | − ret = amdgpu_bo_create_kernel(psp->adev, PSP_SECUREDISPLAY_SHARED_MEM_SIZE, | |
| 1907 | − PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM, | |
| 1908 | − &psp->securedisplay_context.securedisplay_shared_bo, | |
| 1909 | − &psp->securedisplay_context.securedisplay_shared_mc_addr, | |
| 1910 | − &psp->securedisplay_context.securedisplay_shared_buf); | |
| 1911 | − | |
| 1912 | − return ret; | |
| 1991 | + return psp_ta_init_shared_buf( | |
| 1992 | + psp, &psp->securedisplay_context.context.mem_context, | |
| 1993 | + PSP_SECUREDISPLAY_SHARED_MEM_SIZE); | |
| 1913 | 1994 | } |
| 1914 | 1995 | |
| 1915 | 1996 | static int psp_securedisplay_load(struct psp_context *psp) |
| 1916 | 1997 | { |
| 1917 | 1998 | int ret; |
| 1918 | − struct psp_gfx_cmd_resp *cmd; | |
| 1919 | − | |
| 1920 | − cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL); | |
| 1921 | − if (!cmd) | |
| 1922 | − return -ENOMEM; | |
| 1999 | + struct psp_gfx_cmd_resp *cmd = acquire_psp_cmd_buf(psp); | |
| 1923 | 2000 | |
| 1924 | 2001 | memset(psp->fw_pri_buf, 0, PSP_1_MEG); |
| 1925 | − memcpy(psp->fw_pri_buf, psp->ta_securedisplay_start_addr, psp->ta_securedisplay_ucode_size); | |
| 2002 | + memcpy(psp->fw_pri_buf, psp->securedisplay.start_addr, psp->securedisplay.size_bytes); | |
| 1926 | 2003 | |
| 1927 | 2004 | psp_prep_ta_load_cmd_buf(cmd, |
| 1928 | 2005 | psp->fw_pri_mc_addr, |
| 1929 | − psp->ta_securedisplay_ucode_size, | |
| 1930 | − psp->securedisplay_context.securedisplay_shared_mc_addr, | |
| 2006 | + psp->securedisplay.size_bytes, | |
| 2007 | + psp->securedisplay_context.context.mem_context.shared_mc_addr, | |
| 1931 | 2008 | PSP_SECUREDISPLAY_SHARED_MEM_SIZE); |
| 1932 | 2009 | |
| 1933 | 2010 | ret = psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr); |
| 1934 | 2011 | |
| 1935 | − if (ret) | |
| 1936 | − goto failed; | |
| 2012 | + if (!ret) { | |
| 2013 | + psp->securedisplay_context.context.initialized = true; | |
| 2014 | + psp->securedisplay_context.context.session_id = cmd->resp.session_id; | |
| 2015 | + mutex_init(&psp->securedisplay_context.mutex); | |
| 2016 | + } | |
| 1937 | 2017 | |
| 1938 | − psp->securedisplay_context.securedisplay_initialized = true; | |
| 1939 | − psp->securedisplay_context.session_id = cmd->resp.session_id; | |
| 1940 | − mutex_init(&psp->securedisplay_context.mutex); | |
| 2018 | + release_psp_cmd_buf(psp); | |
| 1941 | 2019 | |
| 1942 | −failed: | |
| 1943 | − kfree(cmd); | |
| 1944 | 2020 | return ret; |
| 1945 | 2021 | } |
| 1946 | 2022 | |
| 1947 | 2023 | static int psp_securedisplay_unload(struct psp_context *psp) |
| 1948 | 2024 | { |
| 1949 | 2025 | int ret; |
| 1950 | − struct psp_gfx_cmd_resp *cmd; | |
| 1951 | − | |
| 1952 | − cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL); | |
| 1953 | − if (!cmd) | |
| 1954 | − return -ENOMEM; | |
| 2026 | + struct psp_gfx_cmd_resp *cmd = acquire_psp_cmd_buf(psp); | |
| 1955 | 2027 | |
| 1956 | − psp_prep_ta_unload_cmd_buf(cmd, psp->securedisplay_context.session_id); | |
| 2028 | + psp_prep_ta_unload_cmd_buf(cmd, psp->securedisplay_context.context.session_id); | |
| 1957 | 2029 | |
| 1958 | 2030 | ret = psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr); |
| 1959 | 2031 | |
| 1960 | − kfree(cmd); | |
| 2032 | + release_psp_cmd_buf(psp); | |
| 1961 | 2033 | |
| 1962 | 2034 | return ret; |
| 1963 | 2035 | } |
| @@ -1973,13 +2045,13 @@ static int psp_securedisplay_initialize(struct psp_context *psp) · 9 unmodified lines | ||
| 1973 | 2045 | if (amdgpu_sriov_vf(psp->adev)) |
| 1974 | 2046 | return 0; |
| 1975 | 2047 | |
| 1976 | − if (!psp->adev->psp.ta_securedisplay_ucode_size || | |
| 1977 | − !psp->adev->psp.ta_securedisplay_start_addr) { | |
| 2048 | + if (!psp->securedisplay.size_bytes || | |
| 2049 | + !psp->securedisplay.start_addr) { | |
| 1978 | 2050 | dev_info(psp->adev->dev, "SECUREDISPLAY: securedisplay ta ucode is not available\n"); |
| 1979 | 2051 | return 0; |
| 1980 | 2052 | } |
| 1981 | 2053 | |
| 1982 | − if (!psp->securedisplay_context.securedisplay_initialized) { | |
| 2054 | + if (!psp->securedisplay_context.context.initialized) { | |
| 1983 | 2055 | ret = psp_securedisplay_init_shared_buf(psp); |
| 1984 | 2056 | if (ret) |
| 1985 | 2057 | return ret; |
| @@ -1996,11 +2068,9 @@ static int psp_securedisplay_initialize(struct psp_context *psp) · 10 unmodified lines | ||
| 1996 | 2068 | if (ret) { |
| 1997 | 2069 | psp_securedisplay_unload(psp); |
| 1998 | 2070 | |
| 1999 | − amdgpu_bo_free_kernel(&psp->securedisplay_context.securedisplay_shared_bo, | |
| 2000 | − &psp->securedisplay_context.securedisplay_shared_mc_addr, | |
| 2001 | − &psp->securedisplay_context.securedisplay_shared_buf); | |
| 2071 | + psp_ta_free_shared_buf(&psp->securedisplay_context.context.mem_context); | |
| 2002 | 2072 | |
| 2003 | − psp->securedisplay_context.securedisplay_initialized = false; | |
| 2073 | + psp->securedisplay_context.context.initialized = false; | |
| 2004 | 2074 | |
| 2005 | 2075 | dev_err(psp->adev->dev, "SECUREDISPLAY TA initialize fail.\n"); |
| 2006 | 2076 | return -EINVAL; |
| @@ -2025,19 +2095,17 @@ static int psp_securedisplay_terminate(struct psp_context *psp) · 18 unmodified lines | ||
| 2025 | 2095 | if (amdgpu_sriov_vf(psp->adev)) |
| 2026 | 2096 | return 0; |
| 2027 | 2097 | |
| 2028 | − if (!psp->securedisplay_context.securedisplay_initialized) | |
| 2098 | + if (!psp->securedisplay_context.context.initialized) | |
| 2029 | 2099 | return 0; |
| 2030 | 2100 | |
| 2031 | 2101 | ret = psp_securedisplay_unload(psp); |
| 2032 | 2102 | if (ret) |
| 2033 | 2103 | return ret; |
| 2034 | 2104 | |
| 2035 | − psp->securedisplay_context.securedisplay_initialized = false; | |
| 2105 | + psp->securedisplay_context.context.initialized = false; | |
| 2036 | 2106 | |
| 2037 | 2107 | /* free securedisplay shared memory */ |
| 2038 | − amdgpu_bo_free_kernel(&psp->securedisplay_context.securedisplay_shared_bo, | |
| 2039 | − &psp->securedisplay_context.securedisplay_shared_mc_addr, | |
| 2040 | − &psp->securedisplay_context.securedisplay_shared_buf); | |
| 2108 | + psp_ta_free_shared_buf(&psp->securedisplay_context.context.mem_context); | |
| 2041 | 2109 | |
| 2042 | 2110 | return ret; |
| 2043 | 2111 | } |
| @@ -2046,7 +2114,7 @@ int psp_securedisplay_invoke(struct psp_context *psp, uint32_t ta_cmd_id) · 2 unmodified lines | ||
| 2046 | 2114 | { |
| 2047 | 2115 | int ret; |
| 2048 | 2116 | |
| 2049 | − if (!psp->securedisplay_context.securedisplay_initialized) | |
| 2117 | + if (!psp->securedisplay_context.context.initialized) | |
| 2050 | 2118 | return -EINVAL; |
| 2051 | 2119 | |
| 2052 | 2120 | if (ta_cmd_id != TA_SECUREDISPLAY_COMMAND__QUERY_TA && |
| @@ -2055,7 +2123,7 @@ int psp_securedisplay_invoke(struct psp_context *psp, uint32_t ta_cmd_id) · 2 unmodified lines | ||
| 2055 | 2123 | |
| 2056 | 2124 | mutex_lock(&psp->securedisplay_context.mutex); |
| 2057 | 2125 | |
| 2058 | − ret = psp_ta_invoke(psp, ta_cmd_id, psp->securedisplay_context.session_id); | |
| 2126 | + ret = psp_ta_invoke(psp, ta_cmd_id, psp->securedisplay_context.context.session_id); | |
| 2059 | 2127 | |
| 2060 | 2128 | mutex_unlock(&psp->securedisplay_context.mutex); |
| 2061 | 2129 | |
| @@ -2069,7 +2137,7 @@ static int psp_hw_start(struct psp_context *psp) · 7 unmodified lines | ||
| 2069 | 2137 | int ret; |
| 2070 | 2138 | |
| 2071 | 2139 | if (!amdgpu_sriov_vf(adev)) { |
| 2072 | − if (psp->kdb_bin_size && | |
| 2140 | + if ((is_psp_fw_valid(psp->kdb)) && | |
| 2073 | 2141 | (psp->funcs->bootloader_load_kdb != NULL)) { |
| 2074 | 2142 | ret = psp_bootloader_load_kdb(psp); |
| 2075 | 2143 | if (ret) { |
| @@ -2078,7 +2146,8 @@ static int psp_hw_start(struct psp_context *psp) · 2 unmodified lines | ||
| 2078 | 2146 | } |
| 2079 | 2147 | } |
| 2080 | 2148 | |
| 2081 | − if (psp->spl_bin_size) { | |
| 2149 | + if ((is_psp_fw_valid(psp->spl)) && | |
| 2150 | + (psp->funcs->bootloader_load_spl != NULL)) { | |
| 2082 | 2151 | ret = psp_bootloader_load_spl(psp); |
| 2083 | 2152 | if (ret) { |
| 2084 | 2153 | DRM_ERROR("PSP load spl failed!\n"); |
| @@ -2086,16 +2155,49 @@ static int psp_hw_start(struct psp_context *psp) · 1 unmodified line | ||
| 2086 | 2155 | } |
| 2087 | 2156 | } |
| 2088 | 2157 | |
| 2089 | − ret = psp_bootloader_load_sysdrv(psp); | |
| 2090 | − if (ret) { | |
| 2091 | − DRM_ERROR("PSP load sysdrv failed!\n"); | |
| 2092 | − return ret; | |
| 2158 | + if ((is_psp_fw_valid(psp->sys)) && | |
| 2159 | + (psp->funcs->bootloader_load_sysdrv != NULL)) { | |
| 2160 | + ret = psp_bootloader_load_sysdrv(psp); | |
| 2161 | + if (ret) { | |
| 2162 | + DRM_ERROR("PSP load sys drv failed!\n"); | |
| 2163 | + return ret; | |
| 2164 | + } | |
| 2093 | 2165 | } |
| 2094 | 2166 | |
| 2095 | − ret = psp_bootloader_load_sos(psp); | |
| 2096 | − if (ret) { | |
| 2097 | − DRM_ERROR("PSP load sos failed!\n"); | |
| 2098 | − return ret; | |
| 2167 | + if ((is_psp_fw_valid(psp->soc_drv)) && | |
| 2168 | + (psp->funcs->bootloader_load_soc_drv != NULL)) { | |
| 2169 | + ret = psp_bootloader_load_soc_drv(psp); | |
| 2170 | + if (ret) { | |
| 2171 | + DRM_ERROR("PSP load soc drv failed!\n"); | |
| 2172 | + return ret; | |
| 2173 | + } | |
| 2174 | + } | |
| 2175 | + | |
| 2176 | + if ((is_psp_fw_valid(psp->intf_drv)) && | |
| 2177 | + (psp->funcs->bootloader_load_intf_drv != NULL)) { | |
| 2178 | + ret = psp_bootloader_load_intf_drv(psp); | |
| 2179 | + if (ret) { | |
| 2180 | + DRM_ERROR("PSP load intf drv failed!\n"); | |
| 2181 | + return ret; | |
| 2182 | + } | |
| 2183 | + } | |
| 2184 | + | |
| 2185 | + if ((is_psp_fw_valid(psp->dbg_drv)) && | |
| 2186 | + (psp->funcs->bootloader_load_dbg_drv != NULL)) { | |
| 2187 | + ret = psp_bootloader_load_dbg_drv(psp); | |
| 2188 | + if (ret) { | |
| 2189 | + DRM_ERROR("PSP load dbg drv failed!\n"); | |
| 2190 | + return ret; | |
| 2191 | + } | |
| 2192 | + } | |
| 2193 | + | |
| 2194 | + if ((is_psp_fw_valid(psp->sos)) && | |
| 2195 | + (psp->funcs->bootloader_load_sos != NULL)) { | |
| 2196 | + ret = psp_bootloader_load_sos(psp); | |
| 2197 | + if (ret) { | |
| 2198 | + DRM_ERROR("PSP load sos failed!\n"); | |
| 2199 | + return ret; | |
| 2200 | + } | |
| 2099 | 2201 | } |
| 2100 | 2202 | } |
| 2101 | 2203 | |
| @@ -2299,8 +2401,6 @@ static int psp_prep_load_ip_fw_cmd_buf(struct amdgpu_firmware_info *ucode, · 197 unmodified lines | ||
| 2299 | 2401 | int ret; |
| 2300 | 2402 | uint64_t fw_mem_mc_addr = ucode->mc_addr; |
| 2301 | 2403 | |
| 2302 | − memset(cmd, 0, sizeof(struct psp_gfx_cmd_resp)); | |
| 2303 | − | |
| 2304 | 2404 | cmd->cmd_id = GFX_CMD_ID_LOAD_IP_FW; |
| 2305 | 2405 | cmd->cmd.cmd_load_ip_fw.fw_phy_addr_lo = lower_32_bits(fw_mem_mc_addr); |
| 2306 | 2406 | cmd->cmd.cmd_load_ip_fw.fw_phy_addr_hi = upper_32_bits(fw_mem_mc_addr); |
| @@ -2313,17 +2413,19 @@ static int psp_prep_load_ip_fw_cmd_buf(struct amdgpu_firmware_info *ucode, · 6 unmodified lines | ||
| 2313 | 2413 | return ret; |
| 2314 | 2414 | } |
| 2315 | 2415 | |
| 2316 | −static int psp_execute_np_fw_load(struct psp_context *psp, | |
| 2416 | +static int psp_execute_non_psp_fw_load(struct psp_context *psp, | |
| 2317 | 2417 | struct amdgpu_firmware_info *ucode) |
| 2318 | 2418 | { |
| 2319 | 2419 | int ret = 0; |
| 2420 | + struct psp_gfx_cmd_resp *cmd = acquire_psp_cmd_buf(psp); | |
| 2320 | 2421 | |
| 2321 | − ret = psp_prep_load_ip_fw_cmd_buf(ucode, psp->cmd); | |
| 2322 | − if (ret) | |
| 2323 | − return ret; | |
| 2422 | + ret = psp_prep_load_ip_fw_cmd_buf(ucode, cmd); | |
| 2423 | + if (!ret) { | |
| 2424 | + ret = psp_cmd_submit_buf(psp, ucode, cmd, | |
| 2425 | + psp->fence_buf_mc_addr); | |
| 2426 | + } | |
| 2324 | 2427 | |
| 2325 | − ret = psp_cmd_submit_buf(psp, ucode, psp->cmd, | |
| 2326 | − psp->fence_buf_mc_addr); | |
| 2428 | + release_psp_cmd_buf(psp); | |
| 2327 | 2429 | |
| 2328 | 2430 | return ret; |
| 2329 | 2431 | } |
| @@ -2334,7 +2436,7 @@ static int psp_load_smu_fw(struct psp_context *psp) · 4 unmodified lines | ||
| 2334 | 2436 | struct amdgpu_device *adev = psp->adev; |
| 2335 | 2437 | struct amdgpu_firmware_info *ucode = |
| 2336 | 2438 | &adev->firmware.ucode[AMDGPU_UCODE_ID_SMC]; |
| 2337 | − struct amdgpu_ras *ras = psp->ras.ras; | |
| 2439 | + struct amdgpu_ras *ras = psp->ras_context.ras; | |
| 2338 | 2440 | |
| 2339 | 2441 | if (!ucode->fw || amdgpu_sriov_vf(psp->adev)) |
| 2340 | 2442 | return 0; |
| @@ -2349,7 +2451,7 @@ static int psp_load_smu_fw(struct psp_context *psp) · 8 unmodified lines | ||
| 2349 | 2451 | } |
| 2350 | 2452 | } |
| 2351 | 2453 | |
| 2352 | − ret = psp_execute_np_fw_load(psp, ucode); | |
| 2454 | + ret = psp_execute_non_psp_fw_load(psp, ucode); | |
| 2353 | 2455 | |
| 2354 | 2456 | if (ret) |
| 2355 | 2457 | DRM_ERROR("PSP load smu failed!\n"); |
| @@ -2404,14 +2506,14 @@ int psp_load_fw_list(struct psp_context *psp, · 48 unmodified lines | ||
| 2404 | 2506 | for (i = 0; i < ucode_count; ++i) { |
| 2405 | 2507 | ucode = ucode_list[i]; |
| 2406 | 2508 | psp_print_fw_hdr(psp, ucode); |
| 2407 | − ret = psp_execute_np_fw_load(psp, ucode); | |
| 2509 | + ret = psp_execute_non_psp_fw_load(psp, ucode); | |
| 2408 | 2510 | if (ret) |
| 2409 | 2511 | return ret; |
| 2410 | 2512 | } |
| 2411 | 2513 | return ret; |
| 2412 | 2514 | } |
| 2413 | 2515 | |
| 2414 | −static int psp_np_fw_load(struct psp_context *psp) | |
| 2516 | +static int psp_load_non_psp_fw(struct psp_context *psp) | |
| 2415 | 2517 | { |
| 2416 | 2518 | int i, ret; |
| 2417 | 2519 | struct amdgpu_firmware_info *ucode; |
| @@ -2450,7 +2552,7 @@ static int psp_np_fw_load(struct psp_context *psp) · 32 unmodified lines | ||
| 2450 | 2552 | |
| 2451 | 2553 | psp_print_fw_hdr(psp, ucode); |
| 2452 | 2554 | |
| 2453 | − ret = psp_execute_np_fw_load(psp, ucode); | |
| 2555 | + ret = psp_execute_non_psp_fw_load(psp, ucode); | |
| 2454 | 2556 | if (ret) |
| 2455 | 2557 | return ret; |
| 2456 | 2558 | |
| @@ -2478,10 +2580,6 @@ static int psp_load_fw(struct amdgpu_device *adev) · 21 unmodified lines | ||
| 2478 | 2580 | goto skip_memalloc; |
| 2479 | 2581 | } |
| 2480 | 2582 | |
| 2481 | − psp->cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL); | |
| 2482 | − if (!psp->cmd) | |
| 2483 | − return -ENOMEM; | |
| 2484 | − | |
| 2485 | 2583 | if (amdgpu_sriov_vf(adev)) { |
| 2486 | 2584 | ret = amdgpu_bo_create_kernel(adev, PSP_1_MEG, PSP_1_MEG, |
| 2487 | 2585 | AMDGPU_GEM_DOMAIN_VRAM, |
| @@ -2527,7 +2625,7 @@ skip_memalloc: · 39 unmodified lines | ||
| 2527 | 2625 | if (ret) |
| 2528 | 2626 | goto failed; |
| 2529 | 2627 | |
| 2530 | − ret = psp_np_fw_load(psp); | |
| 2628 | + ret = psp_load_non_psp_fw(psp); | |
| 2531 | 2629 | if (ret) |
| 2532 | 2630 | goto failed; |
| 2533 | 2631 | |
| @@ -2543,7 +2641,7 @@ skip_memalloc: · 9 unmodified lines | ||
| 2543 | 2641 | return ret; |
| 2544 | 2642 | } |
| 2545 | 2643 | |
| 2546 | − if (psp->adev->psp.ta_fw) { | |
| 2644 | + if (psp->ta_fw) { | |
| 2547 | 2645 | ret = psp_ras_initialize(psp); |
| 2548 | 2646 | if (ret) |
| 2549 | 2647 | dev_err(psp->adev->dev, |
| @@ -2615,7 +2713,7 @@ static int psp_hw_fini(void *handle) · 65 unmodified lines | ||
| 2615 | 2713 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; |
| 2616 | 2714 | struct psp_context *psp = &adev->psp; |
| 2617 | 2715 | |
| 2618 | − if (psp->adev->psp.ta_fw) { | |
| 2716 | + if (psp->ta_fw) { | |
| 2619 | 2717 | psp_ras_terminate(psp); |
| 2620 | 2718 | psp_securedisplay_terminate(psp); |
| 2621 | 2719 | psp_rap_terminate(psp); |
| @@ -2635,9 +2733,6 @@ static int psp_hw_fini(void *handle) · 13 unmodified lines | ||
| 2635 | 2733 | amdgpu_bo_free_kernel(&psp->cmd_buf_bo, &psp->cmd_buf_mc_addr, |
| 2636 | 2734 | (void **)&psp->cmd_buf_mem); |
| 2637 | 2735 | |
| 2638 | − kfree(psp->cmd); | |
| 2639 | − psp->cmd = NULL; | |
| 2640 | − | |
| 2641 | 2736 | return 0; |
| 2642 | 2737 | } |
| 2643 | 2738 | |
| @@ -2648,7 +2743,7 @@ static int psp_suspend(void *handle) · 4 unmodified lines | ||
| 2648 | 2743 | struct psp_context *psp = &adev->psp; |
| 2649 | 2744 | |
| 2650 | 2745 | if (adev->gmc.xgmi.num_physical_nodes > 1 && |
| 2651 | − psp->xgmi_context.initialized == 1) { | |
| 2746 | + psp->xgmi_context.context.initialized) { | |
| 2652 | 2747 | ret = psp_xgmi_terminate(psp); |
| 2653 | 2748 | if (ret) { |
| 2654 | 2749 | DRM_ERROR("Failed to terminate xgmi ta\n"); |
| @@ -2656,7 +2751,7 @@ static int psp_suspend(void *handle) · 1 unmodified line | ||
| 2656 | 2751 | } |
| 2657 | 2752 | } |
| 2658 | 2753 | |
| 2659 | − if (psp->adev->psp.ta_fw) { | |
| 2754 | + if (psp->ta_fw) { | |
| 2660 | 2755 | ret = psp_ras_terminate(psp); |
| 2661 | 2756 | if (ret) { |
| 2662 | 2757 | DRM_ERROR("Failed to terminate ras ta\n"); |
| @@ -2727,7 +2822,7 @@ static int psp_resume(void *handle) · 64 unmodified lines | ||
| 2727 | 2822 | if (ret) |
| 2728 | 2823 | goto failed; |
| 2729 | 2824 | |
| 2730 | − ret = psp_np_fw_load(psp); | |
| 2825 | + ret = psp_load_non_psp_fw(psp); | |
| 2731 | 2826 | if (ret) |
| 2732 | 2827 | goto failed; |
| 2733 | 2828 | |
| @@ -2738,7 +2833,7 @@ static int psp_resume(void *handle) · 4 unmodified lines | ||
| 2738 | 2833 | } |
| 2739 | 2834 | |
| 2740 | 2835 | if (adev->gmc.xgmi.num_physical_nodes > 1) { |
| 2741 | − ret = psp_xgmi_initialize(psp); | |
| 2836 | + ret = psp_xgmi_initialize(psp, false, true); | |
| 2742 | 2837 | /* Warning the XGMI seesion initialize failure |
| 2743 | 2838 | * Instead of stop driver initialization |
| 2744 | 2839 | */ |
| @@ -2747,7 +2842,7 @@ static int psp_resume(void *handle) · 2 unmodified lines | ||
| 2747 | 2842 | "XGMI: Failed to initialize XGMI session\n"); |
| 2748 | 2843 | } |
| 2749 | 2844 | |
| 2750 | − if (psp->adev->psp.ta_fw) { | |
| 2845 | + if (psp->ta_fw) { | |
| 2751 | 2846 | ret = psp_ras_initialize(psp); |
| 2752 | 2847 | if (ret) |
| 2753 | 2848 | dev_err(psp->adev->dev, |
| @@ -2801,17 +2896,15 @@ int psp_gpu_reset(struct amdgpu_device *adev) · 47 unmodified lines | ||
| 2801 | 2896 | int psp_rlc_autoload_start(struct psp_context *psp) |
| 2802 | 2897 | { |
| 2803 | 2898 | int ret; |
| 2804 | − struct psp_gfx_cmd_resp *cmd; | |
| 2805 | − | |
| 2806 | − cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL); | |
| 2807 | − if (!cmd) | |
| 2808 | − return -ENOMEM; | |
| 2899 | + struct psp_gfx_cmd_resp *cmd = acquire_psp_cmd_buf(psp); | |
| 2809 | 2900 | |
| 2810 | 2901 | cmd->cmd_id = GFX_CMD_ID_AUTOLOAD_RLC; |
| 2811 | 2902 | |
| 2812 | 2903 | ret = psp_cmd_submit_buf(psp, NULL, cmd, |
| 2813 | 2904 | psp->fence_buf_mc_addr); |
| 2814 | − kfree(cmd); | |
| 2905 | + | |
| 2906 | + release_psp_cmd_buf(psp); | |
| 2907 | + | |
| 2815 | 2908 | return ret; |
| 2816 | 2909 | } |
| 2817 | 2910 | |
| @@ -2825,7 +2918,7 @@ int psp_update_vcn_sram(struct amdgpu_device *adev, int inst_idx, · 7 unmodified lines | ||
| 2825 | 2918 | ucode.mc_addr = cmd_gpu_addr; |
| 2826 | 2919 | ucode.ucode_size = cmd_size; |
| 2827 | 2920 | |
| 2828 | − return psp_execute_np_fw_load(&adev->psp, &ucode); | |
| 2921 | + return psp_execute_non_psp_fw_load(&adev->psp, &ucode); | |
| 2829 | 2922 | } |
| 2830 | 2923 | |
| 2831 | 2924 | int psp_ring_cmd_submit(struct psp_context *psp, |
| @@ -2901,10 +2994,10 @@ int psp_init_asd_microcode(struct psp_context *psp, · 69 unmodified lines | ||
| 2901 | 2994 | goto out; |
| 2902 | 2995 | |
| 2903 | 2996 | asd_hdr = (const struct psp_firmware_header_v1_0 *)adev->psp.asd_fw->data; |
| 2904 | − adev->psp.asd_fw_version = le32_to_cpu(asd_hdr->header.ucode_version); | |
| 2905 | − adev->psp.asd_feature_version = le32_to_cpu(asd_hdr->sos.fw_version); | |
| 2906 | − adev->psp.asd_ucode_size = le32_to_cpu(asd_hdr->header.ucode_size_bytes); | |
| 2907 | − adev->psp.asd_start_addr = (uint8_t *)asd_hdr + | |
| 2997 | + adev->psp.asd.fw_version = le32_to_cpu(asd_hdr->header.ucode_version); | |
| 2998 | + adev->psp.asd.feature_version = le32_to_cpu(asd_hdr->sos.fw_version); | |
| 2999 | + adev->psp.asd.size_bytes = le32_to_cpu(asd_hdr->header.ucode_size_bytes); | |
| 3000 | + adev->psp.asd.start_addr = (uint8_t *)asd_hdr + | |
| 2908 | 3001 | le32_to_cpu(asd_hdr->header.ucode_array_offset_bytes); |
| 2909 | 3002 | return 0; |
| 2910 | 3003 | out: |
| @@ -2918,7 +3011,7 @@ int psp_init_toc_microcode(struct psp_context *psp, · 7 unmodified lines | ||
| 2918 | 3011 | const char *chip_name) |
| 2919 | 3012 | { |
| 2920 | 3013 | struct amdgpu_device *adev = psp->adev; |
| 2921 | − char fw_name[30]; | |
| 3014 | + char fw_name[PSP_FW_NAME_LEN]; | |
| 2922 | 3015 | const struct psp_firmware_header_v1_0 *toc_hdr; |
| 2923 | 3016 | int err = 0; |
| 2924 | 3017 | |
| @@ -2937,10 +3030,10 @@ int psp_init_toc_microcode(struct psp_context *psp, · 12 unmodified lines | ||
| 2937 | 3030 | goto out; |
| 2938 | 3031 | |
| 2939 | 3032 | toc_hdr = (const struct psp_firmware_header_v1_0 *)adev->psp.toc_fw->data; |
| 2940 | − adev->psp.toc_fw_version = le32_to_cpu(toc_hdr->header.ucode_version); | |
| 2941 | − adev->psp.toc_feature_version = le32_to_cpu(toc_hdr->sos.fw_version); | |
| 2942 | − adev->psp.toc_bin_size = le32_to_cpu(toc_hdr->header.ucode_size_bytes); | |
| 2943 | − adev->psp.toc_start_addr = (uint8_t *)toc_hdr + | |
| 3033 | + adev->psp.toc.fw_version = le32_to_cpu(toc_hdr->header.ucode_version); | |
| 3034 | + adev->psp.toc.feature_version = le32_to_cpu(toc_hdr->sos.fw_version); | |
| 3035 | + adev->psp.toc.size_bytes = le32_to_cpu(toc_hdr->header.ucode_size_bytes); | |
| 3036 | + adev->psp.toc.start_addr = (uint8_t *)toc_hdr + | |
| 2944 | 3037 | le32_to_cpu(toc_hdr->header.ucode_array_offset_bytes); |
| 2945 | 3038 | return 0; |
| 2946 | 3039 | out: |
| @@ -2950,6 +3043,82 @@ out: · 3 unmodified lines | ||
| 2950 | 3043 | return err; |
| 2951 | 3044 | } |
| 2952 | 3045 | |
| 3046 | +static int parse_sos_bin_descriptor(struct psp_context *psp, | |
| 3047 | + const struct psp_fw_bin_desc *desc, | |
| 3048 | + const struct psp_firmware_header_v2_0 *sos_hdr) | |
| 3049 | +{ | |
| 3050 | + uint8_t *ucode_start_addr = NULL; | |
| 3051 | + | |
| 3052 | + if (!psp || !desc || !sos_hdr) | |
| 3053 | + return -EINVAL; | |
| 3054 | + | |
| 3055 | + ucode_start_addr = (uint8_t *)sos_hdr + | |
| 3056 | + le32_to_cpu(desc->offset_bytes) + | |
| 3057 | + le32_to_cpu(sos_hdr->header.ucode_array_offset_bytes); | |
| 3058 | + | |
| 3059 | + switch (desc->fw_type) { | |
| 3060 | + case PSP_FW_TYPE_PSP_SOS: | |
| 3061 | + psp->sos.fw_version = le32_to_cpu(desc->fw_version); | |
| 3062 | + psp->sos.feature_version = le32_to_cpu(desc->fw_version); | |
| 3063 | + psp->sos.size_bytes = le32_to_cpu(desc->size_bytes); | |
| 3064 | + psp->sos.start_addr = ucode_start_addr; | |
| 3065 | + break; | |
| 3066 | + case PSP_FW_TYPE_PSP_SYS_DRV: | |
| 3067 | + psp->sys.fw_version = le32_to_cpu(desc->fw_version); | |
| 3068 | + psp->sys.feature_version = le32_to_cpu(desc->fw_version); | |
| 3069 | + psp->sys.size_bytes = le32_to_cpu(desc->size_bytes); | |
| 3070 | + psp->sys.start_addr = ucode_start_addr; | |
| 3071 | + break; | |
| 3072 | + case PSP_FW_TYPE_PSP_KDB: | |
| 3073 | + psp->kdb.fw_version = le32_to_cpu(desc->fw_version); | |
| 3074 | + psp->kdb.feature_version = le32_to_cpu(desc->fw_version); | |
| 3075 | + psp->kdb.size_bytes = le32_to_cpu(desc->size_bytes); | |
| 3076 | + psp->kdb.start_addr = ucode_start_addr; | |
| 3077 | + break; | |
| 3078 | + case PSP_FW_TYPE_PSP_TOC: | |
| 3079 | + psp->toc.fw_version = le32_to_cpu(desc->fw_version); | |
| 3080 | + psp->toc.feature_version = le32_to_cpu(desc->fw_version); | |
| 3081 | + psp->toc.size_bytes = le32_to_cpu(desc->size_bytes); | |
| 3082 | + psp->toc.start_addr = ucode_start_addr; | |
| 3083 | + break; | |
| 3084 | + case PSP_FW_TYPE_PSP_SPL: | |
| 3085 | + psp->spl.fw_version = le32_to_cpu(desc->fw_version); | |
| 3086 | + psp->spl.feature_version = le32_to_cpu(desc->fw_version); | |
| 3087 | + psp->spl.size_bytes = le32_to_cpu(desc->size_bytes); | |
| 3088 | + psp->spl.start_addr = ucode_start_addr; | |
| 3089 | + break; | |
| 3090 | + case PSP_FW_TYPE_PSP_RL: | |
| 3091 | + psp->rl.fw_version = le32_to_cpu(desc->fw_version); | |
| 3092 | + psp->rl.feature_version = le32_to_cpu(desc->fw_version); | |
| 3093 | + psp->rl.size_bytes = le32_to_cpu(desc->size_bytes); | |
| 3094 | + psp->rl.start_addr = ucode_start_addr; | |
| 3095 | + break; | |
| 3096 | + case PSP_FW_TYPE_PSP_SOC_DRV: | |
| 3097 | + psp->soc_drv.fw_version = le32_to_cpu(desc->fw_version); | |
| 3098 | + psp->soc_drv.feature_version = le32_to_cpu(desc->fw_version); | |
| 3099 | + psp->soc_drv.size_bytes = le32_to_cpu(desc->size_bytes); | |
| 3100 | + psp->soc_drv.start_addr = ucode_start_addr; | |
| 3101 | + break; | |
| 3102 | + case PSP_FW_TYPE_PSP_INTF_DRV: | |
| 3103 | + psp->intf_drv.fw_version = le32_to_cpu(desc->fw_version); | |
| 3104 | + psp->intf_drv.feature_version = le32_to_cpu(desc->fw_version); | |
| 3105 | + psp->intf_drv.size_bytes = le32_to_cpu(desc->size_bytes); | |
| 3106 | + psp->intf_drv.start_addr = ucode_start_addr; | |
| 3107 | + break; | |
| 3108 | + case PSP_FW_TYPE_PSP_DBG_DRV: | |
| 3109 | + psp->dbg_drv.fw_version = le32_to_cpu(desc->fw_version); | |
| 3110 | + psp->dbg_drv.feature_version = le32_to_cpu(desc->fw_version); | |
| 3111 | + psp->dbg_drv.size_bytes = le32_to_cpu(desc->size_bytes); | |
| 3112 | + psp->dbg_drv.start_addr = ucode_start_addr; | |
| 3113 | + break; | |
| 3114 | + default: | |
| 3115 | + dev_warn(psp->adev->dev, "Unsupported PSP FW type: %d\n", desc->fw_type); | |
| 3116 | + break; | |
| 3117 | + } | |
| 3118 | + | |
| 3119 | + return 0; | |
| 3120 | +} | |
| 3121 | + | |
| 2953 | 3122 | static int psp_init_sos_base_fw(struct amdgpu_device *adev) |
| 2954 | 3123 | { |
| 2955 | 3124 | const struct psp_firmware_header_v1_0 *sos_hdr; |
| @@ -2961,32 +3130,34 @@ static int psp_init_sos_base_fw(struct amdgpu_device *adev) · 5 unmodified lines | ||
| 2961 | 3130 | le32_to_cpu(sos_hdr->header.ucode_array_offset_bytes); |
| 2962 | 3131 | |
| 2963 | 3132 | if (adev->gmc.xgmi.connected_to_cpu || (adev->asic_type != CHIP_ALDEBARAN)) { |
| 2964 | − adev->psp.sos_fw_version = le32_to_cpu(sos_hdr->header.ucode_version); | |
| 2965 | − adev->psp.sos_feature_version = le32_to_cpu(sos_hdr->sos.fw_version); | |
| 3133 | + adev->psp.sos.fw_version = le32_to_cpu(sos_hdr->header.ucode_version); | |
| 3134 | + adev->psp.sos.feature_version = le32_to_cpu(sos_hdr->sos.fw_version); | |
| 2966 | 3135 | |
| 2967 | − adev->psp.sys_bin_size = le32_to_cpu(sos_hdr->sos.offset_bytes); | |
| 2968 | − adev->psp.sys_start_addr = ucode_array_start_addr; | |
| 3136 | + adev->psp.sys.size_bytes = le32_to_cpu(sos_hdr->sos.offset_bytes); | |
| 3137 | + adev->psp.sys.start_addr = ucode_array_start_addr; | |
| 2969 | 3138 | |
| 2970 | − adev->psp.sos_bin_size = le32_to_cpu(sos_hdr->sos.size_bytes); | |
| 2971 | − adev->psp.sos_start_addr = ucode_array_start_addr + | |
| 3139 | + adev->psp.sos.size_bytes = le32_to_cpu(sos_hdr->sos.size_bytes); | |
| 3140 | + adev->psp.sos.start_addr = ucode_array_start_addr + | |
| 2972 | 3141 | le32_to_cpu(sos_hdr->sos.offset_bytes); |
| 3142 | + adev->psp.xgmi_context.supports_extended_data = false; | |
| 2973 | 3143 | } else { |
| 2974 | 3144 | /* Load alternate PSP SOS FW */ |
| 2975 | 3145 | sos_hdr_v1_3 = (const struct psp_firmware_header_v1_3 *)adev->psp.sos_fw->data; |
| 2976 | 3146 | |
| 2977 | − adev->psp.sos_fw_version = le32_to_cpu(sos_hdr_v1_3->sos_aux.fw_version); | |
| 2978 | − adev->psp.sos_feature_version = le32_to_cpu(sos_hdr_v1_3->sos_aux.fw_version); | |
| 3147 | + adev->psp.sos.fw_version = le32_to_cpu(sos_hdr_v1_3->sos_aux.fw_version); | |
| 3148 | + adev->psp.sos.feature_version = le32_to_cpu(sos_hdr_v1_3->sos_aux.fw_version); | |
| 2979 | 3149 | |
| 2980 | − adev->psp.sys_bin_size = le32_to_cpu(sos_hdr_v1_3->sys_drv_aux.size_bytes); | |
| 2981 | − adev->psp.sys_start_addr = ucode_array_start_addr + | |
| 3150 | + adev->psp.sys.size_bytes = le32_to_cpu(sos_hdr_v1_3->sys_drv_aux.size_bytes); | |
| 3151 | + adev->psp.sys.start_addr = ucode_array_start_addr + | |
| 2982 | 3152 | le32_to_cpu(sos_hdr_v1_3->sys_drv_aux.offset_bytes); |
| 2983 | 3153 | |
| 2984 | − adev->psp.sos_bin_size = le32_to_cpu(sos_hdr_v1_3->sos_aux.size_bytes); | |
| 2985 | − adev->psp.sos_start_addr = ucode_array_start_addr + | |
| 3154 | + adev->psp.sos.size_bytes = le32_to_cpu(sos_hdr_v1_3->sos_aux.size_bytes); | |
| 3155 | + adev->psp.sos.start_addr = ucode_array_start_addr + | |
| 2986 | 3156 | le32_to_cpu(sos_hdr_v1_3->sos_aux.offset_bytes); |
| 3157 | + adev->psp.xgmi_context.supports_extended_data = true; | |
| 2987 | 3158 | } |
| 2988 | 3159 | |
| 2989 | − if ((adev->psp.sys_bin_size == 0) || (adev->psp.sos_bin_size == 0)) { | |
| 3160 | + if ((adev->psp.sys.size_bytes == 0) || (adev->psp.sos.size_bytes == 0)) { | |
| 2990 | 3161 | dev_warn(adev->dev, "PSP SOS FW not available"); |
| 2991 | 3162 | return -EINVAL; |
| 2992 | 3163 | } |
| @@ -3003,8 +3174,10 @@ int psp_init_sos_microcode(struct psp_context *psp, · 10 unmodified lines | ||
| 3003 | 3174 | const struct psp_firmware_header_v1_1 *sos_hdr_v1_1; |
| 3004 | 3175 | const struct psp_firmware_header_v1_2 *sos_hdr_v1_2; |
| 3005 | 3176 | const struct psp_firmware_header_v1_3 *sos_hdr_v1_3; |
| 3177 | + const struct psp_firmware_header_v2_0 *sos_hdr_v2_0; | |
| 3006 | 3178 | int err = 0; |
| 3007 | 3179 | uint8_t *ucode_array_start_addr; |
| 3180 | + int fw_index = 0; | |
| 3008 | 3181 | |
| 3009 | 3182 | if (!chip_name) { |
| 3010 | 3183 | dev_err(adev->dev, "invalid chip name for sos microcode\n"); |
| @@ -3033,35 +3206,52 @@ int psp_init_sos_microcode(struct psp_context *psp, · 22 unmodified lines | ||
| 3033 | 3206 | |
| 3034 | 3207 | if (sos_hdr->header.header_version_minor == 1) { |
| 3035 | 3208 | sos_hdr_v1_1 = (const struct psp_firmware_header_v1_1 *)adev->psp.sos_fw->data; |
| 3036 | − adev->psp.toc_bin_size = le32_to_cpu(sos_hdr_v1_1->toc.size_bytes); | |
| 3037 | − adev->psp.toc_start_addr = (uint8_t *)adev->psp.sys_start_addr + | |
| 3209 | + adev->psp.toc.size_bytes = le32_to_cpu(sos_hdr_v1_1->toc.size_bytes); | |
| 3210 | + adev->psp.toc.start_addr = (uint8_t *)adev->psp.sys.start_addr + | |
| 3038 | 3211 | le32_to_cpu(sos_hdr_v1_1->toc.offset_bytes); |
| 3039 | − adev->psp.kdb_bin_size = le32_to_cpu(sos_hdr_v1_1->kdb.size_bytes); | |
| 3040 | − adev->psp.kdb_start_addr = (uint8_t *)adev->psp.sys_start_addr + | |
| 3212 | + adev->psp.kdb.size_bytes = le32_to_cpu(sos_hdr_v1_1->kdb.size_bytes); | |
| 3213 | + adev->psp.kdb.start_addr = (uint8_t *)adev->psp.sys.start_addr + | |
| 3041 | 3214 | le32_to_cpu(sos_hdr_v1_1->kdb.offset_bytes); |
| 3042 | 3215 | } |
| 3043 | 3216 | if (sos_hdr->header.header_version_minor == 2) { |
| 3044 | 3217 | sos_hdr_v1_2 = (const struct psp_firmware_header_v1_2 *)adev->psp.sos_fw->data; |
| 3045 | − adev->psp.kdb_bin_size = le32_to_cpu(sos_hdr_v1_2->kdb.size_bytes); | |
| 3046 | − adev->psp.kdb_start_addr = (uint8_t *)adev->psp.sys_start_addr + | |
| 3218 | + adev->psp.kdb.size_bytes = le32_to_cpu(sos_hdr_v1_2->kdb.size_bytes); | |
| 3219 | + adev->psp.kdb.start_addr = (uint8_t *)adev->psp.sys.start_addr + | |
| 3047 | 3220 | le32_to_cpu(sos_hdr_v1_2->kdb.offset_bytes); |
| 3048 | 3221 | } |
| 3049 | 3222 | if (sos_hdr->header.header_version_minor == 3) { |
| 3050 | 3223 | sos_hdr_v1_3 = (const struct psp_firmware_header_v1_3 *)adev->psp.sos_fw->data; |
| 3051 | − adev->psp.toc_bin_size = le32_to_cpu(sos_hdr_v1_3->v1_1.toc.size_bytes); | |
| 3052 | − adev->psp.toc_start_addr = ucode_array_start_addr + | |
| 3224 | + adev->psp.toc.size_bytes = le32_to_cpu(sos_hdr_v1_3->v1_1.toc.size_bytes); | |
| 3225 | + adev->psp.toc.start_addr = ucode_array_start_addr + | |
| 3053 | 3226 | le32_to_cpu(sos_hdr_v1_3->v1_1.toc.offset_bytes); |
| 3054 | − adev->psp.kdb_bin_size = le32_to_cpu(sos_hdr_v1_3->v1_1.kdb.size_bytes); | |
| 3055 | − adev->psp.kdb_start_addr = ucode_array_start_addr + | |
| 3227 | + adev->psp.kdb.size_bytes = le32_to_cpu(sos_hdr_v1_3->v1_1.kdb.size_bytes); | |
| 3228 | + adev->psp.kdb.start_addr = ucode_array_start_addr + | |
| 3056 | 3229 | le32_to_cpu(sos_hdr_v1_3->v1_1.kdb.offset_bytes); |
| 3057 | − adev->psp.spl_bin_size = le32_to_cpu(sos_hdr_v1_3->spl.size_bytes); | |
| 3058 | − adev->psp.spl_start_addr = ucode_array_start_addr + | |
| 3230 | + adev->psp.spl.size_bytes = le32_to_cpu(sos_hdr_v1_3->spl.size_bytes); | |
| 3231 | + adev->psp.spl.start_addr = ucode_array_start_addr + | |
| 3059 | 3232 | le32_to_cpu(sos_hdr_v1_3->spl.offset_bytes); |
| 3060 | − adev->psp.rl_bin_size = le32_to_cpu(sos_hdr_v1_3->rl.size_bytes); | |
| 3061 | − adev->psp.rl_start_addr = ucode_array_start_addr + | |
| 3233 | + adev->psp.rl.size_bytes = le32_to_cpu(sos_hdr_v1_3->rl.size_bytes); | |
| 3234 | + adev->psp.rl.start_addr = ucode_array_start_addr + | |
| 3062 | 3235 | le32_to_cpu(sos_hdr_v1_3->rl.offset_bytes); |
| 3063 | 3236 | } |
| 3064 | 3237 | break; |
| 3238 | + case 2: | |
| 3239 | + sos_hdr_v2_0 = (const struct psp_firmware_header_v2_0 *)adev->psp.sos_fw->data; | |
| 3240 | + | |
| 3241 | + if (le32_to_cpu(sos_hdr_v2_0->psp_fw_bin_count) >= UCODE_MAX_PSP_PACKAGING) { | |
| 3242 | + dev_err(adev->dev, "packed SOS count exceeds maximum limit\n"); | |
| 3243 | + err = -EINVAL; | |
| 3244 | + goto out; | |
| 3245 | + } | |
| 3246 | + | |
| 3247 | + for (fw_index = 0; fw_index < le32_to_cpu(sos_hdr_v2_0->psp_fw_bin_count); fw_index++) { | |
| 3248 | + err = parse_sos_bin_descriptor(psp, | |
| 3249 | + &sos_hdr_v2_0->psp_fw_bin[fw_index], | |
| 3250 | + sos_hdr_v2_0); | |
| 3251 | + if (err) | |
| 3252 | + goto out; | |
| 3253 | + } | |
| 3254 | + break; | |
| 3065 | 3255 | default: |
| 3066 | 3256 | dev_err(adev->dev, |
| 3067 | 3257 | "unsupported psp sos firmware\n"); |
| @@ -3080,7 +3270,7 @@ out: · 12 unmodified lines | ||
| 3080 | 3270 | } |
| 3081 | 3271 | |
| 3082 | 3272 | static int parse_ta_bin_descriptor(struct psp_context *psp, |
| 3083 | − const struct ta_fw_bin_desc *desc, | |
| 3273 | + const struct psp_fw_bin_desc *desc, | |
| 3084 | 3274 | const struct ta_firmware_header_v2_0 *ta_hdr) |
| 3085 | 3275 | { |
| 3086 | 3276 | uint8_t *ucode_start_addr = NULL; |
| @@ -3094,40 +3284,40 @@ static int parse_ta_bin_descriptor(struct psp_context *psp, · 7 unmodified lines | ||
| 3094 | 3284 | |
| 3095 | 3285 | switch (desc->fw_type) { |
| 3096 | 3286 | case TA_FW_TYPE_PSP_ASD: |
| 3097 | − psp->asd_fw_version = le32_to_cpu(desc->fw_version); | |
| 3098 | − psp->asd_feature_version = le32_to_cpu(desc->fw_version); | |
| 3099 | − psp->asd_ucode_size = le32_to_cpu(desc->size_bytes); | |
| 3100 | − psp->asd_start_addr = ucode_start_addr; | |
| 3287 | + psp->asd.fw_version = le32_to_cpu(desc->fw_version); | |
| 3288 | + psp->asd.feature_version = le32_to_cpu(desc->fw_version); | |
| 3289 | + psp->asd.size_bytes = le32_to_cpu(desc->size_bytes); | |
| 3290 | + psp->asd.start_addr = ucode_start_addr; | |
| 3101 | 3291 | break; |
| 3102 | 3292 | case TA_FW_TYPE_PSP_XGMI: |
| 3103 | − psp->ta_xgmi_ucode_version = le32_to_cpu(desc->fw_version); | |
| 3104 | − psp->ta_xgmi_ucode_size = le32_to_cpu(desc->size_bytes); | |
| 3105 | − psp->ta_xgmi_start_addr = ucode_start_addr; | |
| 3293 | + psp->xgmi.feature_version = le32_to_cpu(desc->fw_version); | |
| 3294 | + psp->xgmi.size_bytes = le32_to_cpu(desc->size_bytes); | |
| 3295 | + psp->xgmi.start_addr = ucode_start_addr; | |
| 3106 | 3296 | break; |
| 3107 | 3297 | case TA_FW_TYPE_PSP_RAS: |
| 3108 | − psp->ta_ras_ucode_version = le32_to_cpu(desc->fw_version); | |
| 3109 | − psp->ta_ras_ucode_size = le32_to_cpu(desc->size_bytes); | |
| 3110 | − psp->ta_ras_start_addr = ucode_start_addr; | |
| 3298 | + psp->ras.feature_version = le32_to_cpu(desc->fw_version); | |
| 3299 | + psp->ras.size_bytes = le32_to_cpu(desc->size_bytes); | |
| 3300 | + psp->ras.start_addr = ucode_start_addr; | |
| 3111 | 3301 | break; |
| 3112 | 3302 | case TA_FW_TYPE_PSP_HDCP: |
| 3113 | − psp->ta_hdcp_ucode_version = le32_to_cpu(desc->fw_version); | |
| 3114 | − psp->ta_hdcp_ucode_size = le32_to_cpu(desc->size_bytes); | |
| 3115 | − psp->ta_hdcp_start_addr = ucode_start_addr; | |
| 3303 | + psp->hdcp.feature_version = le32_to_cpu(desc->fw_version); | |
| 3304 | + psp->hdcp.size_bytes = le32_to_cpu(desc->size_bytes); | |
| 3305 | + psp->hdcp.start_addr = ucode_start_addr; | |
| 3116 | 3306 | break; |
| 3117 | 3307 | case TA_FW_TYPE_PSP_DTM: |
| 3118 | − psp->ta_dtm_ucode_version = le32_to_cpu(desc->fw_version); | |
| 3119 | − psp->ta_dtm_ucode_size = le32_to_cpu(desc->size_bytes); | |
| 3120 | − psp->ta_dtm_start_addr = ucode_start_addr; | |
| 3308 | + psp->dtm.feature_version = le32_to_cpu(desc->fw_version); | |
| 3309 | + psp->dtm.size_bytes = le32_to_cpu(desc->size_bytes); | |
| 3310 | + psp->dtm.start_addr = ucode_start_addr; | |
| 3121 | 3311 | break; |
| 3122 | 3312 | case TA_FW_TYPE_PSP_RAP: |
| 3123 | − psp->ta_rap_ucode_version = le32_to_cpu(desc->fw_version); | |
| 3124 | − psp->ta_rap_ucode_size = le32_to_cpu(desc->size_bytes); | |
| 3125 | − psp->ta_rap_start_addr = ucode_start_addr; | |
| 3313 | + psp->rap.feature_version = le32_to_cpu(desc->fw_version); | |
| 3314 | + psp->rap.size_bytes = le32_to_cpu(desc->size_bytes); | |
| 3315 | + psp->rap.start_addr = ucode_start_addr; | |
| 3126 | 3316 | break; |
| 3127 | 3317 | case TA_FW_TYPE_PSP_SECUREDISPLAY: |
| 3128 | − psp->ta_securedisplay_ucode_version = le32_to_cpu(desc->fw_version); | |
| 3129 | − psp->ta_securedisplay_ucode_size = le32_to_cpu(desc->size_bytes); | |
| 3130 | − psp->ta_securedisplay_start_addr = ucode_start_addr; | |
| 3318 | + psp->securedisplay.feature_version = le32_to_cpu(desc->fw_version); | |
| 3319 | + psp->securedisplay.size_bytes = le32_to_cpu(desc->size_bytes); | |
| 3320 | + psp->securedisplay.start_addr = ucode_start_addr; | |
| 3131 | 3321 | break; |
| 3132 | 3322 | default: |
| 3133 | 3323 | dev_warn(psp->adev->dev, "Unsupported TA type: %d\n", desc->fw_type); |
| @@ -3168,7 +3358,7 @@ int psp_init_ta_microcode(struct psp_context *psp, · 34 unmodified lines | ||
| 3168 | 3358 | goto out; |
| 3169 | 3359 | } |
| 3170 | 3360 | |
| 3171 | − if (le32_to_cpu(ta_hdr->ta_fw_bin_count) >= UCODE_MAX_TA_PACKAGING) { | |
| 3361 | + if (le32_to_cpu(ta_hdr->ta_fw_bin_count) >= UCODE_MAX_PSP_PACKAGING) { | |
| 3172 | 3362 | dev_err(adev->dev, "packed TA count exceeds maximum limit\n"); |
| 3173 | 3363 | err = -EINVAL; |
| 3174 | 3364 | goto out; |
| @@ -3235,11 +3425,12 @@ static ssize_t psp_usbc_pd_fw_sysfs_write(struct device *dev, · 60 unmodified lines | ||
| 3235 | 3425 | { |
| 3236 | 3426 | struct drm_device *ddev = dev_get_drvdata(dev); |
| 3237 | 3427 | struct amdgpu_device *adev = drm_to_adev(ddev); |
| 3238 | − void *cpu_addr; | |
| 3239 | − dma_addr_t dma_addr; | |
| 3240 | 3428 | int ret, idx; |
| 3241 | 3429 | char fw_name[100]; |
| 3242 | 3430 | const struct firmware *usbc_pd_fw; |
| 3431 | + struct amdgpu_bo *fw_buf_bo = NULL; | |
| 3432 | + uint64_t fw_pri_mc_addr; | |
| 3433 | + void *fw_pri_cpu_addr; | |
| 3243 | 3434 | |
| 3244 | 3435 | if (!adev->ip_blocks[AMD_IP_BLOCK_TYPE_PSP].status.late_initialized) { |
| 3245 | 3436 | DRM_INFO("PSP block is not ready yet."); |
| @@ -3254,31 +3445,24 @@ static ssize_t psp_usbc_pd_fw_sysfs_write(struct device *dev, · 8 unmodified lines | ||
| 3254 | 3445 | if (ret) |
| 3255 | 3446 | goto fail; |
| 3256 | 3447 | |
| 3257 | − /* We need contiguous physical mem to place the FW for psp to access */ | |
| 3258 | − cpu_addr = dma_alloc_coherent(adev->dev, usbc_pd_fw->size, &dma_addr, GFP_KERNEL); | |
| 3259 | − | |
| 3260 | − ret = dma_mapping_error(adev->dev, dma_addr); | |
| 3448 | + /* LFB address which is aligned to 1MB boundary per PSP request */ | |
| 3449 | + ret = amdgpu_bo_create_kernel(adev, usbc_pd_fw->size, 0x100000, | |
| 3450 | + AMDGPU_GEM_DOMAIN_VRAM, | |
| 3451 | + &fw_buf_bo, | |
| 3452 | + &fw_pri_mc_addr, | |
| 3453 | + &fw_pri_cpu_addr); | |
| 3261 | 3454 | if (ret) |
| 3262 | 3455 | goto rel_buf; |
| 3263 | 3456 | |
| 3264 | − memcpy_toio(cpu_addr, usbc_pd_fw->data, usbc_pd_fw->size); | |
| 3265 | − | |
| 3266 | − /* | |
| 3267 | − * x86 specific workaround. | |
| 3268 | − * Without it the buffer is invisible in PSP. | |
| 3269 | − * | |
| 3270 | − * TODO Remove once PSP starts snooping CPU cache | |
| 3271 | − */ | |
| 3272 | −#ifdef CONFIG_X86 | |
| 3273 | − clflush_cache_range(cpu_addr, (usbc_pd_fw->size & ~(L1_CACHE_BYTES - 1))); | |
| 3274 | −#endif | |
| 3457 | + memcpy_toio(fw_pri_cpu_addr, usbc_pd_fw->data, usbc_pd_fw->size); | |
| 3275 | 3458 | |
| 3276 | 3459 | mutex_lock(&adev->psp.mutex); |
| 3277 | − ret = psp_load_usbc_pd_fw(&adev->psp, dma_addr); | |
| 3460 | + ret = psp_load_usbc_pd_fw(&adev->psp, fw_pri_mc_addr); | |
| 3278 | 3461 | mutex_unlock(&adev->psp.mutex); |
| 3279 | 3462 | |
| 3463 | + amdgpu_bo_free_kernel(&fw_buf_bo, &fw_pri_mc_addr, &fw_pri_cpu_addr); | |
| 3464 | + | |
| 3280 | 3465 | rel_buf: |
| 3281 | − dma_free_coherent(adev->dev, usbc_pd_fw->size, cpu_addr, dma_addr); | |
| 3282 | 3466 | release_firmware(usbc_pd_fw); |
| 3283 | 3467 | fail: |
| 3284 | 3468 | if (ret) { |
| @@ -3307,7 +3491,10 @@ static DEVICE_ATTR(usbc_pd_fw, S_IRUGO | S_IWUSR, · 22 unmodified lines | ||
| 3307 | 3491 | psp_usbc_pd_fw_sysfs_read, |
| 3308 | 3492 | psp_usbc_pd_fw_sysfs_write); |
| 3309 | 3493 | |
| 3310 | − | |
| 3494 | +int is_psp_fw_valid(struct psp_bin_desc bin) | |
| 3495 | +{ | |
| 3496 | + return bin.size_bytes; | |
| 3497 | +} | |
| 3311 | 3498 | |
| 3312 | 3499 | const struct amd_ip_funcs psp_ip_funcs = { |
| 3313 | 3500 | .name = "psp", |
| @@ -3369,6 +3556,14 @@ const struct amdgpu_ip_block_version psp_v11_0_ip_block = · 55 unmodified lines | ||
| 3369 | 3556 | .funcs = &psp_ip_funcs, |
| 3370 | 3557 | }; |
| 3371 | 3558 | |
| 3559 | +const struct amdgpu_ip_block_version psp_v11_0_8_ip_block = { | |
| 3560 | + .type = AMD_IP_BLOCK_TYPE_PSP, | |
| 3561 | + .major = 11, | |
| 3562 | + .minor = 0, | |
| 3563 | + .rev = 8, | |
| 3564 | + .funcs = &psp_ip_funcs, | |
| 3565 | +}; | |
| 3566 | + | |
| 3372 | 3567 | const struct amdgpu_ip_block_version psp_v12_0_ip_block = |
| 3373 | 3568 | { |
| 3374 | 3569 | .type = AMD_IP_BLOCK_TYPE_PSP, |
| @@ -48,11 +48,15 @@ · 47 unmodified lines | ||
| 48 | 48 | struct psp_context; |
| 49 | 49 | struct psp_xgmi_node_info; |
| 50 | 50 | struct psp_xgmi_topology_info; |
| 51 | +struct psp_bin_desc; | |
| 51 | 52 | |
| 52 | 53 | enum psp_bootloader_cmd { |
| 53 | 54 | PSP_BL__LOAD_SYSDRV = 0x10000, |
| 54 | 55 | PSP_BL__LOAD_SOSDRV = 0x20000, |
| 55 | 56 | PSP_BL__LOAD_KEY_DATABASE = 0x80000, |
| 57 | + PSP_BL__LOAD_SOCDRV = 0xB0000, | |
| 58 | + PSP_BL__LOAD_INTFDRV = 0xC0000, | |
| 59 | + PSP_BL__LOAD_DBGDRV = 0xD0000, | |
| 56 | 60 | PSP_BL__DRAM_LONG_TRAIN = 0x100000, |
| 57 | 61 | PSP_BL__DRAM_SHORT_TRAIN = 0x200000, |
| 58 | 62 | PSP_BL__LOAD_TOS_SPL_TABLE = 0x10000000, |
| @@ -93,6 +97,9 @@ struct psp_funcs · 34 unmodified lines | ||
| 93 | 97 | int (*bootloader_load_kdb)(struct psp_context *psp); |
| 94 | 98 | int (*bootloader_load_spl)(struct psp_context *psp); |
| 95 | 99 | int (*bootloader_load_sysdrv)(struct psp_context *psp); |
| 100 | + int (*bootloader_load_soc_drv)(struct psp_context *psp); | |
| 101 | + int (*bootloader_load_intf_drv)(struct psp_context *psp); | |
| 102 | + int (*bootloader_load_dbg_drv)(struct psp_context *psp); | |
| 96 | 103 | int (*bootloader_load_sos)(struct psp_context *psp); |
| 97 | 104 | int (*ring_init)(struct psp_context *psp, enum psp_ring_type ring_type); |
| 98 | 105 | int (*ring_create)(struct psp_context *psp, |
| @@ -106,7 +113,7 @@ struct psp_funcs · 7 unmodified lines | ||
| 106 | 113 | int (*mem_training)(struct psp_context *psp, uint32_t ops); |
| 107 | 114 | uint32_t (*ring_get_wptr)(struct psp_context *psp); |
| 108 | 115 | void (*ring_set_wptr)(struct psp_context *psp, uint32_t value); |
| 109 | − int (*load_usbc_pd_fw)(struct psp_context *psp, dma_addr_t dma_addr); | |
| 116 | + int (*load_usbc_pd_fw)(struct psp_context *psp, uint64_t fw_pri_mc_addr); | |
| 110 | 117 | int (*read_usbc_pd_fw)(struct psp_context *psp, uint32_t *fw_ver); |
| 111 | 118 | }; |
| 112 | 119 | |
| @@ -116,6 +123,7 @@ struct psp_xgmi_node_info { · 3 unmodified lines | ||
| 116 | 123 | uint8_t num_hops; |
| 117 | 124 | uint8_t is_sharing_enabled; |
| 118 | 125 | enum ta_xgmi_assigned_sdma_engine sdma_engine; |
| 126 | + uint8_t num_links; | |
| 119 | 127 | }; |
| 120 | 128 | |
| 121 | 129 | struct psp_xgmi_topology_info { |
| @@ -128,59 +136,32 @@ struct psp_asd_context { · 6 unmodified lines | ||
| 128 | 136 | uint32_t session_id; |
| 129 | 137 | }; |
| 130 | 138 | |
| 131 | −struct psp_xgmi_context { | |
| 132 | − uint8_t initialized; | |
| 133 | − uint32_t session_id; | |
| 134 | − struct amdgpu_bo *xgmi_shared_bo; | |
| 135 | − uint64_t xgmi_shared_mc_addr; | |
| 136 | − void *xgmi_shared_buf; | |
| 137 | − struct psp_xgmi_topology_info top_info; | |
| 138 | −}; | |
| 139 | − | |
| 140 | −struct psp_ras_context { | |
| 141 | − /*ras fw*/ | |
| 142 | − bool ras_initialized; | |
| 143 | − uint32_t session_id; | |
| 144 | − struct amdgpu_bo *ras_shared_bo; | |
| 145 | − uint64_t ras_shared_mc_addr; | |
| 146 | − void *ras_shared_buf; | |
| 147 | − struct amdgpu_ras *ras; | |
| 139 | +struct ta_mem_context { | |
| 140 | + struct amdgpu_bo *shared_bo; | |
| 141 | + uint64_t shared_mc_addr; | |
| 142 | + void *shared_buf; | |
| 148 | 143 | }; |
| 149 | 144 | |
| 150 | −struct psp_hdcp_context { | |
| 151 | − bool hdcp_initialized; | |
| 145 | +struct ta_context { | |
| 146 | + bool initialized; | |
| 152 | 147 | uint32_t session_id; |
| 153 | − struct amdgpu_bo *hdcp_shared_bo; | |
| 154 | − uint64_t hdcp_shared_mc_addr; | |
| 155 | − void *hdcp_shared_buf; | |
| 156 | − struct mutex mutex; | |
| 148 | + struct ta_mem_context mem_context; | |
| 157 | 149 | }; |
| 158 | 150 | |
| 159 | −struct psp_dtm_context { | |
| 160 | − bool dtm_initialized; | |
| 161 | − uint32_t session_id; | |
| 162 | − struct amdgpu_bo *dtm_shared_bo; | |
| 163 | − uint64_t dtm_shared_mc_addr; | |
| 164 | − void *dtm_shared_buf; | |
| 165 | − struct mutex mutex; | |
| 151 | +struct ta_cp_context { | |
| 152 | + struct ta_context context; | |
| 153 | + struct mutex mutex; | |
| 166 | 154 | }; |
| 167 | 155 | |
| 168 | −struct psp_rap_context { | |
| 169 | − bool rap_initialized; | |
| 170 | − uint32_t session_id; | |
| 171 | − struct amdgpu_bo *rap_shared_bo; | |
| 172 | − uint64_t rap_shared_mc_addr; | |
| 173 | − void *rap_shared_buf; | |
| 174 | − struct mutex mutex; | |
| 156 | +struct psp_xgmi_context { | |
| 157 | + struct ta_context context; | |
| 158 | + struct psp_xgmi_topology_info top_info; | |
| 159 | + bool supports_extended_data; | |
| 175 | 160 | }; |
| 176 | 161 | |
| 177 | −struct psp_securedisplay_context { | |
| 178 | − bool securedisplay_initialized; | |
| 179 | − uint32_t session_id; | |
| 180 | − struct amdgpu_bo *securedisplay_shared_bo; | |
| 181 | − uint64_t securedisplay_shared_mc_addr; | |
| 182 | − void *securedisplay_shared_buf; | |
| 183 | − struct mutex mutex; | |
| 162 | +struct psp_ras_context { | |
| 163 | + struct ta_context context; | |
| 164 | + struct amdgpu_ras *ras; | |
| 184 | 165 | }; |
| 185 | 166 | |
| 186 | 167 | #define MEM_TRAIN_SYSTEM_SIGNATURE 0x54534942 |
| @@ -282,6 +263,13 @@ struct psp_runtime_boot_cfg_entry { · 95 unmodified lines | ||
| 282 | 263 | uint32_t reserved; |
| 283 | 264 | }; |
| 284 | 265 | |
| 266 | +struct psp_bin_desc { | |
| 267 | + uint32_t fw_version; | |
| 268 | + uint32_t feature_version; | |
| 269 | + uint32_t size_bytes; | |
| 270 | + uint8_t *start_addr; | |
| 271 | +}; | |
| 272 | + | |
| 285 | 273 | struct psp_context |
| 286 | 274 | { |
| 287 | 275 | struct amdgpu_device *adev; |
| @@ -297,36 +285,26 @@ struct psp_context · 9 unmodified lines | ||
| 297 | 285 | |
| 298 | 286 | /* sos firmware */ |
| 299 | 287 | const struct firmware *sos_fw; |
| 300 | − uint32_t sos_fw_version; | |
| 301 | − uint32_t sos_feature_version; | |
| 302 | − uint32_t sys_bin_size; | |
| 303 | − uint32_t sos_bin_size; | |
| 304 | − uint32_t toc_bin_size; | |
| 305 | − uint32_t kdb_bin_size; | |
| 306 | − uint32_t spl_bin_size; | |
| 307 | − uint32_t rl_bin_size; | |
| 308 | − uint8_t *sys_start_addr; | |
| 309 | − uint8_t *sos_start_addr; | |
| 310 | − uint8_t *toc_start_addr; | |
| 311 | − uint8_t *kdb_start_addr; | |
| 312 | − uint8_t *spl_start_addr; | |
| 313 | − uint8_t *rl_start_addr; | |
| 288 | + struct psp_bin_desc sys; | |
| 289 | + struct psp_bin_desc sos; | |
| 290 | + struct psp_bin_desc toc; | |
| 291 | + struct psp_bin_desc kdb; | |
| 292 | + struct psp_bin_desc spl; | |
| 293 | + struct psp_bin_desc rl; | |
| 294 | + struct psp_bin_desc soc_drv; | |
| 295 | + struct psp_bin_desc intf_drv; | |
| 296 | + struct psp_bin_desc dbg_drv; | |
| 314 | 297 | |
| 315 | 298 | /* tmr buffer */ |
| 316 | 299 | struct amdgpu_bo *tmr_bo; |
| 317 | 300 | uint64_t tmr_mc_addr; |
| 318 | 301 | |
| 319 | 302 | /* asd firmware */ |
| 320 | − const struct firmware *asd_fw; | |
| 321 | − uint32_t asd_fw_version; | |
| 322 | − uint32_t asd_feature_version; | |
| 323 | − uint32_t asd_ucode_size; | |
| 324 | − uint8_t *asd_start_addr; | |
| 303 | + const struct firmware *asd_fw; | |
| 304 | + struct psp_bin_desc asd; | |
| 325 | 305 | |
| 326 | 306 | /* toc firmware */ |
| 327 | 307 | const struct firmware *toc_fw; |
| 328 | − uint32_t toc_fw_version; | |
| 329 | − uint32_t toc_feature_version; | |
| 330 | 308 | |
| 331 | 309 | /* fence buffer */ |
| 332 | 310 | struct amdgpu_bo *fence_buf_bo; |
| @@ -348,36 +326,20 @@ struct psp_context · 15 unmodified lines | ||
| 348 | 326 | /* xgmi ta firmware and buffer */ |
| 349 | 327 | const struct firmware *ta_fw; |
| 350 | 328 | uint32_t ta_fw_version; |
| 351 | − uint32_t ta_xgmi_ucode_version; | |
| 352 | − uint32_t ta_xgmi_ucode_size; | |
| 353 | − uint8_t *ta_xgmi_start_addr; | |
| 354 | − uint32_t ta_ras_ucode_version; | |
| 355 | − uint32_t ta_ras_ucode_size; | |
| 356 | − uint8_t *ta_ras_start_addr; | |
| 357 | − | |
| 358 | − uint32_t ta_hdcp_ucode_version; | |
| 359 | − uint32_t ta_hdcp_ucode_size; | |
| 360 | − uint8_t *ta_hdcp_start_addr; | |
| 361 | − | |
| 362 | − uint32_t ta_dtm_ucode_version; | |
| 363 | − uint32_t ta_dtm_ucode_size; | |
| 364 | − uint8_t *ta_dtm_start_addr; | |
| 365 | − | |
| 366 | − uint32_t ta_rap_ucode_version; | |
| 367 | − uint32_t ta_rap_ucode_size; | |
| 368 | − uint8_t *ta_rap_start_addr; | |
| 369 | − | |
| 370 | − uint32_t ta_securedisplay_ucode_version; | |
| 371 | − uint32_t ta_securedisplay_ucode_size; | |
| 372 | − uint8_t *ta_securedisplay_start_addr; | |
| 329 | + struct psp_bin_desc xgmi; | |
| 330 | + struct psp_bin_desc ras; | |
| 331 | + struct psp_bin_desc hdcp; | |
| 332 | + struct psp_bin_desc dtm; | |
| 333 | + struct psp_bin_desc rap; | |
| 334 | + struct psp_bin_desc securedisplay; | |
| 373 | 335 | |
| 374 | 336 | struct psp_asd_context asd_context; |
| 375 | 337 | struct psp_xgmi_context xgmi_context; |
| 376 | − struct psp_ras_context ras; | |
| 377 | − struct psp_hdcp_context hdcp_context; | |
| 378 | − struct psp_dtm_context dtm_context; | |
| 379 | − struct psp_rap_context rap_context; | |
| 380 | − struct psp_securedisplay_context securedisplay_context; | |
| 338 | + struct psp_ras_context ras_context; | |
| 339 | + struct ta_cp_context hdcp_context; | |
| 340 | + struct ta_cp_context dtm_context; | |
| 341 | + struct ta_cp_context rap_context; | |
| 342 | + struct ta_cp_context securedisplay_context; | |
| 381 | 343 | struct mutex mutex; |
| 382 | 344 | struct psp_memory_training_context mem_train_ctx; |
| 383 | 345 | |
| @@ -402,6 +364,12 @@ struct amdgpu_psp_funcs { · 18 unmodified lines | ||
| 402 | 364 | ((psp)->funcs->bootloader_load_spl ? (psp)->funcs->bootloader_load_spl((psp)) : 0) |
| 403 | 365 | #define psp_bootloader_load_sysdrv(psp) \ |
| 404 | 366 | ((psp)->funcs->bootloader_load_sysdrv ? (psp)->funcs->bootloader_load_sysdrv((psp)) : 0) |
| 367 | +#define psp_bootloader_load_soc_drv(psp) \ | |
| 368 | + ((psp)->funcs->bootloader_load_soc_drv ? (psp)->funcs->bootloader_load_soc_drv((psp)) : 0) | |
| 369 | +#define psp_bootloader_load_intf_drv(psp) \ | |
| 370 | + ((psp)->funcs->bootloader_load_intf_drv ? (psp)->funcs->bootloader_load_intf_drv((psp)) : 0) | |
| 371 | +#define psp_bootloader_load_dbg_drv(psp) \ | |
| 372 | + ((psp)->funcs->bootloader_load_dbg_drv ? (psp)->funcs->bootloader_load_dbg_drv((psp)) : 0) | |
| 405 | 373 | #define psp_bootloader_load_sos(psp) \ |
| 406 | 374 | ((psp)->funcs->bootloader_load_sos ? (psp)->funcs->bootloader_load_sos((psp)) : 0) |
| 407 | 375 | #define psp_smu_reload_quirk(psp) \ |
| @@ -414,9 +382,9 @@ struct amdgpu_psp_funcs { · 6 unmodified lines | ||
| 414 | 382 | #define psp_ring_get_wptr(psp) (psp)->funcs->ring_get_wptr((psp)) |
| 415 | 383 | #define psp_ring_set_wptr(psp, value) (psp)->funcs->ring_set_wptr((psp), (value)) |
| 416 | 384 | |
| 417 | −#define psp_load_usbc_pd_fw(psp, dma_addr) \ | |
| 385 | +#define psp_load_usbc_pd_fw(psp, fw_pri_mc_addr) \ | |
| 418 | 386 | ((psp)->funcs->load_usbc_pd_fw ? \ |
| 419 | − (psp)->funcs->load_usbc_pd_fw((psp), (dma_addr)) : -EINVAL) | |
| 387 | + (psp)->funcs->load_usbc_pd_fw((psp), (fw_pri_mc_addr)) : -EINVAL) | |
| 420 | 388 | |
| 421 | 389 | #define psp_read_usbc_pd_fw(psp, fw_ver) \ |
| 422 | 390 | ((psp)->funcs->read_usbc_pd_fw ? \ |
| @@ -427,6 +395,7 @@ extern const struct amd_ip_funcs psp_ip_funcs; · 4 unmodified lines | ||
| 427 | 395 | extern const struct amdgpu_ip_block_version psp_v3_1_ip_block; |
| 428 | 396 | extern const struct amdgpu_ip_block_version psp_v10_0_ip_block; |
| 429 | 397 | extern const struct amdgpu_ip_block_version psp_v11_0_ip_block; |
| 398 | +extern const struct amdgpu_ip_block_version psp_v11_0_8_ip_block; | |
| 430 | 399 | extern const struct amdgpu_ip_block_version psp_v12_0_ip_block; |
| 431 | 400 | extern const struct amdgpu_ip_block_version psp_v13_0_ip_block; |
| 432 | 401 | |
| @@ -437,14 +406,15 @@ int psp_gpu_reset(struct amdgpu_device *adev); · 4 unmodified lines | ||
| 437 | 406 | int psp_update_vcn_sram(struct amdgpu_device *adev, int inst_idx, |
| 438 | 407 | uint64_t cmd_gpu_addr, int cmd_size); |
| 439 | 408 | |
| 440 | −int psp_xgmi_initialize(struct psp_context *psp); | |
| 409 | +int psp_xgmi_initialize(struct psp_context *psp, bool set_extended_data, bool load_ta); | |
| 441 | 410 | int psp_xgmi_terminate(struct psp_context *psp); |
| 442 | 411 | int psp_xgmi_invoke(struct psp_context *psp, uint32_t ta_cmd_id); |
| 443 | 412 | int psp_xgmi_get_hive_id(struct psp_context *psp, uint64_t *hive_id); |
| 444 | 413 | int psp_xgmi_get_node_id(struct psp_context *psp, uint64_t *node_id); |
| 445 | 414 | int psp_xgmi_get_topology_info(struct psp_context *psp, |
| 446 | 415 | int number_devices, |
| 447 | − struct psp_xgmi_topology_info *topology); | |
| 416 | + struct psp_xgmi_topology_info *topology, | |
| 417 | + bool get_extended_data); | |
| 448 | 418 | int psp_xgmi_set_topology_info(struct psp_context *psp, |
| 449 | 419 | int number_devices, |
| 450 | 420 | struct psp_xgmi_topology_info *topology); |
| @@ -483,4 +453,5 @@ int psp_load_fw_list(struct psp_context *psp, · 32 unmodified lines | ||
| 483 | 453 | struct amdgpu_firmware_info **ucode_list, int ucode_count); |
| 484 | 454 | void psp_copy_fw(struct psp_context *psp, uint8_t *start_addr, uint32_t bin_size); |
| 485 | 455 | |
| 456 | +int is_psp_fw_valid(struct psp_bin_desc bin); | |
| 486 | 457 | #endif |
| @@ -76,7 +76,7 @@ static ssize_t amdgpu_rap_debugfs_write(struct file *f, const char __user *buf, · 75 unmodified lines | ||
| 76 | 76 | dev_info(adev->dev, "RAP L0 validate test success.\n"); |
| 77 | 77 | } else { |
| 78 | 78 | rap_shared_mem = (struct ta_rap_shared_memory *) |
| 79 | − adev->psp.rap_context.rap_shared_buf; | |
| 79 | + adev->psp.rap_context.context.mem_context.shared_buf; | |
| 80 | 80 | rap_cmd_output = &(rap_shared_mem->rap_out_message.output); |
| 81 | 81 | |
| 82 | 82 | dev_info(adev->dev, "RAP test failed, the output is:\n"); |
| @@ -119,7 +119,7 @@ void amdgpu_rap_debugfs_init(struct amdgpu_device *adev) · 36 unmodified lines | ||
| 119 | 119 | #if defined(CONFIG_DEBUG_FS) |
| 120 | 120 | struct drm_minor *minor = adev_to_drm(adev)->primary; |
| 121 | 121 | |
| 122 | − if (!adev->psp.rap_context.rap_initialized) | |
| 122 | + if (!adev->psp.rap_context.context.initialized) | |
| 123 | 123 | return; |
| 124 | 124 | |
| 125 | 125 | debugfs_create_file("rap_test", S_IWUSR, minor->debugfs_root, |
| @@ -64,15 +64,14 @@ const char *ras_block_string[] = { · 63 unmodified lines | ||
| 64 | 64 | }; |
| 65 | 65 | |
| 66 | 66 | #define ras_err_str(i) (ras_error_string[ffs(i)]) |
| 67 | −#define ras_block_str(i) (ras_block_string[i]) | |
| 68 | 67 | |
| 69 | 68 | #define RAS_DEFAULT_FLAGS (AMDGPU_RAS_FLAG_INIT_BY_VBIOS) |
| 70 | 69 | |
| 71 | 70 | /* inject address is 52 bits */ |
| 72 | 71 | #define RAS_UMC_INJECT_ADDR_LIMIT (0x1ULL << 52) |
| 73 | 72 | |
| 74 | −/* typical ECC bad page rate(1 bad page per 100MB VRAM) */ | |
| 75 | −#define RAS_BAD_PAGE_RATE (100 * 1024 * 1024ULL) | |
| 73 | +/* typical ECC bad page rate is 1 bad page per 100MB VRAM */ | |
| 74 | +#define RAS_BAD_PAGE_COVER (100 * 1024 * 1024ULL) | |
| 76 | 75 | |
| 77 | 76 | enum amdgpu_ras_retire_page_reservation { |
| 78 | 77 | AMDGPU_RAS_RETIRE_PAGE_RESERVED, |
| @@ -355,8 +354,9 @@ static int amdgpu_ras_debugfs_ctrl_parse_data(struct file *f, · 276 unmodified lines | ||
| 355 | 354 | * to see which blocks support RAS on a particular asic. |
| 356 | 355 | * |
| 357 | 356 | */ |
| 358 | −static ssize_t amdgpu_ras_debugfs_ctrl_write(struct file *f, const char __user *buf, | |
| 359 | − size_t size, loff_t *pos) | |
| 357 | +static ssize_t amdgpu_ras_debugfs_ctrl_write(struct file *f, | |
| 358 | + const char __user *buf, | |
| 359 | + size_t size, loff_t *pos) | |
| 360 | 360 | { |
| 361 | 361 | struct amdgpu_device *adev = (struct amdgpu_device *)file_inode(f)->i_private; |
| 362 | 362 | struct ras_debug_if data; |
| @@ -370,7 +370,7 @@ static ssize_t amdgpu_ras_debugfs_ctrl_write(struct file *f, const char __user * · 7 unmodified lines | ||
| 370 | 370 | |
| 371 | 371 | ret = amdgpu_ras_debugfs_ctrl_parse_data(f, buf, size, pos, &data); |
| 372 | 372 | if (ret) |
| 373 | − return -EINVAL; | |
| 373 | + return ret; | |
| 374 | 374 | |
| 375 | 375 | if (data.op == 3) { |
| 376 | 376 | ret = amdgpu_reserve_page_direct(adev, data.inject.address); |
| @@ -403,9 +403,9 @@ static ssize_t amdgpu_ras_debugfs_ctrl_write(struct file *f, const char __user * · 26 unmodified lines | ||
| 403 | 403 | /* umc ce/ue error injection for a bad page is not allowed */ |
| 404 | 404 | if ((data.head.block == AMDGPU_RAS_BLOCK__UMC) && |
| 405 | 405 | amdgpu_ras_check_bad_page(adev, data.inject.address)) { |
| 406 | − dev_warn(adev->dev, "RAS WARN: 0x%llx has been marked " | |
| 407 | − "as bad before error injection!\n", | |
| 408 | − data.inject.address); | |
| 406 | + dev_warn(adev->dev, "RAS WARN: inject: 0x%llx has " | |
| 407 | + "already been marked as bad!\n", | |
| 408 | + data.inject.address); | |
| 409 | 409 | break; |
| 410 | 410 | } |
| 411 | 411 | |
| @@ -439,21 +439,24 @@ static ssize_t amdgpu_ras_debugfs_ctrl_write(struct file *f, const char __user * · 27 unmodified lines | ||
| 439 | 439 | * will reset EEPROM table to 0 entries. |
| 440 | 440 | * |
| 441 | 441 | */ |
| 442 | −static ssize_t amdgpu_ras_debugfs_eeprom_write(struct file *f, const char __user *buf, | |
| 443 | − size_t size, loff_t *pos) | |
| 442 | +static ssize_t amdgpu_ras_debugfs_eeprom_write(struct file *f, | |
| 443 | + const char __user *buf, | |
| 444 | + size_t size, loff_t *pos) | |
| 444 | 445 | { |
| 445 | 446 | struct amdgpu_device *adev = |
| 446 | 447 | (struct amdgpu_device *)file_inode(f)->i_private; |
| 447 | 448 | int ret; |
| 448 | 449 | |
| 449 | 450 | ret = amdgpu_ras_eeprom_reset_table( |
| 450 | − &(amdgpu_ras_get_context(adev)->eeprom_control)); | |
| 451 | + &(amdgpu_ras_get_context(adev)->eeprom_control)); | |
| 451 | 452 | |
| 452 | − if (ret == 1) { | |
| 453 | + if (!ret) { | |
| 454 | + /* Something was written to EEPROM. | |
| 455 | + */ | |
| 453 | 456 | amdgpu_ras_get_context(adev)->flags = RAS_DEFAULT_FLAGS; |
| 454 | 457 | return size; |
| 455 | 458 | } else { |
| 456 | − return -EIO; | |
| 459 | + return ret; | |
| 457 | 460 | } |
| 458 | 461 | } |
| 459 | 462 | |
| @@ -526,7 +529,7 @@ static inline void put_obj(struct ras_manager *obj) · 66 unmodified lines | ||
| 526 | 529 | if (obj && (--obj->use == 0)) |
| 527 | 530 | list_del(&obj->node); |
| 528 | 531 | if (obj && (obj->use < 0)) |
| 529 | − DRM_ERROR("RAS ERROR: Unbalance obj(%s) use\n", obj->head.name); | |
| 532 | + DRM_ERROR("RAS ERROR: Unbalance obj(%s) use\n", ras_block_str(obj->head.block)); | |
| 530 | 533 | } |
| 531 | 534 | |
| 532 | 535 | /* make one obj and return it. */ |
| @@ -789,7 +792,6 @@ static int amdgpu_ras_enable_all_features(struct amdgpu_device *adev, · 256 unmodified lines | ||
| 789 | 792 | .type = default_ras_type, |
| 790 | 793 | .sub_block_index = 0, |
| 791 | 794 | }; |
| 792 | − strcpy(head.name, ras_block_str(i)); | |
| 793 | 795 | if (bypass) { |
| 794 | 796 | /* |
| 795 | 797 | * bypass psp. vbios enable ras for us. |
| @@ -1316,6 +1318,12 @@ static struct dentry *amdgpu_ras_debugfs_create_ctrl_node(struct amdgpu_device * · 520 unmodified lines | ||
| 1316 | 1318 | &con->bad_page_cnt_threshold); |
| 1317 | 1319 | debugfs_create_x32("ras_hw_enabled", 0444, dir, &adev->ras_hw_enabled); |
| 1318 | 1320 | debugfs_create_x32("ras_enabled", 0444, dir, &adev->ras_enabled); |
| 1321 | + debugfs_create_file("ras_eeprom_size", S_IRUGO, dir, adev, | |
| 1322 | + &amdgpu_ras_debugfs_eeprom_size_ops); | |
| 1323 | + con->de_ras_eeprom_table = debugfs_create_file("ras_eeprom_table", | |
| 1324 | + S_IRUGO, dir, adev, | |
| 1325 | + &amdgpu_ras_debugfs_eeprom_table_ops); | |
| 1326 | + amdgpu_ras_debugfs_set_ret_size(&con->eeprom_control); | |
| 1319 | 1327 | |
| 1320 | 1328 | /* |
| 1321 | 1329 | * After one uncorrectable error happens, usually GPU recovery will |
| @@ -1833,13 +1841,12 @@ int amdgpu_ras_save_bad_pages(struct amdgpu_device *adev) · 511 unmodified lines | ||
| 1833 | 1841 | |
| 1834 | 1842 | control = &con->eeprom_control; |
| 1835 | 1843 | data = con->eh_data; |
| 1836 | − save_count = data->count - control->num_recs; | |
| 1844 | + save_count = data->count - control->ras_num_recs; | |
| 1837 | 1845 | /* only new entries are saved */ |
| 1838 | 1846 | if (save_count > 0) { |
| 1839 | − if (amdgpu_ras_eeprom_process_recods(control, | |
| 1840 | − &data->bps[control->num_recs], | |
| 1841 | − true, | |
| 1842 | − save_count)) { | |
| 1847 | + if (amdgpu_ras_eeprom_append(control, | |
| 1848 | + &data->bps[control->ras_num_recs], | |
| 1849 | + save_count)) { | |
| 1843 | 1850 | dev_err(adev->dev, "Failed to save EEPROM table data!"); |
| 1844 | 1851 | return -EIO; |
| 1845 | 1852 | } |
| @@ -1857,28 +1864,24 @@ int amdgpu_ras_save_bad_pages(struct amdgpu_device *adev) · 11 unmodified lines | ||
| 1857 | 1864 | static int amdgpu_ras_load_bad_pages(struct amdgpu_device *adev) |
| 1858 | 1865 | { |
| 1859 | 1866 | struct amdgpu_ras_eeprom_control *control = |
| 1860 | − &adev->psp.ras.ras->eeprom_control; | |
| 1861 | − struct eeprom_table_record *bps = NULL; | |
| 1862 | − int ret = 0; | |
| 1867 | + &adev->psp.ras_context.ras->eeprom_control; | |
| 1868 | + struct eeprom_table_record *bps; | |
| 1869 | + int ret; | |
| 1863 | 1870 | |
| 1864 | 1871 | /* no bad page record, skip eeprom access */ |
| 1865 | − if (!control->num_recs || (amdgpu_bad_page_threshold == 0)) | |
| 1866 | − return ret; | |
| 1872 | + if (control->ras_num_recs == 0 || amdgpu_bad_page_threshold == 0) | |
| 1873 | + return 0; | |
| 1867 | 1874 | |
| 1868 | − bps = kcalloc(control->num_recs, sizeof(*bps), GFP_KERNEL); | |
| 1875 | + bps = kcalloc(control->ras_num_recs, sizeof(*bps), GFP_KERNEL); | |
| 1869 | 1876 | if (!bps) |
| 1870 | 1877 | return -ENOMEM; |
| 1871 | 1878 | |
| 1872 | − if (amdgpu_ras_eeprom_process_recods(control, bps, false, | |
| 1873 | − control->num_recs)) { | |
| 1879 | + ret = amdgpu_ras_eeprom_read(control, bps, control->ras_num_recs); | |
| 1880 | + if (ret) | |
| 1874 | 1881 | dev_err(adev->dev, "Failed to load EEPROM table records!"); |
| 1875 | − ret = -EIO; | |
| 1876 | − goto out; | |
| 1877 | − } | |
| 1878 | − | |
| 1879 | − ret = amdgpu_ras_add_bad_pages(adev, bps, control->num_recs); | |
| 1882 | + else | |
| 1883 | + ret = amdgpu_ras_add_bad_pages(adev, bps, control->ras_num_recs); | |
| 1880 | 1884 | |
| 1881 | −out: | |
| 1882 | 1885 | kfree(bps); |
| 1883 | 1886 | return ret; |
| 1884 | 1887 | } |
| @@ -1918,11 +1921,9 @@ static bool amdgpu_ras_check_bad_page(struct amdgpu_device *adev, · 33 unmodified lines | ||
| 1918 | 1921 | } |
| 1919 | 1922 | |
| 1920 | 1923 | static void amdgpu_ras_validate_threshold(struct amdgpu_device *adev, |
| 1921 | − uint32_t max_length) | |
| 1924 | + uint32_t max_count) | |
| 1922 | 1925 | { |
| 1923 | 1926 | struct amdgpu_ras *con = amdgpu_ras_get_context(adev); |
| 1924 | − int tmp_threshold = amdgpu_bad_page_threshold; | |
| 1925 | − u64 val; | |
| 1926 | 1927 | |
| 1927 | 1928 | /* |
| 1928 | 1929 | * Justification of value bad_page_cnt_threshold in ras structure |
| @@ -1943,18 +1944,15 @@ static void amdgpu_ras_validate_threshold(struct amdgpu_device *adev, · 14 unmodified lines | ||
| 1943 | 1944 | * take no effect. |
| 1944 | 1945 | */ |
| 1945 | 1946 | |
| 1946 | − if (tmp_threshold < -1) | |
| 1947 | − tmp_threshold = -1; | |
| 1948 | − else if (tmp_threshold > max_length) | |
| 1949 | − tmp_threshold = max_length; | |
| 1947 | + if (amdgpu_bad_page_threshold < 0) { | |
| 1948 | + u64 val = adev->gmc.mc_vram_size; | |
| 1950 | 1949 | |
| 1951 | − if (tmp_threshold == -1) { | |
| 1952 | − val = adev->gmc.mc_vram_size; | |
| 1953 | − do_div(val, RAS_BAD_PAGE_RATE); | |
| 1950 | + do_div(val, RAS_BAD_PAGE_COVER); | |
| 1954 | 1951 | con->bad_page_cnt_threshold = min(lower_32_bits(val), |
| 1955 | − max_length); | |
| 1952 | + max_count); | |
| 1956 | 1953 | } else { |
| 1957 | − con->bad_page_cnt_threshold = tmp_threshold; | |
| 1954 | + con->bad_page_cnt_threshold = min_t(int, max_count, | |
| 1955 | + amdgpu_bad_page_threshold); | |
| 1958 | 1956 | } |
| 1959 | 1957 | } |
| 1960 | 1958 | |
| @@ -1962,15 +1960,24 @@ int amdgpu_ras_recovery_init(struct amdgpu_device *adev) · 1 unmodified line | ||
| 1962 | 1960 | { |
| 1963 | 1961 | struct amdgpu_ras *con = amdgpu_ras_get_context(adev); |
| 1964 | 1962 | struct ras_err_handler_data **data; |
| 1965 | − uint32_t max_eeprom_records_len = 0; | |
| 1963 | + u32 max_eeprom_records_count = 0; | |
| 1966 | 1964 | bool exc_err_limit = false; |
| 1967 | 1965 | int ret; |
| 1968 | 1966 | |
| 1969 | − if (adev->ras_enabled && con) | |
| 1970 | − data = &con->eh_data; | |
| 1971 | − else | |
| 1967 | + if (!con) | |
| 1972 | 1968 | return 0; |
| 1973 | 1969 | |
| 1970 | + /* Allow access to RAS EEPROM via debugfs, when the ASIC | |
| 1971 | + * supports RAS and debugfs is enabled, but when | |
| 1972 | + * adev->ras_enabled is unset, i.e. when "ras_enable" | |
| 1973 | + * module parameter is set to 0. | |
| 1974 | + */ | |
| 1975 | + con->adev = adev; | |
| 1976 | + | |
| 1977 | + if (!adev->ras_enabled) | |
| 1978 | + return 0; | |
| 1979 | + | |
| 1980 | + data = &con->eh_data; | |
| 1974 | 1981 | *data = kmalloc(sizeof(**data), GFP_KERNEL | __GFP_ZERO); |
| 1975 | 1982 | if (!*data) { |
| 1976 | 1983 | ret = -ENOMEM; |
| @@ -1980,10 +1987,9 @@ int amdgpu_ras_recovery_init(struct amdgpu_device *adev) · 3 unmodified lines | ||
| 1980 | 1987 | mutex_init(&con->recovery_lock); |
| 1981 | 1988 | INIT_WORK(&con->recovery_work, amdgpu_ras_do_recovery); |
| 1982 | 1989 | atomic_set(&con->in_recovery, 0); |
| 1983 | − con->adev = adev; | |
| 1984 | 1990 | |
| 1985 | − max_eeprom_records_len = amdgpu_ras_eeprom_get_record_max_length(); | |
| 1986 | − amdgpu_ras_validate_threshold(adev, max_eeprom_records_len); | |
| 1991 | + max_eeprom_records_count = amdgpu_ras_eeprom_max_record_count(); | |
| 1992 | + amdgpu_ras_validate_threshold(adev, max_eeprom_records_count); | |
| 1987 | 1993 | |
| 1988 | 1994 | /* Todo: During test the SMU might fail to read the eeprom through I2C |
| 1989 | 1995 | * when the GPU is pending on XGMI reset during probe time |
| @@ -1999,13 +2005,13 @@ int amdgpu_ras_recovery_init(struct amdgpu_device *adev) · 9 unmodified lines | ||
| 1999 | 2005 | if (exc_err_limit || ret) |
| 2000 | 2006 | goto free; |
| 2001 | 2007 | |
| 2002 | − if (con->eeprom_control.num_recs) { | |
| 2008 | + if (con->eeprom_control.ras_num_recs) { | |
| 2003 | 2009 | ret = amdgpu_ras_load_bad_pages(adev); |
| 2004 | 2010 | if (ret) |
| 2005 | 2011 | goto free; |
| 2006 | 2012 | |
| 2007 | 2013 | if (adev->smu.ppt_funcs && adev->smu.ppt_funcs->send_hbm_bad_pages_num) |
| 2008 | − adev->smu.ppt_funcs->send_hbm_bad_pages_num(&adev->smu, con->eeprom_control.num_recs); | |
| 2014 | + adev->smu.ppt_funcs->send_hbm_bad_pages_num(&adev->smu, con->eeprom_control.ras_num_recs); | |
| 2009 | 2015 | } |
| 2010 | 2016 | |
| 2011 | 2017 | return 0; |
| @@ -2015,7 +2021,7 @@ free: · 3 unmodified lines | ||
| 2015 | 2021 | kfree(*data); |
| 2016 | 2022 | con->eh_data = NULL; |
| 2017 | 2023 | out: |
| 2018 | − dev_warn(adev->dev, "Failed to initialize ras recovery!\n"); | |
| 2024 | + dev_warn(adev->dev, "Failed to initialize ras recovery! (%d)\n", ret); | |
| 2019 | 2025 | |
| 2020 | 2026 | /* |
| 2021 | 2027 | * Except error threshold exceeding case, other failure cases in this |
| @@ -49,10 +49,14 @@ enum amdgpu_ras_block { · 48 unmodified lines | ||
| 49 | 49 | AMDGPU_RAS_BLOCK__MP0, |
| 50 | 50 | AMDGPU_RAS_BLOCK__MP1, |
| 51 | 51 | AMDGPU_RAS_BLOCK__FUSE, |
| 52 | + AMDGPU_RAS_BLOCK__MPIO, | |
| 52 | 53 | |
| 53 | 54 | AMDGPU_RAS_BLOCK__LAST |
| 54 | 55 | }; |
| 55 | 56 | |
| 57 | +extern const char *ras_block_string[]; | |
| 58 | + | |
| 59 | +#define ras_block_str(i) (ras_block_string[i]) | |
| 56 | 60 | #define AMDGPU_RAS_BLOCK_COUNT AMDGPU_RAS_BLOCK__LAST |
| 57 | 61 | #define AMDGPU_RAS_BLOCK_MASK ((1ULL << AMDGPU_RAS_BLOCK_COUNT) - 1) |
| 58 | 62 | |
| @@ -306,7 +310,6 @@ struct ras_common_if { · 247 unmodified lines | ||
| 306 | 310 | enum amdgpu_ras_block block; |
| 307 | 311 | enum amdgpu_ras_error_type type; |
| 308 | 312 | uint32_t sub_block_index; |
| 309 | − /* block name */ | |
| 310 | 313 | char name[32]; |
| 311 | 314 | }; |
| 312 | 315 | |
| @@ -318,6 +321,7 @@ struct amdgpu_ras { · 5 unmodified lines | ||
| 318 | 321 | /* sysfs */ |
| 319 | 322 | struct device_attribute features_attr; |
| 320 | 323 | struct bin_attribute badpages_attr; |
| 324 | + struct dentry *de_ras_eeprom_table; | |
| 321 | 325 | /* block array */ |
| 322 | 326 | struct ras_manager *objs; |
| 323 | 327 | |
| @@ -417,7 +421,7 @@ struct ras_badpage { · 93 unmodified lines | ||
| 417 | 421 | /* interfaces for IP */ |
| 418 | 422 | struct ras_fs_if { |
| 419 | 423 | struct ras_common_if head; |
| 420 | − char sysfs_name[32]; | |
| 424 | + const char* sysfs_name; | |
| 421 | 425 | char debugfs_name[32]; |
| 422 | 426 | }; |
| 423 | 427 | |
| @@ -469,8 +473,8 @@ struct ras_debug_if { · 45 unmodified lines | ||
| 469 | 473 | * 8: feature disable |
| 470 | 474 | */ |
| 471 | 475 | |
| 472 | −#define amdgpu_ras_get_context(adev) ((adev)->psp.ras.ras) | |
| 473 | −#define amdgpu_ras_set_context(adev, ras_con) ((adev)->psp.ras.ras = (ras_con)) | |
| 476 | +#define amdgpu_ras_get_context(adev) ((adev)->psp.ras_context.ras) | |
| 477 | +#define amdgpu_ras_set_context(adev, ras_con) ((adev)->psp.ras_context.ras = (ras_con)) | |
| 474 | 478 | |
| 475 | 479 | /* check if ras is supported on block, say, sdma, gfx */ |
| 476 | 480 | static inline int amdgpu_ras_is_supported(struct amdgpu_device *adev, |
| @@ -26,94 +26,131 @@ · 25 unmodified lines | ||
| 26 | 26 | #include "amdgpu_ras.h" |
| 27 | 27 | #include <linux/bits.h> |
| 28 | 28 | #include "atom.h" |
| 29 | +#include "amdgpu_eeprom.h" | |
| 29 | 30 | #include "amdgpu_atomfirmware.h" |
| 31 | +#include <linux/debugfs.h> | |
| 32 | +#include <linux/uaccess.h> | |
| 30 | 33 | |
| 31 | −#define EEPROM_I2C_TARGET_ADDR_VEGA20 0xA0 | |
| 32 | −#define EEPROM_I2C_TARGET_ADDR_ARCTURUS 0xA8 | |
| 33 | −#define EEPROM_I2C_TARGET_ADDR_ARCTURUS_D342 0xA0 | |
| 34 | −#define EEPROM_I2C_TARGET_ADDR_SIENNA_CICHLID 0xA0 | |
| 35 | −#define EEPROM_I2C_TARGET_ADDR_ALDEBARAN 0xA0 | |
| 34 | +#define EEPROM_I2C_MADDR_VEGA20 0x0 | |
| 35 | +#define EEPROM_I2C_MADDR_ARCTURUS 0x40000 | |
| 36 | +#define EEPROM_I2C_MADDR_ARCTURUS_D342 0x0 | |
| 37 | +#define EEPROM_I2C_MADDR_SIENNA_CICHLID 0x0 | |
| 38 | +#define EEPROM_I2C_MADDR_ALDEBARAN 0x0 | |
| 36 | 39 | |
| 37 | 40 | /* |
| 38 | 41 | * The 2 macros bellow represent the actual size in bytes that |
| 39 | 42 | * those entities occupy in the EEPROM memory. |
| 40 | − * EEPROM_TABLE_RECORD_SIZE is different than sizeof(eeprom_table_record) which | |
| 43 | + * RAS_TABLE_RECORD_SIZE is different than sizeof(eeprom_table_record) which | |
| 41 | 44 | * uses uint64 to store 6b fields such as retired_page. |
| 42 | 45 | */ |
| 43 | −#define EEPROM_TABLE_HEADER_SIZE 20 | |
| 44 | −#define EEPROM_TABLE_RECORD_SIZE 24 | |
| 45 | − | |
| 46 | −#define EEPROM_ADDRESS_SIZE 0x2 | |
| 46 | +#define RAS_TABLE_HEADER_SIZE 20 | |
| 47 | +#define RAS_TABLE_RECORD_SIZE 24 | |
| 47 | 48 | |
| 48 | 49 | /* Table hdr is 'AMDR' */ |
| 49 | −#define EEPROM_TABLE_HDR_VAL 0x414d4452 | |
| 50 | −#define EEPROM_TABLE_VER 0x00010000 | |
| 50 | +#define RAS_TABLE_HDR_VAL 0x414d4452 | |
| 51 | +#define RAS_TABLE_VER 0x00010000 | |
| 51 | 52 | |
| 52 | 53 | /* Bad GPU tag ‘BADG’ */ |
| 53 | −#define EEPROM_TABLE_HDR_BAD 0x42414447 | |
| 54 | +#define RAS_TABLE_HDR_BAD 0x42414447 | |
| 55 | + | |
| 56 | +/* Assume 2-Mbit size EEPROM and take up the whole space. */ | |
| 57 | +#define RAS_TBL_SIZE_BYTES (256 * 1024) | |
| 58 | +#define RAS_TABLE_START 0 | |
| 59 | +#define RAS_HDR_START RAS_TABLE_START | |
| 60 | +#define RAS_RECORD_START (RAS_HDR_START + RAS_TABLE_HEADER_SIZE) | |
| 61 | +#define RAS_MAX_RECORD_COUNT ((RAS_TBL_SIZE_BYTES - RAS_TABLE_HEADER_SIZE) \ | |
| 62 | + / RAS_TABLE_RECORD_SIZE) | |
| 63 | + | |
| 64 | +/* Given a zero-based index of an EEPROM RAS record, yields the EEPROM | |
| 65 | + * offset off of RAS_TABLE_START. That is, this is something you can | |
| 66 | + * add to control->i2c_address, and then tell I2C layer to read | |
| 67 | + * from/write to there. _N is the so called absolute index, | |
| 68 | + * because it starts right after the table header. | |
| 69 | + */ | |
| 70 | +#define RAS_INDEX_TO_OFFSET(_C, _N) ((_C)->ras_record_offset + \ | |
| 71 | + (_N) * RAS_TABLE_RECORD_SIZE) | |
| 72 | + | |
| 73 | +#define RAS_OFFSET_TO_INDEX(_C, _O) (((_O) - \ | |
| 74 | + (_C)->ras_record_offset) / RAS_TABLE_RECORD_SIZE) | |
| 75 | + | |
| 76 | +/* Given a 0-based relative record index, 0, 1, 2, ..., etc., off | |
| 77 | + * of "fri", return the absolute record index off of the end of | |
| 78 | + * the table header. | |
| 79 | + */ | |
| 80 | +#define RAS_RI_TO_AI(_C, _I) (((_I) + (_C)->ras_fri) % \ | |
| 81 | + (_C)->ras_max_record_count) | |
| 54 | 82 | |
| 55 | −/* Assume 2 Mbit size */ | |
| 56 | −#define EEPROM_SIZE_BYTES 256000 | |
| 57 | −#define EEPROM_PAGE__SIZE_BYTES 256 | |
| 58 | −#define EEPROM_HDR_START 0 | |
| 59 | −#define EEPROM_RECORD_START (EEPROM_HDR_START + EEPROM_TABLE_HEADER_SIZE) | |
| 60 | −#define EEPROM_MAX_RECORD_NUM ((EEPROM_SIZE_BYTES - EEPROM_TABLE_HEADER_SIZE) / EEPROM_TABLE_RECORD_SIZE) | |
| 61 | −#define EEPROM_ADDR_MSB_MASK GENMASK(17, 8) | |
| 83 | +#define RAS_NUM_RECS(_tbl_hdr) (((_tbl_hdr)->tbl_size - \ | |
| 84 | + RAS_TABLE_HEADER_SIZE) / RAS_TABLE_RECORD_SIZE) | |
| 62 | 85 | |
| 63 | 86 | #define to_amdgpu_device(x) (container_of(x, struct amdgpu_ras, eeprom_control))->adev |
| 64 | 87 | |
| 65 | 88 | static bool __is_ras_eeprom_supported(struct amdgpu_device *adev) |
| 66 | 89 | { |
| 67 | − if ((adev->asic_type == CHIP_VEGA20) || | |
| 68 | − (adev->asic_type == CHIP_ARCTURUS) || | |
| 69 | − (adev->asic_type == CHIP_SIENNA_CICHLID) || | |
| 70 | − (adev->asic_type == CHIP_ALDEBARAN)) | |
| 71 | − return true; | |
| 72 | − | |
| 73 | − return false; | |
| 90 | + return adev->asic_type == CHIP_VEGA20 || | |
| 91 | + adev->asic_type == CHIP_ARCTURUS || | |
| 92 | + adev->asic_type == CHIP_SIENNA_CICHLID || | |
| 93 | + adev->asic_type == CHIP_ALDEBARAN; | |
| 74 | 94 | } |
| 75 | 95 | |
| 76 | 96 | static bool __get_eeprom_i2c_addr_arct(struct amdgpu_device *adev, |
| 77 | − uint16_t *i2c_addr) | |
| 97 | + struct amdgpu_ras_eeprom_control *control) | |
| 78 | 98 | { |
| 79 | 99 | struct atom_context *atom_ctx = adev->mode_info.atom_context; |
| 80 | 100 | |
| 81 | − if (!i2c_addr || !atom_ctx) | |
| 101 | + if (!control || !atom_ctx) | |
| 82 | 102 | return false; |
| 83 | 103 | |
| 84 | 104 | if (strnstr(atom_ctx->vbios_version, |
| 85 | 105 | "D342", |
| 86 | 106 | sizeof(atom_ctx->vbios_version))) |
| 87 | − *i2c_addr = EEPROM_I2C_TARGET_ADDR_ARCTURUS_D342; | |
| 107 | + control->i2c_address = EEPROM_I2C_MADDR_ARCTURUS_D342; | |
| 88 | 108 | else |
| 89 | − *i2c_addr = EEPROM_I2C_TARGET_ADDR_ARCTURUS; | |
| 109 | + control->i2c_address = EEPROM_I2C_MADDR_ARCTURUS; | |
| 90 | 110 | |
| 91 | 111 | return true; |
| 92 | 112 | } |
| 93 | 113 | |
| 94 | 114 | static bool __get_eeprom_i2c_addr(struct amdgpu_device *adev, |
| 95 | − uint16_t *i2c_addr) | |
| 115 | + struct amdgpu_ras_eeprom_control *control) | |
| 96 | 116 | { |
| 97 | − if (!i2c_addr) | |
| 117 | + uint8_t ras_rom_i2c_slave_addr; | |
| 118 | + | |
| 119 | + if (!control) | |
| 98 | 120 | return false; |
| 99 | 121 | |
| 100 | − if (amdgpu_atomfirmware_ras_rom_addr(adev, (uint8_t*)i2c_addr)) | |
| 101 | − return true; | |
| 122 | + control->i2c_address = 0; | |
| 123 | + | |
| 124 | + if (amdgpu_atomfirmware_ras_rom_addr(adev, &ras_rom_i2c_slave_addr)) | |
| 125 | + { | |
| 126 | + switch (ras_rom_i2c_slave_addr) { | |
| 127 | + case 0xA0: | |
| 128 | + control->i2c_address = 0; | |
| 129 | + return true; | |
| 130 | + case 0xA8: | |
| 131 | + control->i2c_address = 0x40000; | |
| 132 | + return true; | |
| 133 | + default: | |
| 134 | + dev_warn(adev->dev, "RAS EEPROM I2C slave address %02x not supported", | |
| 135 | + ras_rom_i2c_slave_addr); | |
| 136 | + return false; | |
| 137 | + } | |
| 138 | + } | |
| 102 | 139 | |
| 103 | 140 | switch (adev->asic_type) { |
| 104 | 141 | case CHIP_VEGA20: |
| 105 | − *i2c_addr = EEPROM_I2C_TARGET_ADDR_VEGA20; | |
| 142 | + control->i2c_address = EEPROM_I2C_MADDR_VEGA20; | |
| 106 | 143 | break; |
| 107 | 144 | |
| 108 | 145 | case CHIP_ARCTURUS: |
| 109 | − return __get_eeprom_i2c_addr_arct(adev, i2c_addr); | |
| 146 | + return __get_eeprom_i2c_addr_arct(adev, control); | |
| 110 | 147 | |
| 111 | 148 | case CHIP_SIENNA_CICHLID: |
| 112 | − *i2c_addr = EEPROM_I2C_TARGET_ADDR_SIENNA_CICHLID; | |
| 149 | + control->i2c_address = EEPROM_I2C_MADDR_SIENNA_CICHLID; | |
| 113 | 150 | break; |
| 114 | 151 | |
| 115 | 152 | case CHIP_ALDEBARAN: |
| 116 | − *i2c_addr = EEPROM_I2C_TARGET_ADDR_ALDEBARAN; | |
| 153 | + control->i2c_address = EEPROM_I2C_MADDR_ALDEBARAN; | |
| 117 | 154 | break; |
| 118 | 155 | |
| 119 | 156 | default: |
| @@ -123,10 +160,11 @@ static bool __get_eeprom_i2c_addr(struct amdgpu_device *adev, · 3 unmodified lines | ||
| 123 | 160 | return true; |
| 124 | 161 | } |
| 125 | 162 | |
| 126 | −static void __encode_table_header_to_buff(struct amdgpu_ras_eeprom_table_header *hdr, | |
| 127 | − unsigned char *buff) | |
| 163 | +static void | |
| 164 | +__encode_table_header_to_buf(struct amdgpu_ras_eeprom_table_header *hdr, | |
| 165 | + unsigned char *buf) | |
| 128 | 166 | { |
| 129 | − uint32_t *pp = (uint32_t *) buff; | |
| 167 | + u32 *pp = (uint32_t *)buf; | |
| 130 | 168 | |
| 131 | 169 | pp[0] = cpu_to_le32(hdr->header); |
| 132 | 170 | pp[1] = cpu_to_le32(hdr->version); |
| @@ -135,10 +173,11 @@ static void __encode_table_header_to_buff(struct amdgpu_ras_eeprom_table_header · 2 unmodified lines | ||
| 135 | 173 | pp[4] = cpu_to_le32(hdr->checksum); |
| 136 | 174 | } |
| 137 | 175 | |
| 138 | −static void __decode_table_header_from_buff(struct amdgpu_ras_eeprom_table_header *hdr, | |
| 139 | − unsigned char *buff) | |
| 176 | +static void | |
| 177 | +__decode_table_header_from_buf(struct amdgpu_ras_eeprom_table_header *hdr, | |
| 178 | + unsigned char *buf) | |
| 140 | 179 | { |
| 141 | − uint32_t *pp = (uint32_t *)buff; | |
| 180 | + u32 *pp = (uint32_t *)buf; | |
| 142 | 181 | |
| 143 | 182 | hdr->header = le32_to_cpu(pp[0]); |
| 144 | 183 | hdr->version = le32_to_cpu(pp[1]); |
| @@ -147,303 +186,168 @@ static void __decode_table_header_from_buff(struct amdgpu_ras_eeprom_table_heade · 2 unmodified lines | ||
| 147 | 186 | hdr->checksum = le32_to_cpu(pp[4]); |
| 148 | 187 | } |
| 149 | 188 | |
| 150 | −static int __update_table_header(struct amdgpu_ras_eeprom_control *control, | |
| 151 | − unsigned char *buff) | |
| 189 | +static int __write_table_header(struct amdgpu_ras_eeprom_control *control) | |
| 152 | 190 | { |
| 153 | − int ret = 0; | |
| 191 | + u8 buf[RAS_TABLE_HEADER_SIZE]; | |
| 154 | 192 | struct amdgpu_device *adev = to_amdgpu_device(control); |
| 155 | − struct i2c_msg msg = { | |
| 156 | − .addr = 0, | |
| 157 | − .flags = 0, | |
| 158 | − .len = EEPROM_ADDRESS_SIZE + EEPROM_TABLE_HEADER_SIZE, | |
| 159 | − .buf = buff, | |
| 160 | − }; | |
| 161 | − | |
| 193 | + int res; | |
| 162 | 194 | |
| 163 | − *(uint16_t *)buff = EEPROM_HDR_START; | |
| 164 | − __encode_table_header_to_buff(&control->tbl_hdr, buff + EEPROM_ADDRESS_SIZE); | |
| 165 | − | |
| 166 | − msg.addr = control->i2c_address; | |
| 195 | + memset(buf, 0, sizeof(buf)); | |
| 196 | + __encode_table_header_to_buf(&control->tbl_hdr, buf); | |
| 167 | 197 | |
| 168 | 198 | /* i2c may be unstable in gpu reset */ |
| 169 | 199 | down_read(&adev->reset_sem); |
| 170 | − ret = i2c_transfer(&adev->pm.smu_i2c, &msg, 1); | |
| 200 | + res = amdgpu_eeprom_write(&adev->pm.smu_i2c, | |
| 201 | + control->i2c_address + | |
| 202 | + control->ras_header_offset, | |
| 203 | + buf, RAS_TABLE_HEADER_SIZE); | |
| 171 | 204 | up_read(&adev->reset_sem); |
| 172 | 205 | |
| 173 | − if (ret < 1) | |
| 174 | − DRM_ERROR("Failed to write EEPROM table header, ret:%d", ret); | |
| 175 | − | |
| 176 | − return ret; | |
| 177 | −} | |
| 178 | − | |
| 179 | −static uint32_t __calc_hdr_byte_sum(struct amdgpu_ras_eeprom_control *control) | |
| 180 | −{ | |
| 181 | − int i; | |
| 182 | − uint32_t tbl_sum = 0; | |
| 183 | − | |
| 184 | − /* Header checksum, skip checksum field in the calculation */ | |
| 185 | − for (i = 0; i < sizeof(control->tbl_hdr) - sizeof(control->tbl_hdr.checksum); i++) | |
| 186 | − tbl_sum += *(((unsigned char *)&control->tbl_hdr) + i); | |
| 187 | − | |
| 188 | − return tbl_sum; | |
| 189 | −} | |
| 190 | − | |
| 191 | −static uint32_t __calc_recs_byte_sum(struct eeprom_table_record *records, | |
| 192 | − int num) | |
| 193 | −{ | |
| 194 | − int i, j; | |
| 195 | − uint32_t tbl_sum = 0; | |
| 196 | − | |
| 197 | − /* Records checksum */ | |
| 198 | − for (i = 0; i < num; i++) { | |
| 199 | − struct eeprom_table_record *record = &records[i]; | |
| 200 | − | |
| 201 | − for (j = 0; j < sizeof(*record); j++) { | |
| 202 | − tbl_sum += *(((unsigned char *)record) + j); | |
| 203 | − } | |
| 206 | + if (res < 0) { | |
| 207 | + DRM_ERROR("Failed to write EEPROM table header:%d", res); | |
| 208 | + } else if (res < RAS_TABLE_HEADER_SIZE) { | |
| 209 | + DRM_ERROR("Short write:%d out of %d\n", | |
| 210 | + res, RAS_TABLE_HEADER_SIZE); | |
| 211 | + res = -EIO; | |
| 212 | + } else { | |
| 213 | + res = 0; | |
| 204 | 214 | } |
| 205 | 215 | |
| 206 | − return tbl_sum; | |
| 207 | −} | |
| 208 | − | |
| 209 | −static inline uint32_t __calc_tbl_byte_sum(struct amdgpu_ras_eeprom_control *control, | |
| 210 | − struct eeprom_table_record *records, int num) | |
| 211 | −{ | |
| 212 | − return __calc_hdr_byte_sum(control) + __calc_recs_byte_sum(records, num); | |
| 213 | −} | |
| 214 | − | |
| 215 | −/* Checksum = 256 -((sum of all table entries) mod 256) */ | |
| 216 | −static void __update_tbl_checksum(struct amdgpu_ras_eeprom_control *control, | |
| 217 | − struct eeprom_table_record *records, int num, | |
| 218 | − uint32_t old_hdr_byte_sum) | |
| 219 | −{ | |
| 220 | − /* | |
| 221 | − * This will update the table sum with new records. | |
| 222 | − * | |
| 223 | − * TODO: What happens when the EEPROM table is to be wrapped around | |
| 224 | − * and old records from start will get overridden. | |
| 225 | − */ | |
| 226 | − | |
| 227 | − /* need to recalculate updated header byte sum */ | |
| 228 | − control->tbl_byte_sum -= old_hdr_byte_sum; | |
| 229 | − control->tbl_byte_sum += __calc_tbl_byte_sum(control, records, num); | |
| 230 | − | |
| 231 | − control->tbl_hdr.checksum = 256 - (control->tbl_byte_sum % 256); | |
| 216 | + return res; | |
| 232 | 217 | } |
| 233 | 218 | |
| 234 | −/* table sum mod 256 + checksum must equals 256 */ | |
| 235 | −static bool __validate_tbl_checksum(struct amdgpu_ras_eeprom_control *control, | |
| 236 | − struct eeprom_table_record *records, int num) | |
| 219 | +static u8 __calc_hdr_byte_sum(const struct amdgpu_ras_eeprom_control *control) | |
| 237 | 220 | { |
| 238 | − control->tbl_byte_sum = __calc_tbl_byte_sum(control, records, num); | |
| 221 | + int ii; | |
| 222 | + u8 *pp, csum; | |
| 223 | + size_t sz; | |
| 239 | 224 | |
| 240 | − if (control->tbl_hdr.checksum + (control->tbl_byte_sum % 256) != 256) { | |
| 241 | − DRM_WARN("Checksum mismatch, checksum: %u ", control->tbl_hdr.checksum); | |
| 242 | − return false; | |
| 243 | − } | |
| 225 | + /* Header checksum, skip checksum field in the calculation */ | |
| 226 | + sz = sizeof(control->tbl_hdr) - sizeof(control->tbl_hdr.checksum); | |
| 227 | + pp = (u8 *) &control->tbl_hdr; | |
| 228 | + csum = 0; | |
| 229 | + for (ii = 0; ii < sz; ii++, pp++) | |
| 230 | + csum += *pp; | |
| 244 | 231 | |
| 245 | − return true; | |
| 232 | + return csum; | |
| 246 | 233 | } |
| 247 | 234 | |
| 248 | 235 | static int amdgpu_ras_eeprom_correct_header_tag( |
| 249 | − struct amdgpu_ras_eeprom_control *control, | |
| 250 | − uint32_t header) | |
| 236 | + struct amdgpu_ras_eeprom_control *control, | |
| 237 | + uint32_t header) | |
| 251 | 238 | { |
| 252 | − unsigned char buff[EEPROM_ADDRESS_SIZE + EEPROM_TABLE_HEADER_SIZE]; | |
| 253 | 239 | struct amdgpu_ras_eeprom_table_header *hdr = &control->tbl_hdr; |
| 254 | − int ret = 0; | |
| 255 | − | |
| 256 | − memset(buff, 0, EEPROM_ADDRESS_SIZE + EEPROM_TABLE_HEADER_SIZE); | |
| 257 | − | |
| 258 | − mutex_lock(&control->tbl_mutex); | |
| 240 | + u8 *hh; | |
| 241 | + int res; | |
| 242 | + u8 csum; | |
| 243 | + | |
| 244 | + csum = -hdr->checksum; | |
| 245 | + | |
| 246 | + hh = (void *) &hdr->header; | |
| 247 | + csum -= (hh[0] + hh[1] + hh[2] + hh[3]); | |
| 248 | + hh = (void *) &header; | |
| 249 | + csum += hh[0] + hh[1] + hh[2] + hh[3]; | |
| 250 | + csum = -csum; | |
| 251 | + mutex_lock(&control->ras_tbl_mutex); | |
| 259 | 252 | hdr->header = header; |
| 260 | − ret = __update_table_header(control, buff); | |
| 261 | − mutex_unlock(&control->tbl_mutex); | |
| 253 | + hdr->checksum = csum; | |
| 254 | + res = __write_table_header(control); | |
| 255 | + mutex_unlock(&control->ras_tbl_mutex); | |
| 262 | 256 | |
| 263 | − return ret; | |
| 257 | + return res; | |
| 264 | 258 | } |
| 265 | 259 | |
| 260 | +/** | |
| 261 | + * amdgpu_ras_eeprom_reset_table -- Reset the RAS EEPROM table | |
| 262 | + * @control: pointer to control structure | |
| 263 | + * | |
| 264 | + * Reset the contents of the header of the RAS EEPROM table. | |
| 265 | + * Return 0 on success, -errno on error. | |
| 266 | + */ | |
| 266 | 267 | int amdgpu_ras_eeprom_reset_table(struct amdgpu_ras_eeprom_control *control) |
| 267 | 268 | { |
| 268 | − unsigned char buff[EEPROM_ADDRESS_SIZE + EEPROM_TABLE_HEADER_SIZE] = { 0 }; | |
| 269 | 269 | struct amdgpu_ras_eeprom_table_header *hdr = &control->tbl_hdr; |
| 270 | − int ret = 0; | |
| 271 | − | |
| 272 | − mutex_lock(&control->tbl_mutex); | |
| 273 | − | |
| 274 | − hdr->header = EEPROM_TABLE_HDR_VAL; | |
| 275 | − hdr->version = EEPROM_TABLE_VER; | |
| 276 | − hdr->first_rec_offset = EEPROM_RECORD_START; | |
| 277 | − hdr->tbl_size = EEPROM_TABLE_HEADER_SIZE; | |
| 278 | − | |
| 279 | − control->tbl_byte_sum = 0; | |
| 280 | − __update_tbl_checksum(control, NULL, 0, 0); | |
| 281 | − control->next_addr = EEPROM_RECORD_START; | |
| 282 | − | |
| 283 | − ret = __update_table_header(control, buff); | |
| 284 | − | |
| 285 | − mutex_unlock(&control->tbl_mutex); | |
| 286 | − | |
| 287 | − return ret; | |
| 288 | − | |
| 289 | −} | |
| 290 | − | |
| 291 | −int amdgpu_ras_eeprom_init(struct amdgpu_ras_eeprom_control *control, | |
| 292 | − bool *exceed_err_limit) | |
| 293 | −{ | |
| 294 | − int ret = 0; | |
| 295 | − struct amdgpu_device *adev = to_amdgpu_device(control); | |
| 296 | − unsigned char buff[EEPROM_ADDRESS_SIZE + EEPROM_TABLE_HEADER_SIZE] = { 0 }; | |
| 297 | − struct amdgpu_ras_eeprom_table_header *hdr = &control->tbl_hdr; | |
| 298 | − struct amdgpu_ras *ras = amdgpu_ras_get_context(adev); | |
| 299 | − struct i2c_msg msg = { | |
| 300 | − .addr = 0, | |
| 301 | − .flags = I2C_M_RD, | |
| 302 | − .len = EEPROM_ADDRESS_SIZE + EEPROM_TABLE_HEADER_SIZE, | |
| 303 | − .buf = buff, | |
| 304 | − }; | |
| 305 | − | |
| 306 | − *exceed_err_limit = false; | |
| 307 | − | |
| 308 | − if (!__is_ras_eeprom_supported(adev)) | |
| 309 | − return 0; | |
| 310 | − | |
| 311 | − /* Verify i2c adapter is initialized */ | |
| 312 | − if (!adev->pm.smu_i2c.algo) | |
| 313 | − return -ENOENT; | |
| 270 | + u8 csum; | |
| 271 | + int res; | |
| 314 | 272 | |
| 315 | − if (!__get_eeprom_i2c_addr(adev, &control->i2c_address)) | |
| 316 | − return -EINVAL; | |
| 273 | + mutex_lock(&control->ras_tbl_mutex); | |
| 317 | 274 | |
| 318 | − mutex_init(&control->tbl_mutex); | |
| 275 | + hdr->header = RAS_TABLE_HDR_VAL; | |
| 276 | + hdr->version = RAS_TABLE_VER; | |
| 277 | + hdr->first_rec_offset = RAS_RECORD_START; | |
| 278 | + hdr->tbl_size = RAS_TABLE_HEADER_SIZE; | |
| 319 | 279 | |
| 320 | − msg.addr = control->i2c_address; | |
| 321 | − /* Read/Create table header from EEPROM address 0 */ | |
| 322 | − ret = i2c_transfer(&adev->pm.smu_i2c, &msg, 1); | |
| 323 | − if (ret < 1) { | |
| 324 | − DRM_ERROR("Failed to read EEPROM table header, ret:%d", ret); | |
| 325 | − return ret; | |
| 326 | − } | |
| 280 | + csum = __calc_hdr_byte_sum(control); | |
| 281 | + csum = -csum; | |
| 282 | + hdr->checksum = csum; | |
| 283 | + res = __write_table_header(control); | |
| 327 | 284 | |
| 328 | − __decode_table_header_from_buff(hdr, &buff[2]); | |
| 285 | + control->ras_num_recs = 0; | |
| 286 | + control->ras_fri = 0; | |
| 329 | 287 | |
| 330 | − if (hdr->header == EEPROM_TABLE_HDR_VAL) { | |
| 331 | − control->num_recs = (hdr->tbl_size - EEPROM_TABLE_HEADER_SIZE) / | |
| 332 | − EEPROM_TABLE_RECORD_SIZE; | |
| 333 | − control->tbl_byte_sum = __calc_hdr_byte_sum(control); | |
| 334 | − control->next_addr = EEPROM_RECORD_START; | |
| 288 | + amdgpu_ras_debugfs_set_ret_size(control); | |
| 335 | 289 | |
| 336 | − DRM_DEBUG_DRIVER("Found existing EEPROM table with %d records", | |
| 337 | − control->num_recs); | |
| 338 | − | |
| 339 | − } else if ((hdr->header == EEPROM_TABLE_HDR_BAD) && | |
| 340 | − (amdgpu_bad_page_threshold != 0)) { | |
| 341 | − if (ras->bad_page_cnt_threshold > control->num_recs) { | |
| 342 | − dev_info(adev->dev, "Using one valid bigger bad page " | |
| 343 | − "threshold and correcting eeprom header tag.\n"); | |
| 344 | − ret = amdgpu_ras_eeprom_correct_header_tag(control, | |
| 345 | − EEPROM_TABLE_HDR_VAL); | |
| 346 | − } else { | |
| 347 | − *exceed_err_limit = true; | |
| 348 | − dev_err(adev->dev, "Exceeding the bad_page_threshold parameter, " | |
| 349 | − "disabling the GPU.\n"); | |
| 350 | − } | |
| 351 | − } else { | |
| 352 | − DRM_INFO("Creating new EEPROM table"); | |
| 290 | + mutex_unlock(&control->ras_tbl_mutex); | |
| 353 | 291 | |
| 354 | − ret = amdgpu_ras_eeprom_reset_table(control); | |
| 355 | − } | |
| 356 | − | |
| 357 | − return ret == 1 ? 0 : -EIO; | |
| 292 | + return res; | |
| 358 | 293 | } |
| 359 | 294 | |
| 360 | −static void __encode_table_record_to_buff(struct amdgpu_ras_eeprom_control *control, | |
| 361 | − struct eeprom_table_record *record, | |
| 362 | − unsigned char *buff) | |
| 295 | +static void | |
| 296 | +__encode_table_record_to_buf(struct amdgpu_ras_eeprom_control *control, | |
| 297 | + struct eeprom_table_record *record, | |
| 298 | + unsigned char *buf) | |
| 363 | 299 | { |
| 364 | 300 | __le64 tmp = 0; |
| 365 | 301 | int i = 0; |
| 366 | 302 | |
| 367 | 303 | /* Next are all record fields according to EEPROM page spec in LE foramt */ |
| 368 | − buff[i++] = record->err_type; | |
| 304 | + buf[i++] = record->err_type; | |
| 369 | 305 | |
| 370 | − buff[i++] = record->bank; | |
| 306 | + buf[i++] = record->bank; | |
| 371 | 307 | |
| 372 | 308 | tmp = cpu_to_le64(record->ts); |
| 373 | − memcpy(buff + i, &tmp, 8); | |
| 309 | + memcpy(buf + i, &tmp, 8); | |
| 374 | 310 | i += 8; |
| 375 | 311 | |
| 376 | 312 | tmp = cpu_to_le64((record->offset & 0xffffffffffff)); |
| 377 | − memcpy(buff + i, &tmp, 6); | |
| 313 | + memcpy(buf + i, &tmp, 6); | |
| 378 | 314 | i += 6; |
| 379 | 315 | |
| 380 | − buff[i++] = record->mem_channel; | |
| 381 | − buff[i++] = record->mcumc_id; | |
| 316 | + buf[i++] = record->mem_channel; | |
| 317 | + buf[i++] = record->mcumc_id; | |
| 382 | 318 | |
| 383 | 319 | tmp = cpu_to_le64((record->retired_page & 0xffffffffffff)); |
| 384 | − memcpy(buff + i, &tmp, 6); | |
| 320 | + memcpy(buf + i, &tmp, 6); | |
| 385 | 321 | } |
| 386 | 322 | |
| 387 | −static void __decode_table_record_from_buff(struct amdgpu_ras_eeprom_control *control, | |
| 388 | − struct eeprom_table_record *record, | |
| 389 | − unsigned char *buff) | |
| 323 | +static void | |
| 324 | +__decode_table_record_from_buf(struct amdgpu_ras_eeprom_control *control, | |
| 325 | + struct eeprom_table_record *record, | |
| 326 | + unsigned char *buf) | |
| 390 | 327 | { |
| 391 | 328 | __le64 tmp = 0; |
| 392 | 329 | int i = 0; |
| 393 | 330 | |
| 394 | 331 | /* Next are all record fields according to EEPROM page spec in LE foramt */ |
| 395 | − record->err_type = buff[i++]; | |
| 332 | + record->err_type = buf[i++]; | |
| 396 | 333 | |
| 397 | − record->bank = buff[i++]; | |
| 334 | + record->bank = buf[i++]; | |
| 398 | 335 | |
| 399 | − memcpy(&tmp, buff + i, 8); | |
| 336 | + memcpy(&tmp, buf + i, 8); | |
| 400 | 337 | record->ts = le64_to_cpu(tmp); |
| 401 | 338 | i += 8; |
| 402 | 339 | |
| 403 | − memcpy(&tmp, buff + i, 6); | |
| 340 | + memcpy(&tmp, buf + i, 6); | |
| 404 | 341 | record->offset = (le64_to_cpu(tmp) & 0xffffffffffff); |
| 405 | 342 | i += 6; |
| 406 | 343 | |
| 407 | − record->mem_channel = buff[i++]; | |
| 408 | − record->mcumc_id = buff[i++]; | |
| 344 | + record->mem_channel = buf[i++]; | |
| 345 | + record->mcumc_id = buf[i++]; | |
| 409 | 346 | |
| 410 | − memcpy(&tmp, buff + i, 6); | |
| 347 | + memcpy(&tmp, buf + i, 6); | |
| 411 | 348 | record->retired_page = (le64_to_cpu(tmp) & 0xffffffffffff); |
| 412 | 349 | } |
| 413 | 350 | |
| 414 | −/* | |
| 415 | − * When reaching end of EEPROM memory jump back to 0 record address | |
| 416 | − * When next record access will go beyond EEPROM page boundary modify bits A17/A8 | |
| 417 | − * in I2C selector to go to next page | |
| 418 | − */ | |
| 419 | −static uint32_t __correct_eeprom_dest_address(uint32_t curr_address) | |
| 420 | −{ | |
| 421 | − uint32_t next_address = curr_address + EEPROM_TABLE_RECORD_SIZE; | |
| 422 | − | |
| 423 | − /* When all EEPROM memory used jump back to 0 address */ | |
| 424 | − if (next_address > EEPROM_SIZE_BYTES) { | |
| 425 | − DRM_INFO("Reached end of EEPROM memory, jumping to 0 " | |
| 426 | − "and overriding old record"); | |
| 427 | − return EEPROM_RECORD_START; | |
| 428 | − } | |
| 429 | − | |
| 430 | − /* | |
| 431 | − * To check if we overflow page boundary compare next address with | |
| 432 | − * current and see if bits 17/8 of the EEPROM address will change | |
| 433 | − * If they do start from the next 256b page | |
| 434 | − * | |
| 435 | − * https://www.st.com/resource/en/datasheet/m24m02-dr.pdf sec. 5.1.2 | |
| 436 | − */ | |
| 437 | − if ((curr_address & EEPROM_ADDR_MSB_MASK) != (next_address & EEPROM_ADDR_MSB_MASK)) { | |
| 438 | − DRM_DEBUG_DRIVER("Reached end of EEPROM memory page, jumping to next: %lx", | |
| 439 | − (next_address & EEPROM_ADDR_MSB_MASK)); | |
| 440 | − | |
| 441 | − return (next_address & EEPROM_ADDR_MSB_MASK); | |
| 442 | − } | |
| 443 | − | |
| 444 | − return curr_address; | |
| 445 | −} | |
| 446 | − | |
| 447 | 351 | bool amdgpu_ras_eeprom_check_err_threshold(struct amdgpu_device *adev) |
| 448 | 352 | { |
| 449 | 353 | struct amdgpu_ras *con = amdgpu_ras_get_context(adev); |
| @@ -458,197 +362,756 @@ bool amdgpu_ras_eeprom_check_err_threshold(struct amdgpu_device *adev) · 8 unmodified lines | ||
| 458 | 362 | if (!(con->features & BIT(AMDGPU_RAS_BLOCK__UMC))) |
| 459 | 363 | return false; |
| 460 | 364 | |
| 461 | − if (con->eeprom_control.tbl_hdr.header == EEPROM_TABLE_HDR_BAD) { | |
| 365 | + if (con->eeprom_control.tbl_hdr.header == RAS_TABLE_HDR_BAD) { | |
| 462 | 366 | dev_warn(adev->dev, "This GPU is in BAD status."); |
| 463 | − dev_warn(adev->dev, "Please retire it or setting one bigger " | |
| 464 | − "threshold value when reloading driver.\n"); | |
| 367 | + dev_warn(adev->dev, "Please retire it or set a larger " | |
| 368 | + "threshold value when reloading driver.\n"); | |
| 465 | 369 | return true; |
| 466 | 370 | } |
| 467 | 371 | |
| 468 | 372 | return false; |
| 469 | 373 | } |
| 470 | 374 | |
| 471 | −int amdgpu_ras_eeprom_process_recods(struct amdgpu_ras_eeprom_control *control, | |
| 472 | − struct eeprom_table_record *records, | |
| 473 | − bool write, | |
| 474 | − int num) | |
| 375 | +/** | |
| 376 | + * __amdgpu_ras_eeprom_write -- write indexed from buffer to EEPROM | |
| 377 | + * @control: pointer to control structure | |
| 378 | + * @buf: pointer to buffer containing data to write | |
| 379 | + * @fri: start writing at this index | |
| 380 | + * @num: number of records to write | |
| 381 | + * | |
| 382 | + * The caller must hold the table mutex in @control. | |
| 383 | + * Return 0 on success, -errno otherwise. | |
| 384 | + */ | |
| 385 | +static int __amdgpu_ras_eeprom_write(struct amdgpu_ras_eeprom_control *control, | |
| 386 | + u8 *buf, const u32 fri, const u32 num) | |
| 475 | 387 | { |
| 476 | − int i, ret = 0; | |
| 477 | − struct i2c_msg *msgs, *msg; | |
| 478 | − unsigned char *buffs, *buff; | |
| 479 | − struct eeprom_table_record *record; | |
| 480 | 388 | struct amdgpu_device *adev = to_amdgpu_device(control); |
| 481 | − struct amdgpu_ras *ras = amdgpu_ras_get_context(adev); | |
| 389 | + u32 buf_size; | |
| 390 | + int res; | |
| 482 | 391 | |
| 483 | − if (!__is_ras_eeprom_supported(adev)) | |
| 484 | − return 0; | |
| 392 | + /* i2c may be unstable in gpu reset */ | |
| 393 | + down_read(&adev->reset_sem); | |
| 394 | + buf_size = num * RAS_TABLE_RECORD_SIZE; | |
| 395 | + res = amdgpu_eeprom_write(&adev->pm.smu_i2c, | |
| 396 | + control->i2c_address + | |
| 397 | + RAS_INDEX_TO_OFFSET(control, fri), | |
| 398 | + buf, buf_size); | |
| 399 | + up_read(&adev->reset_sem); | |
| 400 | + if (res < 0) { | |
| 401 | + DRM_ERROR("Writing %d EEPROM table records error:%d", | |
| 402 | + num, res); | |
| 403 | + } else if (res < buf_size) { | |
| 404 | + /* Short write, return error. | |
| 405 | + */ | |
| 406 | + DRM_ERROR("Wrote %d records out of %d", | |
| 407 | + res / RAS_TABLE_RECORD_SIZE, num); | |
| 408 | + res = -EIO; | |
| 409 | + } else { | |
| 410 | + res = 0; | |
| 411 | + } | |
| 485 | 412 | |
| 486 | − buffs = kcalloc(num, EEPROM_ADDRESS_SIZE + EEPROM_TABLE_RECORD_SIZE, | |
| 487 | − GFP_KERNEL); | |
| 488 | − if (!buffs) | |
| 489 | − return -ENOMEM; | |
| 413 | + return res; | |
| 414 | +} | |
| 490 | 415 | |
| 491 | − mutex_lock(&control->tbl_mutex); | |
| 416 | +static int | |
| 417 | +amdgpu_ras_eeprom_append_table(struct amdgpu_ras_eeprom_control *control, | |
| 418 | + struct eeprom_table_record *record, | |
| 419 | + const u32 num) | |
| 420 | +{ | |
| 421 | + u32 a, b, i; | |
| 422 | + u8 *buf, *pp; | |
| 423 | + int res; | |
| 424 | + | |
| 425 | + buf = kcalloc(num, RAS_TABLE_RECORD_SIZE, GFP_KERNEL); | |
| 426 | + if (!buf) | |
| 427 | + return -ENOMEM; | |
| 492 | 428 | |
| 493 | − msgs = kcalloc(num, sizeof(*msgs), GFP_KERNEL); | |
| 494 | − if (!msgs) { | |
| 495 | − ret = -ENOMEM; | |
| 496 | − goto free_buff; | |
| 429 | + /* Encode all of them in one go. | |
| 430 | + */ | |
| 431 | + pp = buf; | |
| 432 | + for (i = 0; i < num; i++, pp += RAS_TABLE_RECORD_SIZE) | |
| 433 | + __encode_table_record_to_buf(control, &record[i], pp); | |
| 434 | + | |
| 435 | + /* a, first record index to write into. | |
| 436 | + * b, last record index to write into. | |
| 437 | + * a = first index to read (fri) + number of records in the table, | |
| 438 | + * b = a + @num - 1. | |
| 439 | + * Let N = control->ras_max_num_record_count, then we have, | |
| 440 | + * case 0: 0 <= a <= b < N, | |
| 441 | + * just append @num records starting at a; | |
| 442 | + * case 1: 0 <= a < N <= b, | |
| 443 | + * append (N - a) records starting at a, and | |
| 444 | + * append the remainder, b % N + 1, starting at 0. | |
| 445 | + * case 2: 0 <= fri < N <= a <= b, then modulo N we get two subcases, | |
| 446 | + * case 2a: 0 <= a <= b < N | |
| 447 | + * append num records starting at a; and fix fri if b overwrote it, | |
| 448 | + * and since a <= b, if b overwrote it then a must've also, | |
| 449 | + * and if b didn't overwrite it, then a didn't also. | |
| 450 | + * case 2b: 0 <= b < a < N | |
| 451 | + * write num records starting at a, which wraps around 0=N | |
| 452 | + * and overwrite fri unconditionally. Now from case 2a, | |
| 453 | + * this means that b eclipsed fri to overwrite it and wrap | |
| 454 | + * around 0 again, i.e. b = 2N+r pre modulo N, so we unconditionally | |
| 455 | + * set fri = b + 1 (mod N). | |
| 456 | + * Now, since fri is updated in every case, except the trivial case 0, | |
| 457 | + * the number of records present in the table after writing, is, | |
| 458 | + * num_recs - 1 = b - fri (mod N), and we take the positive value, | |
| 459 | + * by adding an arbitrary multiple of N before taking the modulo N | |
| 460 | + * as shown below. | |
| 461 | + */ | |
| 462 | + a = control->ras_fri + control->ras_num_recs; | |
| 463 | + b = a + num - 1; | |
| 464 | + if (b < control->ras_max_record_count) { | |
| 465 | + res = __amdgpu_ras_eeprom_write(control, buf, a, num); | |
| 466 | + } else if (a < control->ras_max_record_count) { | |
| 467 | + u32 g0, g1; | |
| 468 | + | |
| 469 | + g0 = control->ras_max_record_count - a; | |
| 470 | + g1 = b % control->ras_max_record_count + 1; | |
| 471 | + res = __amdgpu_ras_eeprom_write(control, buf, a, g0); | |
| 472 | + if (res) | |
| 473 | + goto Out; | |
| 474 | + res = __amdgpu_ras_eeprom_write(control, | |
| 475 | + buf + g0 * RAS_TABLE_RECORD_SIZE, | |
| 476 | + 0, g1); | |
| 477 | + if (res) | |
| 478 | + goto Out; | |
| 479 | + if (g1 > control->ras_fri) | |
| 480 | + control->ras_fri = g1 % control->ras_max_record_count; | |
| 481 | + } else { | |
| 482 | + a %= control->ras_max_record_count; | |
| 483 | + b %= control->ras_max_record_count; | |
| 484 | + | |
| 485 | + if (a <= b) { | |
| 486 | + /* Note that, b - a + 1 = num. */ | |
| 487 | + res = __amdgpu_ras_eeprom_write(control, buf, a, num); | |
| 488 | + if (res) | |
| 489 | + goto Out; | |
| 490 | + if (b >= control->ras_fri) | |
| 491 | + control->ras_fri = (b + 1) % control->ras_max_record_count; | |
| 492 | + } else { | |
| 493 | + u32 g0, g1; | |
| 494 | + | |
| 495 | + /* b < a, which means, we write from | |
| 496 | + * a to the end of the table, and from | |
| 497 | + * the start of the table to b. | |
| 498 | + */ | |
| 499 | + g0 = control->ras_max_record_count - a; | |
| 500 | + g1 = b + 1; | |
| 501 | + res = __amdgpu_ras_eeprom_write(control, buf, a, g0); | |
| 502 | + if (res) | |
| 503 | + goto Out; | |
| 504 | + res = __amdgpu_ras_eeprom_write(control, | |
| 505 | + buf + g0 * RAS_TABLE_RECORD_SIZE, | |
| 506 | + 0, g1); | |
| 507 | + if (res) | |
| 508 | + goto Out; | |
| 509 | + control->ras_fri = g1 % control->ras_max_record_count; | |
| 510 | + } | |
| 497 | 511 | } |
| 512 | + control->ras_num_recs = 1 + (control->ras_max_record_count + b | |
| 513 | + - control->ras_fri) | |
| 514 | + % control->ras_max_record_count; | |
| 515 | +Out: | |
| 516 | + kfree(buf); | |
| 517 | + return res; | |
| 518 | +} | |
| 498 | 519 | |
| 499 | − /* | |
| 500 | − * If saved bad pages number exceeds the bad page threshold for | |
| 501 | − * the whole VRAM, update table header to mark the BAD GPU tag | |
| 502 | − * and schedule one ras recovery after eeprom write is done, | |
| 503 | − * this can avoid the missing for latest records. | |
| 504 | − * | |
| 505 | − * This new header will be picked up and checked in the bootup | |
| 506 | − * by ras recovery, which may break bootup process to notify | |
| 507 | − * user this GPU is in bad state and to retire such GPU for | |
| 508 | − * further check. | |
| 520 | +static int | |
| 521 | +amdgpu_ras_eeprom_update_header(struct amdgpu_ras_eeprom_control *control) | |
| 522 | +{ | |
| 523 | + struct amdgpu_device *adev = to_amdgpu_device(control); | |
| 524 | + struct amdgpu_ras *ras = amdgpu_ras_get_context(adev); | |
| 525 | + u8 *buf, *pp, csum; | |
| 526 | + u32 buf_size; | |
| 527 | + int res; | |
| 528 | + | |
| 529 | + /* Modify the header if it exceeds. | |
| 509 | 530 | */ |
| 510 | − if (write && (amdgpu_bad_page_threshold != 0) && | |
| 511 | − ((control->num_recs + num) >= ras->bad_page_cnt_threshold)) { | |
| 531 | + if (amdgpu_bad_page_threshold != 0 && | |
| 532 | + control->ras_num_recs >= ras->bad_page_cnt_threshold) { | |
| 512 | 533 | dev_warn(adev->dev, |
| 513 | − "Saved bad pages(%d) reaches threshold value(%d).\n", | |
| 514 | − control->num_recs + num, ras->bad_page_cnt_threshold); | |
| 515 | − control->tbl_hdr.header = EEPROM_TABLE_HDR_BAD; | |
| 534 | + "Saved bad pages %d reaches threshold value %d\n", | |
| 535 | + control->ras_num_recs, ras->bad_page_cnt_threshold); | |
| 536 | + control->tbl_hdr.header = RAS_TABLE_HDR_BAD; | |
| 537 | + } | |
| 538 | + | |
| 539 | + control->tbl_hdr.version = RAS_TABLE_VER; | |
| 540 | + control->tbl_hdr.first_rec_offset = RAS_INDEX_TO_OFFSET(control, control->ras_fri); | |
| 541 | + control->tbl_hdr.tbl_size = RAS_TABLE_HEADER_SIZE + control->ras_num_recs * RAS_TABLE_RECORD_SIZE; | |
| 542 | + control->tbl_hdr.checksum = 0; | |
| 543 | + | |
| 544 | + buf_size = control->ras_num_recs * RAS_TABLE_RECORD_SIZE; | |
| 545 | + buf = kcalloc(control->ras_num_recs, RAS_TABLE_RECORD_SIZE, GFP_KERNEL); | |
| 546 | + if (!buf) { | |
| 547 | + DRM_ERROR("allocating memory for table of size %d bytes failed\n", | |
| 548 | + control->tbl_hdr.tbl_size); | |
| 549 | + res = -ENOMEM; | |
| 550 | + goto Out; | |
| 516 | 551 | } |
| 517 | 552 | |
| 518 | − /* In case of overflow just start from beginning to not lose newest records */ | |
| 519 | − if (write && (control->next_addr + EEPROM_TABLE_RECORD_SIZE * num > EEPROM_SIZE_BYTES)) | |
| 520 | − control->next_addr = EEPROM_RECORD_START; | |
| 553 | + down_read(&adev->reset_sem); | |
| 554 | + res = amdgpu_eeprom_read(&adev->pm.smu_i2c, | |
| 555 | + control->i2c_address + | |
| 556 | + control->ras_record_offset, | |
| 557 | + buf, buf_size); | |
| 558 | + up_read(&adev->reset_sem); | |
| 559 | + if (res < 0) { | |
| 560 | + DRM_ERROR("EEPROM failed reading records:%d\n", | |
| 561 | + res); | |
| 562 | + goto Out; | |
| 563 | + } else if (res < buf_size) { | |
| 564 | + DRM_ERROR("EEPROM read %d out of %d bytes\n", | |
| 565 | + res, buf_size); | |
| 566 | + res = -EIO; | |
| 567 | + goto Out; | |
| 568 | + } | |
| 521 | 569 | |
| 522 | − /* | |
| 523 | − * TODO Currently makes EEPROM writes for each record, this creates | |
| 524 | − * internal fragmentation. Optimized the code to do full page write of | |
| 525 | − * 256b | |
| 570 | + /* Recalc the checksum. | |
| 526 | 571 | */ |
| 527 | − for (i = 0; i < num; i++) { | |
| 528 | − buff = &buffs[i * (EEPROM_ADDRESS_SIZE + EEPROM_TABLE_RECORD_SIZE)]; | |
| 529 | − record = &records[i]; | |
| 530 | − msg = &msgs[i]; | |
| 572 | + csum = 0; | |
| 573 | + for (pp = buf; pp < buf + buf_size; pp++) | |
| 574 | + csum += *pp; | |
| 575 | + | |
| 576 | + csum += __calc_hdr_byte_sum(control); | |
| 577 | + /* avoid sign extension when assigning to "checksum" */ | |
| 578 | + csum = -csum; | |
| 579 | + control->tbl_hdr.checksum = csum; | |
| 580 | + res = __write_table_header(control); | |
| 581 | +Out: | |
| 582 | + kfree(buf); | |
| 583 | + return res; | |
| 584 | +} | |
| 531 | 585 | |
| 532 | − control->next_addr = __correct_eeprom_dest_address(control->next_addr); | |
| 586 | +/** | |
| 587 | + * amdgpu_ras_eeprom_append -- append records to the EEPROM RAS table | |
| 588 | + * @control: pointer to control structure | |
| 589 | + * @record: array of records to append | |
| 590 | + * @num: number of records in @record array | |
| 591 | + * | |
| 592 | + * Append @num records to the table, calculate the checksum and write | |
| 593 | + * the table back to EEPROM. The maximum number of records that | |
| 594 | + * can be appended is between 1 and control->ras_max_record_count, | |
| 595 | + * regardless of how many records are already stored in the table. | |
| 596 | + * | |
| 597 | + * Return 0 on success or if EEPROM is not supported, -errno on error. | |
| 598 | + */ | |
| 599 | +int amdgpu_ras_eeprom_append(struct amdgpu_ras_eeprom_control *control, | |
| 600 | + struct eeprom_table_record *record, | |
| 601 | + const u32 num) | |
| 602 | +{ | |
| 603 | + struct amdgpu_device *adev = to_amdgpu_device(control); | |
| 604 | + int res; | |
| 533 | 605 | |
| 534 | − /* | |
| 535 | − * Update bits 16,17 of EEPROM address in I2C address by setting them | |
| 536 | − * to bits 1,2 of Device address byte | |
| 537 | − */ | |
| 538 | − msg->addr = control->i2c_address | | |
| 539 | − ((control->next_addr & EEPROM_ADDR_MSB_MASK) >> 15); | |
| 540 | − msg->flags = write ? 0 : I2C_M_RD; | |
| 541 | − msg->len = EEPROM_ADDRESS_SIZE + EEPROM_TABLE_RECORD_SIZE; | |
| 542 | − msg->buf = buff; | |
| 543 | − | |
| 544 | − /* Insert the EEPROM dest addess, bits 0-15 */ | |
| 545 | − buff[0] = ((control->next_addr >> 8) & 0xff); | |
| 546 | − buff[1] = (control->next_addr & 0xff); | |
| 547 | − | |
| 548 | − /* EEPROM table content is stored in LE format */ | |
| 549 | − if (write) | |
| 550 | − __encode_table_record_to_buff(control, record, buff + EEPROM_ADDRESS_SIZE); | |
| 551 | − | |
| 552 | − /* | |
| 553 | − * The destination EEPROM address might need to be corrected to account | |
| 554 | − * for page or entire memory wrapping | |
| 555 | − */ | |
| 556 | − control->next_addr += EEPROM_TABLE_RECORD_SIZE; | |
| 606 | + if (!__is_ras_eeprom_supported(adev)) | |
| 607 | + return 0; | |
| 608 | + | |
| 609 | + if (num == 0) { | |
| 610 | + DRM_ERROR("will not append 0 records\n"); | |
| 611 | + return -EINVAL; | |
| 612 | + } else if (num > control->ras_max_record_count) { | |
| 613 | + DRM_ERROR("cannot append %d records than the size of table %d\n", | |
| 614 | + num, control->ras_max_record_count); | |
| 615 | + return -EINVAL; | |
| 557 | 616 | } |
| 558 | 617 | |
| 618 | + mutex_lock(&control->ras_tbl_mutex); | |
| 619 | + | |
| 620 | + res = amdgpu_ras_eeprom_append_table(control, record, num); | |
| 621 | + if (!res) | |
| 622 | + res = amdgpu_ras_eeprom_update_header(control); | |
| 623 | + if (!res) | |
| 624 | + amdgpu_ras_debugfs_set_ret_size(control); | |
| 625 | + | |
| 626 | + mutex_unlock(&control->ras_tbl_mutex); | |
| 627 | + return res; | |
| 628 | +} | |
| 629 | + | |
| 630 | +/** | |
| 631 | + * __amdgpu_ras_eeprom_read -- read indexed from EEPROM into buffer | |
| 632 | + * @control: pointer to control structure | |
| 633 | + * @buf: pointer to buffer to read into | |
| 634 | + * @fri: first record index, start reading at this index, absolute index | |
| 635 | + * @num: number of records to read | |
| 636 | + * | |
| 637 | + * The caller must hold the table mutex in @control. | |
| 638 | + * Return 0 on success, -errno otherwise. | |
| 639 | + */ | |
| 640 | +static int __amdgpu_ras_eeprom_read(struct amdgpu_ras_eeprom_control *control, | |
| 641 | + u8 *buf, const u32 fri, const u32 num) | |
| 642 | +{ | |
| 643 | + struct amdgpu_device *adev = to_amdgpu_device(control); | |
| 644 | + u32 buf_size; | |
| 645 | + int res; | |
| 646 | + | |
| 559 | 647 | /* i2c may be unstable in gpu reset */ |
| 560 | 648 | down_read(&adev->reset_sem); |
| 561 | − ret = i2c_transfer(&adev->pm.smu_i2c, msgs, num); | |
| 649 | + buf_size = num * RAS_TABLE_RECORD_SIZE; | |
| 650 | + res = amdgpu_eeprom_read(&adev->pm.smu_i2c, | |
| 651 | + control->i2c_address + | |
| 652 | + RAS_INDEX_TO_OFFSET(control, fri), | |
| 653 | + buf, buf_size); | |
| 562 | 654 | up_read(&adev->reset_sem); |
| 655 | + if (res < 0) { | |
| 656 | + DRM_ERROR("Reading %d EEPROM table records error:%d", | |
| 657 | + num, res); | |
| 658 | + } else if (res < buf_size) { | |
| 659 | + /* Short read, return error. | |
| 660 | + */ | |
| 661 | + DRM_ERROR("Read %d records out of %d", | |
| 662 | + res / RAS_TABLE_RECORD_SIZE, num); | |
| 663 | + res = -EIO; | |
| 664 | + } else { | |
| 665 | + res = 0; | |
| 666 | + } | |
| 667 | + | |
| 668 | + return res; | |
| 669 | +} | |
| 670 | + | |
| 671 | +/** | |
| 672 | + * amdgpu_ras_eeprom_read -- read EEPROM | |
| 673 | + * @control: pointer to control structure | |
| 674 | + * @record: array of records to read into | |
| 675 | + * @num: number of records in @record | |
| 676 | + * | |
| 677 | + * Reads num records from the RAS table in EEPROM and | |
| 678 | + * writes the data into @record array. | |
| 679 | + * | |
| 680 | + * Returns 0 on success, -errno on error. | |
| 681 | + */ | |
| 682 | +int amdgpu_ras_eeprom_read(struct amdgpu_ras_eeprom_control *control, | |
| 683 | + struct eeprom_table_record *record, | |
| 684 | + const u32 num) | |
| 685 | +{ | |
| 686 | + struct amdgpu_device *adev = to_amdgpu_device(control); | |
| 687 | + int i, res; | |
| 688 | + u8 *buf, *pp; | |
| 689 | + u32 g0, g1; | |
| 563 | 690 | |
| 564 | − if (ret < 1) { | |
| 565 | − DRM_ERROR("Failed to process EEPROM table records, ret:%d", ret); | |
| 691 | + if (!__is_ras_eeprom_supported(adev)) | |
| 692 | + return 0; | |
| 566 | 693 | |
| 567 | − /* TODO Restore prev next EEPROM address ? */ | |
| 568 | − goto free_msgs; | |
| 694 | + if (num == 0) { | |
| 695 | + DRM_ERROR("will not read 0 records\n"); | |
| 696 | + return -EINVAL; | |
| 697 | + } else if (num > control->ras_num_recs) { | |
| 698 | + DRM_ERROR("too many records to read:%d available:%d\n", | |
| 699 | + num, control->ras_num_recs); | |
| 700 | + return -EINVAL; | |
| 569 | 701 | } |
| 570 | 702 | |
| 703 | + buf = kcalloc(num, RAS_TABLE_RECORD_SIZE, GFP_KERNEL); | |
| 704 | + if (!buf) | |
| 705 | + return -ENOMEM; | |
| 571 | 706 | |
| 572 | − if (!write) { | |
| 573 | − for (i = 0; i < num; i++) { | |
| 574 | − buff = &buffs[i*(EEPROM_ADDRESS_SIZE + EEPROM_TABLE_RECORD_SIZE)]; | |
| 575 | − record = &records[i]; | |
| 707 | + /* Determine how many records to read, from the first record | |
| 708 | + * index, fri, to the end of the table, and from the beginning | |
| 709 | + * of the table, such that the total number of records is | |
| 710 | + * @num, and we handle wrap around when fri > 0 and | |
| 711 | + * fri + num > RAS_MAX_RECORD_COUNT. | |
| 712 | + * | |
| 713 | + * First we compute the index of the last element | |
| 714 | + * which would be fetched from each region, | |
| 715 | + * g0 is in [fri, fri + num - 1], and | |
| 716 | + * g1 is in [0, RAS_MAX_RECORD_COUNT - 1]. | |
| 717 | + * Then, if g0 < RAS_MAX_RECORD_COUNT, the index of | |
| 718 | + * the last element to fetch, we set g0 to _the number_ | |
| 719 | + * of elements to fetch, @num, since we know that the last | |
| 720 | + * indexed to be fetched does not exceed the table. | |
| 721 | + * | |
| 722 | + * If, however, g0 >= RAS_MAX_RECORD_COUNT, then | |
| 723 | + * we set g0 to the number of elements to read | |
| 724 | + * until the end of the table, and g1 to the number of | |
| 725 | + * elements to read from the beginning of the table. | |
| 726 | + */ | |
| 727 | + g0 = control->ras_fri + num - 1; | |
| 728 | + g1 = g0 % control->ras_max_record_count; | |
| 729 | + if (g0 < control->ras_max_record_count) { | |
| 730 | + g0 = num; | |
| 731 | + g1 = 0; | |
| 732 | + } else { | |
| 733 | + g0 = control->ras_max_record_count - control->ras_fri; | |
| 734 | + g1 += 1; | |
| 735 | + } | |
| 576 | 736 | |
| 577 | − __decode_table_record_from_buff(control, record, buff + EEPROM_ADDRESS_SIZE); | |
| 578 | − } | |
| 737 | + mutex_lock(&control->ras_tbl_mutex); | |
| 738 | + res = __amdgpu_ras_eeprom_read(control, buf, control->ras_fri, g0); | |
| 739 | + if (res) | |
| 740 | + goto Out; | |
| 741 | + if (g1) { | |
| 742 | + res = __amdgpu_ras_eeprom_read(control, | |
| 743 | + buf + g0 * RAS_TABLE_RECORD_SIZE, | |
| 744 | + 0, g1); | |
| 745 | + if (res) | |
| 746 | + goto Out; | |
| 579 | 747 | } |
| 580 | 748 | |
| 581 | − if (write) { | |
| 582 | − uint32_t old_hdr_byte_sum = __calc_hdr_byte_sum(control); | |
| 749 | + res = 0; | |
| 750 | + | |
| 751 | + /* Read up everything? Then transform. | |
| 752 | + */ | |
| 753 | + pp = buf; | |
| 754 | + for (i = 0; i < num; i++, pp += RAS_TABLE_RECORD_SIZE) | |
| 755 | + __decode_table_record_from_buf(control, &record[i], pp); | |
| 756 | +Out: | |
| 757 | + kfree(buf); | |
| 758 | + mutex_unlock(&control->ras_tbl_mutex); | |
| 759 | + | |
| 760 | + return res; | |
| 761 | +} | |
| 762 | + | |
| 763 | +inline uint32_t amdgpu_ras_eeprom_max_record_count(void) | |
| 764 | +{ | |
| 765 | + return RAS_MAX_RECORD_COUNT; | |
| 766 | +} | |
| 767 | + | |
| 768 | +static ssize_t | |
| 769 | +amdgpu_ras_debugfs_eeprom_size_read(struct file *f, char __user *buf, | |
| 770 | + size_t size, loff_t *pos) | |
| 771 | +{ | |
| 772 | + struct amdgpu_device *adev = (struct amdgpu_device *)file_inode(f)->i_private; | |
| 773 | + struct amdgpu_ras *ras = amdgpu_ras_get_context(adev); | |
| 774 | + struct amdgpu_ras_eeprom_control *control = ras ? &ras->eeprom_control : NULL; | |
| 775 | + u8 data[50]; | |
| 776 | + int res; | |
| 777 | + | |
| 778 | + if (!size) | |
| 779 | + return size; | |
| 780 | + | |
| 781 | + if (!ras || !control) { | |
| 782 | + res = snprintf(data, sizeof(data), "Not supported\n"); | |
| 783 | + } else { | |
| 784 | + res = snprintf(data, sizeof(data), "%d bytes or %d records\n", | |
| 785 | + RAS_TBL_SIZE_BYTES, control->ras_max_record_count); | |
| 786 | + } | |
| 787 | + | |
| 788 | + if (*pos >= res) | |
| 789 | + return 0; | |
| 790 | + | |
| 791 | + res -= *pos; | |
| 792 | + res = min_t(size_t, res, size); | |
| 793 | + | |
| 794 | + if (copy_to_user(buf, &data[*pos], res)) | |
| 795 | + return -EFAULT; | |
| 796 | + | |
| 797 | + *pos += res; | |
| 583 | 798 | |
| 584 | − /* | |
| 585 | − * Update table header with size and CRC and account for table | |
| 586 | − * wrap around where the assumption is that we treat it as empty | |
| 587 | − * table | |
| 588 | − * | |
| 589 | − * TODO - Check the assumption is correct | |
| 799 | + return res; | |
| 800 | +} | |
| 801 | + | |
| 802 | +const struct file_operations amdgpu_ras_debugfs_eeprom_size_ops = { | |
| 803 | + .owner = THIS_MODULE, | |
| 804 | + .read = amdgpu_ras_debugfs_eeprom_size_read, | |
| 805 | + .write = NULL, | |
| 806 | + .llseek = default_llseek, | |
| 807 | +}; | |
| 808 | + | |
| 809 | +static const char *tbl_hdr_str = " Signature Version FirstOffs Size Checksum\n"; | |
| 810 | +static const char *tbl_hdr_fmt = "0x%08X 0x%08X 0x%08X 0x%08X 0x%08X\n"; | |
| 811 | +#define tbl_hdr_fmt_size (5 * (2+8) + 4 + 1) | |
| 812 | +static const char *rec_hdr_str = "Index Offset ErrType Bank/CU TimeStamp Offs/Addr MemChl MCUMCID RetiredPage\n"; | |
| 813 | +static const char *rec_hdr_fmt = "%5d 0x%05X %7s 0x%02X 0x%016llX 0x%012llX 0x%02X 0x%02X 0x%012llX\n"; | |
| 814 | +#define rec_hdr_fmt_size (5 + 1 + 7 + 1 + 7 + 1 + 7 + 1 + 18 + 1 + 14 + 1 + 6 + 1 + 7 + 1 + 14 + 1) | |
| 815 | + | |
| 816 | +static const char *record_err_type_str[AMDGPU_RAS_EEPROM_ERR_COUNT] = { | |
| 817 | + "ignore", | |
| 818 | + "re", | |
| 819 | + "ue", | |
| 820 | +}; | |
| 821 | + | |
| 822 | +static loff_t amdgpu_ras_debugfs_table_size(struct amdgpu_ras_eeprom_control *control) | |
| 823 | +{ | |
| 824 | + return strlen(tbl_hdr_str) + tbl_hdr_fmt_size + | |
| 825 | + strlen(rec_hdr_str) + rec_hdr_fmt_size * control->ras_num_recs; | |
| 826 | +} | |
| 827 | + | |
| 828 | +void amdgpu_ras_debugfs_set_ret_size(struct amdgpu_ras_eeprom_control *control) | |
| 829 | +{ | |
| 830 | + struct amdgpu_ras *ras = container_of(control, struct amdgpu_ras, | |
| 831 | + eeprom_control); | |
| 832 | + struct dentry *de = ras->de_ras_eeprom_table; | |
| 833 | + | |
| 834 | + if (de) | |
| 835 | + d_inode(de)->i_size = amdgpu_ras_debugfs_table_size(control); | |
| 836 | +} | |
| 837 | + | |
| 838 | +static ssize_t amdgpu_ras_debugfs_table_read(struct file *f, char __user *buf, | |
| 839 | + size_t size, loff_t *pos) | |
| 840 | +{ | |
| 841 | + struct amdgpu_device *adev = (struct amdgpu_device *)file_inode(f)->i_private; | |
| 842 | + struct amdgpu_ras *ras = amdgpu_ras_get_context(adev); | |
| 843 | + struct amdgpu_ras_eeprom_control *control = &ras->eeprom_control; | |
| 844 | + const size_t orig_size = size; | |
| 845 | + int res = -EFAULT; | |
| 846 | + size_t data_len; | |
| 847 | + | |
| 848 | + mutex_lock(&control->ras_tbl_mutex); | |
| 849 | + | |
| 850 | + /* We want *pos - data_len > 0, which means there's | |
| 851 | + * bytes to be printed from data. | |
| 852 | + */ | |
| 853 | + data_len = strlen(tbl_hdr_str); | |
| 854 | + if (*pos < data_len) { | |
| 855 | + data_len -= *pos; | |
| 856 | + data_len = min_t(size_t, data_len, size); | |
| 857 | + if (copy_to_user(buf, &tbl_hdr_str[*pos], data_len)) | |
| 858 | + goto Out; | |
| 859 | + buf += data_len; | |
| 860 | + size -= data_len; | |
| 861 | + *pos += data_len; | |
| 862 | + } | |
| 863 | + | |
| 864 | + data_len = strlen(tbl_hdr_str) + tbl_hdr_fmt_size; | |
| 865 | + if (*pos < data_len && size > 0) { | |
| 866 | + u8 data[tbl_hdr_fmt_size + 1]; | |
| 867 | + loff_t lpos; | |
| 868 | + | |
| 869 | + snprintf(data, sizeof(data), tbl_hdr_fmt, | |
| 870 | + control->tbl_hdr.header, | |
| 871 | + control->tbl_hdr.version, | |
| 872 | + control->tbl_hdr.first_rec_offset, | |
| 873 | + control->tbl_hdr.tbl_size, | |
| 874 | + control->tbl_hdr.checksum); | |
| 875 | + | |
| 876 | + data_len -= *pos; | |
| 877 | + data_len = min_t(size_t, data_len, size); | |
| 878 | + lpos = *pos - strlen(tbl_hdr_str); | |
| 879 | + if (copy_to_user(buf, &data[lpos], data_len)) | |
| 880 | + goto Out; | |
| 881 | + buf += data_len; | |
| 882 | + size -= data_len; | |
| 883 | + *pos += data_len; | |
| 884 | + } | |
| 885 | + | |
| 886 | + data_len = strlen(tbl_hdr_str) + tbl_hdr_fmt_size + strlen(rec_hdr_str); | |
| 887 | + if (*pos < data_len && size > 0) { | |
| 888 | + loff_t lpos; | |
| 889 | + | |
| 890 | + data_len -= *pos; | |
| 891 | + data_len = min_t(size_t, data_len, size); | |
| 892 | + lpos = *pos - strlen(tbl_hdr_str) - tbl_hdr_fmt_size; | |
| 893 | + if (copy_to_user(buf, &rec_hdr_str[lpos], data_len)) | |
| 894 | + goto Out; | |
| 895 | + buf += data_len; | |
| 896 | + size -= data_len; | |
| 897 | + *pos += data_len; | |
| 898 | + } | |
| 899 | + | |
| 900 | + data_len = amdgpu_ras_debugfs_table_size(control); | |
| 901 | + if (*pos < data_len && size > 0) { | |
| 902 | + u8 dare[RAS_TABLE_RECORD_SIZE]; | |
| 903 | + u8 data[rec_hdr_fmt_size + 1]; | |
| 904 | + struct eeprom_table_record record; | |
| 905 | + int s, r; | |
| 906 | + | |
| 907 | + /* Find the starting record index | |
| 590 | 908 | */ |
| 591 | − control->num_recs += num; | |
| 592 | − control->num_recs %= EEPROM_MAX_RECORD_NUM; | |
| 593 | − control->tbl_hdr.tbl_size += EEPROM_TABLE_RECORD_SIZE * num; | |
| 594 | − if (control->tbl_hdr.tbl_size > EEPROM_SIZE_BYTES) | |
| 595 | − control->tbl_hdr.tbl_size = EEPROM_TABLE_HEADER_SIZE + | |
| 596 | − control->num_recs * EEPROM_TABLE_RECORD_SIZE; | |
| 597 | − | |
| 598 | − __update_tbl_checksum(control, records, num, old_hdr_byte_sum); | |
| 599 | − | |
| 600 | − __update_table_header(control, buffs); | |
| 601 | − } else if (!__validate_tbl_checksum(control, records, num)) { | |
| 602 | − DRM_WARN("EEPROM Table checksum mismatch!"); | |
| 603 | − /* TODO Uncomment when EEPROM read/write is relliable */ | |
| 604 | − /* ret = -EIO; */ | |
| 909 | + s = *pos - strlen(tbl_hdr_str) - tbl_hdr_fmt_size - | |
| 910 | + strlen(rec_hdr_str); | |
| 911 | + s = s / rec_hdr_fmt_size; | |
| 912 | + r = *pos - strlen(tbl_hdr_str) - tbl_hdr_fmt_size - | |
| 913 | + strlen(rec_hdr_str); | |
| 914 | + r = r % rec_hdr_fmt_size; | |
| 915 | + | |
| 916 | + for ( ; size > 0 && s < control->ras_num_recs; s++) { | |
| 917 | + u32 ai = RAS_RI_TO_AI(control, s); | |
| 918 | + /* Read a single record | |
| 919 | + */ | |
| 920 | + res = __amdgpu_ras_eeprom_read(control, dare, ai, 1); | |
| 921 | + if (res) | |
| 922 | + goto Out; | |
| 923 | + __decode_table_record_from_buf(control, &record, dare); | |
| 924 | + snprintf(data, sizeof(data), rec_hdr_fmt, | |
| 925 | + s, | |
| 926 | + RAS_INDEX_TO_OFFSET(control, ai), | |
| 927 | + record_err_type_str[record.err_type], | |
| 928 | + record.bank, | |
| 929 | + record.ts, | |
| 930 | + record.offset, | |
| 931 | + record.mem_channel, | |
| 932 | + record.mcumc_id, | |
| 933 | + record.retired_page); | |
| 934 | + | |
| 935 | + data_len = min_t(size_t, rec_hdr_fmt_size - r, size); | |
| 936 | + if (copy_to_user(buf, &data[r], data_len)) { | |
| 937 | + res = -EFAULT; | |
| 938 | + goto Out; | |
| 939 | + } | |
| 940 | + buf += data_len; | |
| 941 | + size -= data_len; | |
| 942 | + *pos += data_len; | |
| 943 | + r = 0; | |
| 944 | + } | |
| 605 | 945 | } |
| 946 | + res = 0; | |
| 947 | +Out: | |
| 948 | + mutex_unlock(&control->ras_tbl_mutex); | |
| 949 | + return res < 0 ? res : orig_size - size; | |
| 950 | +} | |
| 606 | 951 | |
| 607 | −free_msgs: | |
| 608 | − kfree(msgs); | |
| 952 | +static ssize_t | |
| 953 | +amdgpu_ras_debugfs_eeprom_table_read(struct file *f, char __user *buf, | |
| 954 | + size_t size, loff_t *pos) | |
| 955 | +{ | |
| 956 | + struct amdgpu_device *adev = (struct amdgpu_device *)file_inode(f)->i_private; | |
| 957 | + struct amdgpu_ras *ras = amdgpu_ras_get_context(adev); | |
| 958 | + struct amdgpu_ras_eeprom_control *control = ras ? &ras->eeprom_control : NULL; | |
| 959 | + u8 data[81]; | |
| 960 | + int res; | |
| 961 | + | |
| 962 | + if (!size) | |
| 963 | + return size; | |
| 964 | + | |
| 965 | + if (!ras || !control) { | |
| 966 | + res = snprintf(data, sizeof(data), "Not supported\n"); | |
| 967 | + if (*pos >= res) | |
| 968 | + return 0; | |
| 969 | + | |
| 970 | + res -= *pos; | |
| 971 | + res = min_t(size_t, res, size); | |
| 609 | 972 | |
| 610 | −free_buff: | |
| 611 | − kfree(buffs); | |
| 973 | + if (copy_to_user(buf, &data[*pos], res)) | |
| 974 | + return -EFAULT; | |
| 612 | 975 | |
| 613 | − mutex_unlock(&control->tbl_mutex); | |
| 976 | + *pos += res; | |
| 614 | 977 | |
| 615 | − return ret == num ? 0 : -EIO; | |
| 978 | + return res; | |
| 979 | + } else { | |
| 980 | + return amdgpu_ras_debugfs_table_read(f, buf, size, pos); | |
| 981 | + } | |
| 616 | 982 | } |
| 617 | 983 | |
| 618 | −inline uint32_t amdgpu_ras_eeprom_get_record_max_length(void) | |
| 984 | +const struct file_operations amdgpu_ras_debugfs_eeprom_table_ops = { | |
| 985 | + .owner = THIS_MODULE, | |
| 986 | + .read = amdgpu_ras_debugfs_eeprom_table_read, | |
| 987 | + .write = NULL, | |
| 988 | + .llseek = default_llseek, | |
| 989 | +}; | |
| 990 | + | |
| 991 | +/** | |
| 992 | + * __verify_ras_table_checksum -- verify the RAS EEPROM table checksum | |
| 993 | + * @control: pointer to control structure | |
| 994 | + * | |
| 995 | + * Check the checksum of the stored in EEPROM RAS table. | |
| 996 | + * | |
| 997 | + * Return 0 if the checksum is correct, | |
| 998 | + * positive if it is not correct, and | |
| 999 | + * -errno on I/O error. | |
| 1000 | + */ | |
| 1001 | +static int __verify_ras_table_checksum(struct amdgpu_ras_eeprom_control *control) | |
| 619 | 1002 | { |
| 620 | − return EEPROM_MAX_RECORD_NUM; | |
| 1003 | + struct amdgpu_device *adev = to_amdgpu_device(control); | |
| 1004 | + int buf_size, res; | |
| 1005 | + u8 csum, *buf, *pp; | |
| 1006 | + | |
| 1007 | + buf_size = RAS_TABLE_HEADER_SIZE + | |
| 1008 | + control->ras_num_recs * RAS_TABLE_RECORD_SIZE; | |
| 1009 | + buf = kzalloc(buf_size, GFP_KERNEL); | |
| 1010 | + if (!buf) { | |
| 1011 | + DRM_ERROR("Out of memory checking RAS table checksum.\n"); | |
| 1012 | + return -ENOMEM; | |
| 1013 | + } | |
| 1014 | + | |
| 1015 | + res = amdgpu_eeprom_read(&adev->pm.smu_i2c, | |
| 1016 | + control->i2c_address + | |
| 1017 | + control->ras_header_offset, | |
| 1018 | + buf, buf_size); | |
| 1019 | + if (res < buf_size) { | |
| 1020 | + DRM_ERROR("Partial read for checksum, res:%d\n", res); | |
| 1021 | + /* On partial reads, return -EIO. | |
| 1022 | + */ | |
| 1023 | + if (res >= 0) | |
| 1024 | + res = -EIO; | |
| 1025 | + goto Out; | |
| 1026 | + } | |
| 1027 | + | |
| 1028 | + csum = 0; | |
| 1029 | + for (pp = buf; pp < buf + buf_size; pp++) | |
| 1030 | + csum += *pp; | |
| 1031 | +Out: | |
| 1032 | + kfree(buf); | |
| 1033 | + return res < 0 ? res : csum; | |
| 621 | 1034 | } |
| 622 | 1035 | |
| 623 | −/* Used for testing if bugs encountered */ | |
| 624 | −#if 0 | |
| 625 | −void amdgpu_ras_eeprom_test(struct amdgpu_ras_eeprom_control *control) | |
| 1036 | +int amdgpu_ras_eeprom_init(struct amdgpu_ras_eeprom_control *control, | |
| 1037 | + bool *exceed_err_limit) | |
| 626 | 1038 | { |
| 627 | − int i; | |
| 628 | − struct eeprom_table_record *recs = kcalloc(1, sizeof(*recs), GFP_KERNEL); | |
| 1039 | + struct amdgpu_device *adev = to_amdgpu_device(control); | |
| 1040 | + unsigned char buf[RAS_TABLE_HEADER_SIZE] = { 0 }; | |
| 1041 | + struct amdgpu_ras_eeprom_table_header *hdr = &control->tbl_hdr; | |
| 1042 | + struct amdgpu_ras *ras = amdgpu_ras_get_context(adev); | |
| 1043 | + int res; | |
| 1044 | + | |
| 1045 | + *exceed_err_limit = false; | |
| 1046 | + | |
| 1047 | + if (!__is_ras_eeprom_supported(adev)) | |
| 1048 | + return 0; | |
| 629 | 1049 | |
| 630 | − if (!recs) | |
| 631 | − return; | |
| 1050 | + /* Verify i2c adapter is initialized */ | |
| 1051 | + if (!adev->pm.smu_i2c.algo) | |
| 1052 | + return -ENOENT; | |
| 632 | 1053 | |
| 633 | − for (i = 0; i < 1 ; i++) { | |
| 634 | − recs[i].address = 0xdeadbeef; | |
| 635 | − recs[i].retired_page = i; | |
| 1054 | + if (!__get_eeprom_i2c_addr(adev, control)) | |
| 1055 | + return -EINVAL; | |
| 1056 | + | |
| 1057 | + control->ras_header_offset = RAS_HDR_START; | |
| 1058 | + control->ras_record_offset = RAS_RECORD_START; | |
| 1059 | + control->ras_max_record_count = RAS_MAX_RECORD_COUNT; | |
| 1060 | + mutex_init(&control->ras_tbl_mutex); | |
| 1061 | + | |
| 1062 | + /* Read the table header from EEPROM address */ | |
| 1063 | + res = amdgpu_eeprom_read(&adev->pm.smu_i2c, | |
| 1064 | + control->i2c_address + control->ras_header_offset, | |
| 1065 | + buf, RAS_TABLE_HEADER_SIZE); | |
| 1066 | + if (res < RAS_TABLE_HEADER_SIZE) { | |
| 1067 | + DRM_ERROR("Failed to read EEPROM table header, res:%d", res); | |
| 1068 | + return res >= 0 ? -EIO : res; | |
| 636 | 1069 | } |
| 637 | 1070 | |
| 638 | − if (!amdgpu_ras_eeprom_process_recods(control, recs, true, 1)) { | |
| 1071 | + __decode_table_header_from_buf(hdr, buf); | |
| 639 | 1072 | |
| 640 | − memset(recs, 0, sizeof(*recs) * 1); | |
| 1073 | + control->ras_num_recs = RAS_NUM_RECS(hdr); | |
| 1074 | + control->ras_fri = RAS_OFFSET_TO_INDEX(control, hdr->first_rec_offset); | |
| 641 | 1075 | |
| 642 | − control->next_addr = EEPROM_RECORD_START; | |
| 1076 | + if (hdr->header == RAS_TABLE_HDR_VAL) { | |
| 1077 | + DRM_DEBUG_DRIVER("Found existing EEPROM table with %d records", | |
| 1078 | + control->ras_num_recs); | |
| 1079 | + res = __verify_ras_table_checksum(control); | |
| 1080 | + if (res) | |
| 1081 | + DRM_ERROR("RAS table incorrect checksum or error:%d\n", | |
| 1082 | + res); | |
| 1083 | + } else if (hdr->header == RAS_TABLE_HDR_BAD && | |
| 1084 | + amdgpu_bad_page_threshold != 0) { | |
| 1085 | + res = __verify_ras_table_checksum(control); | |
| 1086 | + if (res) | |
| 1087 | + DRM_ERROR("RAS Table incorrect checksum or error:%d\n", | |
| 1088 | + res); | |
| 1089 | + if (ras->bad_page_cnt_threshold > control->ras_num_recs) { | |
| 1090 | + /* This means that, the threshold was increased since | |
| 1091 | + * the last time the system was booted, and now, | |
| 1092 | + * ras->bad_page_cnt_threshold - control->num_recs > 0, | |
| 1093 | + * so that at least one more record can be saved, | |
| 1094 | + * before the page count threshold is reached. | |
| 1095 | + */ | |
| 1096 | + dev_info(adev->dev, | |
| 1097 | + "records:%d threshold:%d, resetting " | |
| 1098 | + "RAS table header signature", | |
| 1099 | + control->ras_num_recs, | |
| 1100 | + ras->bad_page_cnt_threshold); | |
| 1101 | + res = amdgpu_ras_eeprom_correct_header_tag(control, | |
| 1102 | + RAS_TABLE_HDR_VAL); | |
| 1103 | + } else { | |
| 1104 | + *exceed_err_limit = true; | |
| 1105 | + dev_err(adev->dev, | |
| 1106 | + "RAS records:%d exceed threshold:%d, " | |
| 1107 | + "maybe retire this GPU?", | |
| 1108 | + control->ras_num_recs, ras->bad_page_cnt_threshold); | |
| 1109 | + } | |
| 1110 | + } else { | |
| 1111 | + DRM_INFO("Creating a new EEPROM table"); | |
| 643 | 1112 | |
| 644 | − if (!amdgpu_ras_eeprom_process_recods(control, recs, false, 1)) { | |
| 645 | − for (i = 0; i < 1; i++) | |
| 646 | − DRM_INFO("rec.address :0x%llx, rec.retired_page :%llu", | |
| 647 | − recs[i].address, recs[i].retired_page); | |
| 648 | − } else | |
| 649 | − DRM_ERROR("Failed in reading from table"); | |
| 1113 | + res = amdgpu_ras_eeprom_reset_table(control); | |
| 1114 | + } | |
| 650 | 1115 | |
| 651 | − } else | |
| 652 | − DRM_ERROR("Failed in writing to table"); | |
| 1116 | + return res < 0 ? res : 0; | |
| 653 | 1117 | } |
| 654 | −#endif | |
| @@ -28,10 +28,11 @@ · 27 unmodified lines | ||
| 28 | 28 | |
| 29 | 29 | struct amdgpu_device; |
| 30 | 30 | |
| 31 | −enum amdgpu_ras_eeprom_err_type{ | |
| 32 | − AMDGPU_RAS_EEPROM_ERR_PLACE_HOLDER, | |
| 31 | +enum amdgpu_ras_eeprom_err_type { | |
| 32 | + AMDGPU_RAS_EEPROM_ERR_NA, | |
| 33 | 33 | AMDGPU_RAS_EEPROM_ERR_RECOVERABLE, |
| 34 | − AMDGPU_RAS_EEPROM_ERR_NON_RECOVERABLE | |
| 34 | + AMDGPU_RAS_EEPROM_ERR_NON_RECOVERABLE, | |
| 35 | + AMDGPU_RAS_EEPROM_ERR_COUNT, | |
| 35 | 36 | }; |
| 36 | 37 | |
| 37 | 38 | struct amdgpu_ras_eeprom_table_header { |
| @@ -40,15 +41,45 @@ struct amdgpu_ras_eeprom_table_header { · 2 unmodified lines | ||
| 40 | 41 | uint32_t first_rec_offset; |
| 41 | 42 | uint32_t tbl_size; |
| 42 | 43 | uint32_t checksum; |
| 43 | −}__attribute__((__packed__)); | |
| 44 | +} __packed; | |
| 44 | 45 | |
| 45 | 46 | struct amdgpu_ras_eeprom_control { |
| 46 | 47 | struct amdgpu_ras_eeprom_table_header tbl_hdr; |
| 47 | − uint32_t next_addr; | |
| 48 | − unsigned int num_recs; | |
| 49 | − struct mutex tbl_mutex; | |
| 50 | − uint32_t tbl_byte_sum; | |
| 51 | − uint16_t i2c_address; // 8-bit represented address | |
| 48 | + | |
| 49 | + /* Base I2C EEPPROM 19-bit memory address, | |
| 50 | + * where the table is located. For more information, | |
| 51 | + * see top of amdgpu_eeprom.c. | |
| 52 | + */ | |
| 53 | + u32 i2c_address; | |
| 54 | + | |
| 55 | + /* The byte offset off of @i2c_address | |
| 56 | + * where the table header is found, | |
| 57 | + * and where the records start--always | |
| 58 | + * right after the header. | |
| 59 | + */ | |
| 60 | + u32 ras_header_offset; | |
| 61 | + u32 ras_record_offset; | |
| 62 | + | |
| 63 | + /* Number of records in the table. | |
| 64 | + */ | |
| 65 | + u32 ras_num_recs; | |
| 66 | + | |
| 67 | + /* First record index to read, 0-based. | |
| 68 | + * Range is [0, num_recs-1]. This is | |
| 69 | + * an absolute index, starting right after | |
| 70 | + * the table header. | |
| 71 | + */ | |
| 72 | + u32 ras_fri; | |
| 73 | + | |
| 74 | + /* Maximum possible number of records | |
| 75 | + * we could store, i.e. the maximum capacity | |
| 76 | + * of the table. | |
| 77 | + */ | |
| 78 | + u32 ras_max_record_count; | |
| 79 | + | |
| 80 | + /* Protect table access via this mutex. | |
| 81 | + */ | |
| 82 | + struct mutex ras_tbl_mutex; | |
| 52 | 83 | }; |
| 53 | 84 | |
| 54 | 85 | /* |
| @@ -74,21 +105,26 @@ struct eeprom_table_record { · 19 unmodified lines | ||
| 74 | 105 | |
| 75 | 106 | unsigned char mem_channel; |
| 76 | 107 | unsigned char mcumc_id; |
| 77 | −}__attribute__((__packed__)); | |
| 108 | +} __packed; | |
| 78 | 109 | |
| 79 | 110 | int amdgpu_ras_eeprom_init(struct amdgpu_ras_eeprom_control *control, |
| 80 | − bool *exceed_err_limit); | |
| 111 | + bool *exceed_err_limit); | |
| 112 | + | |
| 81 | 113 | int amdgpu_ras_eeprom_reset_table(struct amdgpu_ras_eeprom_control *control); |
| 82 | 114 | |
| 83 | 115 | bool amdgpu_ras_eeprom_check_err_threshold(struct amdgpu_device *adev); |
| 84 | 116 | |
| 85 | −int amdgpu_ras_eeprom_process_recods(struct amdgpu_ras_eeprom_control *control, | |
| 86 | − struct eeprom_table_record *records, | |
| 87 | − bool write, | |
| 88 | − int num); | |
| 117 | +int amdgpu_ras_eeprom_read(struct amdgpu_ras_eeprom_control *control, | |
| 118 | + struct eeprom_table_record *records, const u32 num); | |
| 119 | + | |
| 120 | +int amdgpu_ras_eeprom_append(struct amdgpu_ras_eeprom_control *control, | |
| 121 | + struct eeprom_table_record *records, const u32 num); | |
| 122 | + | |
| 123 | +inline uint32_t amdgpu_ras_eeprom_max_record_count(void); | |
| 89 | 124 | |
| 90 | −inline uint32_t amdgpu_ras_eeprom_get_record_max_length(void); | |
| 125 | +void amdgpu_ras_debugfs_set_ret_size(struct amdgpu_ras_eeprom_control *control); | |
| 91 | 126 | |
| 92 | −void amdgpu_ras_eeprom_test(struct amdgpu_ras_eeprom_control *control); | |
| 127 | +extern const struct file_operations amdgpu_ras_debugfs_eeprom_size_ops; | |
| 128 | +extern const struct file_operations amdgpu_ras_debugfs_eeprom_table_ops; | |
| 93 | 129 | |
| 94 | 130 | #endif // _AMDGPU_RAS_EEPROM_H |
| @@ -48,6 +48,9 @@ · 47 unmodified lines | ||
| 48 | 48 | #define AMDGPU_FENCE_FLAG_INT (1 << 1) |
| 49 | 49 | #define AMDGPU_FENCE_FLAG_TC_WB_ONLY (1 << 2) |
| 50 | 50 | |
| 51 | +/* fence flag bit to indicate the face is embedded in job*/ | |
| 52 | +#define AMDGPU_FENCE_FLAG_EMBED_IN_JOB_BIT (DMA_FENCE_FLAG_USER_BITS + 1) | |
| 53 | + | |
| 51 | 54 | #define to_amdgpu_ring(s) container_of((s), struct amdgpu_ring, sched) |
| 52 | 55 | |
| 53 | 56 | #define AMDGPU_IB_POOL_SIZE (1024 * 1024) |
| @@ -106,9 +109,6 @@ struct amdgpu_fence_driver { · 52 unmodified lines | ||
| 106 | 109 | struct dma_fence **fences; |
| 107 | 110 | }; |
| 108 | 111 | |
| 109 | −int amdgpu_fence_driver_init(struct amdgpu_device *adev); | |
| 110 | −void amdgpu_fence_driver_fini_hw(struct amdgpu_device *adev); | |
| 111 | −void amdgpu_fence_driver_fini_sw(struct amdgpu_device *adev); | |
| 112 | 112 | void amdgpu_fence_driver_force_completion(struct amdgpu_ring *ring); |
| 113 | 113 | |
| 114 | 114 | int amdgpu_fence_driver_init_ring(struct amdgpu_ring *ring, |
| @@ -117,9 +117,11 @@ int amdgpu_fence_driver_init_ring(struct amdgpu_ring *ring, · 2 unmodified lines | ||
| 117 | 117 | int amdgpu_fence_driver_start_ring(struct amdgpu_ring *ring, |
| 118 | 118 | struct amdgpu_irq_src *irq_src, |
| 119 | 119 | unsigned irq_type); |
| 120 | −void amdgpu_fence_driver_suspend(struct amdgpu_device *adev); | |
| 121 | −void amdgpu_fence_driver_resume(struct amdgpu_device *adev); | |
| 122 | −int amdgpu_fence_emit(struct amdgpu_ring *ring, struct dma_fence **fence, | |
| 120 | +void amdgpu_fence_driver_hw_init(struct amdgpu_device *adev); | |
| 121 | +void amdgpu_fence_driver_hw_fini(struct amdgpu_device *adev); | |
| 122 | +int amdgpu_fence_driver_sw_init(struct amdgpu_device *adev); | |
| 123 | +void amdgpu_fence_driver_sw_fini(struct amdgpu_device *adev); | |
| 124 | +int amdgpu_fence_emit(struct amdgpu_ring *ring, struct dma_fence **fence, struct amdgpu_job *job, | |
| 123 | 125 | unsigned flags); |
| 124 | 126 | int amdgpu_fence_emit_polling(struct amdgpu_ring *ring, uint32_t *s, |
| 125 | 127 | uint32_t timeout); |
| @@ -127,8 +127,8 @@ struct amdgpu_rlc_funcs { · 126 unmodified lines | ||
| 127 | 127 | void (*reset)(struct amdgpu_device *adev); |
| 128 | 128 | void (*start)(struct amdgpu_device *adev); |
| 129 | 129 | void (*update_spm_vmid)(struct amdgpu_device *adev, unsigned vmid); |
| 130 | − void (*rlcg_wreg)(struct amdgpu_device *adev, u32 offset, u32 v, u32 acc_flags, u32 hwip); | |
| 131 | − u32 (*rlcg_rreg)(struct amdgpu_device *adev, u32 offset, u32 acc_flags, u32 hwip); | |
| 130 | + void (*sriov_wreg)(struct amdgpu_device *adev, u32 offset, u32 v, u32 acc_flags, u32 hwip); | |
| 131 | + u32 (*sriov_rreg)(struct amdgpu_device *adev, u32 offset, u32 acc_flags, u32 hwip); | |
| 132 | 132 | bool (*is_rlcg_access_range)(struct amdgpu_device *adev, uint32_t reg); |
| 133 | 133 | }; |
| 134 | 134 | |
| @@ -105,7 +105,6 @@ int amdgpu_sdma_ras_late_init(struct amdgpu_device *adev, · 104 unmodified lines | ||
| 105 | 105 | adev->sdma.ras_if->block = AMDGPU_RAS_BLOCK__SDMA; |
| 106 | 106 | adev->sdma.ras_if->type = AMDGPU_RAS_ERROR__MULTI_UNCORRECTABLE; |
| 107 | 107 | adev->sdma.ras_if->sub_block_index = 0; |
| 108 | − strcpy(adev->sdma.ras_if->name, "sdma"); | |
| 109 | 108 | } |
| 110 | 109 | fs_info.head = ih_info->head = *adev->sdma.ras_if; |
| 111 | 110 | |
| @@ -80,7 +80,7 @@ void psp_securedisplay_parse_resp_status(struct psp_context *psp, · 79 unmodified lines | ||
| 80 | 80 | void psp_prep_securedisplay_cmd_buf(struct psp_context *psp, struct securedisplay_cmd **cmd, |
| 81 | 81 | enum ta_securedisplay_command command_id) |
| 82 | 82 | { |
| 83 | − *cmd = (struct securedisplay_cmd *)psp->securedisplay_context.securedisplay_shared_buf; | |
| 83 | + *cmd = (struct securedisplay_cmd *)psp->securedisplay_context.context.mem_context.shared_buf; | |
| 84 | 84 | memset(*cmd, 0, sizeof(struct securedisplay_cmd)); |
| 85 | 85 | (*cmd)->status = TA_SECUREDISPLAY_STATUS__GENERIC_FAILURE; |
| 86 | 86 | (*cmd)->cmd_id = command_id; |
| @@ -170,7 +170,7 @@ void amdgpu_securedisplay_debugfs_init(struct amdgpu_device *adev) · 83 unmodified lines | ||
| 170 | 170 | { |
| 171 | 171 | #if defined(CONFIG_DEBUG_FS) |
| 172 | 172 | |
| 173 | − if (!adev->psp.securedisplay_context.securedisplay_initialized) | |
| 173 | + if (!adev->psp.securedisplay_context.context.initialized) | |
| 174 | 174 | return; |
| 175 | 175 | |
| 176 | 176 | debugfs_create_file("securedisplay_test", S_IWUSR, adev_to_drm(adev)->primary->debugfs_root, |
| @@ -28,6 +28,8 @@ · 27 unmodified lines | ||
| 28 | 28 | * Christian König <christian.koenig@amd.com> |
| 29 | 29 | */ |
| 30 | 30 | |
| 31 | +#include <linux/dma-fence-chain.h> | |
| 32 | + | |
| 31 | 33 | #include "amdgpu.h" |
| 32 | 34 | #include "amdgpu_trace.h" |
| 33 | 35 | #include "amdgpu_amdkfd.h" |
| @@ -186,6 +188,55 @@ int amdgpu_sync_vm_fence(struct amdgpu_sync *sync, struct dma_fence *fence) · 152 unmodified lines | ||
| 186 | 188 | return amdgpu_sync_fence(sync, fence); |
| 187 | 189 | } |
| 188 | 190 | |
| 191 | +/* Determine based on the owner and mode if we should sync to a fence or not */ | |
| 192 | +static bool amdgpu_sync_test_fence(struct amdgpu_device *adev, | |
| 193 | + enum amdgpu_sync_mode mode, | |
| 194 | + void *owner, struct dma_fence *f) | |
| 195 | +{ | |
| 196 | + void *fence_owner = amdgpu_sync_get_owner(f); | |
| 197 | + | |
| 198 | + /* Always sync to moves, no matter what */ | |
| 199 | + if (fence_owner == AMDGPU_FENCE_OWNER_UNDEFINED) | |
| 200 | + return true; | |
| 201 | + | |
| 202 | + /* We only want to trigger KFD eviction fences on | |
| 203 | + * evict or move jobs. Skip KFD fences otherwise. | |
| 204 | + */ | |
| 205 | + if (fence_owner == AMDGPU_FENCE_OWNER_KFD && | |
| 206 | + owner != AMDGPU_FENCE_OWNER_UNDEFINED) | |
| 207 | + return false; | |
| 208 | + | |
| 209 | + /* Never sync to VM updates either. */ | |
| 210 | + if (fence_owner == AMDGPU_FENCE_OWNER_VM && | |
| 211 | + owner != AMDGPU_FENCE_OWNER_UNDEFINED) | |
| 212 | + return false; | |
| 213 | + | |
| 214 | + /* Ignore fences depending on the sync mode */ | |
| 215 | + switch (mode) { | |
| 216 | + case AMDGPU_SYNC_ALWAYS: | |
| 217 | + return true; | |
| 218 | + | |
| 219 | + case AMDGPU_SYNC_NE_OWNER: | |
| 220 | + if (amdgpu_sync_same_dev(adev, f) && | |
| 221 | + fence_owner == owner) | |
| 222 | + return false; | |
| 223 | + break; | |
| 224 | + | |
| 225 | + case AMDGPU_SYNC_EQ_OWNER: | |
| 226 | + if (amdgpu_sync_same_dev(adev, f) && | |
| 227 | + fence_owner != owner) | |
| 228 | + return false; | |
| 229 | + break; | |
| 230 | + | |
| 231 | + case AMDGPU_SYNC_EXPLICIT: | |
| 232 | + return false; | |
| 233 | + } | |
| 234 | + | |
| 235 | + WARN(debug_evictions && fence_owner == AMDGPU_FENCE_OWNER_KFD, | |
| 236 | + "Adding eviction fence to sync obj"); | |
| 237 | + return true; | |
| 238 | +} | |
| 239 | + | |
| 189 | 240 | /** |
| 190 | 241 | * amdgpu_sync_resv - sync to a reservation object |
| 191 | 242 | * |
| @@ -211,67 +262,34 @@ int amdgpu_sync_resv(struct amdgpu_device *adev, struct amdgpu_sync *sync, · 19 unmodified lines | ||
| 211 | 262 | |
| 212 | 263 | /* always sync to the exclusive fence */ |
| 213 | 264 | f = dma_resv_excl_fence(resv); |
| 214 | − r = amdgpu_sync_fence(sync, f); | |
| 265 | + dma_fence_chain_for_each(f, f) { | |
| 266 | + struct dma_fence_chain *chain = to_dma_fence_chain(f); | |
| 267 | + | |
| 268 | + if (amdgpu_sync_test_fence(adev, mode, owner, chain ? | |
| 269 | + chain->fence : f)) { | |
| 270 | + r = amdgpu_sync_fence(sync, f); | |
| 271 | + dma_fence_put(f); | |
| 272 | + if (r) | |
| 273 | + return r; | |
| 274 | + break; | |
| 275 | + } | |
| 276 | + } | |
| 215 | 277 | |
| 216 | 278 | flist = dma_resv_shared_list(resv); |
| 217 | − if (!flist || r) | |
| 218 | − return r; | |
| 279 | + if (!flist) | |
| 280 | + return 0; | |
| 219 | 281 | |
| 220 | 282 | for (i = 0; i < flist->shared_count; ++i) { |
| 221 | − void *fence_owner; | |
| 222 | − | |
| 223 | 283 | f = rcu_dereference_protected(flist->shared[i], |
| 224 | 284 | dma_resv_held(resv)); |
| 225 | 285 | |
| 226 | − fence_owner = amdgpu_sync_get_owner(f); | |
| 227 | − | |
| 228 | − /* Always sync to moves, no matter what */ | |
| 229 | − if (fence_owner == AMDGPU_FENCE_OWNER_UNDEFINED) { | |
| 286 | + if (amdgpu_sync_test_fence(adev, mode, owner, f)) { | |
| 230 | 287 | r = amdgpu_sync_fence(sync, f); |
| 231 | 288 | if (r) |
| 232 | − break; | |
| 233 | − } | |
| 234 | − | |
| 235 | − /* We only want to trigger KFD eviction fences on | |
| 236 | − * evict or move jobs. Skip KFD fences otherwise. | |
| 237 | − */ | |
| 238 | − if (fence_owner == AMDGPU_FENCE_OWNER_KFD && | |
| 239 | − owner != AMDGPU_FENCE_OWNER_UNDEFINED) | |
| 240 | − continue; | |
| 241 | − | |
| 242 | − /* Never sync to VM updates either. */ | |
| 243 | − if (fence_owner == AMDGPU_FENCE_OWNER_VM && | |
| 244 | − owner != AMDGPU_FENCE_OWNER_UNDEFINED) | |
| 245 | − continue; | |
| 246 | − | |
| 247 | − /* Ignore fences depending on the sync mode */ | |
| 248 | − switch (mode) { | |
| 249 | − case AMDGPU_SYNC_ALWAYS: | |
| 250 | − break; | |
| 251 | − | |
| 252 | − case AMDGPU_SYNC_NE_OWNER: | |
| 253 | − if (amdgpu_sync_same_dev(adev, f) && | |
| 254 | − fence_owner == owner) | |
| 255 | − continue; | |
| 256 | − break; | |
| 257 | − | |
| 258 | − case AMDGPU_SYNC_EQ_OWNER: | |
| 259 | − if (amdgpu_sync_same_dev(adev, f) && | |
| 260 | − fence_owner != owner) | |
| 261 | − continue; | |
| 262 | − break; | |
| 263 | − | |
| 264 | − case AMDGPU_SYNC_EXPLICIT: | |
| 265 | − continue; | |
| 289 | + return r; | |
| 266 | 290 | } |
| 267 | − | |
| 268 | − WARN(debug_evictions && fence_owner == AMDGPU_FENCE_OWNER_KFD, | |
| 269 | − "Adding eviction fence to sync obj"); | |
| 270 | − r = amdgpu_sync_fence(sync, f); | |
| 271 | − if (r) | |
| 272 | − break; | |
| 273 | 291 | } |
| 274 | − return r; | |
| 292 | + return 0; | |
| 275 | 293 | } |
| 276 | 294 | |
| 277 | 295 | /** |
| @@ -149,14 +149,16 @@ static void amdgpu_evict_flags(struct ttm_buffer_object *bo, · 148 unmodified lines | ||
| 149 | 149 | * BOs to be evicted from VRAM |
| 150 | 150 | */ |
| 151 | 151 | amdgpu_bo_placement_from_domain(abo, AMDGPU_GEM_DOMAIN_VRAM | |
| 152 | − AMDGPU_GEM_DOMAIN_GTT); | |
| 152 | + AMDGPU_GEM_DOMAIN_GTT | | |
| 153 | + AMDGPU_GEM_DOMAIN_CPU); | |
| 153 | 154 | abo->placements[0].fpfn = adev->gmc.visible_vram_size >> PAGE_SHIFT; |
| 154 | 155 | abo->placements[0].lpfn = 0; |
| 155 | 156 | abo->placement.busy_placement = &abo->placements[1]; |
| 156 | 157 | abo->placement.num_busy_placement = 1; |
| 157 | 158 | } else { |
| 158 | 159 | /* Move to GTT memory */ |
| 159 | − amdgpu_bo_placement_from_domain(abo, AMDGPU_GEM_DOMAIN_GTT); | |
| 160 | + amdgpu_bo_placement_from_domain(abo, AMDGPU_GEM_DOMAIN_GTT | | |
| 161 | + AMDGPU_GEM_DOMAIN_CPU); | |
| 160 | 162 | } |
| 161 | 163 | break; |
| 162 | 164 | case TTM_PL_TT: |
| @@ -521,7 +523,7 @@ static int amdgpu_bo_move(struct ttm_buffer_object *bo, bool evict, · 358 unmodified lines | ||
| 521 | 523 | hop->fpfn = 0; |
| 522 | 524 | hop->lpfn = 0; |
| 523 | 525 | hop->mem_type = TTM_PL_TT; |
| 524 | − hop->flags = 0; | |
| 526 | + hop->flags = TTM_PL_FLAG_TEMPORARY; | |
| 525 | 527 | return -EMULTIHOP; |
| 526 | 528 | } |
| 527 | 529 | |
| @@ -1121,7 +1123,7 @@ static int amdgpu_ttm_tt_populate(struct ttm_device *bdev, · 593 unmodified lines | ||
| 1121 | 1123 | struct amdgpu_ttm_tt *gtt = (void *)ttm; |
| 1122 | 1124 | |
| 1123 | 1125 | /* user pages are bound by amdgpu_ttm_tt_pin_userptr() */ |
| 1124 | − if (gtt && gtt->userptr) { | |
| 1126 | + if (gtt->userptr) { | |
| 1125 | 1127 | ttm->sg = kzalloc(sizeof(struct sg_table), GFP_KERNEL); |
| 1126 | 1128 | if (!ttm->sg) |
| 1127 | 1129 | return -ENOMEM; |
| @@ -1146,7 +1148,7 @@ static void amdgpu_ttm_tt_unpopulate(struct ttm_device *bdev, · 18 unmodified lines | ||
| 1146 | 1148 | struct amdgpu_ttm_tt *gtt = (void *)ttm; |
| 1147 | 1149 | struct amdgpu_device *adev; |
| 1148 | 1150 | |
| 1149 | − if (gtt && gtt->userptr) { | |
| 1151 | + if (gtt->userptr) { | |
| 1150 | 1152 | amdgpu_ttm_tt_set_user_pages(ttm, NULL); |
| 1151 | 1153 | kfree(ttm->sg); |
| 1152 | 1154 | ttm->sg = NULL; |
| @@ -1394,6 +1396,41 @@ static bool amdgpu_ttm_bo_eviction_valuable(struct ttm_buffer_object *bo, · 241 unmodified lines | ||
| 1394 | 1396 | return ttm_bo_eviction_valuable(bo, place); |
| 1395 | 1397 | } |
| 1396 | 1398 | |
| 1399 | +static void amdgpu_ttm_vram_mm_access(struct amdgpu_device *adev, loff_t pos, | |
| 1400 | + void *buf, size_t size, bool write) | |
| 1401 | +{ | |
| 1402 | + while (size) { | |
| 1403 | + uint64_t aligned_pos = ALIGN_DOWN(pos, 4); | |
| 1404 | + uint64_t bytes = 4 - (pos & 0x3); | |
| 1405 | + uint32_t shift = (pos & 0x3) * 8; | |
| 1406 | + uint32_t mask = 0xffffffff << shift; | |
| 1407 | + uint32_t value = 0; | |
| 1408 | + | |
| 1409 | + if (size < bytes) { | |
| 1410 | + mask &= 0xffffffff >> (bytes - size) * 8; | |
| 1411 | + bytes = size; | |
| 1412 | + } | |
| 1413 | + | |
| 1414 | + if (mask != 0xffffffff) { | |
| 1415 | + amdgpu_device_mm_access(adev, aligned_pos, &value, 4, false); | |
| 1416 | + if (write) { | |
| 1417 | + value &= ~mask; | |
| 1418 | + value |= (*(uint32_t *)buf << shift) & mask; | |
| 1419 | + amdgpu_device_mm_access(adev, aligned_pos, &value, 4, true); | |
| 1420 | + } else { | |
| 1421 | + value = (value & mask) >> shift; | |
| 1422 | + memcpy(buf, &value, bytes); | |
| 1423 | + } | |
| 1424 | + } else { | |
| 1425 | + amdgpu_device_mm_access(adev, aligned_pos, buf, 4, write); | |
| 1426 | + } | |
| 1427 | + | |
| 1428 | + pos += bytes; | |
| 1429 | + buf += bytes; | |
| 1430 | + size -= bytes; | |
| 1431 | + } | |
| 1432 | +} | |
| 1433 | + | |
| 1397 | 1434 | /** |
| 1398 | 1435 | * amdgpu_ttm_access_memory - Read or Write memory that backs a buffer object. |
| 1399 | 1436 | * |
| @@ -1413,8 +1450,6 @@ static int amdgpu_ttm_access_memory(struct ttm_buffer_object *bo, · 13 unmodified lines | ||
| 1413 | 1450 | struct amdgpu_bo *abo = ttm_to_amdgpu_bo(bo); |
| 1414 | 1451 | struct amdgpu_device *adev = amdgpu_ttm_adev(abo->tbo.bdev); |
| 1415 | 1452 | struct amdgpu_res_cursor cursor; |
| 1416 | − unsigned long flags; | |
| 1417 | − uint32_t value = 0; | |
| 1418 | 1453 | int ret = 0; |
| 1419 | 1454 | |
| 1420 | 1455 | if (bo->resource->mem_type != TTM_PL_VRAM) |
| @@ -1422,41 +1457,21 @@ static int amdgpu_ttm_access_memory(struct ttm_buffer_object *bo, · 1 unmodified line | ||
| 1422 | 1457 | |
| 1423 | 1458 | amdgpu_res_first(bo->resource, offset, len, &cursor); |
| 1424 | 1459 | while (cursor.remaining) { |
| 1425 | − uint64_t aligned_pos = cursor.start & ~(uint64_t)3; | |
| 1426 | − uint64_t bytes = 4 - (cursor.start & 3); | |
| 1427 | − uint32_t shift = (cursor.start & 3) * 8; | |
| 1428 | − uint32_t mask = 0xffffffff << shift; | |
| 1429 | − | |
| 1430 | − if (cursor.size < bytes) { | |
| 1431 | − mask &= 0xffffffff >> (bytes - cursor.size) * 8; | |
| 1432 | − bytes = cursor.size; | |
| 1433 | − } | |
| 1434 | − | |
| 1435 | − if (mask != 0xffffffff) { | |
| 1436 | − spin_lock_irqsave(&adev->mmio_idx_lock, flags); | |
| 1437 | − WREG32_NO_KIQ(mmMM_INDEX, ((uint32_t)aligned_pos) | 0x80000000); | |
| 1438 | − WREG32_NO_KIQ(mmMM_INDEX_HI, aligned_pos >> 31); | |
| 1439 | − value = RREG32_NO_KIQ(mmMM_DATA); | |
| 1440 | − if (write) { | |
| 1441 | − value &= ~mask; | |
| 1442 | − value |= (*(uint32_t *)buf << shift) & mask; | |
| 1443 | − WREG32_NO_KIQ(mmMM_DATA, value); | |
| 1444 | − } | |
| 1445 | − spin_unlock_irqrestore(&adev->mmio_idx_lock, flags); | |
| 1446 | − if (!write) { | |
| 1447 | − value = (value & mask) >> shift; | |
| 1448 | − memcpy(buf, &value, bytes); | |
| 1449 | − } | |
| 1450 | − } else { | |
| 1451 | − bytes = cursor.size & ~0x3ULL; | |
| 1452 | − amdgpu_device_vram_access(adev, cursor.start, | |
| 1453 | − (uint32_t *)buf, bytes, | |
| 1454 | − write); | |
| 1460 | + size_t count, size = cursor.size; | |
| 1461 | + loff_t pos = cursor.start; | |
| 1462 | + | |
| 1463 | + count = amdgpu_device_aper_access(adev, pos, buf, size, write); | |
| 1464 | + size -= count; | |
| 1465 | + if (size) { | |
| 1466 | + /* using MM to access rest vram and handle un-aligned address */ | |
| 1467 | + pos += count; | |
| 1468 | + buf += count; | |
| 1469 | + amdgpu_ttm_vram_mm_access(adev, pos, buf, size, write); | |
| 1455 | 1470 | } |
| 1456 | 1471 | |
| 1457 | − ret += bytes; | |
| 1458 | − buf = (uint8_t *)buf + bytes; | |
| 1459 | − amdgpu_res_next(&cursor, bytes); | |
| 1472 | + ret += cursor.size; | |
| 1473 | + buf += cursor.size; | |
| 1474 | + amdgpu_res_next(&cursor, cursor.size); | |
| 1460 | 1475 | } |
| 1461 | 1476 | |
| 1462 | 1477 | return ret; |
| @@ -2146,7 +2161,6 @@ static ssize_t amdgpu_ttm_vram_write(struct file *f, const char __user *buf, · 683 unmodified lines | ||
| 2146 | 2161 | return -ENXIO; |
| 2147 | 2162 | |
| 2148 | 2163 | while (size) { |
| 2149 | − unsigned long flags; | |
| 2150 | 2164 | uint32_t value; |
| 2151 | 2165 | |
| 2152 | 2166 | if (*pos >= adev->gmc.mc_vram_size) |
| @@ -2156,11 +2170,7 @@ static ssize_t amdgpu_ttm_vram_write(struct file *f, const char __user *buf, · 3 unmodified lines | ||
| 2156 | 2170 | if (r) |
| 2157 | 2171 | return r; |
| 2158 | 2172 | |
| 2159 | − spin_lock_irqsave(&adev->mmio_idx_lock, flags); | |
| 2160 | − WREG32_NO_KIQ(mmMM_INDEX, ((uint32_t)*pos) | 0x80000000); | |
| 2161 | − WREG32_NO_KIQ(mmMM_INDEX_HI, *pos >> 31); | |
| 2162 | − WREG32_NO_KIQ(mmMM_DATA, value); | |
| 2163 | − spin_unlock_irqrestore(&adev->mmio_idx_lock, flags); | |
| 2173 | + amdgpu_device_mm_access(adev, *pos, &value, 4, true); | |
| 2164 | 2174 | |
| 2165 | 2175 | result += 4; |
| 2166 | 2176 | buf += 4; |
| @@ -52,7 +52,7 @@ struct amdgpu_gtt_mgr { · 51 unmodified lines | ||
| 52 | 52 | struct ttm_resource_manager manager; |
| 53 | 53 | struct drm_mm mm; |
| 54 | 54 | spinlock_t lock; |
| 55 | − atomic64_t available; | |
| 55 | + atomic64_t used; | |
| 56 | 56 | }; |
| 57 | 57 | |
| 58 | 58 | struct amdgpu_preempt_mgr { |
| @@ -409,6 +409,12 @@ amdgpu_ucode_get_load_type(struct amdgpu_device *adev, int load_type) · 408 unmodified lines | ||
| 409 | 409 | return AMDGPU_FW_LOAD_DIRECT; |
| 410 | 410 | else |
| 411 | 411 | return AMDGPU_FW_LOAD_PSP; |
| 412 | + case CHIP_CYAN_SKILLFISH: | |
| 413 | + if (!(load_type && | |
| 414 | + adev->apu_flags & AMD_APU_IS_CYAN_SKILLFISH2)) | |
| 415 | + return AMDGPU_FW_LOAD_DIRECT; | |
| 416 | + else | |
| 417 | + return AMDGPU_FW_LOAD_PSP; | |
| 412 | 418 | default: |
| 413 | 419 | DRM_ERROR("Unknown firmware load type\n"); |
| 414 | 420 | } |
| @@ -416,6 +422,84 @@ amdgpu_ucode_get_load_type(struct amdgpu_device *adev, int load_type) · 1 unmodified line | ||
| 416 | 422 | return AMDGPU_FW_LOAD_DIRECT; |
| 417 | 423 | } |
| 418 | 424 | |
| 425 | +const char *amdgpu_ucode_name(enum AMDGPU_UCODE_ID ucode_id) | |
| 426 | +{ | |
| 427 | + switch (ucode_id) { | |
| 428 | + case AMDGPU_UCODE_ID_SDMA0: | |
| 429 | + return "SDMA0"; | |
| 430 | + case AMDGPU_UCODE_ID_SDMA1: | |
| 431 | + return "SDMA1"; | |
| 432 | + case AMDGPU_UCODE_ID_SDMA2: | |
| 433 | + return "SDMA2"; | |
| 434 | + case AMDGPU_UCODE_ID_SDMA3: | |
| 435 | + return "SDMA3"; | |
| 436 | + case AMDGPU_UCODE_ID_SDMA4: | |
| 437 | + return "SDMA4"; | |
| 438 | + case AMDGPU_UCODE_ID_SDMA5: | |
| 439 | + return "SDMA5"; | |
| 440 | + case AMDGPU_UCODE_ID_SDMA6: | |
| 441 | + return "SDMA6"; | |
| 442 | + case AMDGPU_UCODE_ID_SDMA7: | |
| 443 | + return "SDMA7"; | |
| 444 | + case AMDGPU_UCODE_ID_CP_CE: | |
| 445 | + return "CP_CE"; | |
| 446 | + case AMDGPU_UCODE_ID_CP_PFP: | |
| 447 | + return "CP_PFP"; | |
| 448 | + case AMDGPU_UCODE_ID_CP_ME: | |
| 449 | + return "CP_ME"; | |
| 450 | + case AMDGPU_UCODE_ID_CP_MEC1: | |
| 451 | + return "CP_MEC1"; | |
| 452 | + case AMDGPU_UCODE_ID_CP_MEC1_JT: | |
| 453 | + return "CP_MEC1_JT"; | |
| 454 | + case AMDGPU_UCODE_ID_CP_MEC2: | |
| 455 | + return "CP_MEC2"; | |
| 456 | + case AMDGPU_UCODE_ID_CP_MEC2_JT: | |
| 457 | + return "CP_MEC2_JT"; | |
| 458 | + case AMDGPU_UCODE_ID_CP_MES: | |
| 459 | + return "CP_MES"; | |
| 460 | + case AMDGPU_UCODE_ID_CP_MES_DATA: | |
| 461 | + return "CP_MES_DATA"; | |
| 462 | + case AMDGPU_UCODE_ID_RLC_RESTORE_LIST_CNTL: | |
| 463 | + return "RLC_RESTORE_LIST_CNTL"; | |
| 464 | + case AMDGPU_UCODE_ID_RLC_RESTORE_LIST_GPM_MEM: | |
| 465 | + return "RLC_RESTORE_LIST_GPM_MEM"; | |
| 466 | + case AMDGPU_UCODE_ID_RLC_RESTORE_LIST_SRM_MEM: | |
| 467 | + return "RLC_RESTORE_LIST_SRM_MEM"; | |
| 468 | + case AMDGPU_UCODE_ID_RLC_IRAM: | |
| 469 | + return "RLC_IRAM"; | |
| 470 | + case AMDGPU_UCODE_ID_RLC_DRAM: | |
| 471 | + return "RLC_DRAM"; | |
| 472 | + case AMDGPU_UCODE_ID_RLC_G: | |
| 473 | + return "RLC_G"; | |
| 474 | + case AMDGPU_UCODE_ID_STORAGE: | |
| 475 | + return "STORAGE"; | |
| 476 | + case AMDGPU_UCODE_ID_SMC: | |
| 477 | + return "SMC"; | |
| 478 | + case AMDGPU_UCODE_ID_UVD: | |
| 479 | + return "UVD"; | |
| 480 | + case AMDGPU_UCODE_ID_UVD1: | |
| 481 | + return "UVD1"; | |
| 482 | + case AMDGPU_UCODE_ID_VCE: | |
| 483 | + return "VCE"; | |
| 484 | + case AMDGPU_UCODE_ID_VCN: | |
| 485 | + return "VCN"; | |
| 486 | + case AMDGPU_UCODE_ID_VCN1: | |
| 487 | + return "VCN1"; | |
| 488 | + case AMDGPU_UCODE_ID_DMCU_ERAM: | |
| 489 | + return "DMCU_ERAM"; | |
| 490 | + case AMDGPU_UCODE_ID_DMCU_INTV: | |
| 491 | + return "DMCU_INTV"; | |
| 492 | + case AMDGPU_UCODE_ID_VCN0_RAM: | |
| 493 | + return "VCN0_RAM"; | |
| 494 | + case AMDGPU_UCODE_ID_VCN1_RAM: | |
| 495 | + return "VCN1_RAM"; | |
| 496 | + case AMDGPU_UCODE_ID_DMCUB: | |
| 497 | + return "DMCUB"; | |
| 498 | + default: | |
| 499 | + return "UNKNOWN UCODE"; | |
| 500 | + } | |
| 501 | +} | |
| 502 | + | |
| 419 | 503 | #define FW_VERSION_ATTR(name, mode, field) \ |
| 420 | 504 | static ssize_t show_##name(struct device *dev, \ |
| 421 | 505 | struct device_attribute *attr, \ |
| @@ -440,10 +524,10 @@ FW_VERSION_ATTR(rlc_srlg_fw_version, 0444, gfx.rlc_srlg_fw_version); · 18 unmodified lines | ||
| 440 | 524 | FW_VERSION_ATTR(rlc_srls_fw_version, 0444, gfx.rlc_srls_fw_version); |
| 441 | 525 | FW_VERSION_ATTR(mec_fw_version, 0444, gfx.mec_fw_version); |
| 442 | 526 | FW_VERSION_ATTR(mec2_fw_version, 0444, gfx.mec2_fw_version); |
| 443 | −FW_VERSION_ATTR(sos_fw_version, 0444, psp.sos_fw_version); | |
| 444 | −FW_VERSION_ATTR(asd_fw_version, 0444, psp.asd_fw_version); | |
| 445 | −FW_VERSION_ATTR(ta_ras_fw_version, 0444, psp.ta_ras_ucode_version); | |
| 446 | −FW_VERSION_ATTR(ta_xgmi_fw_version, 0444, psp.ta_xgmi_ucode_version); | |
| 527 | +FW_VERSION_ATTR(sos_fw_version, 0444, psp.sos.fw_version); | |
| 528 | +FW_VERSION_ATTR(asd_fw_version, 0444, psp.asd.fw_version); | |
| 529 | +FW_VERSION_ATTR(ta_ras_fw_version, 0444, psp.ras.feature_version); | |
| 530 | +FW_VERSION_ATTR(ta_xgmi_fw_version, 0444, psp.xgmi.feature_version); | |
| 447 | 531 | FW_VERSION_ATTR(smc_fw_version, 0444, pm.fw_version); |
| 448 | 532 | FW_VERSION_ATTR(sdma_fw_version, 0444, sdma.instance[0].fw_version); |
| 449 | 533 | FW_VERSION_ATTR(sdma2_fw_version, 0444, sdma.instance[1].fw_version); |
| @@ -71,7 +71,7 @@ struct smc_firmware_header_v2_1 { · 70 unmodified lines | ||
| 71 | 71 | uint32_t pptable_entry_offset; |
| 72 | 72 | }; |
| 73 | 73 | |
| 74 | −struct psp_fw_bin_desc { | |
| 74 | +struct psp_fw_legacy_bin_desc { | |
| 75 | 75 | uint32_t fw_version; |
| 76 | 76 | uint32_t offset_bytes; |
| 77 | 77 | uint32_t size_bytes; |
| @@ -80,50 +80,67 @@ struct psp_fw_bin_desc { · 2 unmodified lines | ||
| 80 | 80 | /* version_major=1, version_minor=0 */ |
| 81 | 81 | struct psp_firmware_header_v1_0 { |
| 82 | 82 | struct common_firmware_header header; |
| 83 | − struct psp_fw_bin_desc sos; | |
| 83 | + struct psp_fw_legacy_bin_desc sos; | |
| 84 | 84 | }; |
| 85 | 85 | |
| 86 | 86 | /* version_major=1, version_minor=1 */ |
| 87 | 87 | struct psp_firmware_header_v1_1 { |
| 88 | 88 | struct psp_firmware_header_v1_0 v1_0; |
| 89 | − struct psp_fw_bin_desc toc; | |
| 90 | − struct psp_fw_bin_desc kdb; | |
| 89 | + struct psp_fw_legacy_bin_desc toc; | |
| 90 | + struct psp_fw_legacy_bin_desc kdb; | |
| 91 | 91 | }; |
| 92 | 92 | |
| 93 | 93 | /* version_major=1, version_minor=2 */ |
| 94 | 94 | struct psp_firmware_header_v1_2 { |
| 95 | 95 | struct psp_firmware_header_v1_0 v1_0; |
| 96 | − struct psp_fw_bin_desc res; | |
| 97 | − struct psp_fw_bin_desc kdb; | |
| 96 | + struct psp_fw_legacy_bin_desc res; | |
| 97 | + struct psp_fw_legacy_bin_desc kdb; | |
| 98 | 98 | }; |
| 99 | 99 | |
| 100 | 100 | /* version_major=1, version_minor=3 */ |
| 101 | 101 | struct psp_firmware_header_v1_3 { |
| 102 | 102 | struct psp_firmware_header_v1_1 v1_1; |
| 103 | − struct psp_fw_bin_desc spl; | |
| 104 | − struct psp_fw_bin_desc rl; | |
| 105 | − struct psp_fw_bin_desc sys_drv_aux; | |
| 106 | − struct psp_fw_bin_desc sos_aux; | |
| 103 | + struct psp_fw_legacy_bin_desc spl; | |
| 104 | + struct psp_fw_legacy_bin_desc rl; | |
| 105 | + struct psp_fw_legacy_bin_desc sys_drv_aux; | |
| 106 | + struct psp_fw_legacy_bin_desc sos_aux; | |
| 107 | +}; | |
| 108 | + | |
| 109 | +struct psp_fw_bin_desc { | |
| 110 | + uint32_t fw_type; | |
| 111 | + uint32_t fw_version; | |
| 112 | + uint32_t offset_bytes; | |
| 113 | + uint32_t size_bytes; | |
| 114 | +}; | |
| 115 | + | |
| 116 | +enum psp_fw_type { | |
| 117 | + PSP_FW_TYPE_UNKOWN, | |
| 118 | + PSP_FW_TYPE_PSP_SOS, | |
| 119 | + PSP_FW_TYPE_PSP_SYS_DRV, | |
| 120 | + PSP_FW_TYPE_PSP_KDB, | |
| 121 | + PSP_FW_TYPE_PSP_TOC, | |
| 122 | + PSP_FW_TYPE_PSP_SPL, | |
| 123 | + PSP_FW_TYPE_PSP_RL, | |
| 124 | + PSP_FW_TYPE_PSP_SOC_DRV, | |
| 125 | + PSP_FW_TYPE_PSP_INTF_DRV, | |
| 126 | + PSP_FW_TYPE_PSP_DBG_DRV, | |
| 127 | +}; | |
| 128 | + | |
| 129 | +/* version_major=2, version_minor=0 */ | |
| 130 | +struct psp_firmware_header_v2_0 { | |
| 131 | + struct common_firmware_header header; | |
| 132 | + uint32_t psp_fw_bin_count; | |
| 133 | + struct psp_fw_bin_desc psp_fw_bin[]; | |
| 107 | 134 | }; |
| 108 | 135 | |
| 109 | 136 | /* version_major=1, version_minor=0 */ |
| 110 | 137 | struct ta_firmware_header_v1_0 { |
| 111 | 138 | struct common_firmware_header header; |
| 112 | − uint32_t ta_xgmi_ucode_version; | |
| 113 | − uint32_t ta_xgmi_offset_bytes; | |
| 114 | − uint32_t ta_xgmi_size_bytes; | |
| 115 | − uint32_t ta_ras_ucode_version; | |
| 116 | − uint32_t ta_ras_offset_bytes; | |
| 117 | − uint32_t ta_ras_size_bytes; | |
| 118 | − uint32_t ta_hdcp_ucode_version; | |
| 119 | − uint32_t ta_hdcp_offset_bytes; | |
| 120 | − uint32_t ta_hdcp_size_bytes; | |
| 121 | − uint32_t ta_dtm_ucode_version; | |
| 122 | − uint32_t ta_dtm_offset_bytes; | |
| 123 | − uint32_t ta_dtm_size_bytes; | |
| 124 | − uint32_t ta_securedisplay_ucode_version; | |
| 125 | − uint32_t ta_securedisplay_offset_bytes; | |
| 126 | − uint32_t ta_securedisplay_size_bytes; | |
| 139 | + struct psp_fw_legacy_bin_desc xgmi; | |
| 140 | + struct psp_fw_legacy_bin_desc ras; | |
| 141 | + struct psp_fw_legacy_bin_desc hdcp; | |
| 142 | + struct psp_fw_legacy_bin_desc dtm; | |
| 143 | + struct psp_fw_legacy_bin_desc securedisplay; | |
| 127 | 144 | }; |
| 128 | 145 | |
| 129 | 146 | enum ta_fw_type { |
| @@ -138,18 +155,11 @@ enum ta_fw_type { · 8 unmodified lines | ||
| 138 | 155 | TA_FW_TYPE_MAX_INDEX, |
| 139 | 156 | }; |
| 140 | 157 | |
| 141 | −struct ta_fw_bin_desc { | |
| 142 | − uint32_t fw_type; | |
| 143 | − uint32_t fw_version; | |
| 144 | − uint32_t offset_bytes; | |
| 145 | − uint32_t size_bytes; | |
| 146 | −}; | |
| 147 | − | |
| 148 | 158 | /* version_major=2, version_minor=0 */ |
| 149 | 159 | struct ta_firmware_header_v2_0 { |
| 150 | 160 | struct common_firmware_header header; |
| 151 | 161 | uint32_t ta_fw_bin_count; |
| 152 | − struct ta_fw_bin_desc ta_fw_bin[]; | |
| 162 | + struct psp_fw_bin_desc ta_fw_bin[]; | |
| 153 | 163 | }; |
| 154 | 164 | |
| 155 | 165 | /* version_major=1, version_minor=0 */ |
| @@ -312,6 +322,7 @@ union amdgpu_firmware_header { · 156 unmodified lines | ||
| 312 | 322 | struct psp_firmware_header_v1_0 psp; |
| 313 | 323 | struct psp_firmware_header_v1_1 psp_v1_1; |
| 314 | 324 | struct psp_firmware_header_v1_3 psp_v1_3; |
| 325 | + struct psp_firmware_header_v2_0 psp_v2_0; | |
| 315 | 326 | struct ta_firmware_header_v1_0 ta; |
| 316 | 327 | struct ta_firmware_header_v2_0 ta_v2_0; |
| 317 | 328 | struct gfx_firmware_header_v1_0 gfx; |
| @@ -326,7 +337,7 @@ union amdgpu_firmware_header { · 8 unmodified lines | ||
| 326 | 337 | uint8_t raw[0x100]; |
| 327 | 338 | }; |
| 328 | 339 | |
| 329 | −#define UCODE_MAX_TA_PACKAGING ((sizeof(union amdgpu_firmware_header) - sizeof(struct common_firmware_header) - 4) / sizeof(struct ta_fw_bin_desc)) | |
| 340 | +#define UCODE_MAX_PSP_PACKAGING ((sizeof(union amdgpu_firmware_header) - sizeof(struct common_firmware_header) - 4) / sizeof(struct psp_fw_bin_desc)) | |
| 330 | 341 | |
| 331 | 342 | /* |
| 332 | 343 | * fw loading support |
| @@ -449,4 +460,6 @@ void amdgpu_ucode_sysfs_fini(struct amdgpu_device *adev); · 116 unmodified lines | ||
| 449 | 460 | enum amdgpu_firmware_load_type |
| 450 | 461 | amdgpu_ucode_get_load_type(struct amdgpu_device *adev, int load_type); |
| 451 | 462 | |
| 463 | +const char *amdgpu_ucode_name(enum AMDGPU_UCODE_ID ucode_id); | |
| 464 | + | |
| 452 | 465 | #endif |
| @@ -41,7 +41,6 @@ int amdgpu_umc_ras_late_init(struct amdgpu_device *adev) · 40 unmodified lines | ||
| 41 | 41 | adev->umc.ras_if->block = AMDGPU_RAS_BLOCK__UMC; |
| 42 | 42 | adev->umc.ras_if->type = AMDGPU_RAS_ERROR__MULTI_UNCORRECTABLE; |
| 43 | 43 | adev->umc.ras_if->sub_block_index = 0; |
| 44 | − strcpy(adev->umc.ras_if->name, "umc"); | |
| 45 | 44 | } |
| 46 | 45 | ih_info.head = fs_info.head = *adev->umc.ras_if; |
| 47 | 46 | |
| @@ -134,7 +133,7 @@ int amdgpu_umc_process_ras_data_cb(struct amdgpu_device *adev, · 86 unmodified lines | ||
| 134 | 133 | amdgpu_ras_save_bad_pages(adev); |
| 135 | 134 | |
| 136 | 135 | if (adev->smu.ppt_funcs && adev->smu.ppt_funcs->send_hbm_bad_pages_num) |
| 137 | − adev->smu.ppt_funcs->send_hbm_bad_pages_num(&adev->smu, con->eeprom_control.num_recs); | |
| 136 | + adev->smu.ppt_funcs->send_hbm_bad_pages_num(&adev->smu, con->eeprom_control.ras_num_recs); | |
| 138 | 137 | } |
| 139 | 138 | |
| 140 | 139 | amdgpu_ras_reset_gpu(adev); |
| @@ -326,7 +326,6 @@ int amdgpu_uvd_sw_fini(struct amdgpu_device *adev) · 325 unmodified lines | ||
| 326 | 326 | { |
| 327 | 327 | int i, j; |
| 328 | 328 | |
| 329 | − cancel_delayed_work_sync(&adev->uvd.idle_work); | |
| 330 | 329 | drm_sched_entity_destroy(&adev->uvd.entity); |
| 331 | 330 | |
| 332 | 331 | for (j = 0; j < adev->uvd.num_uvd_inst; ++j) { |
| @@ -218,7 +218,6 @@ int amdgpu_vce_sw_fini(struct amdgpu_device *adev) · 217 unmodified lines | ||
| 218 | 218 | if (adev->vce.vcpu_bo == NULL) |
| 219 | 219 | return 0; |
| 220 | 220 | |
| 221 | − cancel_delayed_work_sync(&adev->vce.idle_work); | |
| 222 | 221 | drm_sched_entity_destroy(&adev->vce.entity); |
| 223 | 222 | |
| 224 | 223 | amdgpu_bo_free_kernel(&adev->vce.vcpu_bo, &adev->vce.gpu_addr, |
| @@ -258,8 +258,6 @@ int amdgpu_vcn_sw_fini(struct amdgpu_device *adev) · 257 unmodified lines | ||
| 258 | 258 | { |
| 259 | 259 | int i, j; |
| 260 | 260 | |
| 261 | − cancel_delayed_work_sync(&adev->vcn.idle_work); | |
| 262 | − | |
| 263 | 261 | for (j = 0; j < adev->vcn.num_vcn_inst; ++j) { |
| 264 | 262 | if (adev->vcn.harvest_config & (1 << j)) |
| 265 | 263 | continue; |
| @@ -531,10 +531,10 @@ static void amdgpu_virt_populate_vf2pf_ucode_info(struct amdgpu_device *adev) · 530 unmodified lines | ||
| 531 | 531 | POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_RLC_SRLS, adev->gfx.rlc_srls_fw_version); |
| 532 | 532 | POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_MEC, adev->gfx.mec_fw_version); |
| 533 | 533 | POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_MEC2, adev->gfx.mec2_fw_version); |
| 534 | − POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_SOS, adev->psp.sos_fw_version); | |
| 535 | − POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_ASD, adev->psp.asd_fw_version); | |
| 536 | − POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_TA_RAS, adev->psp.ta_ras_ucode_version); | |
| 537 | − POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_TA_XGMI, adev->psp.ta_xgmi_ucode_version); | |
| 534 | + POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_SOS, adev->psp.sos.fw_version); | |
| 535 | + POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_ASD, adev->psp.asd.fw_version); | |
| 536 | + POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_TA_RAS, adev->psp.ras.feature_version); | |
| 537 | + POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_TA_XGMI, adev->psp.xgmi.feature_version); | |
| 538 | 538 | POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_SMC, adev->pm.fw_version); |
| 539 | 539 | POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_SDMA, adev->sdma.instance[0].fw_version); |
| 540 | 540 | POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_SDMA2, adev->sdma.instance[1].fw_version); |
| @@ -0,0 +1,643 @@ | ||
| 1 | +// SPDX-License-Identifier: GPL-2.0+ | |
| 2 | + | |
| 3 | +#include <drm/drm_atomic_helper.h> | |
| 4 | +#include <drm/drm_simple_kms_helper.h> | |
| 5 | +#include <drm/drm_vblank.h> | |
| 6 | + | |
| 7 | +#include "amdgpu.h" | |
| 8 | +#ifdef CONFIG_DRM_AMDGPU_SI | |
| 9 | +#include "dce_v6_0.h" | |
| 10 | +#endif | |
| 11 | +#ifdef CONFIG_DRM_AMDGPU_CIK | |
| 12 | +#include "dce_v8_0.h" | |
| 13 | +#endif | |
| 14 | +#include "dce_v10_0.h" | |
| 15 | +#include "dce_v11_0.h" | |
| 16 | +#include "ivsrcid/ivsrcid_vislands30.h" | |
| 17 | +#include "amdgpu_vkms.h" | |
| 18 | +#include "amdgpu_display.h" | |
| 19 | + | |
| 20 | +/** | |
| 21 | + * DOC: amdgpu_vkms | |
| 22 | + * | |
| 23 | + * The amdgpu vkms interface provides a virtual KMS interface for several use | |
| 24 | + * cases: devices without display hardware, platforms where the actual display | |
| 25 | + * hardware is not useful (e.g., servers), SR-IOV virtual functions, device | |
| 26 | + * emulation/simulation, and device bring up prior to display hardware being | |
| 27 | + * usable. We previously emulated a legacy KMS interface, but there was a desire | |
| 28 | + * to move to the atomic KMS interface. The vkms driver did everything we | |
| 29 | + * needed, but we wanted KMS support natively in the driver without buffer | |
| 30 | + * sharing and the ability to support an instance of VKMS per device. We first | |
| 31 | + * looked at splitting vkms into a stub driver and a helper module that other | |
| 32 | + * drivers could use to implement a virtual display, but this strategy ended up | |
| 33 | + * being messy due to driver specific callbacks needed for buffer management. | |
| 34 | + * Ultimately, it proved easier to import the vkms code as it mostly used core | |
| 35 | + * drm helpers anyway. | |
| 36 | + */ | |
| 37 | + | |
| 38 | +static const u32 amdgpu_vkms_formats[] = { | |
| 39 | + DRM_FORMAT_XRGB8888, | |
| 40 | +}; | |
| 41 | + | |
| 42 | +static enum hrtimer_restart amdgpu_vkms_vblank_simulate(struct hrtimer *timer) | |
| 43 | +{ | |
| 44 | + struct amdgpu_vkms_output *output = container_of(timer, | |
| 45 | + struct amdgpu_vkms_output, | |
| 46 | + vblank_hrtimer); | |
| 47 | + struct drm_crtc *crtc = &output->crtc; | |
| 48 | + u64 ret_overrun; | |
| 49 | + bool ret; | |
| 50 | + | |
| 51 | + ret_overrun = hrtimer_forward_now(&output->vblank_hrtimer, | |
| 52 | + output->period_ns); | |
| 53 | + WARN_ON(ret_overrun != 1); | |
| 54 | + | |
| 55 | + ret = drm_crtc_handle_vblank(crtc); | |
| 56 | + if (!ret) | |
| 57 | + DRM_ERROR("amdgpu_vkms failure on handling vblank"); | |
| 58 | + | |
| 59 | + return HRTIMER_RESTART; | |
| 60 | +} | |
| 61 | + | |
| 62 | +static int amdgpu_vkms_enable_vblank(struct drm_crtc *crtc) | |
| 63 | +{ | |
| 64 | + struct drm_device *dev = crtc->dev; | |
| 65 | + unsigned int pipe = drm_crtc_index(crtc); | |
| 66 | + struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; | |
| 67 | + struct amdgpu_vkms_output *out = drm_crtc_to_amdgpu_vkms_output(crtc); | |
| 68 | + | |
| 69 | + drm_calc_timestamping_constants(crtc, &crtc->mode); | |
| 70 | + | |
| 71 | + hrtimer_init(&out->vblank_hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); | |
| 72 | + out->vblank_hrtimer.function = &amdgpu_vkms_vblank_simulate; | |
| 73 | + out->period_ns = ktime_set(0, vblank->framedur_ns); | |
| 74 | + hrtimer_start(&out->vblank_hrtimer, out->period_ns, HRTIMER_MODE_REL); | |
| 75 | + | |
| 76 | + return 0; | |
| 77 | +} | |
| 78 | + | |
| 79 | +static void amdgpu_vkms_disable_vblank(struct drm_crtc *crtc) | |
| 80 | +{ | |
| 81 | + struct amdgpu_vkms_output *out = drm_crtc_to_amdgpu_vkms_output(crtc); | |
| 82 | + | |
| 83 | + hrtimer_cancel(&out->vblank_hrtimer); | |
| 84 | +} | |
| 85 | + | |
| 86 | +static bool amdgpu_vkms_get_vblank_timestamp(struct drm_crtc *crtc, | |
| 87 | + int *max_error, | |
| 88 | + ktime_t *vblank_time, | |
| 89 | + bool in_vblank_irq) | |
| 90 | +{ | |
| 91 | + struct drm_device *dev = crtc->dev; | |
| 92 | + unsigned int pipe = crtc->index; | |
| 93 | + struct amdgpu_vkms_output *output = drm_crtc_to_amdgpu_vkms_output(crtc); | |
| 94 | + struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; | |
| 95 | + | |
| 96 | + if (!READ_ONCE(vblank->enabled)) { | |
| 97 | + *vblank_time = ktime_get(); | |
| 98 | + return true; | |
| 99 | + } | |
| 100 | + | |
| 101 | + *vblank_time = READ_ONCE(output->vblank_hrtimer.node.expires); | |
| 102 | + | |
| 103 | + if (WARN_ON(*vblank_time == vblank->time)) | |
| 104 | + return true; | |
| 105 | + | |
| 106 | + /* | |
| 107 | + * To prevent races we roll the hrtimer forward before we do any | |
| 108 | + * interrupt processing - this is how real hw works (the interrupt is | |
| 109 | + * only generated after all the vblank registers are updated) and what | |
| 110 | + * the vblank core expects. Therefore we need to always correct the | |
| 111 | + * timestampe by one frame. | |
| 112 | + */ | |
| 113 | + *vblank_time -= output->period_ns; | |
| 114 | + | |
| 115 | + return true; | |
| 116 | +} | |
| 117 | + | |
| 118 | +static const struct drm_crtc_funcs amdgpu_vkms_crtc_funcs = { | |
| 119 | + .set_config = drm_atomic_helper_set_config, | |
| 120 | + .destroy = drm_crtc_cleanup, | |
| 121 | + .page_flip = drm_atomic_helper_page_flip, | |
| 122 | + .reset = drm_atomic_helper_crtc_reset, | |
| 123 | + .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state, | |
| 124 | + .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state, | |
| 125 | + .enable_vblank = amdgpu_vkms_enable_vblank, | |
| 126 | + .disable_vblank = amdgpu_vkms_disable_vblank, | |
| 127 | + .get_vblank_timestamp = amdgpu_vkms_get_vblank_timestamp, | |
| 128 | +}; | |
| 129 | + | |
| 130 | +static void amdgpu_vkms_crtc_atomic_enable(struct drm_crtc *crtc, | |
| 131 | + struct drm_atomic_state *state) | |
| 132 | +{ | |
| 133 | + drm_crtc_vblank_on(crtc); | |
| 134 | +} | |
| 135 | + | |
| 136 | +static void amdgpu_vkms_crtc_atomic_disable(struct drm_crtc *crtc, | |
| 137 | + struct drm_atomic_state *state) | |
| 138 | +{ | |
| 139 | + drm_crtc_vblank_off(crtc); | |
| 140 | +} | |
| 141 | + | |
| 142 | +static void amdgpu_vkms_crtc_atomic_flush(struct drm_crtc *crtc, | |
| 143 | + struct drm_atomic_state *state) | |
| 144 | +{ | |
| 145 | + if (crtc->state->event) { | |
| 146 | + spin_lock(&crtc->dev->event_lock); | |
| 147 | + | |
| 148 | + if (drm_crtc_vblank_get(crtc) != 0) | |
| 149 | + drm_crtc_send_vblank_event(crtc, crtc->state->event); | |
| 150 | + else | |
| 151 | + drm_crtc_arm_vblank_event(crtc, crtc->state->event); | |
| 152 | + | |
| 153 | + spin_unlock(&crtc->dev->event_lock); | |
| 154 | + | |
| 155 | + crtc->state->event = NULL; | |
| 156 | + } | |
| 157 | +} | |
| 158 | + | |
| 159 | +static const struct drm_crtc_helper_funcs amdgpu_vkms_crtc_helper_funcs = { | |
| 160 | + .atomic_flush = amdgpu_vkms_crtc_atomic_flush, | |
| 161 | + .atomic_enable = amdgpu_vkms_crtc_atomic_enable, | |
| 162 | + .atomic_disable = amdgpu_vkms_crtc_atomic_disable, | |
| 163 | +}; | |
| 164 | + | |
| 165 | +static int amdgpu_vkms_crtc_init(struct drm_device *dev, struct drm_crtc *crtc, | |
| 166 | + struct drm_plane *primary, struct drm_plane *cursor) | |
| 167 | +{ | |
| 168 | + int ret; | |
| 169 | + | |
| 170 | + ret = drm_crtc_init_with_planes(dev, crtc, primary, cursor, | |
| 171 | + &amdgpu_vkms_crtc_funcs, NULL); | |
| 172 | + if (ret) { | |
| 173 | + DRM_ERROR("Failed to init CRTC\n"); | |
| 174 | + return ret; | |
| 175 | + } | |
| 176 | + | |
| 177 | + drm_crtc_helper_add(crtc, &amdgpu_vkms_crtc_helper_funcs); | |
| 178 | + | |
| 179 | + return ret; | |
| 180 | +} | |
| 181 | + | |
| 182 | +static const struct drm_connector_funcs amdgpu_vkms_connector_funcs = { | |
| 183 | + .fill_modes = drm_helper_probe_single_connector_modes, | |
| 184 | + .destroy = drm_connector_cleanup, | |
| 185 | + .reset = drm_atomic_helper_connector_reset, | |
| 186 | + .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, | |
| 187 | + .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, | |
| 188 | +}; | |
| 189 | + | |
| 190 | +static int amdgpu_vkms_conn_get_modes(struct drm_connector *connector) | |
| 191 | +{ | |
| 192 | + struct drm_device *dev = connector->dev; | |
| 193 | + struct drm_display_mode *mode = NULL; | |
| 194 | + unsigned i; | |
| 195 | + static const struct mode_size { | |
| 196 | + int w; | |
| 197 | + int h; | |
| 198 | + } common_modes[] = { | |
| 199 | + { 640, 480}, | |
| 200 | + { 720, 480}, | |
| 201 | + { 800, 600}, | |
| 202 | + { 848, 480}, | |
| 203 | + {1024, 768}, | |
| 204 | + {1152, 768}, | |
| 205 | + {1280, 720}, | |
| 206 | + {1280, 800}, | |
| 207 | + {1280, 854}, | |
| 208 | + {1280, 960}, | |
| 209 | + {1280, 1024}, | |
| 210 | + {1440, 900}, | |
| 211 | + {1400, 1050}, | |
| 212 | + {1680, 1050}, | |
| 213 | + {1600, 1200}, | |
| 214 | + {1920, 1080}, | |
| 215 | + {1920, 1200}, | |
| 216 | + {2560, 1440}, | |
| 217 | + {4096, 3112}, | |
| 218 | + {3656, 2664}, | |
| 219 | + {3840, 2160}, | |
| 220 | + {4096, 2160}, | |
| 221 | + }; | |
| 222 | + | |
| 223 | + for (i = 0; i < ARRAY_SIZE(common_modes); i++) { | |
| 224 | + mode = drm_cvt_mode(dev, common_modes[i].w, common_modes[i].h, 60, false, false, false); | |
| 225 | + drm_mode_probed_add(connector, mode); | |
| 226 | + } | |
| 227 | + | |
| 228 | + drm_set_preferred_mode(connector, XRES_DEF, YRES_DEF); | |
| 229 | + | |
| 230 | + return ARRAY_SIZE(common_modes); | |
| 231 | +} | |
| 232 | + | |
| 233 | +static const struct drm_connector_helper_funcs amdgpu_vkms_conn_helper_funcs = { | |
| 234 | + .get_modes = amdgpu_vkms_conn_get_modes, | |
| 235 | +}; | |
| 236 | + | |
| 237 | +static const struct drm_plane_funcs amdgpu_vkms_plane_funcs = { | |
| 238 | + .update_plane = drm_atomic_helper_update_plane, | |
| 239 | + .disable_plane = drm_atomic_helper_disable_plane, | |
| 240 | + .destroy = drm_plane_cleanup, | |
| 241 | + .reset = drm_atomic_helper_plane_reset, | |
| 242 | + .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state, | |
| 243 | + .atomic_destroy_state = drm_atomic_helper_plane_destroy_state, | |
| 244 | +}; | |
| 245 | + | |
| 246 | +static void amdgpu_vkms_plane_atomic_update(struct drm_plane *plane, | |
| 247 | + struct drm_atomic_state *old_state) | |
| 248 | +{ | |
| 249 | + return; | |
| 250 | +} | |
| 251 | + | |
| 252 | +static int amdgpu_vkms_plane_atomic_check(struct drm_plane *plane, | |
| 253 | + struct drm_atomic_state *state) | |
| 254 | +{ | |
| 255 | + struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state, | |
| 256 | + plane); | |
| 257 | + struct drm_crtc_state *crtc_state; | |
| 258 | + int ret; | |
| 259 | + | |
| 260 | + if (!new_plane_state->fb || WARN_ON(!new_plane_state->crtc)) | |
| 261 | + return 0; | |
| 262 | + | |
| 263 | + crtc_state = drm_atomic_get_crtc_state(state, | |
| 264 | + new_plane_state->crtc); | |
| 265 | + if (IS_ERR(crtc_state)) | |
| 266 | + return PTR_ERR(crtc_state); | |
| 267 | + | |
| 268 | + ret = drm_atomic_helper_check_plane_state(new_plane_state, crtc_state, | |
| 269 | + DRM_PLANE_HELPER_NO_SCALING, | |
| 270 | + DRM_PLANE_HELPER_NO_SCALING, | |
| 271 | + false, true); | |
| 272 | + if (ret != 0) | |
| 273 | + return ret; | |
| 274 | + | |
| 275 | + /* for now primary plane must be visible and full screen */ | |
| 276 | + if (!new_plane_state->visible) | |
| 277 | + return -EINVAL; | |
| 278 | + | |
| 279 | + return 0; | |
| 280 | +} | |
| 281 | + | |
| 282 | +static int amdgpu_vkms_prepare_fb(struct drm_plane *plane, | |
| 283 | + struct drm_plane_state *new_state) | |
| 284 | +{ | |
| 285 | + struct amdgpu_framebuffer *afb; | |
| 286 | + struct drm_gem_object *obj; | |
| 287 | + struct amdgpu_device *adev; | |
| 288 | + struct amdgpu_bo *rbo; | |
| 289 | + struct list_head list; | |
| 290 | + struct ttm_validate_buffer tv; | |
| 291 | + struct ww_acquire_ctx ticket; | |
| 292 | + uint32_t domain; | |
| 293 | + int r; | |
| 294 | + | |
| 295 | + if (!new_state->fb) { | |
| 296 | + DRM_DEBUG_KMS("No FB bound\n"); | |
| 297 | + return 0; | |
| 298 | + } | |
| 299 | + afb = to_amdgpu_framebuffer(new_state->fb); | |
| 300 | + obj = new_state->fb->obj[0]; | |
| 301 | + rbo = gem_to_amdgpu_bo(obj); | |
| 302 | + adev = amdgpu_ttm_adev(rbo->tbo.bdev); | |
| 303 | + INIT_LIST_HEAD(&list); | |
| 304 | + | |
| 305 | + tv.bo = &rbo->tbo; | |
| 306 | + tv.num_shared = 1; | |
| 307 | + list_add(&tv.head, &list); | |
| 308 | + | |
| 309 | + r = ttm_eu_reserve_buffers(&ticket, &list, false, NULL); | |
| 310 | + if (r) { | |
| 311 | + dev_err(adev->dev, "fail to reserve bo (%d)\n", r); | |
| 312 | + return r; | |
| 313 | + } | |
| 314 | + | |
| 315 | + if (plane->type != DRM_PLANE_TYPE_CURSOR) | |
| 316 | + domain = amdgpu_display_supported_domains(adev, rbo->flags); | |
| 317 | + else | |
| 318 | + domain = AMDGPU_GEM_DOMAIN_VRAM; | |
| 319 | + | |
| 320 | + r = amdgpu_bo_pin(rbo, domain); | |
| 321 | + if (unlikely(r != 0)) { | |
| 322 | + if (r != -ERESTARTSYS) | |
| 323 | + DRM_ERROR("Failed to pin framebuffer with error %d\n", r); | |
| 324 | + ttm_eu_backoff_reservation(&ticket, &list); | |
| 325 | + return r; | |
| 326 | + } | |
| 327 | + | |
| 328 | + r = amdgpu_ttm_alloc_gart(&rbo->tbo); | |
| 329 | + if (unlikely(r != 0)) { | |
| 330 | + amdgpu_bo_unpin(rbo); | |
| 331 | + ttm_eu_backoff_reservation(&ticket, &list); | |
| 332 | + DRM_ERROR("%p bind failed\n", rbo); | |
| 333 | + return r; | |
| 334 | + } | |
| 335 | + | |
| 336 | + ttm_eu_backoff_reservation(&ticket, &list); | |
| 337 | + | |
| 338 | + afb->address = amdgpu_bo_gpu_offset(rbo); | |
| 339 | + | |
| 340 | + amdgpu_bo_ref(rbo); | |
| 341 | + | |
| 342 | + return 0; | |
| 343 | +} | |
| 344 | + | |
| 345 | +static void amdgpu_vkms_cleanup_fb(struct drm_plane *plane, | |
| 346 | + struct drm_plane_state *old_state) | |
| 347 | +{ | |
| 348 | + struct amdgpu_bo *rbo; | |
| 349 | + int r; | |
| 350 | + | |
| 351 | + if (!old_state->fb) | |
| 352 | + return; | |
| 353 | + | |
| 354 | + rbo = gem_to_amdgpu_bo(old_state->fb->obj[0]); | |
| 355 | + r = amdgpu_bo_reserve(rbo, false); | |
| 356 | + if (unlikely(r)) { | |
| 357 | + DRM_ERROR("failed to reserve rbo before unpin\n"); | |
| 358 | + return; | |
| 359 | + } | |
| 360 | + | |
| 361 | + amdgpu_bo_unpin(rbo); | |
| 362 | + amdgpu_bo_unreserve(rbo); | |
| 363 | + amdgpu_bo_unref(&rbo); | |
| 364 | +} | |
| 365 | + | |
| 366 | +static const struct drm_plane_helper_funcs amdgpu_vkms_primary_helper_funcs = { | |
| 367 | + .atomic_update = amdgpu_vkms_plane_atomic_update, | |
| 368 | + .atomic_check = amdgpu_vkms_plane_atomic_check, | |
| 369 | + .prepare_fb = amdgpu_vkms_prepare_fb, | |
| 370 | + .cleanup_fb = amdgpu_vkms_cleanup_fb, | |
| 371 | +}; | |
| 372 | + | |
| 373 | +static struct drm_plane *amdgpu_vkms_plane_init(struct drm_device *dev, | |
| 374 | + enum drm_plane_type type, | |
| 375 | + int index) | |
| 376 | +{ | |
| 377 | + struct drm_plane *plane; | |
| 378 | + int ret; | |
| 379 | + | |
| 380 | + plane = kzalloc(sizeof(*plane), GFP_KERNEL); | |
| 381 | + if (!plane) | |
| 382 | + return ERR_PTR(-ENOMEM); | |
| 383 | + | |
| 384 | + ret = drm_universal_plane_init(dev, plane, 1 << index, | |
| 385 | + &amdgpu_vkms_plane_funcs, | |
| 386 | + amdgpu_vkms_formats, | |
| 387 | + ARRAY_SIZE(amdgpu_vkms_formats), | |
| 388 | + NULL, type, NULL); | |
| 389 | + if (ret) { | |
| 390 | + kfree(plane); | |
| 391 | + return ERR_PTR(ret); | |
| 392 | + } | |
| 393 | + | |
| 394 | + drm_plane_helper_add(plane, &amdgpu_vkms_primary_helper_funcs); | |
| 395 | + | |
| 396 | + return plane; | |
| 397 | +} | |
| 398 | + | |
| 399 | +int amdgpu_vkms_output_init(struct drm_device *dev, | |
| 400 | + struct amdgpu_vkms_output *output, int index) | |
| 401 | +{ | |
| 402 | + struct drm_connector *connector = &output->connector; | |
| 403 | + struct drm_encoder *encoder = &output->encoder; | |
| 404 | + struct drm_crtc *crtc = &output->crtc; | |
| 405 | + struct drm_plane *primary, *cursor = NULL; | |
| 406 | + int ret; | |
| 407 | + | |
| 408 | + primary = amdgpu_vkms_plane_init(dev, DRM_PLANE_TYPE_PRIMARY, index); | |
| 409 | + if (IS_ERR(primary)) | |
| 410 | + return PTR_ERR(primary); | |
| 411 | + | |
| 412 | + ret = amdgpu_vkms_crtc_init(dev, crtc, primary, cursor); | |
| 413 | + if (ret) | |
| 414 | + goto err_crtc; | |
| 415 | + | |
| 416 | + ret = drm_connector_init(dev, connector, &amdgpu_vkms_connector_funcs, | |
| 417 | + DRM_MODE_CONNECTOR_VIRTUAL); | |
| 418 | + if (ret) { | |
| 419 | + DRM_ERROR("Failed to init connector\n"); | |
| 420 | + goto err_connector; | |
| 421 | + } | |
| 422 | + | |
| 423 | + drm_connector_helper_add(connector, &amdgpu_vkms_conn_helper_funcs); | |
| 424 | + | |
| 425 | + ret = drm_simple_encoder_init(dev, encoder, DRM_MODE_ENCODER_VIRTUAL); | |
| 426 | + if (ret) { | |
| 427 | + DRM_ERROR("Failed to init encoder\n"); | |
| 428 | + goto err_encoder; | |
| 429 | + } | |
| 430 | + encoder->possible_crtcs = 1 << index; | |
| 431 | + | |
| 432 | + ret = drm_connector_attach_encoder(connector, encoder); | |
| 433 | + if (ret) { | |
| 434 | + DRM_ERROR("Failed to attach connector to encoder\n"); | |
| 435 | + goto err_attach; | |
| 436 | + } | |
| 437 | + | |
| 438 | + drm_mode_config_reset(dev); | |
| 439 | + | |
| 440 | + return 0; | |
| 441 | + | |
| 442 | +err_attach: | |
| 443 | + drm_encoder_cleanup(encoder); | |
| 444 | + | |
| 445 | +err_encoder: | |
| 446 | + drm_connector_cleanup(connector); | |
| 447 | + | |
| 448 | +err_connector: | |
| 449 | + drm_crtc_cleanup(crtc); | |
| 450 | + | |
| 451 | +err_crtc: | |
| 452 | + drm_plane_cleanup(primary); | |
| 453 | + | |
| 454 | + return ret; | |
| 455 | +} | |
| 456 | + | |
| 457 | +const struct drm_mode_config_funcs amdgpu_vkms_mode_funcs = { | |
| 458 | + .fb_create = amdgpu_display_user_framebuffer_create, | |
| 459 | + .atomic_check = drm_atomic_helper_check, | |
| 460 | + .atomic_commit = drm_atomic_helper_commit, | |
| 461 | +}; | |
| 462 | + | |
| 463 | +static int amdgpu_vkms_sw_init(void *handle) | |
| 464 | +{ | |
| 465 | + int r, i; | |
| 466 | + struct amdgpu_device *adev = (struct amdgpu_device *)handle; | |
| 467 | + | |
| 468 | + adev_to_drm(adev)->max_vblank_count = 0; | |
| 469 | + | |
| 470 | + adev_to_drm(adev)->mode_config.funcs = &amdgpu_vkms_mode_funcs; | |
| 471 | + | |
| 472 | + adev_to_drm(adev)->mode_config.max_width = XRES_MAX; | |
| 473 | + adev_to_drm(adev)->mode_config.max_height = YRES_MAX; | |
| 474 | + | |
| 475 | + adev_to_drm(adev)->mode_config.preferred_depth = 24; | |
| 476 | + adev_to_drm(adev)->mode_config.prefer_shadow = 1; | |
| 477 | + | |
| 478 | + adev_to_drm(adev)->mode_config.fb_base = adev->gmc.aper_base; | |
| 479 | + | |
| 480 | + r = amdgpu_display_modeset_create_props(adev); | |
| 481 | + if (r) | |
| 482 | + return r; | |
| 483 | + | |
| 484 | + adev->amdgpu_vkms_output = kcalloc(adev->mode_info.num_crtc, sizeof(struct amdgpu_vkms_output), GFP_KERNEL); | |
| 485 | + if (!adev->amdgpu_vkms_output) | |
| 486 | + return -ENOMEM; | |
| 487 | + | |
| 488 | + /* allocate crtcs, encoders, connectors */ | |
| 489 | + for (i = 0; i < adev->mode_info.num_crtc; i++) { | |
| 490 | + r = amdgpu_vkms_output_init(adev_to_drm(adev), &adev->amdgpu_vkms_output[i], i); | |
| 491 | + if (r) | |
| 492 | + return r; | |
| 493 | + } | |
| 494 | + | |
| 495 | + drm_kms_helper_poll_init(adev_to_drm(adev)); | |
| 496 | + | |
| 497 | + adev->mode_info.mode_config_initialized = true; | |
| 498 | + return 0; | |
| 499 | +} | |
| 500 | + | |
| 501 | +static int amdgpu_vkms_sw_fini(void *handle) | |
| 502 | +{ | |
| 503 | + struct amdgpu_device *adev = (struct amdgpu_device *)handle; | |
| 504 | + int i = 0; | |
| 505 | + | |
| 506 | + for (i = 0; i < adev->mode_info.num_crtc; i++) | |
| 507 | + if (adev->mode_info.crtcs[i]) | |
| 508 | + hrtimer_cancel(&adev->mode_info.crtcs[i]->vblank_timer); | |
| 509 | + | |
| 510 | + kfree(adev->mode_info.bios_hardcoded_edid); | |
| 511 | + kfree(adev->amdgpu_vkms_output); | |
| 512 | + | |
| 513 | + drm_kms_helper_poll_fini(adev_to_drm(adev)); | |
| 514 | + | |
| 515 | + adev->mode_info.mode_config_initialized = false; | |
| 516 | + return 0; | |
| 517 | +} | |
| 518 | + | |
| 519 | +static int amdgpu_vkms_hw_init(void *handle) | |
| 520 | +{ | |
| 521 | + struct amdgpu_device *adev = (struct amdgpu_device *)handle; | |
| 522 | + | |
| 523 | + switch (adev->asic_type) { | |
| 524 | +#ifdef CONFIG_DRM_AMDGPU_SI | |
| 525 | + case CHIP_TAHITI: | |
| 526 | + case CHIP_PITCAIRN: | |
| 527 | + case CHIP_VERDE: | |
| 528 | + case CHIP_OLAND: | |
| 529 | + dce_v6_0_disable_dce(adev); | |
| 530 | + break; | |
| 531 | +#endif | |
| 532 | +#ifdef CONFIG_DRM_AMDGPU_CIK | |
| 533 | + case CHIP_BONAIRE: | |
| 534 | + case CHIP_HAWAII: | |
| 535 | + case CHIP_KAVERI: | |
| 536 | + case CHIP_KABINI: | |
| 537 | + case CHIP_MULLINS: | |
| 538 | + dce_v8_0_disable_dce(adev); | |
| 539 | + break; | |
| 540 | +#endif | |
| 541 | + case CHIP_FIJI: | |
| 542 | + case CHIP_TONGA: | |
| 543 | + dce_v10_0_disable_dce(adev); | |
| 544 | + break; | |
| 545 | + case CHIP_CARRIZO: | |
| 546 | + case CHIP_STONEY: | |
| 547 | + case CHIP_POLARIS10: | |
| 548 | + case CHIP_POLARIS11: | |
| 549 | + case CHIP_VEGAM: | |
| 550 | + dce_v11_0_disable_dce(adev); | |
| 551 | + break; | |
| 552 | + case CHIP_TOPAZ: | |
| 553 | +#ifdef CONFIG_DRM_AMDGPU_SI | |
| 554 | + case CHIP_HAINAN: | |
| 555 | +#endif | |
| 556 | + /* no DCE */ | |
| 557 | + break; | |
| 558 | + default: | |
| 559 | + break; | |
| 560 | + } | |
| 561 | + return 0; | |
| 562 | +} | |
| 563 | + | |
| 564 | +static int amdgpu_vkms_hw_fini(void *handle) | |
| 565 | +{ | |
| 566 | + return 0; | |
| 567 | +} | |
| 568 | + | |
| 569 | +static int amdgpu_vkms_suspend(void *handle) | |
| 570 | +{ | |
| 571 | + struct amdgpu_device *adev = (struct amdgpu_device *)handle; | |
| 572 | + int r; | |
| 573 | + | |
| 574 | + r = drm_mode_config_helper_suspend(adev_to_drm(adev)); | |
| 575 | + if (r) | |
| 576 | + return r; | |
| 577 | + return amdgpu_vkms_hw_fini(handle); | |
| 578 | +} | |
| 579 | + | |
| 580 | +static int amdgpu_vkms_resume(void *handle) | |
| 581 | +{ | |
| 582 | + struct amdgpu_device *adev = (struct amdgpu_device *)handle; | |
| 583 | + int r; | |
| 584 | + | |
| 585 | + r = amdgpu_vkms_hw_init(handle); | |
| 586 | + if (r) | |
| 587 | + return r; | |
| 588 | + return drm_mode_config_helper_resume(adev_to_drm(adev)); | |
| 589 | +} | |
| 590 | + | |
| 591 | +static bool amdgpu_vkms_is_idle(void *handle) | |
| 592 | +{ | |
| 593 | + return true; | |
| 594 | +} | |
| 595 | + | |
| 596 | +static int amdgpu_vkms_wait_for_idle(void *handle) | |
| 597 | +{ | |
| 598 | + return 0; | |
| 599 | +} | |
| 600 | + | |
| 601 | +static int amdgpu_vkms_soft_reset(void *handle) | |
| 602 | +{ | |
| 603 | + return 0; | |
| 604 | +} | |
| 605 | + | |
| 606 | +static int amdgpu_vkms_set_clockgating_state(void *handle, | |
| 607 | + enum amd_clockgating_state state) | |
| 608 | +{ | |
| 609 | + return 0; | |
| 610 | +} | |
| 611 | + | |
| 612 | +static int amdgpu_vkms_set_powergating_state(void *handle, | |
| 613 | + enum amd_powergating_state state) | |
| 614 | +{ | |
| 615 | + return 0; | |
| 616 | +} | |
| 617 | + | |
| 618 | +static const struct amd_ip_funcs amdgpu_vkms_ip_funcs = { | |
| 619 | + .name = "amdgpu_vkms", | |
| 620 | + .early_init = NULL, | |
| 621 | + .late_init = NULL, | |
| 622 | + .sw_init = amdgpu_vkms_sw_init, | |
| 623 | + .sw_fini = amdgpu_vkms_sw_fini, | |
| 624 | + .hw_init = amdgpu_vkms_hw_init, | |
| 625 | + .hw_fini = amdgpu_vkms_hw_fini, | |
| 626 | + .suspend = amdgpu_vkms_suspend, | |
| 627 | + .resume = amdgpu_vkms_resume, | |
| 628 | + .is_idle = amdgpu_vkms_is_idle, | |
| 629 | + .wait_for_idle = amdgpu_vkms_wait_for_idle, | |
| 630 | + .soft_reset = amdgpu_vkms_soft_reset, | |
| 631 | + .set_clockgating_state = amdgpu_vkms_set_clockgating_state, | |
| 632 | + .set_powergating_state = amdgpu_vkms_set_powergating_state, | |
| 633 | +}; | |
| 634 | + | |
| 635 | +const struct amdgpu_ip_block_version amdgpu_vkms_ip_block = | |
| 636 | +{ | |
| 637 | + .type = AMD_IP_BLOCK_TYPE_DCE, | |
| 638 | + .major = 1, | |
| 639 | + .minor = 0, | |
| 640 | + .rev = 0, | |
| 641 | + .funcs = &amdgpu_vkms_ip_funcs, | |
| 642 | +}; | |
| 643 | + | |
| @@ -0,0 +1,26 @@ | ||
| 1 | +/* SPDX-License-Identifier: GPL-2.0+ */ | |
| 2 | + | |
| 3 | +#ifndef _AMDGPU_VKMS_H_ | |
| 4 | +#define _AMDGPU_VKMS_H_ | |
| 5 | + | |
| 6 | +#define XRES_DEF 1024 | |
| 7 | +#define YRES_DEF 768 | |
| 8 | + | |
| 9 | +#define XRES_MAX 16384 | |
| 10 | +#define YRES_MAX 16384 | |
| 11 | + | |
| 12 | +#define drm_crtc_to_amdgpu_vkms_output(target) \ | |
| 13 | + container_of(target, struct amdgpu_vkms_output, crtc) | |
| 14 | + | |
| 15 | +extern const struct amdgpu_ip_block_version amdgpu_vkms_ip_block; | |
| 16 | + | |
| 17 | +struct amdgpu_vkms_output { | |
| 18 | + struct drm_crtc crtc; | |
| 19 | + struct drm_encoder encoder; | |
| 20 | + struct drm_connector connector; | |
| 21 | + struct hrtimer vblank_hrtimer; | |
| 22 | + ktime_t period_ns; | |
| 23 | + struct drm_pending_vblank_event *event; | |
| 24 | +}; | |
| 25 | + | |
| 26 | +#endif /* _AMDGPU_VKMS_H_ */ | |
| @@ -88,6 +88,46 @@ struct amdgpu_prt_cb { · 87 unmodified lines | ||
| 88 | 88 | struct dma_fence_cb cb; |
| 89 | 89 | }; |
| 90 | 90 | |
| 91 | +/** | |
| 92 | + * amdgpu_vm_set_pasid - manage pasid and vm ptr mapping | |
| 93 | + * | |
| 94 | + * @adev: amdgpu_device pointer | |
| 95 | + * @vm: amdgpu_vm pointer | |
| 96 | + * @pasid: the pasid the VM is using on this GPU | |
| 97 | + * | |
| 98 | + * Set the pasid this VM is using on this GPU, can also be used to remove the | |
| 99 | + * pasid by passing in zero. | |
| 100 | + * | |
| 101 | + */ | |
| 102 | +int amdgpu_vm_set_pasid(struct amdgpu_device *adev, struct amdgpu_vm *vm, | |
| 103 | + u32 pasid) | |
| 104 | +{ | |
| 105 | + int r; | |
| 106 | + | |
| 107 | + if (vm->pasid == pasid) | |
| 108 | + return 0; | |
| 109 | + | |
| 110 | + if (vm->pasid) { | |
| 111 | + r = xa_err(xa_erase_irq(&adev->vm_manager.pasids, vm->pasid)); | |
| 112 | + if (r < 0) | |
| 113 | + return r; | |
| 114 | + | |
| 115 | + vm->pasid = 0; | |
| 116 | + } | |
| 117 | + | |
| 118 | + if (pasid) { | |
| 119 | + r = xa_err(xa_store_irq(&adev->vm_manager.pasids, pasid, vm, | |
| 120 | + GFP_KERNEL)); | |
| 121 | + if (r < 0) | |
| 122 | + return r; | |
| 123 | + | |
| 124 | + vm->pasid = pasid; | |
| 125 | + } | |
| 126 | + | |
| 127 | + | |
| 128 | + return 0; | |
| 129 | +} | |
| 130 | + | |
| 91 | 131 | /* |
| 92 | 132 | * vm eviction_lock can be taken in MMU notifiers. Make sure no reclaim-FS |
| 93 | 133 | * happens while holding this lock anywhere to prevent deadlocks when |
| @@ -886,7 +926,7 @@ static int amdgpu_vm_pt_create(struct amdgpu_device *adev, · 792 unmodified lines | ||
| 886 | 926 | bp.size = amdgpu_vm_bo_size(adev, level); |
| 887 | 927 | bp.byte_align = AMDGPU_GPU_PAGE_SIZE; |
| 888 | 928 | bp.domain = AMDGPU_GEM_DOMAIN_VRAM; |
| 889 | − bp.domain = amdgpu_bo_get_preferred_pin_domain(adev, bp.domain); | |
| 929 | + bp.domain = amdgpu_bo_get_preferred_domain(adev, bp.domain); | |
| 890 | 930 | bp.flags = AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS | |
| 891 | 931 | AMDGPU_GEM_CREATE_CPU_GTT_USWC; |
| 892 | 932 | |
| @@ -1178,7 +1218,7 @@ int amdgpu_vm_flush(struct amdgpu_ring *ring, struct amdgpu_job *job, · 285 unmodified lines | ||
| 1178 | 1218 | amdgpu_gmc_emit_pasid_mapping(ring, job->vmid, job->pasid); |
| 1179 | 1219 | |
| 1180 | 1220 | if (vm_flush_needed || pasid_mapping_needed) { |
| 1181 | − r = amdgpu_fence_emit(ring, &fence, 0); | |
| 1221 | + r = amdgpu_fence_emit(ring, &fence, NULL, 0); | |
| 1182 | 1222 | if (r) |
| 1183 | 1223 | return r; |
| 1184 | 1224 | } |
| @@ -1758,7 +1798,7 @@ int amdgpu_vm_bo_update_mapping(struct amdgpu_device *adev, · 573 unmodified lines | ||
| 1758 | 1798 | r = vm->update_funcs->commit(¶ms, fence); |
| 1759 | 1799 | |
| 1760 | 1800 | if (table_freed) |
| 1761 | − *table_freed = params.table_freed; | |
| 1801 | + *table_freed = *table_freed || params.table_freed; | |
| 1762 | 1802 | |
| 1763 | 1803 | error_unlock: |
| 1764 | 1804 | amdgpu_vm_eviction_unlock(vm); |
| @@ -1816,6 +1856,7 @@ void amdgpu_vm_get_memory(struct amdgpu_vm *vm, uint64_t *vram_mem, · 51 unmodified lines | ||
| 1816 | 1856 | * @adev: amdgpu_device pointer |
| 1817 | 1857 | * @bo_va: requested BO and VM object |
| 1818 | 1858 | * @clear: if true clear the entries |
| 1859 | + * @table_freed: return true if page table is freed | |
| 1819 | 1860 | * |
| 1820 | 1861 | * Fill in the page table entries for @bo_va. |
| 1821 | 1862 | * |
| @@ -1823,7 +1864,7 @@ void amdgpu_vm_get_memory(struct amdgpu_vm *vm, uint64_t *vram_mem, · 1 unmodified line | ||
| 1823 | 1864 | * 0 for success, -EINVAL for failure. |
| 1824 | 1865 | */ |
| 1825 | 1866 | int amdgpu_vm_bo_update(struct amdgpu_device *adev, struct amdgpu_bo_va *bo_va, |
| 1826 | − bool clear) | |
| 1867 | + bool clear, bool *table_freed) | |
| 1827 | 1868 | { |
| 1828 | 1869 | struct amdgpu_bo *bo = bo_va->base.bo; |
| 1829 | 1870 | struct amdgpu_vm *vm = bo_va->base.vm; |
| @@ -1902,7 +1943,7 @@ int amdgpu_vm_bo_update(struct amdgpu_device *adev, struct amdgpu_bo_va *bo_va, · 72 unmodified lines | ||
| 1902 | 1943 | resv, mapping->start, |
| 1903 | 1944 | mapping->last, update_flags, |
| 1904 | 1945 | mapping->offset, mem, |
| 1905 | − pages_addr, last_update, NULL); | |
| 1946 | + pages_addr, last_update, table_freed); | |
| 1906 | 1947 | if (r) |
| 1907 | 1948 | return r; |
| 1908 | 1949 | } |
| @@ -2154,7 +2195,7 @@ int amdgpu_vm_handle_moved(struct amdgpu_device *adev, · 245 unmodified lines | ||
| 2154 | 2195 | |
| 2155 | 2196 | list_for_each_entry_safe(bo_va, tmp, &vm->moved, base.vm_status) { |
| 2156 | 2197 | /* Per VM BOs never need to bo cleared in the page tables */ |
| 2157 | − r = amdgpu_vm_bo_update(adev, bo_va, false); | |
| 2198 | + r = amdgpu_vm_bo_update(adev, bo_va, false, NULL); | |
| 2158 | 2199 | if (r) |
| 2159 | 2200 | return r; |
| 2160 | 2201 | } |
| @@ -2173,7 +2214,7 @@ int amdgpu_vm_handle_moved(struct amdgpu_device *adev, · 12 unmodified lines | ||
| 2173 | 2214 | else |
| 2174 | 2215 | clear = true; |
| 2175 | 2216 | |
| 2176 | − r = amdgpu_vm_bo_update(adev, bo_va, clear); | |
| 2217 | + r = amdgpu_vm_bo_update(adev, bo_va, clear, NULL); | |
| 2177 | 2218 | if (r) |
| 2178 | 2219 | return r; |
| 2179 | 2220 | |
| @@ -2863,14 +2904,13 @@ long amdgpu_vm_wait_idle(struct amdgpu_vm *vm, long timeout) · 683 unmodified lines | ||
| 2863 | 2904 | * |
| 2864 | 2905 | * @adev: amdgpu_device pointer |
| 2865 | 2906 | * @vm: requested vm |
| 2866 | − * @pasid: Process address space identifier | |
| 2867 | 2907 | * |
| 2868 | 2908 | * Init @vm fields. |
| 2869 | 2909 | * |
| 2870 | 2910 | * Returns: |
| 2871 | 2911 | * 0 for success, error for failure. |
| 2872 | 2912 | */ |
| 2873 | −int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm, u32 pasid) | |
| 2913 | +int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm) | |
| 2874 | 2914 | { |
| 2875 | 2915 | struct amdgpu_bo *root_bo; |
| 2876 | 2916 | struct amdgpu_bo_vm *root; |
| @@ -2944,19 +2984,6 @@ int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm, u32 pasid) · 67 unmodified lines | ||
| 2944 | 2984 | |
| 2945 | 2985 | amdgpu_bo_unreserve(vm->root.bo); |
| 2946 | 2986 | |
| 2947 | − if (pasid) { | |
| 2948 | − unsigned long flags; | |
| 2949 | − | |
| 2950 | − spin_lock_irqsave(&adev->vm_manager.pasid_lock, flags); | |
| 2951 | − r = idr_alloc(&adev->vm_manager.pasid_idr, vm, pasid, pasid + 1, | |
| 2952 | − GFP_ATOMIC); | |
| 2953 | − spin_unlock_irqrestore(&adev->vm_manager.pasid_lock, flags); | |
| 2954 | − if (r < 0) | |
| 2955 | − goto error_free_root; | |
| 2956 | − | |
| 2957 | − vm->pasid = pasid; | |
| 2958 | − } | |
| 2959 | − | |
| 2960 | 2987 | INIT_KFIFO(vm->faults); |
| 2961 | 2988 | |
| 2962 | 2989 | return 0; |
| @@ -3012,7 +3039,6 @@ static int amdgpu_vm_check_clean_reserved(struct amdgpu_device *adev, · 49 unmodified lines | ||
| 3012 | 3039 | * |
| 3013 | 3040 | * @adev: amdgpu_device pointer |
| 3014 | 3041 | * @vm: requested vm |
| 3015 | − * @pasid: pasid to use | |
| 3016 | 3042 | * |
| 3017 | 3043 | * This only works on GFX VMs that don't have any BOs added and no |
| 3018 | 3044 | * page tables allocated yet. |
| @@ -3020,7 +3046,6 @@ static int amdgpu_vm_check_clean_reserved(struct amdgpu_device *adev, · 1 unmodified line | ||
| 3020 | 3046 | * Changes the following VM parameters: |
| 3021 | 3047 | * - use_cpu_for_update |
| 3022 | 3048 | * - pte_supports_ats |
| 3023 | − * - pasid (old PASID is released, because compute manages its own PASIDs) | |
| 3024 | 3049 | * |
| 3025 | 3050 | * Reinitializes the page directory to reflect the changed ATS |
| 3026 | 3051 | * setting. |
| @@ -3028,8 +3053,7 @@ static int amdgpu_vm_check_clean_reserved(struct amdgpu_device *adev, · 1 unmodified line | ||
| 3028 | 3053 | * Returns: |
| 3029 | 3054 | * 0 for success, -errno for errors. |
| 3030 | 3055 | */ |
| 3031 | −int amdgpu_vm_make_compute(struct amdgpu_device *adev, struct amdgpu_vm *vm, | |
| 3032 | − u32 pasid) | |
| 3056 | +int amdgpu_vm_make_compute(struct amdgpu_device *adev, struct amdgpu_vm *vm) | |
| 3033 | 3057 | { |
| 3034 | 3058 | bool pte_support_ats = (adev->asic_type == CHIP_RAVEN); |
| 3035 | 3059 | int r; |
| @@ -3043,19 +3067,6 @@ int amdgpu_vm_make_compute(struct amdgpu_device *adev, struct amdgpu_vm *vm, · 7 unmodified lines | ||
| 3043 | 3067 | if (r) |
| 3044 | 3068 | goto unreserve_bo; |
| 3045 | 3069 | |
| 3046 | − if (pasid) { | |
| 3047 | − unsigned long flags; | |
| 3048 | − | |
| 3049 | − spin_lock_irqsave(&adev->vm_manager.pasid_lock, flags); | |
| 3050 | − r = idr_alloc(&adev->vm_manager.pasid_idr, vm, pasid, pasid + 1, | |
| 3051 | − GFP_ATOMIC); | |
| 3052 | − spin_unlock_irqrestore(&adev->vm_manager.pasid_lock, flags); | |
| 3053 | − | |
| 3054 | − if (r == -ENOSPC) | |
| 3055 | − goto unreserve_bo; | |
| 3056 | − r = 0; | |
| 3057 | − } | |
| 3058 | − | |
| 3059 | 3070 | /* Check if PD needs to be reinitialized and do it before |
| 3060 | 3071 | * changing any other state, in case it fails. |
| 3061 | 3072 | */ |
| @@ -3065,7 +3076,7 @@ int amdgpu_vm_make_compute(struct amdgpu_device *adev, struct amdgpu_vm *vm, · 3 unmodified lines | ||
| 3065 | 3076 | to_amdgpu_bo_vm(vm->root.bo), |
| 3066 | 3077 | false); |
| 3067 | 3078 | if (r) |
| 3068 | − goto free_idr; | |
| 3079 | + goto unreserve_bo; | |
| 3069 | 3080 | } |
| 3070 | 3081 | |
| 3071 | 3082 | /* Update VM state */ |
| @@ -3082,7 +3093,7 @@ int amdgpu_vm_make_compute(struct amdgpu_device *adev, struct amdgpu_vm *vm, · 10 unmodified lines | ||
| 3082 | 3093 | r = amdgpu_bo_sync_wait(vm->root.bo, |
| 3083 | 3094 | AMDGPU_FENCE_OWNER_UNDEFINED, true); |
| 3084 | 3095 | if (r) |
| 3085 | − goto free_idr; | |
| 3096 | + goto unreserve_bo; | |
| 3086 | 3097 | |
| 3087 | 3098 | vm->update_funcs = &amdgpu_vm_cpu_funcs; |
| 3088 | 3099 | } else { |
| @@ -3092,36 +3103,11 @@ int amdgpu_vm_make_compute(struct amdgpu_device *adev, struct amdgpu_vm *vm, · 3 unmodified lines | ||
| 3092 | 3103 | vm->last_update = NULL; |
| 3093 | 3104 | vm->is_compute_context = true; |
| 3094 | 3105 | |
| 3095 | − if (vm->pasid) { | |
| 3096 | − unsigned long flags; | |
| 3097 | − | |
| 3098 | − spin_lock_irqsave(&adev->vm_manager.pasid_lock, flags); | |
| 3099 | − idr_remove(&adev->vm_manager.pasid_idr, vm->pasid); | |
| 3100 | − spin_unlock_irqrestore(&adev->vm_manager.pasid_lock, flags); | |
| 3101 | − | |
| 3102 | − /* Free the original amdgpu allocated pasid | |
| 3103 | − * Will be replaced with kfd allocated pasid | |
| 3104 | − */ | |
| 3105 | − amdgpu_pasid_free(vm->pasid); | |
| 3106 | − vm->pasid = 0; | |
| 3107 | − } | |
| 3108 | − | |
| 3109 | 3106 | /* Free the shadow bo for compute VM */ |
| 3110 | 3107 | amdgpu_bo_unref(&to_amdgpu_bo_vm(vm->root.bo)->shadow); |
| 3111 | 3108 | |
| 3112 | − if (pasid) | |
| 3113 | − vm->pasid = pasid; | |
| 3114 | − | |
| 3115 | 3109 | goto unreserve_bo; |
| 3116 | 3110 | |
| 3117 | −free_idr: | |
| 3118 | − if (pasid) { | |
| 3119 | − unsigned long flags; | |
| 3120 | − | |
| 3121 | − spin_lock_irqsave(&adev->vm_manager.pasid_lock, flags); | |
| 3122 | − idr_remove(&adev->vm_manager.pasid_idr, pasid); | |
| 3123 | − spin_unlock_irqrestore(&adev->vm_manager.pasid_lock, flags); | |
| 3124 | − } | |
| 3125 | 3111 | unreserve_bo: |
| 3126 | 3112 | amdgpu_bo_unreserve(vm->root.bo); |
| 3127 | 3113 | return r; |
| @@ -3137,14 +3123,7 @@ unreserve_bo: · 9 unmodified lines | ||
| 3137 | 3123 | */ |
| 3138 | 3124 | void amdgpu_vm_release_compute(struct amdgpu_device *adev, struct amdgpu_vm *vm) |
| 3139 | 3125 | { |
| 3140 | − if (vm->pasid) { | |
| 3141 | − unsigned long flags; | |
| 3142 | − | |
| 3143 | − spin_lock_irqsave(&adev->vm_manager.pasid_lock, flags); | |
| 3144 | − idr_remove(&adev->vm_manager.pasid_idr, vm->pasid); | |
| 3145 | − spin_unlock_irqrestore(&adev->vm_manager.pasid_lock, flags); | |
| 3146 | − } | |
| 3147 | − vm->pasid = 0; | |
| 3126 | + amdgpu_vm_set_pasid(adev, vm, 0); | |
| 3148 | 3127 | vm->is_compute_context = false; |
| 3149 | 3128 | } |
| 3150 | 3129 | |
| @@ -3168,15 +3147,7 @@ void amdgpu_vm_fini(struct amdgpu_device *adev, struct amdgpu_vm *vm) · 17 unmodified lines | ||
| 3168 | 3147 | |
| 3169 | 3148 | root = amdgpu_bo_ref(vm->root.bo); |
| 3170 | 3149 | amdgpu_bo_reserve(root, true); |
| 3171 | − if (vm->pasid) { | |
| 3172 | − unsigned long flags; | |
| 3173 | − | |
| 3174 | − spin_lock_irqsave(&adev->vm_manager.pasid_lock, flags); | |
| 3175 | − idr_remove(&adev->vm_manager.pasid_idr, vm->pasid); | |
| 3176 | − spin_unlock_irqrestore(&adev->vm_manager.pasid_lock, flags); | |
| 3177 | − vm->pasid = 0; | |
| 3178 | − } | |
| 3179 | − | |
| 3150 | + amdgpu_vm_set_pasid(adev, vm, 0); | |
| 3180 | 3151 | dma_fence_wait(vm->last_unlocked, false); |
| 3181 | 3152 | dma_fence_put(vm->last_unlocked); |
| 3182 | 3153 | |
| @@ -3258,8 +3229,7 @@ void amdgpu_vm_manager_init(struct amdgpu_device *adev) · 75 unmodified lines | ||
| 3258 | 3229 | adev->vm_manager.vm_update_mode = 0; |
| 3259 | 3230 | #endif |
| 3260 | 3231 | |
| 3261 | − idr_init(&adev->vm_manager.pasid_idr); | |
| 3262 | − spin_lock_init(&adev->vm_manager.pasid_lock); | |
| 3232 | + xa_init_flags(&adev->vm_manager.pasids, XA_FLAGS_LOCK_IRQ); | |
| 3263 | 3233 | } |
| 3264 | 3234 | |
| 3265 | 3235 | /** |
| @@ -3271,8 +3241,8 @@ void amdgpu_vm_manager_init(struct amdgpu_device *adev) · 5 unmodified lines | ||
| 3271 | 3241 | */ |
| 3272 | 3242 | void amdgpu_vm_manager_fini(struct amdgpu_device *adev) |
| 3273 | 3243 | { |
| 3274 | − WARN_ON(!idr_is_empty(&adev->vm_manager.pasid_idr)); | |
| 3275 | − idr_destroy(&adev->vm_manager.pasid_idr); | |
| 3244 | + WARN_ON(!xa_empty(&adev->vm_manager.pasids)); | |
| 3245 | + xa_destroy(&adev->vm_manager.pasids); | |
| 3276 | 3246 | |
| 3277 | 3247 | amdgpu_vmid_mgr_fini(adev); |
| 3278 | 3248 | } |
| @@ -3341,13 +3311,13 @@ void amdgpu_vm_get_task_info(struct amdgpu_device *adev, u32 pasid, · 62 unmodified lines | ||
| 3341 | 3311 | struct amdgpu_vm *vm; |
| 3342 | 3312 | unsigned long flags; |
| 3343 | 3313 | |
| 3344 | − spin_lock_irqsave(&adev->vm_manager.pasid_lock, flags); | |
| 3314 | + xa_lock_irqsave(&adev->vm_manager.pasids, flags); | |
| 3345 | 3315 | |
| 3346 | − vm = idr_find(&adev->vm_manager.pasid_idr, pasid); | |
| 3316 | + vm = xa_load(&adev->vm_manager.pasids, pasid); | |
| 3347 | 3317 | if (vm) |
| 3348 | 3318 | *task_info = vm->task_info; |
| 3349 | 3319 | |
| 3350 | − spin_unlock_irqrestore(&adev->vm_manager.pasid_lock, flags); | |
| 3320 | + xa_unlock_irqrestore(&adev->vm_manager.pasids, flags); | |
| 3351 | 3321 | } |
| 3352 | 3322 | |
| 3353 | 3323 | /** |
| @@ -3375,12 +3345,13 @@ void amdgpu_vm_set_task_info(struct amdgpu_vm *vm) · 21 unmodified lines | ||
| 3375 | 3345 | * @adev: amdgpu device pointer |
| 3376 | 3346 | * @pasid: PASID of the VM |
| 3377 | 3347 | * @addr: Address of the fault |
| 3348 | + * @write_fault: true is write fault, false is read fault | |
| 3378 | 3349 | * |
| 3379 | 3350 | * Try to gracefully handle a VM fault. Return true if the fault was handled and |
| 3380 | 3351 | * shouldn't be reported any more. |
| 3381 | 3352 | */ |
| 3382 | 3353 | bool amdgpu_vm_handle_fault(struct amdgpu_device *adev, u32 pasid, |
| 3383 | − uint64_t addr) | |
| 3354 | + uint64_t addr, bool write_fault) | |
| 3384 | 3355 | { |
| 3385 | 3356 | bool is_compute_context = false; |
| 3386 | 3357 | struct amdgpu_bo *root; |
| @@ -3389,15 +3360,15 @@ bool amdgpu_vm_handle_fault(struct amdgpu_device *adev, u32 pasid, · 2 unmodified lines | ||
| 3389 | 3360 | struct amdgpu_vm *vm; |
| 3390 | 3361 | int r; |
| 3391 | 3362 | |
| 3392 | − spin_lock_irqsave(&adev->vm_manager.pasid_lock, irqflags); | |
| 3393 | − vm = idr_find(&adev->vm_manager.pasid_idr, pasid); | |
| 3363 | + xa_lock_irqsave(&adev->vm_manager.pasids, irqflags); | |
| 3364 | + vm = xa_load(&adev->vm_manager.pasids, pasid); | |
| 3394 | 3365 | if (vm) { |
| 3395 | 3366 | root = amdgpu_bo_ref(vm->root.bo); |
| 3396 | 3367 | is_compute_context = vm->is_compute_context; |
| 3397 | 3368 | } else { |
| 3398 | 3369 | root = NULL; |
| 3399 | 3370 | } |
| 3400 | − spin_unlock_irqrestore(&adev->vm_manager.pasid_lock, irqflags); | |
| 3371 | + xa_unlock_irqrestore(&adev->vm_manager.pasids, irqflags); | |
| 3401 | 3372 | |
| 3402 | 3373 | if (!root) |
| 3403 | 3374 | return false; |
| @@ -3405,7 +3376,7 @@ bool amdgpu_vm_handle_fault(struct amdgpu_device *adev, u32 pasid, · 1 unmodified line | ||
| 3405 | 3376 | addr /= AMDGPU_GPU_PAGE_SIZE; |
| 3406 | 3377 | |
| 3407 | 3378 | if (is_compute_context && |
| 3408 | − !svm_range_restore_pages(adev, pasid, addr)) { | |
| 3379 | + !svm_range_restore_pages(adev, pasid, addr, write_fault)) { | |
| 3409 | 3380 | amdgpu_bo_unref(&root); |
| 3410 | 3381 | return true; |
| 3411 | 3382 | } |
| @@ -3415,11 +3386,11 @@ bool amdgpu_vm_handle_fault(struct amdgpu_device *adev, u32 pasid, · 3 unmodified lines | ||
| 3415 | 3386 | goto error_unref; |
| 3416 | 3387 | |
| 3417 | 3388 | /* Double check that the VM still exists */ |
| 3418 | − spin_lock_irqsave(&adev->vm_manager.pasid_lock, irqflags); | |
| 3419 | − vm = idr_find(&adev->vm_manager.pasid_idr, pasid); | |
| 3389 | + xa_lock_irqsave(&adev->vm_manager.pasids, irqflags); | |
| 3390 | + vm = xa_load(&adev->vm_manager.pasids, pasid); | |
| 3420 | 3391 | if (vm && vm->root.bo != root) |
| 3421 | 3392 | vm = NULL; |
| 3422 | − spin_unlock_irqrestore(&adev->vm_manager.pasid_lock, irqflags); | |
| 3393 | + xa_unlock_irqrestore(&adev->vm_manager.pasids, irqflags); | |
| 3423 | 3394 | if (!vm) |
| 3424 | 3395 | goto error_unlock; |
| 3425 | 3396 | |
| @@ -359,8 +359,7 @@ struct amdgpu_vm_manager { · 358 unmodified lines | ||
| 359 | 359 | /* PASID to VM mapping, will be used in interrupt context to |
| 360 | 360 | * look up VM of a page fault |
| 361 | 361 | */ |
| 362 | − struct idr pasid_idr; | |
| 363 | − spinlock_t pasid_lock; | |
| 362 | + struct xarray pasids; | |
| 364 | 363 | }; |
| 365 | 364 | |
| 366 | 365 | struct amdgpu_bo_va_mapping; |
| @@ -375,9 +374,12 @@ extern const struct amdgpu_vm_update_funcs amdgpu_vm_sdma_funcs; · 8 unmodified lines | ||
| 375 | 374 | void amdgpu_vm_manager_init(struct amdgpu_device *adev); |
| 376 | 375 | void amdgpu_vm_manager_fini(struct amdgpu_device *adev); |
| 377 | 376 | |
| 377 | +int amdgpu_vm_set_pasid(struct amdgpu_device *adev, struct amdgpu_vm *vm, | |
| 378 | + u32 pasid); | |
| 379 | + | |
| 378 | 380 | long amdgpu_vm_wait_idle(struct amdgpu_vm *vm, long timeout); |
| 379 | −int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm, u32 pasid); | |
| 380 | −int amdgpu_vm_make_compute(struct amdgpu_device *adev, struct amdgpu_vm *vm, u32 pasid); | |
| 381 | +int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm); | |
| 382 | +int amdgpu_vm_make_compute(struct amdgpu_device *adev, struct amdgpu_vm *vm); | |
| 381 | 383 | void amdgpu_vm_release_compute(struct amdgpu_device *adev, struct amdgpu_vm *vm); |
| 382 | 384 | void amdgpu_vm_fini(struct amdgpu_device *adev, struct amdgpu_vm *vm); |
| 383 | 385 | void amdgpu_vm_get_pd_bo(struct amdgpu_vm *vm, |
| @@ -406,7 +408,7 @@ int amdgpu_vm_bo_update_mapping(struct amdgpu_device *adev, · 22 unmodified lines | ||
| 406 | 408 | struct dma_fence **fence, bool *free_table); |
| 407 | 409 | int amdgpu_vm_bo_update(struct amdgpu_device *adev, |
| 408 | 410 | struct amdgpu_bo_va *bo_va, |
| 409 | − bool clear); | |
| 411 | + bool clear, bool *table_freed); | |
| 410 | 412 | bool amdgpu_vm_evictable(struct amdgpu_bo *bo); |
| 411 | 413 | void amdgpu_vm_bo_invalidate(struct amdgpu_device *adev, |
| 412 | 414 | struct amdgpu_bo *bo, bool evicted); |
| @@ -446,7 +448,7 @@ void amdgpu_vm_check_compute_bug(struct amdgpu_device *adev); · 33 unmodified lines | ||
| 446 | 448 | void amdgpu_vm_get_task_info(struct amdgpu_device *adev, u32 pasid, |
| 447 | 449 | struct amdgpu_task_info *task_info); |
| 448 | 450 | bool amdgpu_vm_handle_fault(struct amdgpu_device *adev, u32 pasid, |
| 449 | − uint64_t addr); | |
| 451 | + uint64_t addr, bool write_fault); | |
| 450 | 452 | |
| 451 | 453 | void amdgpu_vm_set_task_info(struct amdgpu_vm *vm); |
| 452 | 454 | |
| @@ -32,6 +32,10 @@ · 31 unmodified lines | ||
| 32 | 32 | #include "wafl/wafl2_4_0_0_smn.h" |
| 33 | 33 | #include "wafl/wafl2_4_0_0_sh_mask.h" |
| 34 | 34 | |
| 35 | +#define smnPCS_XGMI23_PCS_ERROR_STATUS 0x11a01210 | |
| 36 | +#define smnPCS_XGMI3X16_PCS_ERROR_STATUS 0x11a0020c | |
| 37 | +#define smnPCS_GOPX1_PCS_ERROR_STATUS 0x12200210 | |
| 38 | + | |
| 35 | 39 | static DEFINE_MUTEX(xgmi_mutex); |
| 36 | 40 | |
| 37 | 41 | #define AMDGPU_MAX_XGMI_DEVICE_PER_HIVE 4 |
| @@ -63,6 +67,33 @@ static const int wafl_pcs_err_status_reg_arct[] = { · 25 unmodified lines | ||
| 63 | 67 | smnPCS_GOPX1_0_PCS_GOPX1_PCS_ERROR_STATUS + 0x100000, |
| 64 | 68 | }; |
| 65 | 69 | |
| 70 | +static const int xgmi23_pcs_err_status_reg_aldebaran[] = { | |
| 71 | + smnPCS_XGMI23_PCS_ERROR_STATUS, | |
| 72 | + smnPCS_XGMI23_PCS_ERROR_STATUS + 0x100000, | |
| 73 | + smnPCS_XGMI23_PCS_ERROR_STATUS + 0x200000, | |
| 74 | + smnPCS_XGMI23_PCS_ERROR_STATUS + 0x300000, | |
| 75 | + smnPCS_XGMI23_PCS_ERROR_STATUS + 0x400000, | |
| 76 | + smnPCS_XGMI23_PCS_ERROR_STATUS + 0x500000, | |
| 77 | + smnPCS_XGMI23_PCS_ERROR_STATUS + 0x600000, | |
| 78 | + smnPCS_XGMI23_PCS_ERROR_STATUS + 0x700000 | |
| 79 | +}; | |
| 80 | + | |
| 81 | +static const int xgmi3x16_pcs_err_status_reg_aldebaran[] = { | |
| 82 | + smnPCS_XGMI3X16_PCS_ERROR_STATUS, | |
| 83 | + smnPCS_XGMI3X16_PCS_ERROR_STATUS + 0x100000, | |
| 84 | + smnPCS_XGMI3X16_PCS_ERROR_STATUS + 0x200000, | |
| 85 | + smnPCS_XGMI3X16_PCS_ERROR_STATUS + 0x300000, | |
| 86 | + smnPCS_XGMI3X16_PCS_ERROR_STATUS + 0x400000, | |
| 87 | + smnPCS_XGMI3X16_PCS_ERROR_STATUS + 0x500000, | |
| 88 | + smnPCS_XGMI3X16_PCS_ERROR_STATUS + 0x600000, | |
| 89 | + smnPCS_XGMI3X16_PCS_ERROR_STATUS + 0x700000 | |
| 90 | +}; | |
| 91 | + | |
| 92 | +static const int walf_pcs_err_status_reg_aldebaran[] = { | |
| 93 | + smnPCS_GOPX1_PCS_ERROR_STATUS, | |
| 94 | + smnPCS_GOPX1_PCS_ERROR_STATUS + 0x100000 | |
| 95 | +}; | |
| 96 | + | |
| 66 | 97 | static const struct amdgpu_pcs_ras_field xgmi_pcs_ras_fields[] = { |
| 67 | 98 | {"XGMI PCS DataLossErr", |
| 68 | 99 | SOC15_REG_FIELD(XGMI0_PCS_GOPX16_PCS_ERROR_STATUS, DataLossErr)}, |
| @@ -486,6 +517,44 @@ int amdgpu_xgmi_get_hops_count(struct amdgpu_device *adev, · 417 unmodified lines | ||
| 486 | 517 | return -EINVAL; |
| 487 | 518 | } |
| 488 | 519 | |
| 520 | +int amdgpu_xgmi_get_num_links(struct amdgpu_device *adev, | |
| 521 | + struct amdgpu_device *peer_adev) | |
| 522 | +{ | |
| 523 | + struct psp_xgmi_topology_info *top = &adev->psp.xgmi_context.top_info; | |
| 524 | + int i; | |
| 525 | + | |
| 526 | + for (i = 0 ; i < top->num_nodes; ++i) | |
| 527 | + if (top->nodes[i].node_id == peer_adev->gmc.xgmi.node_id) | |
| 528 | + return top->nodes[i].num_links; | |
| 529 | + return -EINVAL; | |
| 530 | +} | |
| 531 | + | |
| 532 | +/* | |
| 533 | + * Devices that support extended data require the entire hive to initialize with | |
| 534 | + * the shared memory buffer flag set. | |
| 535 | + * | |
| 536 | + * Hive locks and conditions apply - see amdgpu_xgmi_add_device | |
| 537 | + */ | |
| 538 | +static int amdgpu_xgmi_initialize_hive_get_data_partition(struct amdgpu_hive_info *hive, | |
| 539 | + bool set_extended_data) | |
| 540 | +{ | |
| 541 | + struct amdgpu_device *tmp_adev; | |
| 542 | + int ret; | |
| 543 | + | |
| 544 | + list_for_each_entry(tmp_adev, &hive->device_list, gmc.xgmi.head) { | |
| 545 | + ret = psp_xgmi_initialize(&tmp_adev->psp, set_extended_data, false); | |
| 546 | + if (ret) { | |
| 547 | + dev_err(tmp_adev->dev, | |
| 548 | + "XGMI: Failed to initialize xgmi session for data partition %i\n", | |
| 549 | + set_extended_data); | |
| 550 | + return ret; | |
| 551 | + } | |
| 552 | + | |
| 553 | + } | |
| 554 | + | |
| 555 | + return 0; | |
| 556 | +} | |
| 557 | + | |
| 489 | 558 | int amdgpu_xgmi_add_device(struct amdgpu_device *adev) |
| 490 | 559 | { |
| 491 | 560 | struct psp_xgmi_topology_info *top_info; |
| @@ -500,7 +569,7 @@ int amdgpu_xgmi_add_device(struct amdgpu_device *adev) · 8 unmodified lines | ||
| 500 | 569 | |
| 501 | 570 | if (!adev->gmc.xgmi.pending_reset && |
| 502 | 571 | amdgpu_device_ip_get_ip_block(adev, AMD_IP_BLOCK_TYPE_PSP)) { |
| 503 | − ret = psp_xgmi_initialize(&adev->psp); | |
| 572 | + ret = psp_xgmi_initialize(&adev->psp, false, true); | |
| 504 | 573 | if (ret) { |
| 505 | 574 | dev_err(adev->dev, |
| 506 | 575 | "XGMI: Failed to initialize xgmi session\n"); |
| @@ -563,7 +632,7 @@ int amdgpu_xgmi_add_device(struct amdgpu_device *adev) · 56 unmodified lines | ||
| 563 | 632 | /* get latest topology info for each device from psp */ |
| 564 | 633 | list_for_each_entry(tmp_adev, &hive->device_list, gmc.xgmi.head) { |
| 565 | 634 | ret = psp_xgmi_get_topology_info(&tmp_adev->psp, count, |
| 566 | − &tmp_adev->psp.xgmi_context.top_info); | |
| 635 | + &tmp_adev->psp.xgmi_context.top_info, false); | |
| 567 | 636 | if (ret) { |
| 568 | 637 | dev_err(tmp_adev->dev, |
| 569 | 638 | "XGMI: Get topology failure on device %llx, hive %llx, ret %d", |
| @@ -573,6 +642,34 @@ int amdgpu_xgmi_add_device(struct amdgpu_device *adev) · 3 unmodified lines | ||
| 573 | 642 | goto exit_unlock; |
| 574 | 643 | } |
| 575 | 644 | } |
| 645 | + | |
| 646 | + /* get topology again for hives that support extended data */ | |
| 647 | + if (adev->psp.xgmi_context.supports_extended_data) { | |
| 648 | + | |
| 649 | + /* initialize the hive to get extended data. */ | |
| 650 | + ret = amdgpu_xgmi_initialize_hive_get_data_partition(hive, true); | |
| 651 | + if (ret) | |
| 652 | + goto exit_unlock; | |
| 653 | + | |
| 654 | + /* get the extended data. */ | |
| 655 | + list_for_each_entry(tmp_adev, &hive->device_list, gmc.xgmi.head) { | |
| 656 | + ret = psp_xgmi_get_topology_info(&tmp_adev->psp, count, | |
| 657 | + &tmp_adev->psp.xgmi_context.top_info, true); | |
| 658 | + if (ret) { | |
| 659 | + dev_err(tmp_adev->dev, | |
| 660 | + "XGMI: Get topology for extended data failure on device %llx, hive %llx, ret %d", | |
| 661 | + tmp_adev->gmc.xgmi.node_id, | |
| 662 | + tmp_adev->gmc.xgmi.hive_id, ret); | |
| 663 | + goto exit_unlock; | |
| 664 | + } | |
| 665 | + } | |
| 666 | + | |
| 667 | + /* initialize the hive to get non-extended data for the next round. */ | |
| 668 | + ret = amdgpu_xgmi_initialize_hive_get_data_partition(hive, false); | |
| 669 | + if (ret) | |
| 670 | + goto exit_unlock; | |
| 671 | + | |
| 672 | + } | |
| 576 | 673 | } |
| 577 | 674 | |
| 578 | 675 | if (!ret && !adev->gmc.xgmi.pending_reset) |
| @@ -651,7 +748,6 @@ static int amdgpu_xgmi_ras_late_init(struct amdgpu_device *adev) · 72 unmodified lines | ||
| 651 | 748 | adev->gmc.xgmi.ras_if->block = AMDGPU_RAS_BLOCK__XGMI_WAFL; |
| 652 | 749 | adev->gmc.xgmi.ras_if->type = AMDGPU_RAS_ERROR__MULTI_UNCORRECTABLE; |
| 653 | 750 | adev->gmc.xgmi.ras_if->sub_block_index = 0; |
| 654 | − strcpy(adev->gmc.xgmi.ras_if->name, "xgmi_wafl"); | |
| 655 | 751 | } |
| 656 | 752 | ih_info.head = fs_info.head = *adev->gmc.xgmi.ras_if; |
| 657 | 753 | r = amdgpu_ras_late_init(adev, adev->gmc.xgmi.ras_if, |
| @@ -706,6 +802,17 @@ static void amdgpu_xgmi_reset_ras_error_count(struct amdgpu_device *adev) · 48 unmodified lines | ||
| 706 | 802 | pcs_clear_status(adev, |
| 707 | 803 | xgmi_pcs_err_status_reg_vg20[i]); |
| 708 | 804 | break; |
| 805 | + case CHIP_ALDEBARAN: | |
| 806 | + for (i = 0; i < ARRAY_SIZE(xgmi23_pcs_err_status_reg_aldebaran); i++) | |
| 807 | + pcs_clear_status(adev, | |
| 808 | + xgmi23_pcs_err_status_reg_aldebaran[i]); | |
| 809 | + for (i = 0; i < ARRAY_SIZE(xgmi23_pcs_err_status_reg_aldebaran); i++) | |
| 810 | + pcs_clear_status(adev, | |
| 811 | + xgmi23_pcs_err_status_reg_aldebaran[i]); | |
| 812 | + for (i = 0; i < ARRAY_SIZE(walf_pcs_err_status_reg_aldebaran); i++) | |
| 813 | + pcs_clear_status(adev, | |
| 814 | + walf_pcs_err_status_reg_aldebaran[i]); | |
| 815 | + break; | |
| 709 | 816 | default: |
| 710 | 817 | break; |
| 711 | 818 | } |
| @@ -783,7 +890,6 @@ static int amdgpu_xgmi_query_ras_error_count(struct amdgpu_device *adev, · 71 unmodified lines | ||
| 783 | 890 | } |
| 784 | 891 | break; |
| 785 | 892 | case CHIP_VEGA20: |
| 786 | − default: | |
| 787 | 893 | /* check xgmi pcs error */ |
| 788 | 894 | for (i = 0; i < ARRAY_SIZE(xgmi_pcs_err_status_reg_vg20); i++) { |
| 789 | 895 | data = RREG32_PCIE(xgmi_pcs_err_status_reg_vg20[i]); |
| @@ -799,6 +905,32 @@ static int amdgpu_xgmi_query_ras_error_count(struct amdgpu_device *adev, · 9 unmodified lines | ||
| 799 | 905 | data, &ue_cnt, &ce_cnt, false); |
| 800 | 906 | } |
| 801 | 907 | break; |
| 908 | + case CHIP_ALDEBARAN: | |
| 909 | + /* check xgmi23 pcs error */ | |
| 910 | + for (i = 0; i < ARRAY_SIZE(xgmi23_pcs_err_status_reg_aldebaran); i++) { | |
| 911 | + data = RREG32_PCIE(xgmi23_pcs_err_status_reg_aldebaran[i]); | |
| 912 | + if (data) | |
| 913 | + amdgpu_xgmi_query_pcs_error_status(adev, | |
| 914 | + data, &ue_cnt, &ce_cnt, true); | |
| 915 | + } | |
| 916 | + /* check xgmi3x16 pcs error */ | |
| 917 | + for (i = 0; i < ARRAY_SIZE(xgmi3x16_pcs_err_status_reg_aldebaran); i++) { | |
| 918 | + data = RREG32_PCIE(xgmi3x16_pcs_err_status_reg_aldebaran[i]); | |
| 919 | + if (data) | |
| 920 | + amdgpu_xgmi_query_pcs_error_status(adev, | |
| 921 | + data, &ue_cnt, &ce_cnt, true); | |
| 922 | + } | |
| 923 | + /* check wafl pcs error */ | |
| 924 | + for (i = 0; i < ARRAY_SIZE(walf_pcs_err_status_reg_aldebaran); i++) { | |
| 925 | + data = RREG32_PCIE(walf_pcs_err_status_reg_aldebaran[i]); | |
| 926 | + if (data) | |
| 927 | + amdgpu_xgmi_query_pcs_error_status(adev, | |
| 928 | + data, &ue_cnt, &ce_cnt, false); | |
| 929 | + } | |
| 930 | + break; | |
| 931 | + default: | |
| 932 | + dev_warn(adev->dev, "XGMI RAS error query not supported"); | |
| 933 | + break; | |
| 802 | 934 | } |
| 803 | 935 | |
| 804 | 936 | adev->gmc.xgmi.ras_funcs->reset_ras_error_count(adev); |
| @@ -59,6 +59,8 @@ int amdgpu_xgmi_remove_device(struct amdgpu_device *adev); · 58 unmodified lines | ||
| 59 | 59 | int amdgpu_xgmi_set_pstate(struct amdgpu_device *adev, int pstate); |
| 60 | 60 | int amdgpu_xgmi_get_hops_count(struct amdgpu_device *adev, |
| 61 | 61 | struct amdgpu_device *peer_adev); |
| 62 | +int amdgpu_xgmi_get_num_links(struct amdgpu_device *adev, | |
| 63 | + struct amdgpu_device *peer_adev); | |
| 62 | 64 | uint64_t amdgpu_xgmi_get_relative_phy_addr(struct amdgpu_device *adev, |
| 63 | 65 | uint64_t addr); |
| 64 | 66 | static inline bool amdgpu_xgmi_same_hive(struct amdgpu_device *adev, |
| @@ -851,7 +851,7 @@ void amdgpu_atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode · 850 unmodified lines | ||
| 851 | 851 | pll->reference_div = amdgpu_crtc->pll_reference_div; |
| 852 | 852 | pll->post_div = amdgpu_crtc->pll_post_div; |
| 853 | 853 | |
| 854 | − amdgpu_pll_compute(pll, amdgpu_crtc->adjusted_clock, &pll_clock, | |
| 854 | + amdgpu_pll_compute(adev, pll, amdgpu_crtc->adjusted_clock, &pll_clock, | |
| 855 | 855 | &fb_div, &frac_fb_div, &ref_div, &post_div); |
| 856 | 856 | |
| 857 | 857 | amdgpu_atombios_crtc_program_ss(adev, ATOM_DISABLE, amdgpu_crtc->pll_id, |
| @@ -70,7 +70,7 @@ · 69 unmodified lines | ||
| 70 | 70 | |
| 71 | 71 | #include "amdgpu_dm.h" |
| 72 | 72 | #include "amdgpu_amdkfd.h" |
| 73 | −#include "dce_virtual.h" | |
| 73 | +#include "amdgpu_vkms.h" | |
| 74 | 74 | |
| 75 | 75 | static const struct amdgpu_video_codec_info cik_video_codecs_encode_array[] = |
| 76 | 76 | { |
| @@ -2259,7 +2259,7 @@ int cik_set_ip_blocks(struct amdgpu_device *adev) · 2182 unmodified lines | ||
| 2259 | 2259 | amdgpu_device_ip_block_add(adev, &cik_sdma_ip_block); |
| 2260 | 2260 | amdgpu_device_ip_block_add(adev, &pp_smu_ip_block); |
| 2261 | 2261 | if (adev->enable_virtual_display) |
| 2262 | − amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block); | |
| 2262 | + amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block); | |
| 2263 | 2263 | #if defined(CONFIG_DRM_AMD_DC) |
| 2264 | 2264 | else if (amdgpu_device_has_dc_support(adev)) |
| 2265 | 2265 | amdgpu_device_ip_block_add(adev, &dm_ip_block); |
| @@ -2277,7 +2277,7 @@ int cik_set_ip_blocks(struct amdgpu_device *adev) · 11 unmodified lines | ||
| 2277 | 2277 | amdgpu_device_ip_block_add(adev, &cik_sdma_ip_block); |
| 2278 | 2278 | amdgpu_device_ip_block_add(adev, &pp_smu_ip_block); |
| 2279 | 2279 | if (adev->enable_virtual_display) |
| 2280 | − amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block); | |
| 2280 | + amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block); | |
| 2281 | 2281 | #if defined(CONFIG_DRM_AMD_DC) |
| 2282 | 2282 | else if (amdgpu_device_has_dc_support(adev)) |
| 2283 | 2283 | amdgpu_device_ip_block_add(adev, &dm_ip_block); |
| @@ -2295,7 +2295,7 @@ int cik_set_ip_blocks(struct amdgpu_device *adev) · 11 unmodified lines | ||
| 2295 | 2295 | amdgpu_device_ip_block_add(adev, &cik_sdma_ip_block); |
| 2296 | 2296 | amdgpu_device_ip_block_add(adev, &kv_smu_ip_block); |
| 2297 | 2297 | if (adev->enable_virtual_display) |
| 2298 | − amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block); | |
| 2298 | + amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block); | |
| 2299 | 2299 | #if defined(CONFIG_DRM_AMD_DC) |
| 2300 | 2300 | else if (amdgpu_device_has_dc_support(adev)) |
| 2301 | 2301 | amdgpu_device_ip_block_add(adev, &dm_ip_block); |
| @@ -2315,7 +2315,7 @@ int cik_set_ip_blocks(struct amdgpu_device *adev) · 13 unmodified lines | ||
| 2315 | 2315 | amdgpu_device_ip_block_add(adev, &cik_sdma_ip_block); |
| 2316 | 2316 | amdgpu_device_ip_block_add(adev, &kv_smu_ip_block); |
| 2317 | 2317 | if (adev->enable_virtual_display) |
| 2318 | − amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block); | |
| 2318 | + amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block); | |
| 2319 | 2319 | #if defined(CONFIG_DRM_AMD_DC) |
| 2320 | 2320 | else if (amdgpu_device_has_dc_support(adev)) |
| 2321 | 2321 | amdgpu_device_ip_block_add(adev, &dm_ip_block); |
| @@ -0,0 +1,51 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright 2018 Advanced Micro Devices, Inc. | |
| 3 | + * | |
| 4 | + * Permission is hereby granted, free of charge, to any person obtaining a | |
| 5 | + * copy of this software and associated documentation files (the "Software"), | |
| 6 | + * to deal in the Software without restriction, including without limitation | |
| 7 | + * the rights to use, copy, modify, merge, publish, distribute, sublicense, | |
| 8 | + * and/or sell copies of the Software, and to permit persons to whom the | |
| 9 | + * Software is furnished to do so, subject to the following conditions: | |
| 10 | + * | |
| 11 | + * The above copyright notice and this permission notice shall be included in | |
| 12 | + * all copies or substantial portions of the Software. | |
| 13 | + * | |
| 14 | + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
| 15 | + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
| 16 | + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |
| 17 | + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR | |
| 18 | + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | |
| 19 | + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | |
| 20 | + * OTHER DEALINGS IN THE SOFTWARE. | |
| 21 | + * | |
| 22 | + */ | |
| 23 | +#include "amdgpu.h" | |
| 24 | +#include "nv.h" | |
| 25 | + | |
| 26 | +#include "soc15_common.h" | |
| 27 | +#include "soc15_hw_ip.h" | |
| 28 | +#include "cyan_skillfish_ip_offset.h" | |
| 29 | + | |
| 30 | +int cyan_skillfish_reg_base_init(struct amdgpu_device *adev) | |
| 31 | +{ | |
| 32 | + /* HW has more IP blocks, only initialized the blocke needed by driver */ | |
| 33 | + uint32_t i; | |
| 34 | + for (i = 0 ; i < MAX_INSTANCE ; ++i) { | |
| 35 | + adev->reg_offset[GC_HWIP][i] = (uint32_t *)(&(GC_BASE.instance[i])); | |
| 36 | + adev->reg_offset[HDP_HWIP][i] = (uint32_t *)(&(HDP_BASE.instance[i])); | |
| 37 | + adev->reg_offset[MMHUB_HWIP][i] = (uint32_t *)(&(MMHUB_BASE.instance[i])); | |
| 38 | + adev->reg_offset[ATHUB_HWIP][i] = (uint32_t *)(&(ATHUB_BASE.instance[i])); | |
| 39 | + adev->reg_offset[NBIO_HWIP][i] = (uint32_t *)(&(NBIO_BASE.instance[i])); | |
| 40 | + adev->reg_offset[MP0_HWIP][i] = (uint32_t *)(&(MP0_BASE.instance[i])); | |
| 41 | + adev->reg_offset[MP1_HWIP][i] = (uint32_t *)(&(MP1_BASE.instance[i])); | |
| 42 | + adev->reg_offset[VCN_HWIP][i] = (uint32_t *)(&(UVD0_BASE.instance[i])); | |
| 43 | + adev->reg_offset[DF_HWIP][i] = (uint32_t *)(&(DF_BASE.instance[i])); | |
| 44 | + adev->reg_offset[DCE_HWIP][i] = (uint32_t *)(&(DMU_BASE.instance[i])); | |
| 45 | + adev->reg_offset[OSSSYS_HWIP][i] = (uint32_t *)(&(OSSSYS_BASE.instance[i])); | |
| 46 | + adev->reg_offset[SDMA0_HWIP][i] = (uint32_t *)(&(GC_BASE.instance[i])); | |
| 47 | + adev->reg_offset[SDMA1_HWIP][i] = (uint32_t *)(&(GC_BASE.instance[i])); | |
| 48 | + adev->reg_offset[SMUIO_HWIP][i] = (uint32_t *)(&(SMUIO_BASE.instance[i])); | |
| 49 | + } | |
| 50 | + return 0; | |
| 51 | +} | |
| @@ -1,780 +0,0 @@ | ||
| 1 | −/* | |
| 2 | − * Copyright 2014 Advanced Micro Devices, Inc. | |
| 3 | − * | |
| 4 | − * Permission is hereby granted, free of charge, to any person obtaining a | |
| 5 | − * copy of this software and associated documentation files (the "Software"), | |
| 6 | − * to deal in the Software without restriction, including without limitation | |
| 7 | − * the rights to use, copy, modify, merge, publish, distribute, sublicense, | |
| 8 | − * and/or sell copies of the Software, and to permit persons to whom the | |
| 9 | − * Software is furnished to do so, subject to the following conditions: | |
| 10 | − * | |
| 11 | − * The above copyright notice and this permission notice shall be included in | |
| 12 | − * all copies or substantial portions of the Software. | |
| 13 | − * | |
| 14 | − * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
| 15 | − * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
| 16 | − * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |
| 17 | − * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR | |
| 18 | − * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | |
| 19 | − * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | |
| 20 | − * OTHER DEALINGS IN THE SOFTWARE. | |
| 21 | − * | |
| 22 | − */ | |
| 23 | − | |
| 24 | −#include <drm/drm_vblank.h> | |
| 25 | − | |
| 26 | −#include "amdgpu.h" | |
| 27 | −#include "amdgpu_pm.h" | |
| 28 | −#include "amdgpu_i2c.h" | |
| 29 | −#include "atom.h" | |
| 30 | −#include "amdgpu_pll.h" | |
| 31 | −#include "amdgpu_connectors.h" | |
| 32 | −#ifdef CONFIG_DRM_AMDGPU_SI | |
| 33 | −#include "dce_v6_0.h" | |
| 34 | −#endif | |
| 35 | −#ifdef CONFIG_DRM_AMDGPU_CIK | |
| 36 | −#include "dce_v8_0.h" | |
| 37 | −#endif | |
| 38 | −#include "dce_v10_0.h" | |
| 39 | −#include "dce_v11_0.h" | |
| 40 | −#include "dce_virtual.h" | |
| 41 | −#include "ivsrcid/ivsrcid_vislands30.h" | |
| 42 | −#include "amdgpu_display.h" | |
| 43 | − | |
| 44 | −#define DCE_VIRTUAL_VBLANK_PERIOD 16666666 | |
| 45 | − | |
| 46 | − | |
| 47 | −static void dce_virtual_set_display_funcs(struct amdgpu_device *adev); | |
| 48 | −static void dce_virtual_set_irq_funcs(struct amdgpu_device *adev); | |
| 49 | −static int dce_virtual_connector_encoder_init(struct amdgpu_device *adev, | |
| 50 | − int index); | |
| 51 | −static int dce_virtual_pageflip(struct amdgpu_device *adev, | |
| 52 | − unsigned crtc_id); | |
| 53 | −static enum hrtimer_restart dce_virtual_vblank_timer_handle(struct hrtimer *vblank_timer); | |
| 54 | −static void dce_virtual_set_crtc_vblank_interrupt_state(struct amdgpu_device *adev, | |
| 55 | − int crtc, | |
| 56 | − enum amdgpu_interrupt_state state); | |
| 57 | − | |
| 58 | −static u32 dce_virtual_vblank_get_counter(struct amdgpu_device *adev, int crtc) | |
| 59 | −{ | |
| 60 | − return 0; | |
| 61 | −} | |
| 62 | − | |
| 63 | −static void dce_virtual_page_flip(struct amdgpu_device *adev, | |
| 64 | − int crtc_id, u64 crtc_base, bool async) | |
| 65 | −{ | |
| 66 | − return; | |
| 67 | −} | |
| 68 | − | |
| 69 | −static int dce_virtual_crtc_get_scanoutpos(struct amdgpu_device *adev, int crtc, | |
| 70 | − u32 *vbl, u32 *position) | |
| 71 | −{ | |
| 72 | − *vbl = 0; | |
| 73 | − *position = 0; | |
| 74 | − | |
| 75 | − return -EINVAL; | |
| 76 | −} | |
| 77 | − | |
| 78 | −static bool dce_virtual_hpd_sense(struct amdgpu_device *adev, | |
| 79 | − enum amdgpu_hpd_id hpd) | |
| 80 | −{ | |
| 81 | − return true; | |
| 82 | −} | |
| 83 | − | |
| 84 | −static void dce_virtual_hpd_set_polarity(struct amdgpu_device *adev, | |
| 85 | − enum amdgpu_hpd_id hpd) | |
| 86 | −{ | |
| 87 | − return; | |
| 88 | −} | |
| 89 | − | |
| 90 | −static u32 dce_virtual_hpd_get_gpio_reg(struct amdgpu_device *adev) | |
| 91 | −{ | |
| 92 | − return 0; | |
| 93 | −} | |
| 94 | − | |
| 95 | −/** | |
| 96 | − * dce_virtual_bandwidth_update - program display watermarks | |
| 97 | − * | |
| 98 | − * @adev: amdgpu_device pointer | |
| 99 | − * | |
| 100 | − * Calculate and program the display watermarks and line | |
| 101 | − * buffer allocation (CIK). | |
| 102 | − */ | |
| 103 | −static void dce_virtual_bandwidth_update(struct amdgpu_device *adev) | |
| 104 | −{ | |
| 105 | − return; | |
| 106 | −} | |
| 107 | − | |
| 108 | −static int dce_virtual_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, | |
| 109 | − u16 *green, u16 *blue, uint32_t size, | |
| 110 | − struct drm_modeset_acquire_ctx *ctx) | |
| 111 | −{ | |
| 112 | − return 0; | |
| 113 | −} | |
| 114 | − | |
| 115 | −static void dce_virtual_crtc_destroy(struct drm_crtc *crtc) | |
| 116 | −{ | |
| 117 | − struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); | |
| 118 | − | |
| 119 | − drm_crtc_cleanup(crtc); | |
| 120 | − kfree(amdgpu_crtc); | |
| 121 | −} | |
| 122 | − | |
| 123 | −static const struct drm_crtc_funcs dce_virtual_crtc_funcs = { | |
| 124 | − .cursor_set2 = NULL, | |
| 125 | − .cursor_move = NULL, | |
| 126 | − .gamma_set = dce_virtual_crtc_gamma_set, | |
| 127 | − .set_config = amdgpu_display_crtc_set_config, | |
| 128 | − .destroy = dce_virtual_crtc_destroy, | |
| 129 | − .page_flip_target = amdgpu_display_crtc_page_flip_target, | |
| 130 | − .get_vblank_counter = amdgpu_get_vblank_counter_kms, | |
| 131 | − .enable_vblank = amdgpu_enable_vblank_kms, | |
| 132 | − .disable_vblank = amdgpu_disable_vblank_kms, | |
| 133 | − .get_vblank_timestamp = drm_crtc_vblank_helper_get_vblank_timestamp, | |
| 134 | −}; | |
| 135 | − | |
| 136 | −static void dce_virtual_crtc_dpms(struct drm_crtc *crtc, int mode) | |
| 137 | −{ | |
| 138 | − struct drm_device *dev = crtc->dev; | |
| 139 | − struct amdgpu_device *adev = drm_to_adev(dev); | |
| 140 | − struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); | |
| 141 | − unsigned type; | |
| 142 | − | |
| 143 | − switch (mode) { | |
| 144 | − case DRM_MODE_DPMS_ON: | |
| 145 | − amdgpu_crtc->enabled = true; | |
| 146 | − /* Make sure VBLANK interrupts are still enabled */ | |
| 147 | − type = amdgpu_display_crtc_idx_to_irq_type(adev, | |
| 148 | − amdgpu_crtc->crtc_id); | |
| 149 | − amdgpu_irq_update(adev, &adev->crtc_irq, type); | |
| 150 | − drm_crtc_vblank_on(crtc); | |
| 151 | − break; | |
| 152 | − case DRM_MODE_DPMS_STANDBY: | |
| 153 | − case DRM_MODE_DPMS_SUSPEND: | |
| 154 | − case DRM_MODE_DPMS_OFF: | |
| 155 | − drm_crtc_vblank_off(crtc); | |
| 156 | − amdgpu_crtc->enabled = false; | |
| 157 | − break; | |
| 158 | − } | |
| 159 | −} | |
| 160 | − | |
| 161 | − | |
| 162 | −static void dce_virtual_crtc_prepare(struct drm_crtc *crtc) | |
| 163 | −{ | |
| 164 | − dce_virtual_crtc_dpms(crtc, DRM_MODE_DPMS_OFF); | |
| 165 | −} | |
| 166 | − | |
| 167 | −static void dce_virtual_crtc_commit(struct drm_crtc *crtc) | |
| 168 | −{ | |
| 169 | − dce_virtual_crtc_dpms(crtc, DRM_MODE_DPMS_ON); | |
| 170 | −} | |
| 171 | − | |
| 172 | −static void dce_virtual_crtc_disable(struct drm_crtc *crtc) | |
| 173 | −{ | |
| 174 | − struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); | |
| 175 | − struct drm_device *dev = crtc->dev; | |
| 176 | − | |
| 177 | − if (dev->num_crtcs) | |
| 178 | − drm_crtc_vblank_off(crtc); | |
| 179 | − | |
| 180 | − amdgpu_crtc->enabled = false; | |
| 181 | − amdgpu_crtc->pll_id = ATOM_PPLL_INVALID; | |
| 182 | − amdgpu_crtc->encoder = NULL; | |
| 183 | − amdgpu_crtc->connector = NULL; | |
| 184 | −} | |
| 185 | − | |
| 186 | −static int dce_virtual_crtc_mode_set(struct drm_crtc *crtc, | |
| 187 | − struct drm_display_mode *mode, | |
| 188 | − struct drm_display_mode *adjusted_mode, | |
| 189 | − int x, int y, struct drm_framebuffer *old_fb) | |
| 190 | −{ | |
| 191 | − struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); | |
| 192 | − | |
| 193 | − /* update the hw version fpr dpm */ | |
| 194 | − amdgpu_crtc->hw_mode = *adjusted_mode; | |
| 195 | − | |
| 196 | − return 0; | |
| 197 | −} | |
| 198 | − | |
| 199 | −static bool dce_virtual_crtc_mode_fixup(struct drm_crtc *crtc, | |
| 200 | − const struct drm_display_mode *mode, | |
| 201 | − struct drm_display_mode *adjusted_mode) | |
| 202 | −{ | |
| 203 | − return true; | |
| 204 | −} | |
| 205 | − | |
| 206 | − | |
| 207 | −static int dce_virtual_crtc_set_base(struct drm_crtc *crtc, int x, int y, | |
| 208 | − struct drm_framebuffer *old_fb) | |
| 209 | −{ | |
| 210 | − return 0; | |
| 211 | −} | |
| 212 | − | |
| 213 | −static int dce_virtual_crtc_set_base_atomic(struct drm_crtc *crtc, | |
| 214 | − struct drm_framebuffer *fb, | |
| 215 | − int x, int y, enum mode_set_atomic state) | |
| 216 | −{ | |
| 217 | − return 0; | |
| 218 | −} | |
| 219 | − | |
| 220 | −static const struct drm_crtc_helper_funcs dce_virtual_crtc_helper_funcs = { | |
| 221 | − .dpms = dce_virtual_crtc_dpms, | |
| 222 | − .mode_fixup = dce_virtual_crtc_mode_fixup, | |
| 223 | − .mode_set = dce_virtual_crtc_mode_set, | |
| 224 | − .mode_set_base = dce_virtual_crtc_set_base, | |
| 225 | − .mode_set_base_atomic = dce_virtual_crtc_set_base_atomic, | |
| 226 | − .prepare = dce_virtual_crtc_prepare, | |
| 227 | − .commit = dce_virtual_crtc_commit, | |
| 228 | − .disable = dce_virtual_crtc_disable, | |
| 229 | − .get_scanout_position = amdgpu_crtc_get_scanout_position, | |
| 230 | −}; | |
| 231 | − | |
| 232 | −static int dce_virtual_crtc_init(struct amdgpu_device *adev, int index) | |
| 233 | −{ | |
| 234 | − struct amdgpu_crtc *amdgpu_crtc; | |
| 235 | − | |
| 236 | − amdgpu_crtc = kzalloc(sizeof(struct amdgpu_crtc) + | |
| 237 | − (AMDGPUFB_CONN_LIMIT * sizeof(struct drm_connector *)), GFP_KERNEL); | |
| 238 | − if (amdgpu_crtc == NULL) | |
| 239 | − return -ENOMEM; | |
| 240 | − | |
| 241 | − drm_crtc_init(adev_to_drm(adev), &amdgpu_crtc->base, &dce_virtual_crtc_funcs); | |
| 242 | − | |
| 243 | − drm_mode_crtc_set_gamma_size(&amdgpu_crtc->base, 256); | |
| 244 | − amdgpu_crtc->crtc_id = index; | |
| 245 | − adev->mode_info.crtcs[index] = amdgpu_crtc; | |
| 246 | − | |
| 247 | − amdgpu_crtc->pll_id = ATOM_PPLL_INVALID; | |
| 248 | − amdgpu_crtc->encoder = NULL; | |
| 249 | − amdgpu_crtc->connector = NULL; | |
| 250 | − amdgpu_crtc->vsync_timer_enabled = AMDGPU_IRQ_STATE_DISABLE; | |
| 251 | − drm_crtc_helper_add(&amdgpu_crtc->base, &dce_virtual_crtc_helper_funcs); | |
| 252 | − | |
| 253 | − hrtimer_init(&amdgpu_crtc->vblank_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); | |
| 254 | − hrtimer_set_expires(&amdgpu_crtc->vblank_timer, DCE_VIRTUAL_VBLANK_PERIOD); | |
| 255 | − amdgpu_crtc->vblank_timer.function = dce_virtual_vblank_timer_handle; | |
| 256 | − hrtimer_start(&amdgpu_crtc->vblank_timer, | |
| 257 | − DCE_VIRTUAL_VBLANK_PERIOD, HRTIMER_MODE_REL); | |
| 258 | − return 0; | |
| 259 | −} | |
| 260 | − | |
| 261 | −static int dce_virtual_early_init(void *handle) | |
| 262 | −{ | |
| 263 | − struct amdgpu_device *adev = (struct amdgpu_device *)handle; | |
| 264 | − | |
| 265 | − dce_virtual_set_display_funcs(adev); | |
| 266 | − dce_virtual_set_irq_funcs(adev); | |
| 267 | − | |
| 268 | − adev->mode_info.num_hpd = 1; | |
| 269 | − adev->mode_info.num_dig = 1; | |
| 270 | − return 0; | |
| 271 | −} | |
| 272 | − | |
| 273 | −static struct drm_encoder * | |
| 274 | −dce_virtual_encoder(struct drm_connector *connector) | |
| 275 | −{ | |
| 276 | − struct drm_encoder *encoder; | |
| 277 | − | |
| 278 | − drm_connector_for_each_possible_encoder(connector, encoder) { | |
| 279 | − if (encoder->encoder_type == DRM_MODE_ENCODER_VIRTUAL) | |
| 280 | − return encoder; | |
| 281 | − } | |
| 282 | − | |
| 283 | − /* pick the first one */ | |
| 284 | − drm_connector_for_each_possible_encoder(connector, encoder) | |
| 285 | − return encoder; | |
| 286 | − | |
| 287 | − return NULL; | |
| 288 | −} | |
| 289 | − | |
| 290 | −static int dce_virtual_get_modes(struct drm_connector *connector) | |
| 291 | −{ | |
| 292 | − struct drm_device *dev = connector->dev; | |
| 293 | − struct drm_display_mode *mode = NULL; | |
| 294 | − unsigned i; | |
| 295 | − static const struct mode_size { | |
| 296 | − int w; | |
| 297 | − int h; | |
| 298 | − } common_modes[] = { | |
| 299 | − { 640, 480}, | |
| 300 | − { 720, 480}, | |
| 301 | − { 800, 600}, | |
| 302 | − { 848, 480}, | |
| 303 | − {1024, 768}, | |
| 304 | − {1152, 768}, | |
| 305 | − {1280, 720}, | |
| 306 | − {1280, 800}, | |
| 307 | − {1280, 854}, | |
| 308 | − {1280, 960}, | |
| 309 | − {1280, 1024}, | |
| 310 | − {1440, 900}, | |
| 311 | − {1400, 1050}, | |
| 312 | − {1680, 1050}, | |
| 313 | − {1600, 1200}, | |
| 314 | − {1920, 1080}, | |
| 315 | − {1920, 1200}, | |
| 316 | − {2560, 1440}, | |
| 317 | − {4096, 3112}, | |
| 318 | − {3656, 2664}, | |
| 319 | − {3840, 2160}, | |
| 320 | − {4096, 2160}, | |
| 321 | − }; | |
| 322 | − | |
| 323 | − for (i = 0; i < ARRAY_SIZE(common_modes); i++) { | |
| 324 | − mode = drm_cvt_mode(dev, common_modes[i].w, common_modes[i].h, 60, false, false, false); | |
| 325 | − drm_mode_probed_add(connector, mode); | |
| 326 | − } | |
| 327 | − | |
| 328 | − return 0; | |
| 329 | −} | |
| 330 | − | |
| 331 | −static enum drm_mode_status dce_virtual_mode_valid(struct drm_connector *connector, | |
| 332 | − struct drm_display_mode *mode) | |
| 333 | −{ | |
| 334 | − return MODE_OK; | |
| 335 | −} | |
| 336 | − | |
| 337 | −static int | |
| 338 | −dce_virtual_dpms(struct drm_connector *connector, int mode) | |
| 339 | −{ | |
| 340 | − return 0; | |
| 341 | −} | |
| 342 | − | |
| 343 | −static int | |
| 344 | −dce_virtual_set_property(struct drm_connector *connector, | |
| 345 | − struct drm_property *property, | |
| 346 | − uint64_t val) | |
| 347 | −{ | |
| 348 | − return 0; | |
| 349 | −} | |
| 350 | − | |
| 351 | −static void dce_virtual_destroy(struct drm_connector *connector) | |
| 352 | −{ | |
| 353 | − drm_connector_unregister(connector); | |
| 354 | − drm_connector_cleanup(connector); | |
| 355 | − kfree(connector); | |
| 356 | −} | |
| 357 | − | |
| 358 | −static void dce_virtual_force(struct drm_connector *connector) | |
| 359 | −{ | |
| 360 | − return; | |
| 361 | −} | |
| 362 | − | |
| 363 | −static const struct drm_connector_helper_funcs dce_virtual_connector_helper_funcs = { | |
| 364 | − .get_modes = dce_virtual_get_modes, | |
| 365 | − .mode_valid = dce_virtual_mode_valid, | |
| 366 | − .best_encoder = dce_virtual_encoder, | |
| 367 | −}; | |
| 368 | − | |
| 369 | −static const struct drm_connector_funcs dce_virtual_connector_funcs = { | |
| 370 | − .dpms = dce_virtual_dpms, | |
| 371 | − .fill_modes = drm_helper_probe_single_connector_modes, | |
| 372 | − .set_property = dce_virtual_set_property, | |
| 373 | − .destroy = dce_virtual_destroy, | |
| 374 | − .force = dce_virtual_force, | |
| 375 | −}; | |
| 376 | − | |
| 377 | −static int dce_virtual_sw_init(void *handle) | |
| 378 | −{ | |
| 379 | − int r, i; | |
| 380 | − struct amdgpu_device *adev = (struct amdgpu_device *)handle; | |
| 381 | − | |
| 382 | − r = amdgpu_irq_add_id(adev, AMDGPU_IRQ_CLIENTID_LEGACY, VISLANDS30_IV_SRCID_SMU_DISP_TIMER2_TRIGGER, &adev->crtc_irq); | |
| 383 | − if (r) | |
| 384 | − return r; | |
| 385 | − | |
| 386 | − adev_to_drm(adev)->max_vblank_count = 0; | |
| 387 | − | |
| 388 | − adev_to_drm(adev)->mode_config.funcs = &amdgpu_mode_funcs; | |
| 389 | − | |
| 390 | − adev_to_drm(adev)->mode_config.max_width = 16384; | |
| 391 | − adev_to_drm(adev)->mode_config.max_height = 16384; | |
| 392 | − | |
| 393 | − adev_to_drm(adev)->mode_config.preferred_depth = 24; | |
| 394 | − adev_to_drm(adev)->mode_config.prefer_shadow = 1; | |
| 395 | − | |
| 396 | − adev_to_drm(adev)->mode_config.fb_base = adev->gmc.aper_base; | |
| 397 | − | |
| 398 | − r = amdgpu_display_modeset_create_props(adev); | |
| 399 | − if (r) | |
| 400 | − return r; | |
| 401 | − | |
| 402 | − adev_to_drm(adev)->mode_config.max_width = 16384; | |
| 403 | − adev_to_drm(adev)->mode_config.max_height = 16384; | |
| 404 | − | |
| 405 | − /* allocate crtcs, encoders, connectors */ | |
| 406 | − for (i = 0; i < adev->mode_info.num_crtc; i++) { | |
| 407 | − r = dce_virtual_crtc_init(adev, i); | |
| 408 | − if (r) | |
| 409 | − return r; | |
| 410 | − r = dce_virtual_connector_encoder_init(adev, i); | |
| 411 | − if (r) | |
| 412 | − return r; | |
| 413 | − } | |
| 414 | − | |
| 415 | − drm_kms_helper_poll_init(adev_to_drm(adev)); | |
| 416 | − | |
| 417 | − adev->mode_info.mode_config_initialized = true; | |
| 418 | − return 0; | |
| 419 | −} | |
| 420 | − | |
| 421 | −static int dce_virtual_sw_fini(void *handle) | |
| 422 | −{ | |
| 423 | − struct amdgpu_device *adev = (struct amdgpu_device *)handle; | |
| 424 | − int i = 0; | |
| 425 | − | |
| 426 | − for (i = 0; i < adev->mode_info.num_crtc; i++) | |
| 427 | − if (adev->mode_info.crtcs[i]) | |
| 428 | − hrtimer_cancel(&adev->mode_info.crtcs[i]->vblank_timer); | |
| 429 | − | |
| 430 | − kfree(adev->mode_info.bios_hardcoded_edid); | |
| 431 | − | |
| 432 | − drm_kms_helper_poll_fini(adev_to_drm(adev)); | |
| 433 | − | |
| 434 | − drm_mode_config_cleanup(adev_to_drm(adev)); | |
| 435 | − /* clear crtcs pointer to avoid dce irq finish routine access freed data */ | |
| 436 | − memset(adev->mode_info.crtcs, 0, sizeof(adev->mode_info.crtcs[0]) * AMDGPU_MAX_CRTCS); | |
| 437 | − adev->mode_info.mode_config_initialized = false; | |
| 438 | − return 0; | |
| 439 | −} | |
| 440 | − | |
| 441 | −static int dce_virtual_hw_init(void *handle) | |
| 442 | −{ | |
| 443 | − struct amdgpu_device *adev = (struct amdgpu_device *)handle; | |
| 444 | − | |
| 445 | − switch (adev->asic_type) { | |
| 446 | −#ifdef CONFIG_DRM_AMDGPU_SI | |
| 447 | − case CHIP_TAHITI: | |
| 448 | − case CHIP_PITCAIRN: | |
| 449 | − case CHIP_VERDE: | |
| 450 | − case CHIP_OLAND: | |
| 451 | − dce_v6_0_disable_dce(adev); | |
| 452 | − break; | |
| 453 | −#endif | |
| 454 | −#ifdef CONFIG_DRM_AMDGPU_CIK | |
| 455 | − case CHIP_BONAIRE: | |
| 456 | − case CHIP_HAWAII: | |
| 457 | − case CHIP_KAVERI: | |
| 458 | − case CHIP_KABINI: | |
| 459 | − case CHIP_MULLINS: | |
| 460 | − dce_v8_0_disable_dce(adev); | |
| 461 | − break; | |
| 462 | −#endif | |
| 463 | − case CHIP_FIJI: | |
| 464 | − case CHIP_TONGA: | |
| 465 | − dce_v10_0_disable_dce(adev); | |
| 466 | − break; | |
| 467 | − case CHIP_CARRIZO: | |
| 468 | − case CHIP_STONEY: | |
| 469 | − case CHIP_POLARIS10: | |
| 470 | − case CHIP_POLARIS11: | |
| 471 | − case CHIP_VEGAM: | |
| 472 | − dce_v11_0_disable_dce(adev); | |
| 473 | − break; | |
| 474 | − case CHIP_TOPAZ: | |
| 475 | −#ifdef CONFIG_DRM_AMDGPU_SI | |
| 476 | − case CHIP_HAINAN: | |
| 477 | −#endif | |
| 478 | − /* no DCE */ | |
| 479 | − break; | |
| 480 | − default: | |
| 481 | − break; | |
| 482 | − } | |
| 483 | − return 0; | |
| 484 | −} | |
| 485 | − | |
| 486 | −static int dce_virtual_hw_fini(void *handle) | |
| 487 | −{ | |
| 488 | − return 0; | |
| 489 | −} | |
| 490 | − | |
| 491 | −static int dce_virtual_suspend(void *handle) | |
| 492 | −{ | |
| 493 | − struct amdgpu_device *adev = (struct amdgpu_device *)handle; | |
| 494 | − int r; | |
| 495 | − | |
| 496 | − r = amdgpu_display_suspend_helper(adev); | |
| 497 | − if (r) | |
| 498 | − return r; | |
| 499 | − return dce_virtual_hw_fini(handle); | |
| 500 | −} | |
| 501 | − | |
| 502 | −static int dce_virtual_resume(void *handle) | |
| 503 | −{ | |
| 504 | − struct amdgpu_device *adev = (struct amdgpu_device *)handle; | |
| 505 | − int r; | |
| 506 | − | |
| 507 | − r = dce_virtual_hw_init(handle); | |
| 508 | − if (r) | |
| 509 | − return r; | |
| 510 | − return amdgpu_display_resume_helper(adev); | |
| 511 | −} | |
| 512 | − | |
| 513 | −static bool dce_virtual_is_idle(void *handle) | |
| 514 | −{ | |
| 515 | − return true; | |
| 516 | −} | |
| 517 | − | |
| 518 | −static int dce_virtual_wait_for_idle(void *handle) | |
| 519 | −{ | |
| 520 | − return 0; | |
| 521 | −} | |
| 522 | − | |
| 523 | −static int dce_virtual_soft_reset(void *handle) | |
| 524 | −{ | |
| 525 | − return 0; | |
| 526 | −} | |
| 527 | − | |
| 528 | −static int dce_virtual_set_clockgating_state(void *handle, | |
| 529 | − enum amd_clockgating_state state) | |
| 530 | −{ | |
| 531 | − return 0; | |
| 532 | −} | |
| 533 | − | |
| 534 | −static int dce_virtual_set_powergating_state(void *handle, | |
| 535 | − enum amd_powergating_state state) | |
| 536 | −{ | |
| 537 | − return 0; | |
| 538 | −} | |
| 539 | − | |
| 540 | −static const struct amd_ip_funcs dce_virtual_ip_funcs = { | |
| 541 | − .name = "dce_virtual", | |
| 542 | − .early_init = dce_virtual_early_init, | |
| 543 | − .late_init = NULL, | |
| 544 | − .sw_init = dce_virtual_sw_init, | |
| 545 | − .sw_fini = dce_virtual_sw_fini, | |
| 546 | − .hw_init = dce_virtual_hw_init, | |
| 547 | − .hw_fini = dce_virtual_hw_fini, | |
| 548 | − .suspend = dce_virtual_suspend, | |
| 549 | − .resume = dce_virtual_resume, | |
| 550 | − .is_idle = dce_virtual_is_idle, | |
| 551 | − .wait_for_idle = dce_virtual_wait_for_idle, | |
| 552 | − .soft_reset = dce_virtual_soft_reset, | |
| 553 | − .set_clockgating_state = dce_virtual_set_clockgating_state, | |
| 554 | − .set_powergating_state = dce_virtual_set_powergating_state, | |
| 555 | −}; | |
| 556 | − | |
| 557 | −/* these are handled by the primary encoders */ | |
| 558 | −static void dce_virtual_encoder_prepare(struct drm_encoder *encoder) | |
| 559 | −{ | |
| 560 | − return; | |
| 561 | −} | |
| 562 | − | |
| 563 | −static void dce_virtual_encoder_commit(struct drm_encoder *encoder) | |
| 564 | −{ | |
| 565 | − return; | |
| 566 | −} | |
| 567 | − | |
| 568 | −static void | |
| 569 | −dce_virtual_encoder_mode_set(struct drm_encoder *encoder, | |
| 570 | − struct drm_display_mode *mode, | |
| 571 | − struct drm_display_mode *adjusted_mode) | |
| 572 | −{ | |
| 573 | − return; | |
| 574 | −} | |
| 575 | − | |
| 576 | −static void dce_virtual_encoder_disable(struct drm_encoder *encoder) | |
| 577 | −{ | |
| 578 | − return; | |
| 579 | −} | |
| 580 | − | |
| 581 | −static void | |
| 582 | −dce_virtual_encoder_dpms(struct drm_encoder *encoder, int mode) | |
| 583 | −{ | |
| 584 | − return; | |
| 585 | −} | |
| 586 | − | |
| 587 | −static bool dce_virtual_encoder_mode_fixup(struct drm_encoder *encoder, | |
| 588 | − const struct drm_display_mode *mode, | |
| 589 | − struct drm_display_mode *adjusted_mode) | |
| 590 | −{ | |
| 591 | − return true; | |
| 592 | −} | |
| 593 | − | |
| 594 | −static const struct drm_encoder_helper_funcs dce_virtual_encoder_helper_funcs = { | |
| 595 | − .dpms = dce_virtual_encoder_dpms, | |
| 596 | − .mode_fixup = dce_virtual_encoder_mode_fixup, | |
| 597 | − .prepare = dce_virtual_encoder_prepare, | |
| 598 | − .mode_set = dce_virtual_encoder_mode_set, | |
| 599 | − .commit = dce_virtual_encoder_commit, | |
| 600 | − .disable = dce_virtual_encoder_disable, | |
| 601 | −}; | |
| 602 | − | |
| 603 | −static void dce_virtual_encoder_destroy(struct drm_encoder *encoder) | |
| 604 | −{ | |
| 605 | − drm_encoder_cleanup(encoder); | |
| 606 | − kfree(encoder); | |
| 607 | −} | |
| 608 | − | |
| 609 | −static const struct drm_encoder_funcs dce_virtual_encoder_funcs = { | |
| 610 | − .destroy = dce_virtual_encoder_destroy, | |
| 611 | −}; | |
| 612 | − | |
| 613 | −static int dce_virtual_connector_encoder_init(struct amdgpu_device *adev, | |
| 614 | − int index) | |
| 615 | −{ | |
| 616 | − struct drm_encoder *encoder; | |
| 617 | − struct drm_connector *connector; | |
| 618 | − | |
| 619 | − /* add a new encoder */ | |
| 620 | − encoder = kzalloc(sizeof(struct drm_encoder), GFP_KERNEL); | |
| 621 | − if (!encoder) | |
| 622 | − return -ENOMEM; | |
| 623 | − encoder->possible_crtcs = 1 << index; | |
| 624 | − drm_encoder_init(adev_to_drm(adev), encoder, &dce_virtual_encoder_funcs, | |
| 625 | − DRM_MODE_ENCODER_VIRTUAL, NULL); | |
| 626 | − drm_encoder_helper_add(encoder, &dce_virtual_encoder_helper_funcs); | |
| 627 | − | |
| 628 | − connector = kzalloc(sizeof(struct drm_connector), GFP_KERNEL); | |
| 629 | − if (!connector) { | |
| 630 | − kfree(encoder); | |
| 631 | − return -ENOMEM; | |
| 632 | − } | |
| 633 | − | |
| 634 | − /* add a new connector */ | |
| 635 | − drm_connector_init(adev_to_drm(adev), connector, &dce_virtual_connector_funcs, | |
| 636 | − DRM_MODE_CONNECTOR_VIRTUAL); | |
| 637 | − drm_connector_helper_add(connector, &dce_virtual_connector_helper_funcs); | |
| 638 | − connector->display_info.subpixel_order = SubPixelHorizontalRGB; | |
| 639 | − connector->interlace_allowed = false; | |
| 640 | − connector->doublescan_allowed = false; | |
| 641 | − | |
| 642 | − /* link them */ | |
| 643 | − drm_connector_attach_encoder(connector, encoder); | |
| 644 | − | |
| 645 | − return 0; | |
| 646 | −} | |
| 647 | − | |
| 648 | −static const struct amdgpu_display_funcs dce_virtual_display_funcs = { | |
| 649 | − .bandwidth_update = &dce_virtual_bandwidth_update, | |
| 650 | − .vblank_get_counter = &dce_virtual_vblank_get_counter, | |
| 651 | − .backlight_set_level = NULL, | |
| 652 | − .backlight_get_level = NULL, | |
| 653 | − .hpd_sense = &dce_virtual_hpd_sense, | |
| 654 | − .hpd_set_polarity = &dce_virtual_hpd_set_polarity, | |
| 655 | − .hpd_get_gpio_reg = &dce_virtual_hpd_get_gpio_reg, | |
| 656 | − .page_flip = &dce_virtual_page_flip, | |
| 657 | − .page_flip_get_scanoutpos = &dce_virtual_crtc_get_scanoutpos, | |
| 658 | − .add_encoder = NULL, | |
| 659 | − .add_connector = NULL, | |
| 660 | −}; | |
| 661 | − | |
| 662 | −static void dce_virtual_set_display_funcs(struct amdgpu_device *adev) | |
| 663 | −{ | |
| 664 | − adev->mode_info.funcs = &dce_virtual_display_funcs; | |
| 665 | −} | |
| 666 | − | |
| 667 | −static int dce_virtual_pageflip(struct amdgpu_device *adev, | |
| 668 | − unsigned crtc_id) | |
| 669 | −{ | |
| 670 | − unsigned long flags; | |
| 671 | − struct amdgpu_crtc *amdgpu_crtc; | |
| 672 | − struct amdgpu_flip_work *works; | |
| 673 | − | |
| 674 | − amdgpu_crtc = adev->mode_info.crtcs[crtc_id]; | |
| 675 | − | |
| 676 | − if (crtc_id >= adev->mode_info.num_crtc) { | |
| 677 | − DRM_ERROR("invalid pageflip crtc %d\n", crtc_id); | |
| 678 | − return -EINVAL; | |
| 679 | − } | |
| 680 | − | |
| 681 | − /* IRQ could occur when in initial stage */ | |
| 682 | − if (amdgpu_crtc == NULL) | |
| 683 | − return 0; | |
| 684 | − | |
| 685 | − spin_lock_irqsave(&adev_to_drm(adev)->event_lock, flags); | |
| 686 | − works = amdgpu_crtc->pflip_works; | |
| 687 | − if (amdgpu_crtc->pflip_status != AMDGPU_FLIP_SUBMITTED) { | |
| 688 | − DRM_DEBUG_DRIVER("amdgpu_crtc->pflip_status = %d != " | |
| 689 | − "AMDGPU_FLIP_SUBMITTED(%d)\n", | |
| 690 | − amdgpu_crtc->pflip_status, | |
| 691 | − AMDGPU_FLIP_SUBMITTED); | |
| 692 | − spin_unlock_irqrestore(&adev_to_drm(adev)->event_lock, flags); | |
| 693 | − return 0; | |
| 694 | − } | |
| 695 | − | |
| 696 | − /* page flip completed. clean up */ | |
| 697 | − amdgpu_crtc->pflip_status = AMDGPU_FLIP_NONE; | |
| 698 | − amdgpu_crtc->pflip_works = NULL; | |
| 699 | − | |
| 700 | − /* wakeup usersapce */ | |
| 701 | − if (works->event) | |
| 702 | − drm_crtc_send_vblank_event(&amdgpu_crtc->base, works->event); | |
| 703 | − | |
| 704 | − spin_unlock_irqrestore(&adev_to_drm(adev)->event_lock, flags); | |
| 705 | − | |
| 706 | − drm_crtc_vblank_put(&amdgpu_crtc->base); | |
| 707 | − amdgpu_bo_unref(&works->old_abo); | |
| 708 | − kfree(works->shared); | |
| 709 | − kfree(works); | |
| 710 | − | |
| 711 | − return 0; | |
| 712 | −} | |
| 713 | − | |
| 714 | −static enum hrtimer_restart dce_virtual_vblank_timer_handle(struct hrtimer *vblank_timer) | |
| 715 | −{ | |
| 716 | − struct amdgpu_crtc *amdgpu_crtc = container_of(vblank_timer, | |
| 717 | − struct amdgpu_crtc, vblank_timer); | |
| 718 | − struct drm_device *ddev = amdgpu_crtc->base.dev; | |
| 719 | − struct amdgpu_device *adev = drm_to_adev(ddev); | |
| 720 | − struct amdgpu_irq_src *source = adev->irq.client[AMDGPU_IRQ_CLIENTID_LEGACY].sources | |
| 721 | − [VISLANDS30_IV_SRCID_SMU_DISP_TIMER2_TRIGGER]; | |
| 722 | − int irq_type = amdgpu_display_crtc_idx_to_irq_type(adev, | |
| 723 | − amdgpu_crtc->crtc_id); | |
| 724 | − | |
| 725 | − if (amdgpu_irq_enabled(adev, source, irq_type)) { | |
| 726 | − drm_handle_vblank(ddev, amdgpu_crtc->crtc_id); | |
| 727 | − dce_virtual_pageflip(adev, amdgpu_crtc->crtc_id); | |
| 728 | − } | |
| 729 | − hrtimer_start(vblank_timer, DCE_VIRTUAL_VBLANK_PERIOD, | |
| 730 | − HRTIMER_MODE_REL); | |
| 731 | − | |
| 732 | − return HRTIMER_NORESTART; | |
| 733 | −} | |
| 734 | − | |
| 735 | −static void dce_virtual_set_crtc_vblank_interrupt_state(struct amdgpu_device *adev, | |
| 736 | − int crtc, | |
| 737 | − enum amdgpu_interrupt_state state) | |
| 738 | −{ | |
| 739 | − if (crtc >= adev->mode_info.num_crtc || !adev->mode_info.crtcs[crtc]) { | |
| 740 | − DRM_DEBUG("invalid crtc %d\n", crtc); | |
| 741 | − return; | |
| 742 | − } | |
| 743 | − | |
| 744 | − adev->mode_info.crtcs[crtc]->vsync_timer_enabled = state; | |
| 745 | − DRM_DEBUG("[FM]set crtc %d vblank interrupt state %d\n", crtc, state); | |
| 746 | −} | |
| 747 | − | |
| 748 | − | |
| 749 | −static int dce_virtual_set_crtc_irq_state(struct amdgpu_device *adev, | |
| 750 | − struct amdgpu_irq_src *source, | |
| 751 | − unsigned type, | |
| 752 | − enum amdgpu_interrupt_state state) | |
| 753 | −{ | |
| 754 | − if (type > AMDGPU_CRTC_IRQ_VBLANK6) | |
| 755 | − return -EINVAL; | |
| 756 | − | |
| 757 | − dce_virtual_set_crtc_vblank_interrupt_state(adev, type, state); | |
| 758 | − | |
| 759 | − return 0; | |
| 760 | −} | |
| 761 | − | |
| 762 | −static const struct amdgpu_irq_src_funcs dce_virtual_crtc_irq_funcs = { | |
| 763 | − .set = dce_virtual_set_crtc_irq_state, | |
| 764 | − .process = NULL, | |
| 765 | −}; | |
| 766 | − | |
| 767 | −static void dce_virtual_set_irq_funcs(struct amdgpu_device *adev) | |
| 768 | −{ | |
| 769 | − adev->crtc_irq.num_types = adev->mode_info.num_crtc; | |
| 770 | − adev->crtc_irq.funcs = &dce_virtual_crtc_irq_funcs; | |
| 771 | −} | |
| 772 | − | |
| 773 | −const struct amdgpu_ip_block_version dce_virtual_ip_block = | |
| 774 | −{ | |
| 775 | − .type = AMD_IP_BLOCK_TYPE_DCE, | |
| 776 | − .major = 1, | |
| 777 | − .minor = 0, | |
| 778 | − .rev = 0, | |
| 779 | − .funcs = &dce_virtual_ip_funcs, | |
| 780 | −}; | |
| @@ -56,6 +56,10 @@ · 55 unmodified lines | ||
| 56 | 56 | #define GFX10_NUM_GFX_RINGS_Sienna_Cichlid 1 |
| 57 | 57 | #define GFX10_MEC_HPD_SIZE 2048 |
| 58 | 58 | |
| 59 | +#define RLCG_VFGATE_DISABLED 0x4000000 | |
| 60 | +#define RLCG_WRONG_OPERATION_TYPE 0x2000000 | |
| 61 | +#define RLCG_NOT_IN_RANGE 0x1000000 | |
| 62 | + | |
| 59 | 63 | #define F32_CE_PROGRAM_RAM_SIZE 65536 |
| 60 | 64 | #define RLCG_UCODE_LOADING_START_ADDRESS 0x00002000L |
| 61 | 65 | |
| @@ -181,6 +185,9 @@ · 119 unmodified lines | ||
| 181 | 185 | #define GFX_RLCG_GC_READ (0x1 << 28) |
| 182 | 186 | #define GFX_RLCG_MMHUB_WRITE (0x2 << 28) |
| 183 | 187 | |
| 188 | +#define RLCG_ERROR_REPORT_ENABLED(adev) \ | |
| 189 | + (amdgpu_sriov_reg_indirect_mmhub(adev) || amdgpu_sriov_reg_indirect_gc(adev)) | |
| 190 | + | |
| 184 | 191 | MODULE_FIRMWARE("amdgpu/navi10_ce.bin"); |
| 185 | 192 | MODULE_FIRMWARE("amdgpu/navi10_pfp.bin"); |
| 186 | 193 | MODULE_FIRMWARE("amdgpu/navi10_me.bin"); |
| @@ -249,6 +256,39 @@ MODULE_FIRMWARE("amdgpu/yellow_carp_mec.bin"); · 62 unmodified lines | ||
| 249 | 256 | MODULE_FIRMWARE("amdgpu/yellow_carp_mec2.bin"); |
| 250 | 257 | MODULE_FIRMWARE("amdgpu/yellow_carp_rlc.bin"); |
| 251 | 258 | |
| 259 | +MODULE_FIRMWARE("amdgpu/cyan_skillfish_ce.bin"); | |
| 260 | +MODULE_FIRMWARE("amdgpu/cyan_skillfish_pfp.bin"); | |
| 261 | +MODULE_FIRMWARE("amdgpu/cyan_skillfish_me.bin"); | |
| 262 | +MODULE_FIRMWARE("amdgpu/cyan_skillfish_mec.bin"); | |
| 263 | +MODULE_FIRMWARE("amdgpu/cyan_skillfish_mec2.bin"); | |
| 264 | +MODULE_FIRMWARE("amdgpu/cyan_skillfish_rlc.bin"); | |
| 265 | + | |
| 266 | +MODULE_FIRMWARE("amdgpu/cyan_skillfish2_ce.bin"); | |
| 267 | +MODULE_FIRMWARE("amdgpu/cyan_skillfish2_pfp.bin"); | |
| 268 | +MODULE_FIRMWARE("amdgpu/cyan_skillfish2_me.bin"); | |
| 269 | +MODULE_FIRMWARE("amdgpu/cyan_skillfish2_mec.bin"); | |
| 270 | +MODULE_FIRMWARE("amdgpu/cyan_skillfish2_mec2.bin"); | |
| 271 | +MODULE_FIRMWARE("amdgpu/cyan_skillfish2_rlc.bin"); | |
| 272 | + | |
| 273 | +static const struct soc15_reg_golden golden_settings_gc_10_0[] = | |
| 274 | +{ | |
| 275 | + SOC15_REG_GOLDEN_VALUE(GC, 0, mmGRBM_CAM_INDEX, 0xffffffff, 0x00000000), | |
| 276 | + /* TA_GRAD_ADJ_UCONFIG -> TA_GRAD_ADJ */ | |
| 277 | + SOC15_REG_GOLDEN_VALUE(GC, 0, mmGRBM_CAM_DATA, 0xffffffff, 0x2544c382), | |
| 278 | + /* VGT_TF_RING_SIZE_UMD -> VGT_TF_RING_SIZE */ | |
| 279 | + SOC15_REG_GOLDEN_VALUE(GC, 0, mmGRBM_CAM_DATA, 0xffffffff, 0x2262c24e), | |
| 280 | + /* VGT_HS_OFFCHIP_PARAM_UMD -> VGT_HS_OFFCHIP_PARAM */ | |
| 281 | + SOC15_REG_GOLDEN_VALUE(GC, 0, mmGRBM_CAM_DATA, 0xffffffff, 0x226cc24f), | |
| 282 | + /* VGT_TF_MEMORY_BASE_UMD -> VGT_TF_MEMORY_BASE */ | |
| 283 | + SOC15_REG_GOLDEN_VALUE(GC, 0, mmGRBM_CAM_DATA, 0xffffffff, 0x226ec250), | |
| 284 | + /* VGT_TF_MEMORY_BASE_HI_UMD -> VGT_TF_MEMORY_BASE_HI */ | |
| 285 | + SOC15_REG_GOLDEN_VALUE(GC, 0, mmGRBM_CAM_DATA, 0xffffffff, 0x2278c261), | |
| 286 | + /* VGT_ESGS_RING_SIZE_UMD -> VGT_ESGS_RING_SIZE */ | |
| 287 | + SOC15_REG_GOLDEN_VALUE(GC, 0, mmGRBM_CAM_DATA, 0xffffffff, 0x2232c240), | |
| 288 | + /* VGT_GSVS_RING_SIZE_UMD -> VGT_GSVS_RING_SIZE */ | |
| 289 | + SOC15_REG_GOLDEN_VALUE(GC, 0, mmGRBM_CAM_DATA, 0xffffffff, 0x2233c241), | |
| 290 | +}; | |
| 291 | + | |
| 252 | 292 | static const struct soc15_reg_golden golden_settings_gc_10_1[] = |
| 253 | 293 | { |
| 254 | 294 | SOC15_REG_GOLDEN_VALUE(GC, 0, mmCB_HW_CONTROL_4, 0xffffffff, 0x00400014), |
| @@ -1486,6 +1526,7 @@ static u32 gfx_v10_rlcg_rw(struct amdgpu_device *adev, u32 offset, u32 v, uint32 · 1231 unmodified lines | ||
| 1486 | 1526 | uint32_t i = 0; |
| 1487 | 1527 | uint32_t retries = 50000; |
| 1488 | 1528 | u32 ret = 0; |
| 1529 | + u32 tmp; | |
| 1489 | 1530 | |
| 1490 | 1531 | scratch_reg0 = adev->rmmio + |
| 1491 | 1532 | (adev->reg_offset[GC_HWIP][0][mmSCRATCH_REG0_BASE_IDX] + mmSCRATCH_REG0) * 4; |
| @@ -1519,9 +1560,8 @@ static u32 gfx_v10_rlcg_rw(struct amdgpu_device *adev, u32 offset, u32 v, uint32 · 27 unmodified lines | ||
| 1519 | 1560 | writel(v, scratch_reg0); |
| 1520 | 1561 | writel(offset | flag, scratch_reg1); |
| 1521 | 1562 | writel(1, spare_int); |
| 1522 | − for (i = 0; i < retries; i++) { | |
| 1523 | − u32 tmp; | |
| 1524 | 1563 | |
| 1564 | + for (i = 0; i < retries; i++) { | |
| 1525 | 1565 | tmp = readl(scratch_reg1); |
| 1526 | 1566 | if (!(tmp & flag)) |
| 1527 | 1567 | break; |
| @@ -1529,8 +1569,19 @@ static u32 gfx_v10_rlcg_rw(struct amdgpu_device *adev, u32 offset, u32 v, uint32 · 1 unmodified line | ||
| 1529 | 1569 | udelay(10); |
| 1530 | 1570 | } |
| 1531 | 1571 | |
| 1532 | − if (i >= retries) | |
| 1533 | − pr_err("timeout: rlcg program reg:0x%05x failed !\n", offset); | |
| 1572 | + if (i >= retries) { | |
| 1573 | + if (RLCG_ERROR_REPORT_ENABLED(adev)) { | |
| 1574 | + if (tmp & RLCG_VFGATE_DISABLED) | |
| 1575 | + pr_err("The vfgate is disabled, program reg:0x%05x failed!\n", offset); | |
| 1576 | + else if (tmp & RLCG_WRONG_OPERATION_TYPE) | |
| 1577 | + pr_err("Wrong operation type, program reg:0x%05x failed!\n", offset); | |
| 1578 | + else if (tmp & RLCG_NOT_IN_RANGE) | |
| 1579 | + pr_err("The register is not in range, program reg:0x%05x failed!\n", offset); | |
| 1580 | + else | |
| 1581 | + pr_err("Unknown error type, program reg:0x%05x failed!\n", offset); | |
| 1582 | + } else | |
| 1583 | + pr_err("timeout: rlcg program reg:0x%05x failed!\n", offset); | |
| 1584 | + } | |
| 1534 | 1585 | } |
| 1535 | 1586 | |
| 1536 | 1587 | ret = readl(scratch_reg0); |
| @@ -1538,7 +1589,7 @@ static u32 gfx_v10_rlcg_rw(struct amdgpu_device *adev, u32 offset, u32 v, uint32 · 1 unmodified line | ||
| 1538 | 1589 | return ret; |
| 1539 | 1590 | } |
| 1540 | 1591 | |
| 1541 | −static void gfx_v10_rlcg_wreg(struct amdgpu_device *adev, u32 offset, u32 value, u32 acc_flags, u32 hwip) | |
| 1592 | +static void gfx_v10_sriov_wreg(struct amdgpu_device *adev, u32 offset, u32 value, u32 acc_flags, u32 hwip) | |
| 1542 | 1593 | { |
| 1543 | 1594 | u32 rlcg_flag; |
| 1544 | 1595 | |
| @@ -1554,7 +1605,7 @@ static void gfx_v10_rlcg_wreg(struct amdgpu_device *adev, u32 offset, u32 value, · 9 unmodified lines | ||
| 1554 | 1605 | WREG32(offset, value); |
| 1555 | 1606 | } |
| 1556 | 1607 | |
| 1557 | −static u32 gfx_v10_rlcg_rreg(struct amdgpu_device *adev, u32 offset, u32 acc_flags, u32 hwip) | |
| 1608 | +static u32 gfx_v10_sriov_rreg(struct amdgpu_device *adev, u32 offset, u32 acc_flags, u32 hwip) | |
| 1558 | 1609 | { |
| 1559 | 1610 | u32 rlcg_flag; |
| 1560 | 1611 | |
| @@ -3488,12 +3539,51 @@ static const struct soc15_reg_golden golden_settings_gc_10_3_5[] = { · 1927 unmodified lines | ||
| 3488 | 3539 | SOC15_REG_GOLDEN_VALUE(GC, 0, mmUTCL1_CTRL, 0xffbfffff, 0x00a00000) |
| 3489 | 3540 | }; |
| 3490 | 3541 | |
| 3542 | +static const struct soc15_reg_golden golden_settings_gc_10_0_cyan_skillfish[] = { | |
| 3543 | + SOC15_REG_GOLDEN_VALUE(GC, 0, mmGRBM_GFX_INDEX, 0xffffffff, 0xe0000000), | |
| 3544 | + SOC15_REG_GOLDEN_VALUE(GC, 0, mmGE_FAST_CLKS, 0x3fffffff, 0x0000493e), | |
| 3545 | + SOC15_REG_GOLDEN_VALUE(GC, 0, mmCGTT_CPF_CLK_CTRL, 0xfcff8fff, 0xf8000100), | |
| 3546 | + SOC15_REG_GOLDEN_VALUE(GC, 0, mmCGTT_SPI_CLK_CTRL, 0xff7f0fff, 0x3c000100), | |
| 3547 | + SOC15_REG_GOLDEN_VALUE(GC, 0, mmCB_HW_CONTROL_3, 0xa0000000, 0xa0000000), | |
| 3548 | + SOC15_REG_GOLDEN_VALUE(GC, 0, mmCB_HW_CONTROL_4, 0x00008000, 0x003c8014), | |
| 3549 | + SOC15_REG_GOLDEN_VALUE(GC, 0, mmCH_DRAM_BURST_CTRL, 0x00000010, 0x00000017), | |
| 3550 | + SOC15_REG_GOLDEN_VALUE(GC, 0, mmCH_PIPE_STEER, 0xffffffff, 0xd8d8d8d8), | |
| 3551 | + SOC15_REG_GOLDEN_VALUE(GC, 0, mmCH_VC5_ENABLE, 0x00000003, 0x00000003), | |
| 3552 | + SOC15_REG_GOLDEN_VALUE(GC, 0, mmCP_SD_CNTL, 0x800007ff, 0x000005ff), | |
| 3553 | + SOC15_REG_GOLDEN_VALUE(GC, 0, mmDB_DEBUG, 0xffffffff, 0x20000000), | |
| 3554 | + SOC15_REG_GOLDEN_VALUE(GC, 0, mmDB_DEBUG3, 0xffffffff, 0x00000200), | |
| 3555 | + SOC15_REG_GOLDEN_VALUE(GC, 0, mmDB_DEBUG4, 0xffffffff, 0x04800000), | |
| 3556 | + SOC15_REG_GOLDEN_VALUE(GC, 0, mmDB_LAST_OF_BURST_CONFIG, 0xffffffff, 0x03860210), | |
| 3557 | + SOC15_REG_GOLDEN_VALUE(GC, 0, mmGB_ADDR_CONFIG, 0x0c1800ff, 0x00000044), | |
| 3558 | + SOC15_REG_GOLDEN_VALUE(GC, 0, mmGCR_GENERAL_CNTL, 0x00009d00, 0x00008500), | |
| 3559 | + SOC15_REG_GOLDEN_VALUE(GC, 0, mmGCMC_VM_CACHEABLE_DRAM_ADDRESS_END, 0xffffffff, 0x000fffff), | |
| 3560 | + SOC15_REG_GOLDEN_VALUE(GC, 0, mmGL1_DRAM_BURST_CTRL, 0x00000010, 0x00000017), | |
| 3561 | + SOC15_REG_GOLDEN_VALUE(GC, 0, mmGL1_PIPE_STEER, 0xfcfcfcfc, 0xd8d8d8d8), | |
| 3562 | + SOC15_REG_GOLDEN_VALUE(GC, 0, mmGL2_PIPE_STEER_0, 0x77707770, 0x21302130), | |
| 3563 | + SOC15_REG_GOLDEN_VALUE(GC, 0, mmGL2_PIPE_STEER_1, 0x77707770, 0x21302130), | |
| 3564 | + SOC15_REG_GOLDEN_VALUE(GC, 0, mmGL2A_ADDR_MATCH_MASK, 0xffffffff, 0xffffffcf), | |
| 3565 | + SOC15_REG_GOLDEN_VALUE(GC, 0, mmGL2C_ADDR_MATCH_MASK, 0xffffffff, 0xffffffcf), | |
| 3566 | + SOC15_REG_GOLDEN_VALUE(GC, 0, mmGL2C_CGTT_SCLK_CTRL, 0x10000000, 0x10000100), | |
| 3567 | + SOC15_REG_GOLDEN_VALUE(GC, 0, mmGL2C_CTRL2, 0xfc02002f, 0x9402002f), | |
| 3568 | + SOC15_REG_GOLDEN_VALUE(GC, 0, mmGL2C_CTRL3, 0x00002188, 0x00000188), | |
| 3569 | + SOC15_REG_GOLDEN_VALUE(GC, 0, mmPA_SC_ENHANCE, 0x08000009, 0x08000009), | |
| 3570 | + SOC15_REG_GOLDEN_VALUE(GC, 0, mmPA_SC_BINNER_EVENT_CNTL_0, 0xcc3fcc03, 0x842a4c02), | |
| 3571 | + SOC15_REG_GOLDEN_VALUE(GC, 0, mmPA_SC_LINE_STIPPLE_STATE, 0x0000000f, 0x00000000), | |
| 3572 | + SOC15_REG_GOLDEN_VALUE(GC, 0, mmRMI_SPARE, 0xffff3109, 0xffff3101), | |
| 3573 | + SOC15_REG_GOLDEN_VALUE(GC, 0, mmSQ_ARB_CONFIG, 0x00000100, 0x00000130), | |
| 3574 | + SOC15_REG_GOLDEN_VALUE(GC, 0, mmSQ_LDS_CLK_CTRL, 0xffffffff, 0xffffffff), | |
| 3575 | + SOC15_REG_GOLDEN_VALUE(GC, 0, mmTA_CNTL_AUX, 0x00030008, 0x01030000), | |
| 3576 | + SOC15_REG_GOLDEN_VALUE(GC, 0, mmUTCL1_CTRL, 0x00800000, 0x00800000) | |
| 3577 | +}; | |
| 3578 | + | |
| 3491 | 3579 | #define DEFAULT_SH_MEM_CONFIG \ |
| 3492 | 3580 | ((SH_MEM_ADDRESS_MODE_64 << SH_MEM_CONFIG__ADDRESS_MODE__SHIFT) | \ |
| 3493 | 3581 | (SH_MEM_ALIGNMENT_MODE_UNALIGNED << SH_MEM_CONFIG__ALIGNMENT_MODE__SHIFT) | \ |
| 3494 | 3582 | (SH_MEM_RETRY_MODE_ALL << SH_MEM_CONFIG__RETRY_MODE__SHIFT) | \ |
| 3495 | 3583 | (3 << SH_MEM_CONFIG__INITIAL_INST_PREFETCH__SHIFT)) |
| 3496 | 3584 | |
| 3585 | +/* TODO: pending on golden setting value of gb address config */ | |
| 3586 | +#define CYAN_SKILLFISH_GB_ADDR_CONFIG_GOLDEN 0x00100044 | |
| 3497 | 3587 | |
| 3498 | 3588 | static void gfx_v10_0_set_ring_funcs(struct amdgpu_device *adev); |
| 3499 | 3589 | static void gfx_v10_0_set_irq_funcs(struct amdgpu_device *adev); |
| @@ -3718,6 +3808,14 @@ static void gfx_v10_0_init_golden_registers(struct amdgpu_device *adev) · 218 unmodified lines | ||
| 3718 | 3808 | golden_settings_gc_10_3_5, |
| 3719 | 3809 | (const u32)ARRAY_SIZE(golden_settings_gc_10_3_5)); |
| 3720 | 3810 | break; |
| 3811 | + case CHIP_CYAN_SKILLFISH: | |
| 3812 | + soc15_program_register_sequence(adev, | |
| 3813 | + golden_settings_gc_10_0, | |
| 3814 | + (const u32)ARRAY_SIZE(golden_settings_gc_10_0)); | |
| 3815 | + soc15_program_register_sequence(adev, | |
| 3816 | + golden_settings_gc_10_0_cyan_skillfish, | |
| 3817 | + (const u32)ARRAY_SIZE(golden_settings_gc_10_0_cyan_skillfish)); | |
| 3818 | + break; | |
| 3721 | 3819 | default: |
| 3722 | 3820 | break; |
| 3723 | 3821 | } |
| @@ -3891,6 +3989,7 @@ static void gfx_v10_0_check_fw_write_wait(struct amdgpu_device *adev) · 167 unmodified lines | ||
| 3891 | 3989 | case CHIP_NAVI10: |
| 3892 | 3990 | case CHIP_NAVI12: |
| 3893 | 3991 | case CHIP_NAVI14: |
| 3992 | + case CHIP_CYAN_SKILLFISH: | |
| 3894 | 3993 | if ((adev->gfx.me_fw_version >= 0x00000046) && |
| 3895 | 3994 | (adev->gfx.me_feature_version >= 27) && |
| 3896 | 3995 | (adev->gfx.pfp_fw_version >= 0x00000068) && |
| @@ -4025,6 +4124,12 @@ static int gfx_v10_0_init_microcode(struct amdgpu_device *adev) · 128 unmodified lines | ||
| 4025 | 4124 | case CHIP_YELLOW_CARP: |
| 4026 | 4125 | chip_name = "yellow_carp"; |
| 4027 | 4126 | break; |
| 4127 | + case CHIP_CYAN_SKILLFISH: | |
| 4128 | + if (adev->apu_flags & AMD_APU_IS_CYAN_SKILLFISH2) | |
| 4129 | + chip_name = "cyan_skillfish2"; | |
| 4130 | + else | |
| 4131 | + chip_name = "cyan_skillfish"; | |
| 4132 | + break; | |
| 4028 | 4133 | default: |
| 4029 | 4134 | BUG(); |
| 4030 | 4135 | } |
| @@ -4516,6 +4621,7 @@ static void gfx_v10_0_read_wave_data(struct amdgpu_device *adev, uint32_t simd, · 485 unmodified lines | ||
| 4516 | 4621 | dst[(*no_fields)++] = wave_read_ind(adev, wave, ixSQ_WAVE_IB_STS2); |
| 4517 | 4622 | dst[(*no_fields)++] = wave_read_ind(adev, wave, ixSQ_WAVE_IB_DBG1); |
| 4518 | 4623 | dst[(*no_fields)++] = wave_read_ind(adev, wave, ixSQ_WAVE_M0); |
| 4624 | + dst[(*no_fields)++] = wave_read_ind(adev, wave, ixSQ_WAVE_MODE); | |
| 4519 | 4625 | } |
| 4520 | 4626 | |
| 4521 | 4627 | static void gfx_v10_0_read_wave_sgprs(struct amdgpu_device *adev, uint32_t simd, |
| @@ -4604,6 +4710,14 @@ static void gfx_v10_0_gpu_early_init(struct amdgpu_device *adev) · 82 unmodified lines | ||
| 4604 | 4710 | adev->gfx.config.gb_addr_config_fields.num_pkrs = |
| 4605 | 4711 | 1 << REG_GET_FIELD(gb_addr_config, GB_ADDR_CONFIG, NUM_PKRS); |
| 4606 | 4712 | break; |
| 4713 | + case CHIP_CYAN_SKILLFISH: | |
| 4714 | + adev->gfx.config.max_hw_contexts = 8; | |
| 4715 | + adev->gfx.config.sc_prim_fifo_size_frontend = 0x20; | |
| 4716 | + adev->gfx.config.sc_prim_fifo_size_backend = 0x100; | |
| 4717 | + adev->gfx.config.sc_hiz_tile_fifo_size = 0x30; | |
| 4718 | + adev->gfx.config.sc_earlyz_tile_fifo_size = 0x4C0; | |
| 4719 | + gb_addr_config = CYAN_SKILLFISH_GB_ADDR_CONFIG_GOLDEN; | |
| 4720 | + break; | |
| 4607 | 4721 | default: |
| 4608 | 4722 | BUG(); |
| 4609 | 4723 | break; |
| @@ -4708,6 +4822,7 @@ static int gfx_v10_0_sw_init(void *handle) · 98 unmodified lines | ||
| 4708 | 4822 | case CHIP_NAVI10: |
| 4709 | 4823 | case CHIP_NAVI14: |
| 4710 | 4824 | case CHIP_NAVI12: |
| 4825 | + case CHIP_CYAN_SKILLFISH: | |
| 4711 | 4826 | adev->gfx.me.num_me = 1; |
| 4712 | 4827 | adev->gfx.me.num_pipe_per_me = 1; |
| 4713 | 4828 | adev->gfx.me.num_queue_per_pipe = 1; |
| @@ -5319,7 +5434,8 @@ static int gfx_v10_0_rlc_resume(struct amdgpu_device *adev) · 605 unmodified lines | ||
| 5319 | 5434 | { |
| 5320 | 5435 | int r; |
| 5321 | 5436 | |
| 5322 | − if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) { | |
| 5437 | + if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP && | |
| 5438 | + adev->psp.autoload_supported) { | |
| 5323 | 5439 | |
| 5324 | 5440 | r = gfx_v10_0_wait_for_rlc_autoload_complete(adev); |
| 5325 | 5441 | if (r) |
| @@ -5379,7 +5495,7 @@ static int gfx_v10_0_parse_rlc_toc(struct amdgpu_device *adev) · 53 unmodified lines | ||
| 5379 | 5495 | int ret; |
| 5380 | 5496 | RLC_TABLE_OF_CONTENT *rlc_toc; |
| 5381 | 5497 | |
| 5382 | − ret = amdgpu_bo_create_reserved(adev, adev->psp.toc_bin_size, PAGE_SIZE, | |
| 5498 | + ret = amdgpu_bo_create_reserved(adev, adev->psp.toc.size_bytes, PAGE_SIZE, | |
| 5383 | 5499 | AMDGPU_GEM_DOMAIN_GTT, |
| 5384 | 5500 | &adev->gfx.rlc.rlc_toc_bo, |
| 5385 | 5501 | &adev->gfx.rlc.rlc_toc_gpu_addr, |
| @@ -5390,7 +5506,7 @@ static int gfx_v10_0_parse_rlc_toc(struct amdgpu_device *adev) · 4 unmodified lines | ||
| 5390 | 5506 | } |
| 5391 | 5507 | |
| 5392 | 5508 | /* Copy toc from psp sos fw to rlc toc buffer */ |
| 5393 | − memcpy(adev->gfx.rlc.rlc_toc_buf, adev->psp.toc_start_addr, adev->psp.toc_bin_size); | |
| 5509 | + memcpy(adev->gfx.rlc.rlc_toc_buf, adev->psp.toc.start_addr, adev->psp.toc.size_bytes); | |
| 5394 | 5510 | |
| 5395 | 5511 | rlc_toc = (RLC_TABLE_OF_CONTENT *)adev->gfx.rlc.rlc_toc_buf; |
| 5396 | 5512 | while (rlc_toc && (rlc_toc->id > FIRMWARE_ID_INVALID) && |
| @@ -7608,10 +7724,8 @@ static int gfx_v10_0_soft_reset(void *handle) · 2211 unmodified lines | ||
| 7608 | 7724 | |
| 7609 | 7725 | static uint64_t gfx_v10_0_get_gpu_clock_counter(struct amdgpu_device *adev) |
| 7610 | 7726 | { |
| 7611 | − uint64_t clock; | |
| 7727 | + uint64_t clock, clock_lo, clock_hi, hi_check; | |
| 7612 | 7728 | |
| 7613 | − amdgpu_gfx_off_ctrl(adev, false); | |
| 7614 | − mutex_lock(&adev->gfx.gpu_clock_mutex); | |
| 7615 | 7729 | switch (adev->asic_type) { |
| 7616 | 7730 | case CHIP_VANGOGH: |
| 7617 | 7731 | case CHIP_YELLOW_CARP: |
| @@ -7619,12 +7733,21 @@ static uint64_t gfx_v10_0_get_gpu_clock_counter(struct amdgpu_device *adev) · 1 unmodified line | ||
| 7619 | 7733 | ((uint64_t)RREG32_SOC15(SMUIO, 0, mmGOLDEN_TSC_COUNT_UPPER_Vangogh) << 32ULL); |
| 7620 | 7734 | break; |
| 7621 | 7735 | default: |
| 7622 | − clock = (uint64_t)RREG32_SOC15(SMUIO, 0, mmGOLDEN_TSC_COUNT_LOWER) | | |
| 7623 | − ((uint64_t)RREG32_SOC15(SMUIO, 0, mmGOLDEN_TSC_COUNT_UPPER) << 32ULL); | |
| 7736 | + preempt_disable(); | |
| 7737 | + clock_hi = RREG32_SOC15_NO_KIQ(SMUIO, 0, mmGOLDEN_TSC_COUNT_UPPER); | |
| 7738 | + clock_lo = RREG32_SOC15_NO_KIQ(SMUIO, 0, mmGOLDEN_TSC_COUNT_LOWER); | |
| 7739 | + hi_check = RREG32_SOC15_NO_KIQ(SMUIO, 0, mmGOLDEN_TSC_COUNT_UPPER); | |
| 7740 | + /* The SMUIO TSC clock frequency is 100MHz, which sets 32-bit carry over | |
| 7741 | + * roughly every 42 seconds. | |
| 7742 | + */ | |
| 7743 | + if (hi_check != clock_hi) { | |
| 7744 | + clock_lo = RREG32_SOC15_NO_KIQ(SMUIO, 0, mmGOLDEN_TSC_COUNT_LOWER); | |
| 7745 | + clock_hi = hi_check; | |
| 7746 | + } | |
| 7747 | + preempt_enable(); | |
| 7748 | + clock = clock_lo | (clock_hi << 32ULL); | |
| 7624 | 7749 | break; |
| 7625 | 7750 | } |
| 7626 | − mutex_unlock(&adev->gfx.gpu_clock_mutex); | |
| 7627 | − amdgpu_gfx_off_ctrl(adev, true); | |
| 7628 | 7751 | return clock; |
| 7629 | 7752 | } |
| 7630 | 7753 | |
| @@ -7665,6 +7788,7 @@ static int gfx_v10_0_early_init(void *handle) · 34 unmodified lines | ||
| 7665 | 7788 | case CHIP_NAVI10: |
| 7666 | 7789 | case CHIP_NAVI14: |
| 7667 | 7790 | case CHIP_NAVI12: |
| 7791 | + case CHIP_CYAN_SKILLFISH: | |
| 7668 | 7792 | adev->gfx.num_gfx_rings = GFX10_NUM_GFX_RINGS_NV1X; |
| 7669 | 7793 | break; |
| 7670 | 7794 | case CHIP_SIENNA_CICHLID: |
| @@ -8261,8 +8385,8 @@ static const struct amdgpu_rlc_funcs gfx_v10_0_rlc_funcs_sriov = { · 590 unmodified lines | ||
| 8261 | 8385 | .reset = gfx_v10_0_rlc_reset, |
| 8262 | 8386 | .start = gfx_v10_0_rlc_start, |
| 8263 | 8387 | .update_spm_vmid = gfx_v10_0_update_spm_vmid, |
| 8264 | − .rlcg_wreg = gfx_v10_rlcg_wreg, | |
| 8265 | − .rlcg_rreg = gfx_v10_rlcg_rreg, | |
| 8388 | + .sriov_wreg = gfx_v10_sriov_wreg, | |
| 8389 | + .sriov_rreg = gfx_v10_sriov_rreg, | |
| 8266 | 8390 | .is_rlcg_access_range = gfx_v10_0_is_rlcg_access_range, |
| 8267 | 8391 | }; |
| 8268 | 8392 | |
| @@ -9425,6 +9549,7 @@ static void gfx_v10_0_set_rlc_funcs(struct amdgpu_device *adev) · 1156 unmodified lines | ||
| 9425 | 9549 | case CHIP_DIMGREY_CAVEFISH: |
| 9426 | 9550 | case CHIP_BEIGE_GOBY: |
| 9427 | 9551 | case CHIP_YELLOW_CARP: |
| 9552 | + case CHIP_CYAN_SKILLFISH: | |
| 9428 | 9553 | adev->gfx.rlc.funcs = &gfx_v10_0_rlc_funcs; |
| 9429 | 9554 | break; |
| 9430 | 9555 | case CHIP_NAVI12: |
| @@ -3027,6 +3027,7 @@ static void gfx_v6_0_read_wave_data(struct amdgpu_device *adev, uint32_t simd, u · 3026 unmodified lines | ||
| 3027 | 3027 | dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_TMA_HI); |
| 3028 | 3028 | dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_IB_DBG0); |
| 3029 | 3029 | dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_M0); |
| 3030 | + dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_MODE); | |
| 3030 | 3031 | } |
| 3031 | 3032 | |
| 3032 | 3033 | static void gfx_v6_0_read_wave_sgprs(struct amdgpu_device *adev, uint32_t simd, |
| @@ -4198,6 +4198,7 @@ static void gfx_v7_0_read_wave_data(struct amdgpu_device *adev, uint32_t simd, u · 4197 unmodified lines | ||
| 4198 | 4198 | dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_TMA_HI); |
| 4199 | 4199 | dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_IB_DBG0); |
| 4200 | 4200 | dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_M0); |
| 4201 | + dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_MODE); | |
| 4201 | 4202 | } |
| 4202 | 4203 | |
| 4203 | 4204 | static void gfx_v7_0_read_wave_sgprs(struct amdgpu_device *adev, uint32_t simd, |
| @@ -5279,6 +5279,7 @@ static void gfx_v8_0_read_wave_data(struct amdgpu_device *adev, uint32_t simd, u · 5278 unmodified lines | ||
| 5279 | 5279 | dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_TMA_HI); |
| 5280 | 5280 | dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_IB_DBG0); |
| 5281 | 5281 | dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_M0); |
| 5282 | + dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_MODE); | |
| 5282 | 5283 | } |
| 5283 | 5284 | |
| 5284 | 5285 | static void gfx_v8_0_read_wave_sgprs(struct amdgpu_device *adev, uint32_t simd, |
| @@ -787,7 +787,7 @@ static void gfx_v9_0_rlcg_w(struct amdgpu_device *adev, u32 offset, u32 v, u32 f · 786 unmodified lines | ||
| 787 | 787 | |
| 788 | 788 | } |
| 789 | 789 | |
| 790 | −static void gfx_v9_0_rlcg_wreg(struct amdgpu_device *adev, u32 offset, | |
| 790 | +static void gfx_v9_0_sriov_wreg(struct amdgpu_device *adev, u32 offset, | |
| 791 | 791 | u32 v, u32 acc_flags, u32 hwip) |
| 792 | 792 | { |
| 793 | 793 | if ((acc_flags & AMDGPU_REGS_RLC) && |
| @@ -2090,6 +2090,7 @@ static void gfx_v9_0_read_wave_data(struct amdgpu_device *adev, uint32_t simd, u · 1296 unmodified lines | ||
| 2090 | 2090 | dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_IB_STS); |
| 2091 | 2091 | dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_IB_DBG0); |
| 2092 | 2092 | dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_M0); |
| 2093 | + dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_MODE); | |
| 2093 | 2094 | } |
| 2094 | 2095 | |
| 2095 | 2096 | static void gfx_v9_0_read_wave_sgprs(struct amdgpu_device *adev, uint32_t simd, |
| @@ -5150,7 +5151,7 @@ static const struct amdgpu_rlc_funcs gfx_v9_0_rlc_funcs = { · 3054 unmodified lines | ||
| 5150 | 5151 | .reset = gfx_v9_0_rlc_reset, |
| 5151 | 5152 | .start = gfx_v9_0_rlc_start, |
| 5152 | 5153 | .update_spm_vmid = gfx_v9_0_update_spm_vmid, |
| 5153 | − .rlcg_wreg = gfx_v9_0_rlcg_wreg, | |
| 5154 | + .sriov_wreg = gfx_v9_0_sriov_wreg, | |
| 5154 | 5155 | .is_rlcg_access_range = gfx_v9_0_is_rlcg_access_range, |
| 5155 | 5156 | }; |
| 5156 | 5157 | |
| @@ -85,7 +85,7 @@ static const struct soc15_reg_golden golden_settings_gc_9_4_2_alde[] = { · 84 unmodified lines | ||
| 85 | 85 | SOC15_REG_GOLDEN_VALUE(GC, 0, regTCI_CNTL_3, 0xff, 0x20), |
| 86 | 86 | }; |
| 87 | 87 | |
| 88 | −/** | |
| 88 | +/* | |
| 89 | 89 | * This shader is used to clear VGPRS and LDS, and also write the input |
| 90 | 90 | * pattern into the write back buffer, which will be used by driver to |
| 91 | 91 | * check whether all SIMDs have been covered. |
| @@ -206,7 +206,7 @@ const struct soc15_reg_entry vgpr_init_regs_aldebaran[] = { · 114 unmodified lines | ||
| 206 | 206 | { SOC15_REG_ENTRY(GC, 0, regCOMPUTE_STATIC_THREAD_MGMT_SE7), 0xffffffff }, |
| 207 | 207 | }; |
| 208 | 208 | |
| 209 | −/** | |
| 209 | +/* | |
| 210 | 210 | * The below shaders are used to clear SGPRS, and also write the input |
| 211 | 211 | * pattern into the write back buffer. The first two dispatch should be |
| 212 | 212 | * scheduled simultaneously which make sure that all SGPRS could be |
| @@ -302,7 +302,7 @@ const struct soc15_reg_entry sgpr96_init_regs_aldebaran[] = { · 89 unmodified lines | ||
| 302 | 302 | { SOC15_REG_ENTRY(GC, 0, regCOMPUTE_STATIC_THREAD_MGMT_SE7), 0xffffffff }, |
| 303 | 303 | }; |
| 304 | 304 | |
| 305 | −/** | |
| 305 | +/* | |
| 306 | 306 | * This shader is used to clear the uninitiated sgprs after the above |
| 307 | 307 | * two dispatches, because of hardware feature, dispath 0 couldn't clear |
| 308 | 308 | * top hole sgprs. Therefore need 4 waves per SIMD to cover these sgprs |
| @@ -75,9 +75,8 @@ int gfxhub_v1_1_get_xgmi_info(struct amdgpu_device *adev) · 74 unmodified lines | ||
| 75 | 75 | max_physical_node_id = 7; |
| 76 | 76 | break; |
| 77 | 77 | case CHIP_ALDEBARAN: |
| 78 | − /* just using duplicates for Aldebaran support, revisit later */ | |
| 79 | − max_num_physical_nodes = 8; | |
| 80 | − max_physical_node_id = 7; | |
| 78 | + max_num_physical_nodes = 16; | |
| 79 | + max_physical_node_id = 15; | |
| 81 | 80 | break; |
| 82 | 81 | default: |
| 83 | 82 | return -EINVAL; |
| @@ -93,6 +93,7 @@ static int gmc_v10_0_process_interrupt(struct amdgpu_device *adev, · 92 unmodified lines | ||
| 93 | 93 | struct amdgpu_iv_entry *entry) |
| 94 | 94 | { |
| 95 | 95 | bool retry_fault = !!(entry->src_data[1] & 0x80); |
| 96 | + bool write_fault = !!(entry->src_data[1] & 0x20); | |
| 96 | 97 | struct amdgpu_vmhub *hub = &adev->vmhub[entry->vmid_src]; |
| 97 | 98 | struct amdgpu_task_info task_info; |
| 98 | 99 | uint32_t status = 0; |
| @@ -121,7 +122,7 @@ static int gmc_v10_0_process_interrupt(struct amdgpu_device *adev, · 22 unmodified lines | ||
| 121 | 122 | /* Try to handle the recoverable page faults by filling page |
| 122 | 123 | * tables |
| 123 | 124 | */ |
| 124 | − if (amdgpu_vm_handle_fault(adev, entry->pasid, addr)) | |
| 125 | + if (amdgpu_vm_handle_fault(adev, entry->pasid, addr, write_fault)) | |
| 125 | 126 | return 1; |
| 126 | 127 | } |
| 127 | 128 | |
| @@ -810,6 +811,7 @@ static int gmc_v10_0_mc_init(struct amdgpu_device *adev) · 682 unmodified lines | ||
| 810 | 811 | case CHIP_DIMGREY_CAVEFISH: |
| 811 | 812 | case CHIP_BEIGE_GOBY: |
| 812 | 813 | case CHIP_YELLOW_CARP: |
| 814 | + case CHIP_CYAN_SKILLFISH: | |
| 813 | 815 | default: |
| 814 | 816 | adev->gmc.gart_size = 512ULL << 20; |
| 815 | 817 | break; |
| @@ -879,6 +881,7 @@ static int gmc_v10_0_sw_init(void *handle) · 63 unmodified lines | ||
| 879 | 881 | case CHIP_DIMGREY_CAVEFISH: |
| 880 | 882 | case CHIP_BEIGE_GOBY: |
| 881 | 883 | case CHIP_YELLOW_CARP: |
| 884 | + case CHIP_CYAN_SKILLFISH: | |
| 882 | 885 | adev->num_vmhubs = 2; |
| 883 | 886 | /* |
| 884 | 887 | * To fulfill 4-level page support, |
| @@ -996,6 +999,7 @@ static void gmc_v10_0_init_golden_registers(struct amdgpu_device *adev) · 111 unmodified lines | ||
| 996 | 999 | case CHIP_DIMGREY_CAVEFISH: |
| 997 | 1000 | case CHIP_BEIGE_GOBY: |
| 998 | 1001 | case CHIP_YELLOW_CARP: |
| 1002 | + case CHIP_CYAN_SKILLFISH: | |
| 999 | 1003 | break; |
| 1000 | 1004 | default: |
| 1001 | 1005 | break; |
| @@ -53,7 +53,9 @@ · 52 unmodified lines | ||
| 53 | 53 | #include "mmhub_v1_7.h" |
| 54 | 54 | #include "umc_v6_1.h" |
| 55 | 55 | #include "umc_v6_0.h" |
| 56 | +#include "umc_v6_7.h" | |
| 56 | 57 | #include "hdp_v4_0.h" |
| 58 | +#include "mca_v3_0.h" | |
| 57 | 59 | |
| 58 | 60 | #include "ivsrcid/vmc/irqsrcs_vmc_1_0.h" |
| 59 | 61 | |
| @@ -505,6 +507,7 @@ static int gmc_v9_0_process_interrupt(struct amdgpu_device *adev, · 445 unmodified lines | ||
| 505 | 507 | struct amdgpu_iv_entry *entry) |
| 506 | 508 | { |
| 507 | 509 | bool retry_fault = !!(entry->src_data[1] & 0x80); |
| 510 | + bool write_fault = !!(entry->src_data[1] & 0x20); | |
| 508 | 511 | uint32_t status = 0, cid = 0, rw = 0; |
| 509 | 512 | struct amdgpu_task_info task_info; |
| 510 | 513 | struct amdgpu_vmhub *hub; |
| @@ -535,7 +538,7 @@ static int gmc_v9_0_process_interrupt(struct amdgpu_device *adev, · 24 unmodified lines | ||
| 535 | 538 | /* Try to handle the recoverable page faults by filling page |
| 536 | 539 | * tables |
| 537 | 540 | */ |
| 538 | − if (amdgpu_vm_handle_fault(adev, entry->pasid, addr)) | |
| 541 | + if (amdgpu_vm_handle_fault(adev, entry->pasid, addr, write_fault)) | |
| 539 | 542 | return 1; |
| 540 | 543 | } |
| 541 | 544 | |
| @@ -1168,6 +1171,18 @@ static void gmc_v9_0_set_umc_funcs(struct amdgpu_device *adev) · 626 unmodified lines | ||
| 1168 | 1171 | adev->umc.channel_idx_tbl = &umc_v6_1_channel_idx_tbl[0][0]; |
| 1169 | 1172 | adev->umc.ras_funcs = &umc_v6_1_ras_funcs; |
| 1170 | 1173 | break; |
| 1174 | + case CHIP_ALDEBARAN: | |
| 1175 | + adev->umc.max_ras_err_cnt_per_query = UMC_V6_7_TOTAL_CHANNEL_NUM; | |
| 1176 | + adev->umc.channel_inst_num = UMC_V6_7_CHANNEL_INSTANCE_NUM; | |
| 1177 | + adev->umc.umc_inst_num = UMC_V6_7_UMC_INSTANCE_NUM; | |
| 1178 | + adev->umc.channel_offs = UMC_V6_7_PER_CHANNEL_OFFSET; | |
| 1179 | + if (!adev->gmc.xgmi.connected_to_cpu) | |
| 1180 | + adev->umc.ras_funcs = &umc_v6_7_ras_funcs; | |
| 1181 | + if (1 & adev->smuio.funcs->get_die_id(adev)) | |
| 1182 | + adev->umc.channel_idx_tbl = &umc_v6_7_channel_idx_tbl_first[0][0]; | |
| 1183 | + else | |
| 1184 | + adev->umc.channel_idx_tbl = &umc_v6_7_channel_idx_tbl_second[0][0]; | |
| 1185 | + break; | |
| 1171 | 1186 | default: |
| 1172 | 1187 | break; |
| 1173 | 1188 | } |
| @@ -1216,6 +1231,18 @@ static void gmc_v9_0_set_hdp_ras_funcs(struct amdgpu_device *adev) · 42 unmodified lines | ||
| 1216 | 1231 | adev->hdp.ras_funcs = &hdp_v4_0_ras_funcs; |
| 1217 | 1232 | } |
| 1218 | 1233 | |
| 1234 | +static void gmc_v9_0_set_mca_funcs(struct amdgpu_device *adev) | |
| 1235 | +{ | |
| 1236 | + switch (adev->asic_type) { | |
| 1237 | + case CHIP_ALDEBARAN: | |
| 1238 | + if (!adev->gmc.xgmi.connected_to_cpu) | |
| 1239 | + adev->mca.funcs = &mca_v3_0_funcs; | |
| 1240 | + break; | |
| 1241 | + default: | |
| 1242 | + break; | |
| 1243 | + } | |
| 1244 | +} | |
| 1245 | + | |
| 1219 | 1246 | static int gmc_v9_0_early_init(void *handle) |
| 1220 | 1247 | { |
| 1221 | 1248 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; |
| @@ -1237,6 +1264,7 @@ static int gmc_v9_0_early_init(void *handle) · 15 unmodified lines | ||
| 1237 | 1264 | gmc_v9_0_set_mmhub_ras_funcs(adev); |
| 1238 | 1265 | gmc_v9_0_set_gfxhub_funcs(adev); |
| 1239 | 1266 | gmc_v9_0_set_hdp_ras_funcs(adev); |
| 1267 | + gmc_v9_0_set_mca_funcs(adev); | |
| 1240 | 1268 | |
| 1241 | 1269 | adev->gmc.shared_aperture_start = 0x2000000000000000ULL; |
| 1242 | 1270 | adev->gmc.shared_aperture_end = |
| @@ -1448,6 +1476,8 @@ static int gmc_v9_0_sw_init(void *handle) · 205 unmodified lines | ||
| 1448 | 1476 | adev->gfxhub.funcs->init(adev); |
| 1449 | 1477 | |
| 1450 | 1478 | adev->mmhub.funcs->init(adev); |
| 1479 | + if (adev->mca.funcs) | |
| 1480 | + adev->mca.funcs->init(adev); | |
| 1451 | 1481 | |
| 1452 | 1482 | spin_lock_init(&adev->gmc.invalidate_lock); |
| 1453 | 1483 | |
| @@ -0,0 +1,125 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright 2021 Advanced Micro Devices, Inc. | |
| 3 | + * | |
| 4 | + * Permission is hereby granted, free of charge, to any person obtaining a | |
| 5 | + * copy of this software and associated documentation files (the "Software"), | |
| 6 | + * to deal in the Software without restriction, including without limitation | |
| 7 | + * the rights to use, copy, modify, merge, publish, distribute, sublicense, | |
| 8 | + * and/or sell copies of the Software, and to permit persons to whom the | |
| 9 | + * Software is furnished to do so, subject to the following conditions: | |
| 10 | + * | |
| 11 | + * The above copyright notice and this permission notice shall be included in | |
| 12 | + * all copies or substantial portions of the Software. | |
| 13 | + * | |
| 14 | + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
| 15 | + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
| 16 | + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |
| 17 | + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR | |
| 18 | + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | |
| 19 | + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | |
| 20 | + * OTHER DEALINGS IN THE SOFTWARE. | |
| 21 | + * | |
| 22 | + */ | |
| 23 | +#include "amdgpu_ras.h" | |
| 24 | +#include "amdgpu.h" | |
| 25 | +#include "amdgpu_mca.h" | |
| 26 | + | |
| 27 | +#define smnMCMP0_STATUST0 0x03830408 | |
| 28 | +#define smnMCMP1_STATUST0 0x03b30408 | |
| 29 | +#define smnMCMPIO_STATUST0 0x0c930408 | |
| 30 | + | |
| 31 | + | |
| 32 | +static void mca_v3_0_mp0_query_ras_error_count(struct amdgpu_device *adev, | |
| 33 | + void *ras_error_status) | |
| 34 | +{ | |
| 35 | + amdgpu_mca_query_ras_error_count(adev, | |
| 36 | + smnMCMP0_STATUST0, | |
| 37 | + ras_error_status); | |
| 38 | +} | |
| 39 | + | |
| 40 | +static int mca_v3_0_mp0_ras_late_init(struct amdgpu_device *adev) | |
| 41 | +{ | |
| 42 | + return amdgpu_mca_ras_late_init(adev, &adev->mca.mp0); | |
| 43 | +} | |
| 44 | + | |
| 45 | +static void mca_v3_0_mp0_ras_fini(struct amdgpu_device *adev) | |
| 46 | +{ | |
| 47 | + amdgpu_mca_ras_fini(adev, &adev->mca.mp0); | |
| 48 | +} | |
| 49 | + | |
| 50 | +const struct amdgpu_mca_ras_funcs mca_v3_0_mp0_ras_funcs = { | |
| 51 | + .ras_late_init = mca_v3_0_mp0_ras_late_init, | |
| 52 | + .ras_fini = mca_v3_0_mp0_ras_fini, | |
| 53 | + .query_ras_error_count = mca_v3_0_mp0_query_ras_error_count, | |
| 54 | + .query_ras_error_address = NULL, | |
| 55 | + .ras_block = AMDGPU_RAS_BLOCK__MP0, | |
| 56 | + .sysfs_name = "mp0_err_count", | |
| 57 | +}; | |
| 58 | + | |
| 59 | +static void mca_v3_0_mp1_query_ras_error_count(struct amdgpu_device *adev, | |
| 60 | + void *ras_error_status) | |
| 61 | +{ | |
| 62 | + amdgpu_mca_query_ras_error_count(adev, | |
| 63 | + smnMCMP1_STATUST0, | |
| 64 | + ras_error_status); | |
| 65 | +} | |
| 66 | + | |
| 67 | +static int mca_v3_0_mp1_ras_late_init(struct amdgpu_device *adev) | |
| 68 | +{ | |
| 69 | + return amdgpu_mca_ras_late_init(adev, &adev->mca.mp1); | |
| 70 | +} | |
| 71 | + | |
| 72 | +static void mca_v3_0_mp1_ras_fini(struct amdgpu_device *adev) | |
| 73 | +{ | |
| 74 | + amdgpu_mca_ras_fini(adev, &adev->mca.mp1); | |
| 75 | +} | |
| 76 | + | |
| 77 | +const struct amdgpu_mca_ras_funcs mca_v3_0_mp1_ras_funcs = { | |
| 78 | + .ras_late_init = mca_v3_0_mp1_ras_late_init, | |
| 79 | + .ras_fini = mca_v3_0_mp1_ras_fini, | |
| 80 | + .query_ras_error_count = mca_v3_0_mp1_query_ras_error_count, | |
| 81 | + .query_ras_error_address = NULL, | |
| 82 | + .ras_block = AMDGPU_RAS_BLOCK__MP1, | |
| 83 | + .sysfs_name = "mp1_err_count", | |
| 84 | +}; | |
| 85 | + | |
| 86 | +static void mca_v3_0_mpio_query_ras_error_count(struct amdgpu_device *adev, | |
| 87 | + void *ras_error_status) | |
| 88 | +{ | |
| 89 | + amdgpu_mca_query_ras_error_count(adev, | |
| 90 | + smnMCMPIO_STATUST0, | |
| 91 | + ras_error_status); | |
| 92 | +} | |
| 93 | + | |
| 94 | +static int mca_v3_0_mpio_ras_late_init(struct amdgpu_device *adev) | |
| 95 | +{ | |
| 96 | + return amdgpu_mca_ras_late_init(adev, &adev->mca.mpio); | |
| 97 | +} | |
| 98 | + | |
| 99 | +static void mca_v3_0_mpio_ras_fini(struct amdgpu_device *adev) | |
| 100 | +{ | |
| 101 | + amdgpu_mca_ras_fini(adev, &adev->mca.mpio); | |
| 102 | +} | |
| 103 | + | |
| 104 | +const struct amdgpu_mca_ras_funcs mca_v3_0_mpio_ras_funcs = { | |
| 105 | + .ras_late_init = mca_v3_0_mpio_ras_late_init, | |
| 106 | + .ras_fini = mca_v3_0_mpio_ras_fini, | |
| 107 | + .query_ras_error_count = mca_v3_0_mpio_query_ras_error_count, | |
| 108 | + .query_ras_error_address = NULL, | |
| 109 | + .ras_block = AMDGPU_RAS_BLOCK__MPIO, | |
| 110 | + .sysfs_name = "mpio_err_count", | |
| 111 | +}; | |
| 112 | + | |
| 113 | + | |
| 114 | +static void mca_v3_0_init(struct amdgpu_device *adev) | |
| 115 | +{ | |
| 116 | + struct amdgpu_mca *mca = &adev->mca; | |
| 117 | + | |
| 118 | + mca->mp0.ras_funcs = &mca_v3_0_mp0_ras_funcs; | |
| 119 | + mca->mp1.ras_funcs = &mca_v3_0_mp1_ras_funcs; | |
| 120 | + mca->mpio.ras_funcs = &mca_v3_0_mpio_ras_funcs; | |
| 121 | +} | |
| 122 | + | |
| 123 | +const struct amdgpu_mca_funcs mca_v3_0_funcs = { | |
| 124 | + .init = mca_v3_0_init, | |
| 125 | +}; | |
| @@ -0,0 +1,26 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright (C) 2021 Advanced Micro Devices, Inc. | |
| 3 | + * | |
| 4 | + * Permission is hereby granted, free of charge, to any person obtaining a | |
| 5 | + * copy of this software and associated documentation files (the "Software"), | |
| 6 | + * to deal in the Software without restriction, including without limitation | |
| 7 | + * the rights to use, copy, modify, merge, publish, distribute, sublicense, | |
| 8 | + * and/or sell copies of the Software, and to permit persons to whom the | |
| 9 | + * Software is furnished to do so, subject to the following conditions: | |
| 10 | + * | |
| 11 | + * The above copyright notice and this permission notice shall be included | |
| 12 | + * in all copies or substantial portions of the Software. | |
| 13 | + * | |
| 14 | + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | |
| 15 | + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
| 16 | + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |
| 17 | + * THE COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN | |
| 18 | + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | |
| 19 | + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |
| 20 | + */ | |
| 21 | +#ifndef __MCA_V3_0_H__ | |
| 22 | +#define __MCA_V3_0_H__ | |
| 23 | + | |
| 24 | +extern const struct amdgpu_mca_funcs mca_v3_0_funcs; | |
| 25 | + | |
| 26 | +#endif | |
| @@ -24,9 +24,7 @@ · 23 unmodified lines | ||
| 24 | 24 | #ifndef __MMSCH_V1_0_H__ |
| 25 | 25 | #define __MMSCH_V1_0_H__ |
| 26 | 26 | |
| 27 | −#define MMSCH_VERSION_MAJOR 1 | |
| 28 | −#define MMSCH_VERSION_MINOR 0 | |
| 29 | −#define MMSCH_VERSION (MMSCH_VERSION_MAJOR << 16 | MMSCH_VERSION_MINOR) | |
| 27 | +#define MMSCH_VERSION 0x1 | |
| 30 | 28 | |
| 31 | 29 | enum mmsch_v1_0_command_type { |
| 32 | 30 | MMSCH_COMMAND__DIRECT_REG_WRITE = 0, |
| @@ -96,7 +96,11 @@ static int xgpu_nv_poll_ack(struct amdgpu_device *adev) · 95 unmodified lines | ||
| 96 | 96 | |
| 97 | 97 | static int xgpu_nv_poll_msg(struct amdgpu_device *adev, enum idh_event event) |
| 98 | 98 | { |
| 99 | − int r, timeout = NV_MAILBOX_POLL_MSG_TIMEDOUT; | |
| 99 | + int r; | |
| 100 | + uint64_t timeout, now; | |
| 101 | + | |
| 102 | + now = (uint64_t)ktime_to_ms(ktime_get()); | |
| 103 | + timeout = now + NV_MAILBOX_POLL_MSG_TIMEDOUT; | |
| 100 | 104 | |
| 101 | 105 | do { |
| 102 | 106 | r = xgpu_nv_mailbox_rcv_msg(adev, event); |
| @@ -104,8 +108,8 @@ static int xgpu_nv_poll_msg(struct amdgpu_device *adev, enum idh_event event) · 1 unmodified line | ||
| 104 | 108 | return 0; |
| 105 | 109 | |
| 106 | 110 | msleep(10); |
| 107 | − timeout -= 10; | |
| 108 | − } while (timeout > 1); | |
| 111 | + now = (uint64_t)ktime_to_ms(ktime_get()); | |
| 112 | + } while (timeout > now); | |
| 109 | 113 | |
| 110 | 114 | |
| 111 | 115 | return -ETIME; |
| @@ -149,9 +153,10 @@ static void xgpu_nv_mailbox_trans_msg (struct amdgpu_device *adev, · 37 unmodified lines | ||
| 149 | 153 | static int xgpu_nv_send_access_requests(struct amdgpu_device *adev, |
| 150 | 154 | enum idh_request req) |
| 151 | 155 | { |
| 152 | − int r; | |
| 156 | + int r, retry = 1; | |
| 153 | 157 | enum idh_event event = -1; |
| 154 | 158 | |
| 159 | +send_request: | |
| 155 | 160 | xgpu_nv_mailbox_trans_msg(adev, req, 0, 0, 0); |
| 156 | 161 | |
| 157 | 162 | switch (req) { |
| @@ -170,6 +175,9 @@ static int xgpu_nv_send_access_requests(struct amdgpu_device *adev, · 12 unmodified lines | ||
| 170 | 175 | if (event != -1) { |
| 171 | 176 | r = xgpu_nv_poll_msg(adev, event); |
| 172 | 177 | if (r) { |
| 178 | + if (retry++ < 2) | |
| 179 | + goto send_request; | |
| 180 | + | |
| 173 | 181 | if (req != IDH_REQ_GPU_INIT_DATA) { |
| 174 | 182 | pr_err("Doesn't get msg:%d from pf, error=%d\n", event, r); |
| 175 | 183 | return r; |
| @@ -279,6 +287,8 @@ static void xgpu_nv_mailbox_flr_work(struct work_struct *work) · 103 unmodified lines | ||
| 279 | 287 | amdgpu_virt_fini_data_exchange(adev); |
| 280 | 288 | atomic_set(&adev->in_gpu_reset, 1); |
| 281 | 289 | |
| 290 | + xgpu_nv_mailbox_trans_msg(adev, IDH_READY_TO_RESET, 0, 0, 0); | |
| 291 | + | |
| 282 | 292 | do { |
| 283 | 293 | if (xgpu_nv_mailbox_peek_msg(adev) == IDH_FLR_NOTIFICATION_CMPL) |
| 284 | 294 | goto flr_done; |
| @@ -37,7 +37,8 @@ enum idh_request { · 36 unmodified lines | ||
| 37 | 37 | IDH_REQ_GPU_RESET_ACCESS, |
| 38 | 38 | IDH_REQ_GPU_INIT_DATA, |
| 39 | 39 | |
| 40 | − IDH_LOG_VF_ERROR = 200, | |
| 40 | + IDH_LOG_VF_ERROR = 200, | |
| 41 | + IDH_READY_TO_RESET = 201, | |
| 41 | 42 | }; |
| 42 | 43 | |
| 43 | 44 | enum idh_event { |
| @@ -508,6 +508,26 @@ static void nbio_v2_3_apply_l1_link_width_reconfig_wa(struct amdgpu_device *adev · 507 unmodified lines | ||
| 508 | 508 | WREG32_PCIE(smnPCIE_LC_LINK_WIDTH_CNTL, reg_data); |
| 509 | 509 | } |
| 510 | 510 | |
| 511 | +static void nbio_v2_3_clear_doorbell_interrupt(struct amdgpu_device *adev) | |
| 512 | +{ | |
| 513 | + uint32_t reg, reg_data; | |
| 514 | + | |
| 515 | + if (adev->asic_type != CHIP_SIENNA_CICHLID) | |
| 516 | + return; | |
| 517 | + | |
| 518 | + reg = RREG32_SOC15(NBIO, 0, mmBIF_RB_CNTL); | |
| 519 | + | |
| 520 | + /* Clear Interrupt Status | |
| 521 | + */ | |
| 522 | + if ((reg & BIF_RB_CNTL__RB_ENABLE_MASK) == 0) { | |
| 523 | + reg = RREG32_SOC15(NBIO, 0, mmBIF_DOORBELL_INT_CNTL); | |
| 524 | + if (reg & BIF_DOORBELL_INT_CNTL__DOORBELL_INTERRUPT_STATUS_MASK) { | |
| 525 | + reg_data = 1 << BIF_DOORBELL_INT_CNTL__DOORBELL_INTERRUPT_CLEAR__SHIFT; | |
| 526 | + WREG32_SOC15(NBIO, 0, mmBIF_DOORBELL_INT_CNTL, reg_data); | |
| 527 | + } | |
| 528 | + } | |
| 529 | +} | |
| 530 | + | |
| 511 | 531 | const struct amdgpu_nbio_funcs nbio_v2_3_funcs = { |
| 512 | 532 | .get_hdp_flush_req_offset = nbio_v2_3_get_hdp_flush_req_offset, |
| 513 | 533 | .get_hdp_flush_done_offset = nbio_v2_3_get_hdp_flush_done_offset, |
| @@ -531,4 +551,5 @@ const struct amdgpu_nbio_funcs nbio_v2_3_funcs = { · 17 unmodified lines | ||
| 531 | 551 | .program_aspm = nbio_v2_3_program_aspm, |
| 532 | 552 | .apply_lc_spc_mode_wa = nbio_v2_3_apply_lc_spc_mode_wa, |
| 533 | 553 | .apply_l1_link_width_reconfig_wa = nbio_v2_3_apply_l1_link_width_reconfig_wa, |
| 554 | + .clear_doorbell_interrupt = nbio_v2_3_clear_doorbell_interrupt, | |
| 534 | 555 | }; |
| @@ -85,6 +85,11 @@ · 84 unmodified lines | ||
| 85 | 85 | #define mmRCC_DEV0_EPF0_STRAP0_ALDE 0x0015 |
| 86 | 86 | #define mmRCC_DEV0_EPF0_STRAP0_ALDE_BASE_IDX 2 |
| 87 | 87 | |
| 88 | +#define mmBIF_DOORBELL_INT_CNTL_ALDE 0x3878 | |
| 89 | +#define mmBIF_DOORBELL_INT_CNTL_ALDE_BASE_IDX 2 | |
| 90 | +#define BIF_DOORBELL_INT_CNTL_ALDE__DOORBELL_INTERRUPT_DISABLE__SHIFT 0x18 | |
| 91 | +#define BIF_DOORBELL_INT_CNTL_ALDE__DOORBELL_INTERRUPT_DISABLE_MASK 0x01000000L | |
| 92 | + | |
| 88 | 93 | static void nbio_v7_4_query_ras_error_count(struct amdgpu_device *adev, |
| 89 | 94 | void *ras_error_status); |
| 90 | 95 | |
| @@ -346,14 +351,21 @@ static void nbio_v7_4_handle_ras_controller_intr_no_bifring(struct amdgpu_device · 255 unmodified lines | ||
| 346 | 351 | struct ras_err_data err_data = {0, 0, 0, NULL}; |
| 347 | 352 | struct amdgpu_ras *ras = amdgpu_ras_get_context(adev); |
| 348 | 353 | |
| 349 | − bif_doorbell_intr_cntl = RREG32_SOC15(NBIO, 0, mmBIF_DOORBELL_INT_CNTL); | |
| 354 | + if (adev->asic_type == CHIP_ALDEBARAN) | |
| 355 | + bif_doorbell_intr_cntl = RREG32_SOC15(NBIO, 0, mmBIF_DOORBELL_INT_CNTL_ALDE); | |
| 356 | + else | |
| 357 | + bif_doorbell_intr_cntl = RREG32_SOC15(NBIO, 0, mmBIF_DOORBELL_INT_CNTL); | |
| 358 | + | |
| 350 | 359 | if (REG_GET_FIELD(bif_doorbell_intr_cntl, |
| 351 | 360 | BIF_DOORBELL_INT_CNTL, RAS_CNTLR_INTERRUPT_STATUS)) { |
| 352 | 361 | /* driver has to clear the interrupt status when bif ring is disabled */ |
| 353 | 362 | bif_doorbell_intr_cntl = REG_SET_FIELD(bif_doorbell_intr_cntl, |
| 354 | 363 | BIF_DOORBELL_INT_CNTL, |
| 355 | 364 | RAS_CNTLR_INTERRUPT_CLEAR, 1); |
| 356 | − WREG32_SOC15(NBIO, 0, mmBIF_DOORBELL_INT_CNTL, bif_doorbell_intr_cntl); | |
| 365 | + if (adev->asic_type == CHIP_ALDEBARAN) | |
| 366 | + WREG32_SOC15(NBIO, 0, mmBIF_DOORBELL_INT_CNTL_ALDE, bif_doorbell_intr_cntl); | |
| 367 | + else | |
| 368 | + WREG32_SOC15(NBIO, 0, mmBIF_DOORBELL_INT_CNTL, bif_doorbell_intr_cntl); | |
| 357 | 369 | |
| 358 | 370 | if (!ras->disable_ras_err_cnt_harvest) { |
| 359 | 371 | /* |
| @@ -372,13 +384,13 @@ static void nbio_v7_4_handle_ras_controller_intr_no_bifring(struct amdgpu_device · 12 unmodified lines | ||
| 372 | 384 | "errors detected in %s block, " |
| 373 | 385 | "no user action is needed.\n", |
| 374 | 386 | obj->err_data.ce_count, |
| 375 | − adev->nbio.ras_if->name); | |
| 387 | + ras_block_str(adev->nbio.ras_if->block)); | |
| 376 | 388 | |
| 377 | 389 | if (err_data.ue_count) |
| 378 | 390 | dev_info(adev->dev, "%ld uncorrectable hardware " |
| 379 | 391 | "errors detected in %s block\n", |
| 380 | 392 | obj->err_data.ue_count, |
| 381 | − adev->nbio.ras_if->name); | |
| 393 | + ras_block_str(adev->nbio.ras_if->block)); | |
| 382 | 394 | } |
| 383 | 395 | |
| 384 | 396 | dev_info(adev->dev, "RAS controller interrupt triggered " |
| @@ -395,14 +407,22 @@ static void nbio_v7_4_handle_ras_err_event_athub_intr_no_bifring(struct amdgpu_d · 10 unmodified lines | ||
| 395 | 407 | { |
| 396 | 408 | uint32_t bif_doorbell_intr_cntl; |
| 397 | 409 | |
| 398 | − bif_doorbell_intr_cntl = RREG32_SOC15(NBIO, 0, mmBIF_DOORBELL_INT_CNTL); | |
| 410 | + if (adev->asic_type == CHIP_ALDEBARAN) | |
| 411 | + bif_doorbell_intr_cntl = RREG32_SOC15(NBIO, 0, mmBIF_DOORBELL_INT_CNTL_ALDE); | |
| 412 | + else | |
| 413 | + bif_doorbell_intr_cntl = RREG32_SOC15(NBIO, 0, mmBIF_DOORBELL_INT_CNTL); | |
| 414 | + | |
| 399 | 415 | if (REG_GET_FIELD(bif_doorbell_intr_cntl, |
| 400 | 416 | BIF_DOORBELL_INT_CNTL, RAS_ATHUB_ERR_EVENT_INTERRUPT_STATUS)) { |
| 401 | 417 | /* driver has to clear the interrupt status when bif ring is disabled */ |
| 402 | 418 | bif_doorbell_intr_cntl = REG_SET_FIELD(bif_doorbell_intr_cntl, |
| 403 | 419 | BIF_DOORBELL_INT_CNTL, |
| 404 | 420 | RAS_ATHUB_ERR_EVENT_INTERRUPT_CLEAR, 1); |
| 405 | − WREG32_SOC15(NBIO, 0, mmBIF_DOORBELL_INT_CNTL, bif_doorbell_intr_cntl); | |
| 421 | + | |
| 422 | + if (adev->asic_type == CHIP_ALDEBARAN) | |
| 423 | + WREG32_SOC15(NBIO, 0, mmBIF_DOORBELL_INT_CNTL_ALDE, bif_doorbell_intr_cntl); | |
| 424 | + else | |
| 425 | + WREG32_SOC15(NBIO, 0, mmBIF_DOORBELL_INT_CNTL, bif_doorbell_intr_cntl); | |
| 406 | 426 | |
| 407 | 427 | amdgpu_ras_global_ras_isr(adev); |
| 408 | 428 | } |
| @@ -572,7 +592,11 @@ static void nbio_v7_4_query_ras_error_count(struct amdgpu_device *adev, · 163 unmodified lines | ||
| 572 | 592 | static void nbio_v7_4_enable_doorbell_interrupt(struct amdgpu_device *adev, |
| 573 | 593 | bool enable) |
| 574 | 594 | { |
| 575 | − WREG32_FIELD15(NBIO, 0, BIF_DOORBELL_INT_CNTL, | |
| 595 | + if (adev->asic_type == CHIP_ALDEBARAN) | |
| 596 | + WREG32_FIELD15(NBIO, 0, BIF_DOORBELL_INT_CNTL_ALDE, | |
| 597 | + DOORBELL_INTERRUPT_DISABLE, enable ? 0 : 1); | |
| 598 | + else | |
| 599 | + WREG32_FIELD15(NBIO, 0, BIF_DOORBELL_INT_CNTL, | |
| 576 | 600 | DOORBELL_INTERRUPT_DISABLE, enable ? 0 : 1); |
| 577 | 601 | } |
| 578 | 602 | |
| @@ -58,7 +58,7 @@ · 57 unmodified lines | ||
| 58 | 58 | #include "jpeg_v2_0.h" |
| 59 | 59 | #include "vcn_v3_0.h" |
| 60 | 60 | #include "jpeg_v3_0.h" |
| 61 | −#include "dce_virtual.h" | |
| 61 | +#include "amdgpu_vkms.h" | |
| 62 | 62 | #include "mes_v10_1.h" |
| 63 | 63 | #include "mxgpu_nv.h" |
| 64 | 64 | #include "smuio_v11_0.h" |
| @@ -666,6 +666,9 @@ legacy_init: · 601 unmodified lines | ||
| 666 | 666 | case CHIP_YELLOW_CARP: |
| 667 | 667 | yellow_carp_reg_base_init(adev); |
| 668 | 668 | break; |
| 669 | + case CHIP_CYAN_SKILLFISH: | |
| 670 | + cyan_skillfish_reg_base_init(adev); | |
| 671 | + break; | |
| 669 | 672 | default: |
| 670 | 673 | return -EINVAL; |
| 671 | 674 | } |
| @@ -682,7 +685,10 @@ int nv_set_ip_blocks(struct amdgpu_device *adev) · 10 unmodified lines | ||
| 682 | 685 | { |
| 683 | 686 | int r; |
| 684 | 687 | |
| 685 | − if (adev->flags & AMD_IS_APU) { | |
| 688 | + if (adev->asic_type == CHIP_CYAN_SKILLFISH) { | |
| 689 | + adev->nbio.funcs = &nbio_v2_3_funcs; | |
| 690 | + adev->nbio.hdp_flush_reg = &nbio_v2_3_hdp_flush_reg; | |
| 691 | + } else if (adev->flags & AMD_IS_APU) { | |
| 686 | 692 | adev->nbio.funcs = &nbio_v7_2_funcs; |
| 687 | 693 | adev->nbio.hdp_flush_reg = &nbio_v7_2_hdp_flush_reg; |
| 688 | 694 | } else { |
| @@ -715,7 +721,7 @@ int nv_set_ip_blocks(struct amdgpu_device *adev) · 26 unmodified lines | ||
| 715 | 721 | !amdgpu_sriov_vf(adev)) |
| 716 | 722 | amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block); |
| 717 | 723 | if (adev->enable_virtual_display || amdgpu_sriov_vf(adev)) |
| 718 | − amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block); | |
| 724 | + amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block); | |
| 719 | 725 | #if defined(CONFIG_DRM_AMD_DC) |
| 720 | 726 | else if (amdgpu_device_has_dc_support(adev)) |
| 721 | 727 | amdgpu_device_ip_block_add(adev, &dm_ip_block); |
| @@ -743,7 +749,7 @@ int nv_set_ip_blocks(struct amdgpu_device *adev) · 21 unmodified lines | ||
| 743 | 749 | if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) |
| 744 | 750 | amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block); |
| 745 | 751 | if (adev->enable_virtual_display || amdgpu_sriov_vf(adev)) |
| 746 | − amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block); | |
| 752 | + amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block); | |
| 747 | 753 | #if defined(CONFIG_DRM_AMD_DC) |
| 748 | 754 | else if (amdgpu_device_has_dc_support(adev)) |
| 749 | 755 | amdgpu_device_ip_block_add(adev, &dm_ip_block); |
| @@ -773,7 +779,7 @@ int nv_set_ip_blocks(struct amdgpu_device *adev) · 23 unmodified lines | ||
| 773 | 779 | is_support_sw_smu(adev)) |
| 774 | 780 | amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block); |
| 775 | 781 | if (adev->enable_virtual_display || amdgpu_sriov_vf(adev)) |
| 776 | − amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block); | |
| 782 | + amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block); | |
| 777 | 783 | #if defined(CONFIG_DRM_AMD_DC) |
| 778 | 784 | else if (amdgpu_device_has_dc_support(adev)) |
| 779 | 785 | amdgpu_device_ip_block_add(adev, &dm_ip_block); |
| @@ -796,7 +802,7 @@ int nv_set_ip_blocks(struct amdgpu_device *adev) · 16 unmodified lines | ||
| 796 | 802 | is_support_sw_smu(adev)) |
| 797 | 803 | amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block); |
| 798 | 804 | if (adev->enable_virtual_display || amdgpu_sriov_vf(adev)) |
| 799 | − amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block); | |
| 805 | + amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block); | |
| 800 | 806 | #if defined(CONFIG_DRM_AMD_DC) |
| 801 | 807 | else if (amdgpu_device_has_dc_support(adev)) |
| 802 | 808 | amdgpu_device_ip_block_add(adev, &dm_ip_block); |
| @@ -817,7 +823,7 @@ int nv_set_ip_blocks(struct amdgpu_device *adev) · 14 unmodified lines | ||
| 817 | 823 | amdgpu_device_ip_block_add(adev, &psp_v11_0_ip_block); |
| 818 | 824 | amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block); |
| 819 | 825 | if (adev->enable_virtual_display || amdgpu_sriov_vf(adev)) |
| 820 | − amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block); | |
| 826 | + amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block); | |
| 821 | 827 | #if defined(CONFIG_DRM_AMD_DC) |
| 822 | 828 | else if (amdgpu_device_has_dc_support(adev)) |
| 823 | 829 | amdgpu_device_ip_block_add(adev, &dm_ip_block); |
| @@ -837,7 +843,7 @@ int nv_set_ip_blocks(struct amdgpu_device *adev) · 13 unmodified lines | ||
| 837 | 843 | is_support_sw_smu(adev)) |
| 838 | 844 | amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block); |
| 839 | 845 | if (adev->enable_virtual_display || amdgpu_sriov_vf(adev)) |
| 840 | − amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block); | |
| 846 | + amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block); | |
| 841 | 847 | #if defined(CONFIG_DRM_AMD_DC) |
| 842 | 848 | else if (amdgpu_device_has_dc_support(adev)) |
| 843 | 849 | amdgpu_device_ip_block_add(adev, &dm_ip_block); |
| @@ -859,7 +865,7 @@ int nv_set_ip_blocks(struct amdgpu_device *adev) · 15 unmodified lines | ||
| 859 | 865 | amdgpu_device_ip_block_add(adev, &gfx_v10_0_ip_block); |
| 860 | 866 | amdgpu_device_ip_block_add(adev, &sdma_v5_2_ip_block); |
| 861 | 867 | if (adev->enable_virtual_display || amdgpu_sriov_vf(adev)) |
| 862 | − amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block); | |
| 868 | + amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block); | |
| 863 | 869 | #if defined(CONFIG_DRM_AMD_DC) |
| 864 | 870 | else if (amdgpu_device_has_dc_support(adev)) |
| 865 | 871 | amdgpu_device_ip_block_add(adev, &dm_ip_block); |
| @@ -877,11 +883,11 @@ int nv_set_ip_blocks(struct amdgpu_device *adev) · 11 unmodified lines | ||
| 877 | 883 | amdgpu_device_ip_block_add(adev, &psp_v13_0_ip_block); |
| 878 | 884 | amdgpu_device_ip_block_add(adev, &smu_v13_0_ip_block); |
| 879 | 885 | if (adev->enable_virtual_display || amdgpu_sriov_vf(adev)) |
| 880 | − amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block); | |
| 886 | + amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block); | |
| 881 | 887 | amdgpu_device_ip_block_add(adev, &gfx_v10_0_ip_block); |
| 882 | 888 | amdgpu_device_ip_block_add(adev, &sdma_v5_2_ip_block); |
| 883 | 889 | if (adev->enable_virtual_display || amdgpu_sriov_vf(adev)) |
| 884 | − amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block); | |
| 890 | + amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block); | |
| 885 | 891 | #if defined(CONFIG_DRM_AMD_DC) |
| 886 | 892 | else if (amdgpu_device_has_dc_support(adev)) |
| 887 | 893 | amdgpu_device_ip_block_add(adev, &dm_ip_block); |
| @@ -889,6 +895,20 @@ int nv_set_ip_blocks(struct amdgpu_device *adev) · 1 unmodified line | ||
| 889 | 895 | amdgpu_device_ip_block_add(adev, &vcn_v3_0_ip_block); |
| 890 | 896 | amdgpu_device_ip_block_add(adev, &jpeg_v3_0_ip_block); |
| 891 | 897 | break; |
| 898 | + case CHIP_CYAN_SKILLFISH: | |
| 899 | + amdgpu_device_ip_block_add(adev, &nv_common_ip_block); | |
| 900 | + amdgpu_device_ip_block_add(adev, &gmc_v10_0_ip_block); | |
| 901 | + amdgpu_device_ip_block_add(adev, &navi10_ih_ip_block); | |
| 902 | + if (adev->apu_flags & AMD_APU_IS_CYAN_SKILLFISH2) { | |
| 903 | + if (likely(adev->firmware.load_type == AMDGPU_FW_LOAD_PSP)) | |
| 904 | + amdgpu_device_ip_block_add(adev, &psp_v11_0_8_ip_block); | |
| 905 | + amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block); | |
| 906 | + } | |
| 907 | + if (adev->enable_virtual_display || amdgpu_sriov_vf(adev)) | |
| 908 | + amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block); | |
| 909 | + amdgpu_device_ip_block_add(adev, &gfx_v10_0_ip_block); | |
| 910 | + amdgpu_device_ip_block_add(adev, &sdma_v5_0_ip_block); | |
| 911 | + break; | |
| 892 | 912 | default: |
| 893 | 913 | return -EINVAL; |
| 894 | 914 | } |
| @@ -1241,6 +1261,11 @@ static int nv_common_early_init(void *handle) · 346 unmodified lines | ||
| 1241 | 1261 | else |
| 1242 | 1262 | adev->external_rev_id = adev->rev_id + 0x01; |
| 1243 | 1263 | break; |
| 1264 | + case CHIP_CYAN_SKILLFISH: | |
| 1265 | + adev->cg_flags = 0; | |
| 1266 | + adev->pg_flags = 0; | |
| 1267 | + adev->external_rev_id = adev->rev_id + 0x82; | |
| 1268 | + break; | |
| 1244 | 1269 | default: |
| 1245 | 1270 | /* FIXME: not supported yet */ |
| 1246 | 1271 | return -EINVAL; |
| @@ -38,5 +38,6 @@ void vangogh_reg_base_init(struct amdgpu_device *adev); · 37 unmodified lines | ||
| 38 | 38 | int dimgrey_cavefish_reg_base_init(struct amdgpu_device *adev); |
| 39 | 39 | int beige_goby_reg_base_init(struct amdgpu_device *adev); |
| 40 | 40 | int yellow_carp_reg_base_init(struct amdgpu_device *adev); |
| 41 | +int cyan_skillfish_reg_base_init(struct amdgpu_device *adev); | |
| 41 | 42 | |
| 42 | 43 | #endif |
| @@ -84,29 +84,29 @@ static int psp_v10_0_init_microcode(struct psp_context *psp) · 83 unmodified lines | ||
| 84 | 84 | |
| 85 | 85 | ta_hdr = (const struct ta_firmware_header_v1_0 *) |
| 86 | 86 | adev->psp.ta_fw->data; |
| 87 | − adev->psp.ta_hdcp_ucode_version = | |
| 88 | − le32_to_cpu(ta_hdr->ta_hdcp_ucode_version); | |
| 89 | − adev->psp.ta_hdcp_ucode_size = | |
| 90 | − le32_to_cpu(ta_hdr->ta_hdcp_size_bytes); | |
| 91 | − adev->psp.ta_hdcp_start_addr = | |
| 87 | + adev->psp.hdcp.feature_version = | |
| 88 | + le32_to_cpu(ta_hdr->hdcp.fw_version); | |
| 89 | + adev->psp.hdcp.size_bytes = | |
| 90 | + le32_to_cpu(ta_hdr->hdcp.size_bytes); | |
| 91 | + adev->psp.hdcp.start_addr = | |
| 92 | 92 | (uint8_t *)ta_hdr + |
| 93 | 93 | le32_to_cpu(ta_hdr->header.ucode_array_offset_bytes); |
| 94 | 94 | |
| 95 | − adev->psp.ta_dtm_ucode_version = | |
| 96 | − le32_to_cpu(ta_hdr->ta_dtm_ucode_version); | |
| 97 | − adev->psp.ta_dtm_ucode_size = | |
| 98 | − le32_to_cpu(ta_hdr->ta_dtm_size_bytes); | |
| 99 | − adev->psp.ta_dtm_start_addr = | |
| 100 | − (uint8_t *)adev->psp.ta_hdcp_start_addr + | |
| 101 | − le32_to_cpu(ta_hdr->ta_dtm_offset_bytes); | |
| 102 | − | |
| 103 | − adev->psp.ta_securedisplay_ucode_version = | |
| 104 | − le32_to_cpu(ta_hdr->ta_securedisplay_ucode_version); | |
| 105 | − adev->psp.ta_securedisplay_ucode_size = | |
| 106 | − le32_to_cpu(ta_hdr->ta_securedisplay_size_bytes); | |
| 107 | − adev->psp.ta_securedisplay_start_addr = | |
| 108 | − (uint8_t *)adev->psp.ta_hdcp_start_addr + | |
| 109 | − le32_to_cpu(ta_hdr->ta_securedisplay_offset_bytes); | |
| 95 | + adev->psp.dtm.feature_version = | |
| 96 | + le32_to_cpu(ta_hdr->dtm.fw_version); | |
| 97 | + adev->psp.dtm.size_bytes = | |
| 98 | + le32_to_cpu(ta_hdr->dtm.size_bytes); | |
| 99 | + adev->psp.dtm.start_addr = | |
| 100 | + (uint8_t *)adev->psp.hdcp.start_addr + | |
| 101 | + le32_to_cpu(ta_hdr->dtm.offset_bytes); | |
| 102 | + | |
| 103 | + adev->psp.securedisplay.feature_version = | |
| 104 | + le32_to_cpu(ta_hdr->securedisplay.fw_version); | |
| 105 | + adev->psp.securedisplay.size_bytes = | |
| 106 | + le32_to_cpu(ta_hdr->securedisplay.size_bytes); | |
| 107 | + adev->psp.securedisplay.start_addr = | |
| 108 | + (uint8_t *)adev->psp.hdcp.start_addr + | |
| 109 | + le32_to_cpu(ta_hdr->securedisplay.offset_bytes); | |
| 110 | 110 | |
| 111 | 111 | adev->psp.ta_fw_version = le32_to_cpu(ta_hdr->header.ucode_version); |
| 112 | 112 | } |
| @@ -80,6 +80,9 @@ MODULE_FIRMWARE("amdgpu/beige_goby_ta.bin"); · 79 unmodified lines | ||
| 80 | 80 | /* For large FW files the time to complete can be very long */ |
| 81 | 81 | #define USBC_PD_POLLING_LIMIT_S 240 |
| 82 | 82 | |
| 83 | +/* Read USB-PD from LFB */ | |
| 84 | +#define GFX_CMD_USB_PD_USE_LFB 0x480 | |
| 85 | + | |
| 83 | 86 | static int psp_v11_0_init_microcode(struct psp_context *psp) |
| 84 | 87 | { |
| 85 | 88 | struct amdgpu_device *adev = psp->adev; |
| @@ -148,15 +151,15 @@ static int psp_v11_0_init_microcode(struct psp_context *psp) · 62 unmodified lines | ||
| 148 | 151 | goto out2; |
| 149 | 152 | |
| 150 | 153 | ta_hdr = (const struct ta_firmware_header_v1_0 *)adev->psp.ta_fw->data; |
| 151 | − adev->psp.ta_xgmi_ucode_version = le32_to_cpu(ta_hdr->ta_xgmi_ucode_version); | |
| 152 | − adev->psp.ta_xgmi_ucode_size = le32_to_cpu(ta_hdr->ta_xgmi_size_bytes); | |
| 153 | − adev->psp.ta_xgmi_start_addr = (uint8_t *)ta_hdr + | |
| 154 | + adev->psp.xgmi.feature_version = le32_to_cpu(ta_hdr->xgmi.fw_version); | |
| 155 | + adev->psp.xgmi.size_bytes = le32_to_cpu(ta_hdr->xgmi.size_bytes); | |
| 156 | + adev->psp.xgmi.start_addr = (uint8_t *)ta_hdr + | |
| 154 | 157 | le32_to_cpu(ta_hdr->header.ucode_array_offset_bytes); |
| 155 | 158 | adev->psp.ta_fw_version = le32_to_cpu(ta_hdr->header.ucode_version); |
| 156 | − adev->psp.ta_ras_ucode_version = le32_to_cpu(ta_hdr->ta_ras_ucode_version); | |
| 157 | − adev->psp.ta_ras_ucode_size = le32_to_cpu(ta_hdr->ta_ras_size_bytes); | |
| 158 | − adev->psp.ta_ras_start_addr = (uint8_t *)adev->psp.ta_xgmi_start_addr + | |
| 159 | − le32_to_cpu(ta_hdr->ta_ras_offset_bytes); | |
| 159 | + adev->psp.ras.feature_version = le32_to_cpu(ta_hdr->ras.fw_version); | |
| 160 | + adev->psp.ras.size_bytes = le32_to_cpu(ta_hdr->ras.size_bytes); | |
| 161 | + adev->psp.ras.start_addr = (uint8_t *)adev->psp.xgmi.start_addr + | |
| 162 | + le32_to_cpu(ta_hdr->ras.offset_bytes); | |
| 160 | 163 | } |
| 161 | 164 | break; |
| 162 | 165 | case CHIP_NAVI10: |
| @@ -183,17 +186,17 @@ static int psp_v11_0_init_microcode(struct psp_context *psp) · 20 unmodified lines | ||
| 183 | 186 | goto out2; |
| 184 | 187 | |
| 185 | 188 | ta_hdr = (const struct ta_firmware_header_v1_0 *)adev->psp.ta_fw->data; |
| 186 | − adev->psp.ta_hdcp_ucode_version = le32_to_cpu(ta_hdr->ta_hdcp_ucode_version); | |
| 187 | − adev->psp.ta_hdcp_ucode_size = le32_to_cpu(ta_hdr->ta_hdcp_size_bytes); | |
| 188 | − adev->psp.ta_hdcp_start_addr = (uint8_t *)ta_hdr + | |
| 189 | + adev->psp.hdcp.feature_version = le32_to_cpu(ta_hdr->hdcp.fw_version); | |
| 190 | + adev->psp.hdcp.size_bytes = le32_to_cpu(ta_hdr->hdcp.size_bytes); | |
| 191 | + adev->psp.hdcp.start_addr = (uint8_t *)ta_hdr + | |
| 189 | 192 | le32_to_cpu(ta_hdr->header.ucode_array_offset_bytes); |
| 190 | 193 | |
| 191 | 194 | adev->psp.ta_fw_version = le32_to_cpu(ta_hdr->header.ucode_version); |
| 192 | 195 | |
| 193 | − adev->psp.ta_dtm_ucode_version = le32_to_cpu(ta_hdr->ta_dtm_ucode_version); | |
| 194 | − adev->psp.ta_dtm_ucode_size = le32_to_cpu(ta_hdr->ta_dtm_size_bytes); | |
| 195 | − adev->psp.ta_dtm_start_addr = (uint8_t *)adev->psp.ta_hdcp_start_addr + | |
| 196 | − le32_to_cpu(ta_hdr->ta_dtm_offset_bytes); | |
| 196 | + adev->psp.dtm.feature_version = le32_to_cpu(ta_hdr->dtm.fw_version); | |
| 197 | + adev->psp.dtm.size_bytes = le32_to_cpu(ta_hdr->dtm.size_bytes); | |
| 198 | + adev->psp.dtm.start_addr = (uint8_t *)adev->psp.hdcp.start_addr + | |
| 199 | + le32_to_cpu(ta_hdr->dtm.offset_bytes); | |
| 197 | 200 | } |
| 198 | 201 | break; |
| 199 | 202 | case CHIP_SIENNA_CICHLID: |
| @@ -284,7 +287,7 @@ static int psp_v11_0_bootloader_load_kdb(struct psp_context *psp) · 84 unmodified lines | ||
| 284 | 287 | return ret; |
| 285 | 288 | |
| 286 | 289 | /* Copy PSP KDB binary to memory */ |
| 287 | − psp_copy_fw(psp, psp->kdb_start_addr, psp->kdb_bin_size); | |
| 290 | + psp_copy_fw(psp, psp->kdb.start_addr, psp->kdb.size_bytes); | |
| 288 | 291 | |
| 289 | 292 | /* Provide the PSP KDB to bootloader */ |
| 290 | 293 | WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_36, |
| @@ -315,7 +318,7 @@ static int psp_v11_0_bootloader_load_spl(struct psp_context *psp) · 24 unmodified lines | ||
| 315 | 318 | return ret; |
| 316 | 319 | |
| 317 | 320 | /* Copy PSP SPL binary to memory */ |
| 318 | − psp_copy_fw(psp, psp->spl_start_addr, psp->spl_bin_size); | |
| 321 | + psp_copy_fw(psp, psp->spl.start_addr, psp->spl.size_bytes); | |
| 319 | 322 | |
| 320 | 323 | /* Provide the PSP SPL to bootloader */ |
| 321 | 324 | WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_36, |
| @@ -346,7 +349,7 @@ static int psp_v11_0_bootloader_load_sysdrv(struct psp_context *psp) · 24 unmodified lines | ||
| 346 | 349 | return ret; |
| 347 | 350 | |
| 348 | 351 | /* Copy PSP System Driver binary to memory */ |
| 349 | − psp_copy_fw(psp, psp->sys_start_addr, psp->sys_bin_size); | |
| 352 | + psp_copy_fw(psp, psp->sys.start_addr, psp->sys.size_bytes); | |
| 350 | 353 | |
| 351 | 354 | /* Provide the sys driver to bootloader */ |
| 352 | 355 | WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_36, |
| @@ -380,7 +383,7 @@ static int psp_v11_0_bootloader_load_sos(struct psp_context *psp) · 27 unmodified lines | ||
| 380 | 383 | return ret; |
| 381 | 384 | |
| 382 | 385 | /* Copy Secure OS binary to PSP memory */ |
| 383 | − psp_copy_fw(psp, psp->sos_start_addr, psp->sos_bin_size); | |
| 386 | + psp_copy_fw(psp, psp->sos.start_addr, psp->sos.size_bytes); | |
| 384 | 387 | |
| 385 | 388 | /* Provide the PSP secure OS to bootloader */ |
| 386 | 389 | WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_36, |
| @@ -753,44 +756,26 @@ static void psp_v11_0_ring_set_wptr(struct psp_context *psp, uint32_t value) · 366 unmodified lines | ||
| 753 | 756 | WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_67, value); |
| 754 | 757 | } |
| 755 | 758 | |
| 756 | −static int psp_v11_0_load_usbc_pd_fw(struct psp_context *psp, dma_addr_t dma_addr) | |
| 759 | +static int psp_v11_0_load_usbc_pd_fw(struct psp_context *psp, uint64_t fw_pri_mc_addr) | |
| 757 | 760 | { |
| 758 | 761 | struct amdgpu_device *adev = psp->adev; |
| 759 | 762 | uint32_t reg_status; |
| 760 | 763 | int ret, i = 0; |
| 761 | 764 | |
| 762 | − /* Write lower 32-bit address of the PD Controller FW */ | |
| 763 | − WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_36, lower_32_bits(dma_addr)); | |
| 764 | − ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_35), | |
| 765 | − 0x80000000, 0x80000000, false); | |
| 766 | − if (ret) | |
| 767 | − return ret; | |
| 768 | − | |
| 769 | − /* Fireup interrupt so PSP can pick up the lower address */ | |
| 770 | − WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_35, 0x800000); | |
| 771 | − ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_35), | |
| 772 | − 0x80000000, 0x80000000, false); | |
| 773 | − if (ret) | |
| 774 | − return ret; | |
| 775 | − | |
| 776 | − reg_status = RREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_35); | |
| 777 | − | |
| 778 | − if ((reg_status & 0xFFFF) != 0) { | |
| 779 | − DRM_ERROR("Lower address load failed - MP0_SMN_C2PMSG_35.Bits [15:0] = %02x...\n", | |
| 780 | − reg_status & 0xFFFF); | |
| 781 | − return -EIO; | |
| 782 | − } | |
| 783 | − | |
| 784 | − /* Write upper 32-bit address of the PD Controller FW */ | |
| 785 | − WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_36, upper_32_bits(dma_addr)); | |
| 765 | + /* | |
| 766 | + * LFB address which is aligned to 1MB address and has to be | |
| 767 | + * right-shifted by 20 so that LFB address can be passed on a 32-bit C2P | |
| 768 | + * register | |
| 769 | + */ | |
| 770 | + WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_36, (fw_pri_mc_addr >> 20)); | |
| 786 | 771 | |
| 787 | 772 | ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_35), |
| 788 | 773 | 0x80000000, 0x80000000, false); |
| 789 | 774 | if (ret) |
| 790 | 775 | return ret; |
| 791 | 776 | |
| 792 | − /* Fireup interrupt so PSP can pick up the upper address */ | |
| 793 | − WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_35, 0x4000000); | |
| 777 | + /* Fireup interrupt so PSP can pick up the address */ | |
| 778 | + WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_35, (GFX_CMD_USB_PD_USE_LFB << 16)); | |
| 794 | 779 | |
| 795 | 780 | /* FW load takes very long time */ |
| 796 | 781 | do { |
| @@ -806,7 +791,7 @@ static int psp_v11_0_load_usbc_pd_fw(struct psp_context *psp, dma_addr_t dma_add · 9 unmodified lines | ||
| 806 | 791 | done: |
| 807 | 792 | |
| 808 | 793 | if ((reg_status & 0xFFFF) != 0) { |
| 809 | − DRM_ERROR("Upper address load failed - MP0_SMN_C2PMSG_35.Bits [15:0] = x%04x\n", | |
| 794 | + DRM_ERROR("Address load failed - MP0_SMN_C2PMSG_35.Bits [15:0] = 0x%04x\n", | |
| 810 | 795 | reg_status & 0xFFFF); |
| 811 | 796 | return -EIO; |
| 812 | 797 | } |
| @@ -0,0 +1,208 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright 2021 Advanced Micro Devices, Inc. | |
| 3 | + * | |
| 4 | + * Permission is hereby granted, free of charge, to any person obtaining a | |
| 5 | + * copy of this software and associated documentation files (the "Software"), | |
| 6 | + * to deal in the Software without restriction, including without limitation | |
| 7 | + * the rights to use, copy, modify, merge, publish, distribute, sublicense, | |
| 8 | + * and/or sell copies of the Software, and to permit persons to whom the | |
| 9 | + * Software is furnished to do so, subject to the following conditions: | |
| 10 | + * | |
| 11 | + * The above copyright notice and this permission notice shall be included in | |
| 12 | + * all copies or substantial portions of the Software. | |
| 13 | + * | |
| 14 | + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
| 15 | + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
| 16 | + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |
| 17 | + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR | |
| 18 | + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | |
| 19 | + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | |
| 20 | + * OTHER DEALINGS IN THE SOFTWARE. | |
| 21 | + * | |
| 22 | + */ | |
| 23 | +#include "amdgpu.h" | |
| 24 | +#include "amdgpu_psp.h" | |
| 25 | +#include "amdgpu_ucode.h" | |
| 26 | +#include "soc15_common.h" | |
| 27 | +#include "psp_v11_0_8.h" | |
| 28 | + | |
| 29 | +#include "mp/mp_11_0_8_offset.h" | |
| 30 | + | |
| 31 | +static int psp_v11_0_8_ring_init(struct psp_context *psp, | |
| 32 | + enum psp_ring_type ring_type) | |
| 33 | +{ | |
| 34 | + int ret = 0; | |
| 35 | + struct psp_ring *ring; | |
| 36 | + struct amdgpu_device *adev = psp->adev; | |
| 37 | + | |
| 38 | + ring = &psp->km_ring; | |
| 39 | + | |
| 40 | + ring->ring_type = ring_type; | |
| 41 | + | |
| 42 | + /* allocate 4k Page of Local Frame Buffer memory for ring */ | |
| 43 | + ring->ring_size = 0x1000; | |
| 44 | + ret = amdgpu_bo_create_kernel(adev, ring->ring_size, PAGE_SIZE, | |
| 45 | + AMDGPU_GEM_DOMAIN_VRAM, | |
| 46 | + &adev->firmware.rbuf, | |
| 47 | + &ring->ring_mem_mc_addr, | |
| 48 | + (void **)&ring->ring_mem); | |
| 49 | + if (ret) { | |
| 50 | + ring->ring_size = 0; | |
| 51 | + return ret; | |
| 52 | + } | |
| 53 | + | |
| 54 | + return 0; | |
| 55 | +} | |
| 56 | + | |
| 57 | +static int psp_v11_0_8_ring_stop(struct psp_context *psp, | |
| 58 | + enum psp_ring_type ring_type) | |
| 59 | +{ | |
| 60 | + int ret = 0; | |
| 61 | + struct amdgpu_device *adev = psp->adev; | |
| 62 | + | |
| 63 | + if (amdgpu_sriov_vf(adev)) { | |
| 64 | + /* Write the ring destroy command*/ | |
| 65 | + WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_101, | |
| 66 | + GFX_CTRL_CMD_ID_DESTROY_GPCOM_RING); | |
| 67 | + /* there might be handshake issue with hardware which needs delay */ | |
| 68 | + mdelay(20); | |
| 69 | + /* Wait for response flag (bit 31) */ | |
| 70 | + ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_101), | |
| 71 | + 0x80000000, 0x80000000, false); | |
| 72 | + } else { | |
| 73 | + /* Write the ring destroy command*/ | |
| 74 | + WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_64, | |
| 75 | + GFX_CTRL_CMD_ID_DESTROY_RINGS); | |
| 76 | + /* there might be handshake issue with hardware which needs delay */ | |
| 77 | + mdelay(20); | |
| 78 | + /* Wait for response flag (bit 31) */ | |
| 79 | + ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_64), | |
| 80 | + 0x80000000, 0x80000000, false); | |
| 81 | + } | |
| 82 | + | |
| 83 | + return ret; | |
| 84 | +} | |
| 85 | + | |
| 86 | +static int psp_v11_0_8_ring_create(struct psp_context *psp, | |
| 87 | + enum psp_ring_type ring_type) | |
| 88 | +{ | |
| 89 | + int ret = 0; | |
| 90 | + unsigned int psp_ring_reg = 0; | |
| 91 | + struct psp_ring *ring = &psp->km_ring; | |
| 92 | + struct amdgpu_device *adev = psp->adev; | |
| 93 | + | |
| 94 | + if (amdgpu_sriov_vf(adev)) { | |
| 95 | + ret = psp_v11_0_8_ring_stop(psp, ring_type); | |
| 96 | + if (ret) { | |
| 97 | + DRM_ERROR("psp_v11_0_8_ring_stop_sriov failed!\n"); | |
| 98 | + return ret; | |
| 99 | + } | |
| 100 | + | |
| 101 | + /* Write low address of the ring to C2PMSG_102 */ | |
| 102 | + psp_ring_reg = lower_32_bits(ring->ring_mem_mc_addr); | |
| 103 | + WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_102, psp_ring_reg); | |
| 104 | + /* Write high address of the ring to C2PMSG_103 */ | |
| 105 | + psp_ring_reg = upper_32_bits(ring->ring_mem_mc_addr); | |
| 106 | + WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_103, psp_ring_reg); | |
| 107 | + | |
| 108 | + /* Write the ring initialization command to C2PMSG_101 */ | |
| 109 | + WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_101, | |
| 110 | + GFX_CTRL_CMD_ID_INIT_GPCOM_RING); | |
| 111 | + | |
| 112 | + /* there might be handshake issue with hardware which needs delay */ | |
| 113 | + mdelay(20); | |
| 114 | + | |
| 115 | + /* Wait for response flag (bit 31) in C2PMSG_101 */ | |
| 116 | + ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_101), | |
| 117 | + 0x80000000, 0x8000FFFF, false); | |
| 118 | + | |
| 119 | + } else { | |
| 120 | + /* Wait for sOS ready for ring creation */ | |
| 121 | + ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_64), | |
| 122 | + 0x80000000, 0x80000000, false); | |
| 123 | + if (ret) { | |
| 124 | + DRM_ERROR("Failed to wait for trust OS ready for ring creation\n"); | |
| 125 | + return ret; | |
| 126 | + } | |
| 127 | + | |
| 128 | + /* Write low address of the ring to C2PMSG_69 */ | |
| 129 | + psp_ring_reg = lower_32_bits(ring->ring_mem_mc_addr); | |
| 130 | + WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_69, psp_ring_reg); | |
| 131 | + /* Write high address of the ring to C2PMSG_70 */ | |
| 132 | + psp_ring_reg = upper_32_bits(ring->ring_mem_mc_addr); | |
| 133 | + WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_70, psp_ring_reg); | |
| 134 | + /* Write size of ring to C2PMSG_71 */ | |
| 135 | + psp_ring_reg = ring->ring_size; | |
| 136 | + WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_71, psp_ring_reg); | |
| 137 | + /* Write the ring initialization command to C2PMSG_64 */ | |
| 138 | + psp_ring_reg = ring_type; | |
| 139 | + psp_ring_reg = psp_ring_reg << 16; | |
| 140 | + WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_64, psp_ring_reg); | |
| 141 | + | |
| 142 | + /* there might be handshake issue with hardware which needs delay */ | |
| 143 | + mdelay(20); | |
| 144 | + | |
| 145 | + /* Wait for response flag (bit 31) in C2PMSG_64 */ | |
| 146 | + ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_64), | |
| 147 | + 0x80000000, 0x8000FFFF, false); | |
| 148 | + } | |
| 149 | + | |
| 150 | + return ret; | |
| 151 | +} | |
| 152 | + | |
| 153 | +static int psp_v11_0_8_ring_destroy(struct psp_context *psp, | |
| 154 | + enum psp_ring_type ring_type) | |
| 155 | +{ | |
| 156 | + int ret = 0; | |
| 157 | + struct psp_ring *ring = &psp->km_ring; | |
| 158 | + struct amdgpu_device *adev = psp->adev; | |
| 159 | + | |
| 160 | + ret = psp_v11_0_8_ring_stop(psp, ring_type); | |
| 161 | + if (ret) | |
| 162 | + DRM_ERROR("Fail to stop psp ring\n"); | |
| 163 | + | |
| 164 | + amdgpu_bo_free_kernel(&adev->firmware.rbuf, | |
| 165 | + &ring->ring_mem_mc_addr, | |
| 166 | + (void **)&ring->ring_mem); | |
| 167 | + | |
| 168 | + return ret; | |
| 169 | +} | |
| 170 | + | |
| 171 | +static uint32_t psp_v11_0_8_ring_get_wptr(struct psp_context *psp) | |
| 172 | +{ | |
| 173 | + uint32_t data; | |
| 174 | + struct amdgpu_device *adev = psp->adev; | |
| 175 | + | |
| 176 | + if (amdgpu_sriov_vf(adev)) | |
| 177 | + data = RREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_102); | |
| 178 | + else | |
| 179 | + data = RREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_67); | |
| 180 | + | |
| 181 | + return data; | |
| 182 | +} | |
| 183 | + | |
| 184 | +static void psp_v11_0_8_ring_set_wptr(struct psp_context *psp, uint32_t value) | |
| 185 | +{ | |
| 186 | + struct amdgpu_device *adev = psp->adev; | |
| 187 | + | |
| 188 | + if (amdgpu_sriov_vf(adev)) { | |
| 189 | + WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_102, value); | |
| 190 | + WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_101, | |
| 191 | + GFX_CTRL_CMD_ID_CONSUME_CMD); | |
| 192 | + } else | |
| 193 | + WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_67, value); | |
| 194 | +} | |
| 195 | + | |
| 196 | +static const struct psp_funcs psp_v11_0_8_funcs = { | |
| 197 | + .ring_init = psp_v11_0_8_ring_init, | |
| 198 | + .ring_create = psp_v11_0_8_ring_create, | |
| 199 | + .ring_stop = psp_v11_0_8_ring_stop, | |
| 200 | + .ring_destroy = psp_v11_0_8_ring_destroy, | |
| 201 | + .ring_get_wptr = psp_v11_0_8_ring_get_wptr, | |
| 202 | + .ring_set_wptr = psp_v11_0_8_ring_set_wptr, | |
| 203 | +}; | |
| 204 | + | |
| 205 | +void psp_v11_0_8_set_psp_funcs(struct psp_context *psp) | |
| 206 | +{ | |
| 207 | + psp->funcs = &psp_v11_0_8_funcs; | |
| 208 | +} | |
| @@ -1,5 +1,5 @@ | ||
| 1 | 1 | /* |
| 2 | − * Copyright 2014 Advanced Micro Devices, Inc. | |
| 2 | + * Copyright 2021 Advanced Micro Devices, Inc. | |
| 3 | 3 | * |
| 4 | 4 | * Permission is hereby granted, free of charge, to any person obtaining a |
| 5 | 5 | * copy of this software and associated documentation files (the "Software"), |
| @@ -20,11 +20,11 @@ · 14 unmodified lines | ||
| 20 | 20 | * OTHER DEALINGS IN THE SOFTWARE. |
| 21 | 21 | * |
| 22 | 22 | */ |
| 23 | +#ifndef __PSP_V11_0_8_H__ | |
| 24 | +#define __PSP_V11_0_8_H__ | |
| 23 | 25 | |
| 24 | −#ifndef __DCE_VIRTUAL_H__ | |
| 25 | −#define __DCE_VIRTUAL_H__ | |
| 26 | +#include "amdgpu_psp.h" | |
| 26 | 27 | |
| 27 | −extern const struct amdgpu_ip_block_version dce_virtual_ip_block; | |
| 28 | +void psp_v11_0_8_set_psp_funcs(struct psp_context *psp); | |
| 28 | 29 | |
| 29 | 30 | #endif |
| 30 | − | |
| @@ -84,23 +84,23 @@ static int psp_v12_0_init_microcode(struct psp_context *psp) · 83 unmodified lines | ||
| 84 | 84 | |
| 85 | 85 | ta_hdr = (const struct ta_firmware_header_v1_0 *) |
| 86 | 86 | adev->psp.ta_fw->data; |
| 87 | − adev->psp.ta_hdcp_ucode_version = | |
| 88 | − le32_to_cpu(ta_hdr->ta_hdcp_ucode_version); | |
| 89 | − adev->psp.ta_hdcp_ucode_size = | |
| 90 | − le32_to_cpu(ta_hdr->ta_hdcp_size_bytes); | |
| 91 | − adev->psp.ta_hdcp_start_addr = | |
| 87 | + adev->psp.hdcp.feature_version = | |
| 88 | + le32_to_cpu(ta_hdr->hdcp.fw_version); | |
| 89 | + adev->psp.hdcp.size_bytes = | |
| 90 | + le32_to_cpu(ta_hdr->hdcp.size_bytes); | |
| 91 | + adev->psp.hdcp.start_addr = | |
| 92 | 92 | (uint8_t *)ta_hdr + |
| 93 | 93 | le32_to_cpu(ta_hdr->header.ucode_array_offset_bytes); |
| 94 | 94 | |
| 95 | 95 | adev->psp.ta_fw_version = le32_to_cpu(ta_hdr->header.ucode_version); |
| 96 | 96 | |
| 97 | − adev->psp.ta_dtm_ucode_version = | |
| 98 | − le32_to_cpu(ta_hdr->ta_dtm_ucode_version); | |
| 99 | − adev->psp.ta_dtm_ucode_size = | |
| 100 | − le32_to_cpu(ta_hdr->ta_dtm_size_bytes); | |
| 101 | − adev->psp.ta_dtm_start_addr = | |
| 102 | − (uint8_t *)adev->psp.ta_hdcp_start_addr + | |
| 103 | − le32_to_cpu(ta_hdr->ta_dtm_offset_bytes); | |
| 97 | + adev->psp.dtm.feature_version = | |
| 98 | + le32_to_cpu(ta_hdr->dtm.fw_version); | |
| 99 | + adev->psp.dtm.size_bytes = | |
| 100 | + le32_to_cpu(ta_hdr->dtm.size_bytes); | |
| 101 | + adev->psp.dtm.start_addr = | |
| 102 | + (uint8_t *)adev->psp.hdcp.start_addr + | |
| 103 | + le32_to_cpu(ta_hdr->dtm.offset_bytes); | |
| 104 | 104 | } |
| 105 | 105 | |
| 106 | 106 | return 0; |
| @@ -138,7 +138,7 @@ static int psp_v12_0_bootloader_load_sysdrv(struct psp_context *psp) · 31 unmodified lines | ||
| 138 | 138 | return ret; |
| 139 | 139 | |
| 140 | 140 | /* Copy PSP System Driver binary to memory */ |
| 141 | − psp_copy_fw(psp, psp->sys_start_addr, psp->sys_bin_size); | |
| 141 | + psp_copy_fw(psp, psp->sys.start_addr, psp->sys.size_bytes); | |
| 142 | 142 | |
| 143 | 143 | /* Provide the sys driver to bootloader */ |
| 144 | 144 | WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_36, |
| @@ -177,7 +177,7 @@ static int psp_v12_0_bootloader_load_sos(struct psp_context *psp) · 32 unmodified lines | ||
| 177 | 177 | return ret; |
| 178 | 178 | |
| 179 | 179 | /* Copy Secure OS binary to PSP memory */ |
| 180 | − psp_copy_fw(psp, psp->sos_start_addr, psp->sos_bin_size); | |
| 180 | + psp_copy_fw(psp, psp->sos.start_addr, psp->sos.size_bytes); | |
| 181 | 181 | |
| 182 | 182 | /* Provide the PSP secure OS to bootloader */ |
| 183 | 183 | WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_36, |
| @@ -35,6 +35,12 @@ MODULE_FIRMWARE("amdgpu/yellow_carp_asd.bin"); · 34 unmodified lines | ||
| 35 | 35 | MODULE_FIRMWARE("amdgpu/yellow_carp_toc.bin"); |
| 36 | 36 | MODULE_FIRMWARE("amdgpu/yellow_carp_ta.bin"); |
| 37 | 37 | |
| 38 | +/* For large FW files the time to complete can be very long */ | |
| 39 | +#define USBC_PD_POLLING_LIMIT_S 240 | |
| 40 | + | |
| 41 | +/* Read USB-PD from LFB */ | |
| 42 | +#define GFX_CMD_USB_PD_USE_LFB 0x480 | |
| 43 | + | |
| 38 | 44 | static int psp_v13_0_init_microcode(struct psp_context *psp) |
| 39 | 45 | { |
| 40 | 46 | struct amdgpu_device *adev = psp->adev; |
| @@ -111,7 +117,9 @@ static int psp_v13_0_wait_for_bootloader(struct psp_context *psp) · 70 unmodified lines | ||
| 111 | 117 | return ret; |
| 112 | 118 | } |
| 113 | 119 | |
| 114 | −static int psp_v13_0_bootloader_load_kdb(struct psp_context *psp) | |
| 120 | +static int psp_v13_0_bootloader_load_component(struct psp_context *psp, | |
| 121 | + struct psp_bin_desc *bin_desc, | |
| 122 | + enum psp_bootloader_cmd bl_cmd) | |
| 115 | 123 | { |
| 116 | 124 | int ret; |
| 117 | 125 | uint32_t psp_gfxdrv_command_reg = 0; |
| @@ -130,12 +138,12 @@ static int psp_v13_0_bootloader_load_kdb(struct psp_context *psp) · 12 unmodified lines | ||
| 130 | 138 | memset(psp->fw_pri_buf, 0, PSP_1_MEG); |
| 131 | 139 | |
| 132 | 140 | /* Copy PSP KDB binary to memory */ |
| 133 | − memcpy(psp->fw_pri_buf, psp->kdb_start_addr, psp->kdb_bin_size); | |
| 141 | + memcpy(psp->fw_pri_buf, bin_desc->start_addr, bin_desc->size_bytes); | |
| 134 | 142 | |
| 135 | 143 | /* Provide the PSP KDB to bootloader */ |
| 136 | 144 | WREG32_SOC15(MP0, 0, regMP0_SMN_C2PMSG_36, |
| 137 | 145 | (uint32_t)(psp->fw_pri_mc_addr >> 20)); |
| 138 | − psp_gfxdrv_command_reg = PSP_BL__LOAD_KEY_DATABASE; | |
| 146 | + psp_gfxdrv_command_reg = bl_cmd; | |
| 139 | 147 | WREG32_SOC15(MP0, 0, regMP0_SMN_C2PMSG_35, |
| 140 | 148 | psp_gfxdrv_command_reg); |
| 141 | 149 | |
| @@ -144,40 +152,29 @@ static int psp_v13_0_bootloader_load_kdb(struct psp_context *psp) · 2 unmodified lines | ||
| 144 | 152 | return ret; |
| 145 | 153 | } |
| 146 | 154 | |
| 147 | −static int psp_v13_0_bootloader_load_sysdrv(struct psp_context *psp) | |
| 155 | +static int psp_v13_0_bootloader_load_kdb(struct psp_context *psp) | |
| 148 | 156 | { |
| 149 | − int ret; | |
| 150 | − uint32_t psp_gfxdrv_command_reg = 0; | |
| 151 | − struct amdgpu_device *adev = psp->adev; | |
| 152 | − | |
| 153 | − /* Check sOS sign of life register to confirm sys driver and sOS | |
| 154 | − * are already been loaded. | |
| 155 | − */ | |
| 156 | − if (psp_v13_0_is_sos_alive(psp)) | |
| 157 | − return 0; | |
| 158 | − | |
| 159 | − ret = psp_v13_0_wait_for_bootloader(psp); | |
| 160 | − if (ret) | |
| 161 | − return ret; | |
| 162 | − | |
| 163 | − memset(psp->fw_pri_buf, 0, PSP_1_MEG); | |
| 164 | − | |
| 165 | − /* Copy PSP System Driver binary to memory */ | |
| 166 | − memcpy(psp->fw_pri_buf, psp->sys_start_addr, psp->sys_bin_size); | |
| 157 | + return psp_v13_0_bootloader_load_component(psp, &psp->kdb, PSP_BL__LOAD_KEY_DATABASE); | |
| 158 | +} | |
| 167 | 159 | |
| 168 | − /* Provide the sys driver to bootloader */ | |
| 169 | − WREG32_SOC15(MP0, 0, regMP0_SMN_C2PMSG_36, | |
| 170 | − (uint32_t)(psp->fw_pri_mc_addr >> 20)); | |
| 171 | − psp_gfxdrv_command_reg = PSP_BL__LOAD_SYSDRV; | |
| 172 | − WREG32_SOC15(MP0, 0, regMP0_SMN_C2PMSG_35, | |
| 173 | − psp_gfxdrv_command_reg); | |
| 160 | +static int psp_v13_0_bootloader_load_sysdrv(struct psp_context *psp) | |
| 161 | +{ | |
| 162 | + return psp_v13_0_bootloader_load_component(psp, &psp->sys, PSP_BL__LOAD_SYSDRV); | |
| 163 | +} | |
| 174 | 164 | |
| 175 | − /* there might be handshake issue with hardware which needs delay */ | |
| 176 | − mdelay(20); | |
| 165 | +static int psp_v13_0_bootloader_load_soc_drv(struct psp_context *psp) | |
| 166 | +{ | |
| 167 | + return psp_v13_0_bootloader_load_component(psp, &psp->soc_drv, PSP_BL__LOAD_SOCDRV); | |
| 168 | +} | |
| 177 | 169 | |
| 178 | − ret = psp_v13_0_wait_for_bootloader(psp); | |
| 170 | +static int psp_v13_0_bootloader_load_intf_drv(struct psp_context *psp) | |
| 171 | +{ | |
| 172 | + return psp_v13_0_bootloader_load_component(psp, &psp->intf_drv, PSP_BL__LOAD_INTFDRV); | |
| 173 | +} | |
| 179 | 174 | |
| 180 | − return ret; | |
| 175 | +static int psp_v13_0_bootloader_load_dbg_drv(struct psp_context *psp) | |
| 176 | +{ | |
| 177 | + return psp_v13_0_bootloader_load_component(psp, &psp->dbg_drv, PSP_BL__LOAD_DBGDRV); | |
| 181 | 178 | } |
| 182 | 179 | |
| 183 | 180 | static int psp_v13_0_bootloader_load_sos(struct psp_context *psp) |
| @@ -199,7 +196,7 @@ static int psp_v13_0_bootloader_load_sos(struct psp_context *psp) · 15 unmodified lines | ||
| 199 | 196 | memset(psp->fw_pri_buf, 0, PSP_1_MEG); |
| 200 | 197 | |
| 201 | 198 | /* Copy Secure OS binary to PSP memory */ |
| 202 | − memcpy(psp->fw_pri_buf, psp->sos_start_addr, psp->sos_bin_size); | |
| 199 | + memcpy(psp->fw_pri_buf, psp->sos.start_addr, psp->sos.size_bytes); | |
| 203 | 200 | |
| 204 | 201 | /* Provide the PSP secure OS to bootloader */ |
| 205 | 202 | WREG32_SOC15(MP0, 0, regMP0_SMN_C2PMSG_36, |
| @@ -382,10 +379,71 @@ static void psp_v13_0_ring_set_wptr(struct psp_context *psp, uint32_t value) · 176 unmodified lines | ||
| 382 | 379 | WREG32_SOC15(MP0, 0, regMP0_SMN_C2PMSG_67, value); |
| 383 | 380 | } |
| 384 | 381 | |
| 382 | +static int psp_v13_0_load_usbc_pd_fw(struct psp_context *psp, uint64_t fw_pri_mc_addr) | |
| 383 | +{ | |
| 384 | + struct amdgpu_device *adev = psp->adev; | |
| 385 | + uint32_t reg_status; | |
| 386 | + int ret, i = 0; | |
| 387 | + | |
| 388 | + /* | |
| 389 | + * LFB address which is aligned to 1MB address and has to be | |
| 390 | + * right-shifted by 20 so that LFB address can be passed on a 32-bit C2P | |
| 391 | + * register | |
| 392 | + */ | |
| 393 | + WREG32_SOC15(MP0, 0, regMP0_SMN_C2PMSG_36, (fw_pri_mc_addr >> 20)); | |
| 394 | + | |
| 395 | + ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, regMP0_SMN_C2PMSG_35), | |
| 396 | + 0x80000000, 0x80000000, false); | |
| 397 | + if (ret) | |
| 398 | + return ret; | |
| 399 | + | |
| 400 | + /* Fireup interrupt so PSP can pick up the address */ | |
| 401 | + WREG32_SOC15(MP0, 0, regMP0_SMN_C2PMSG_35, (GFX_CMD_USB_PD_USE_LFB << 16)); | |
| 402 | + | |
| 403 | + /* FW load takes very long time */ | |
| 404 | + do { | |
| 405 | + msleep(1000); | |
| 406 | + reg_status = RREG32_SOC15(MP0, 0, regMP0_SMN_C2PMSG_35); | |
| 407 | + | |
| 408 | + if (reg_status & 0x80000000) | |
| 409 | + goto done; | |
| 410 | + | |
| 411 | + } while (++i < USBC_PD_POLLING_LIMIT_S); | |
| 412 | + | |
| 413 | + return -ETIME; | |
| 414 | +done: | |
| 415 | + | |
| 416 | + if ((reg_status & 0xFFFF) != 0) { | |
| 417 | + DRM_ERROR("Address load failed - MP0_SMN_C2PMSG_35.Bits [15:0] = %04x\n", | |
| 418 | + reg_status & 0xFFFF); | |
| 419 | + return -EIO; | |
| 420 | + } | |
| 421 | + | |
| 422 | + return 0; | |
| 423 | +} | |
| 424 | + | |
| 425 | +static int psp_v13_0_read_usbc_pd_fw(struct psp_context *psp, uint32_t *fw_ver) | |
| 426 | +{ | |
| 427 | + struct amdgpu_device *adev = psp->adev; | |
| 428 | + int ret; | |
| 429 | + | |
| 430 | + WREG32_SOC15(MP0, 0, regMP0_SMN_C2PMSG_35, C2PMSG_CMD_GFX_USB_PD_FW_VER); | |
| 431 | + | |
| 432 | + ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, regMP0_SMN_C2PMSG_35), | |
| 433 | + 0x80000000, 0x80000000, false); | |
| 434 | + if (!ret) | |
| 435 | + *fw_ver = RREG32_SOC15(MP0, 0, regMP0_SMN_C2PMSG_36); | |
| 436 | + | |
| 437 | + return ret; | |
| 438 | +} | |
| 439 | + | |
| 385 | 440 | static const struct psp_funcs psp_v13_0_funcs = { |
| 386 | 441 | .init_microcode = psp_v13_0_init_microcode, |
| 387 | 442 | .bootloader_load_kdb = psp_v13_0_bootloader_load_kdb, |
| 388 | 443 | .bootloader_load_sysdrv = psp_v13_0_bootloader_load_sysdrv, |
| 444 | + .bootloader_load_soc_drv = psp_v13_0_bootloader_load_soc_drv, | |
| 445 | + .bootloader_load_intf_drv = psp_v13_0_bootloader_load_intf_drv, | |
| 446 | + .bootloader_load_dbg_drv = psp_v13_0_bootloader_load_dbg_drv, | |
| 389 | 447 | .bootloader_load_sos = psp_v13_0_bootloader_load_sos, |
| 390 | 448 | .ring_init = psp_v13_0_ring_init, |
| 391 | 449 | .ring_create = psp_v13_0_ring_create, |
| @@ -393,6 +451,8 @@ static const struct psp_funcs psp_v13_0_funcs = { · 1 unmodified line | ||
| 393 | 451 | .ring_destroy = psp_v13_0_ring_destroy, |
| 394 | 452 | .ring_get_wptr = psp_v13_0_ring_get_wptr, |
| 395 | 453 | .ring_set_wptr = psp_v13_0_ring_set_wptr, |
| 454 | + .load_usbc_pd_fw = psp_v13_0_load_usbc_pd_fw, | |
| 455 | + .read_usbc_pd_fw = psp_v13_0_read_usbc_pd_fw | |
| 396 | 456 | }; |
| 397 | 457 | |
| 398 | 458 | void psp_v13_0_set_psp_funcs(struct psp_context *psp) |
| @@ -103,7 +103,7 @@ static int psp_v3_1_bootloader_load_sysdrv(struct psp_context *psp) · 102 unmodified lines | ||
| 103 | 103 | return ret; |
| 104 | 104 | |
| 105 | 105 | /* Copy PSP System Driver binary to memory */ |
| 106 | − psp_copy_fw(psp, psp->sys_start_addr, psp->sys_bin_size); | |
| 106 | + psp_copy_fw(psp, psp->sys.start_addr, psp->sys.size_bytes); | |
| 107 | 107 | |
| 108 | 108 | /* Provide the sys driver to bootloader */ |
| 109 | 109 | WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_36, |
| @@ -142,7 +142,7 @@ static int psp_v3_1_bootloader_load_sos(struct psp_context *psp) · 32 unmodified lines | ||
| 142 | 142 | return ret; |
| 143 | 143 | |
| 144 | 144 | /* Copy Secure OS binary to PSP memory */ |
| 145 | − psp_copy_fw(psp, psp->sos_start_addr, psp->sos_bin_size); | |
| 145 | + psp_copy_fw(psp, psp->sos.start_addr, psp->sos.size_bytes); | |
| 146 | 146 | |
| 147 | 147 | /* Provide the PSP secure OS to bootloader */ |
| 148 | 148 | WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_36, |
| @@ -51,6 +51,12 @@ MODULE_FIRMWARE("amdgpu/navi14_sdma1.bin"); · 50 unmodified lines | ||
| 51 | 51 | MODULE_FIRMWARE("amdgpu/navi12_sdma.bin"); |
| 52 | 52 | MODULE_FIRMWARE("amdgpu/navi12_sdma1.bin"); |
| 53 | 53 | |
| 54 | +MODULE_FIRMWARE("amdgpu/cyan_skillfish_sdma.bin"); | |
| 55 | +MODULE_FIRMWARE("amdgpu/cyan_skillfish_sdma1.bin"); | |
| 56 | + | |
| 57 | +MODULE_FIRMWARE("amdgpu/cyan_skillfish2_sdma.bin"); | |
| 58 | +MODULE_FIRMWARE("amdgpu/cyan_skillfish2_sdma1.bin"); | |
| 59 | + | |
| 54 | 60 | #define SDMA1_REG_OFFSET 0x600 |
| 55 | 61 | #define SDMA0_HYP_DEC_REG_START 0x5880 |
| 56 | 62 | #define SDMA0_HYP_DEC_REG_END 0x5893 |
| @@ -130,6 +136,37 @@ static const struct soc15_reg_golden golden_settings_sdma_nv12[] = { · 73 unmodified lines | ||
| 130 | 136 | SOC15_REG_GOLDEN_VALUE(GC, 0, mmSDMA1_RLC3_RB_WPTR_POLL_CNTL, 0xfffffff7, 0x00403000), |
| 131 | 137 | }; |
| 132 | 138 | |
| 139 | +static const struct soc15_reg_golden golden_settings_sdma_cyan_skillfish[] = { | |
| 140 | + SOC15_REG_GOLDEN_VALUE(GC, 0, mmSDMA0_CHICKEN_BITS, 0xffbf1f0f, 0x03ab0107), | |
| 141 | + SOC15_REG_GOLDEN_VALUE(GC, 0, mmSDMA0_GB_ADDR_CONFIG, 0x001877ff, 0x00000044), | |
| 142 | + SOC15_REG_GOLDEN_VALUE(GC, 0, mmSDMA0_GB_ADDR_CONFIG_READ, 0x001877ff, 0x00000044), | |
| 143 | + SOC15_REG_GOLDEN_VALUE(GC, 0, mmSDMA0_GFX_RB_WPTR_POLL_CNTL, 0xfffffff7, 0x00403000), | |
| 144 | + SOC15_REG_GOLDEN_VALUE(GC, 0, mmSDMA0_PAGE_RB_WPTR_POLL_CNTL, 0xfffffff7, 0x00403000), | |
| 145 | + SOC15_REG_GOLDEN_VALUE(GC, 0, mmSDMA0_RLC0_RB_WPTR_POLL_CNTL, 0xfffffff7, 0x00403000), | |
| 146 | + SOC15_REG_GOLDEN_VALUE(GC, 0, mmSDMA0_RLC1_RB_WPTR_POLL_CNTL, 0xfffffff7, 0x00403000), | |
| 147 | + SOC15_REG_GOLDEN_VALUE(GC, 0, mmSDMA0_RLC2_RB_WPTR_POLL_CNTL, 0xfffffff7, 0x00403000), | |
| 148 | + SOC15_REG_GOLDEN_VALUE(GC, 0, mmSDMA0_RLC3_RB_WPTR_POLL_CNTL, 0xfffffff7, 0x00403000), | |
| 149 | + SOC15_REG_GOLDEN_VALUE(GC, 0, mmSDMA0_RLC4_RB_WPTR_POLL_CNTL, 0xfffffff7, 0x00403000), | |
| 150 | + SOC15_REG_GOLDEN_VALUE(GC, 0, mmSDMA0_RLC5_RB_WPTR_POLL_CNTL, 0xfffffff7, 0x00403000), | |
| 151 | + SOC15_REG_GOLDEN_VALUE(GC, 0, mmSDMA0_RLC6_RB_WPTR_POLL_CNTL, 0xfffffff7, 0x00403000), | |
| 152 | + SOC15_REG_GOLDEN_VALUE(GC, 0, mmSDMA0_RLC7_RB_WPTR_POLL_CNTL, 0xfffffff7, 0x00403000), | |
| 153 | + SOC15_REG_GOLDEN_VALUE(GC, 0, mmSDMA0_UTCL1_PAGE, 0x007fffff, 0x004c5c00), | |
| 154 | + SOC15_REG_GOLDEN_VALUE(GC, 0, mmSDMA1_CHICKEN_BITS, 0xffbf1f0f, 0x03ab0107), | |
| 155 | + SOC15_REG_GOLDEN_VALUE(GC, 0, mmSDMA1_GB_ADDR_CONFIG, 0x001877ff, 0x00000044), | |
| 156 | + SOC15_REG_GOLDEN_VALUE(GC, 0, mmSDMA1_GB_ADDR_CONFIG_READ, 0x001877ff, 0x00000044), | |
| 157 | + SOC15_REG_GOLDEN_VALUE(GC, 0, mmSDMA1_GFX_RB_WPTR_POLL_CNTL, 0xfffffff7, 0x00403000), | |
| 158 | + SOC15_REG_GOLDEN_VALUE(GC, 0, mmSDMA1_PAGE_RB_WPTR_POLL_CNTL, 0xfffffff7, 0x00403000), | |
| 159 | + SOC15_REG_GOLDEN_VALUE(GC, 0, mmSDMA1_RLC0_RB_WPTR_POLL_CNTL, 0xfffffff7, 0x00403000), | |
| 160 | + SOC15_REG_GOLDEN_VALUE(GC, 0, mmSDMA1_RLC1_RB_WPTR_POLL_CNTL, 0xfffffff7, 0x00403000), | |
| 161 | + SOC15_REG_GOLDEN_VALUE(GC, 0, mmSDMA1_RLC2_RB_WPTR_POLL_CNTL, 0xfffffff7, 0x00403000), | |
| 162 | + SOC15_REG_GOLDEN_VALUE(GC, 0, mmSDMA1_RLC3_RB_WPTR_POLL_CNTL, 0xfffffff7, 0x00403000), | |
| 163 | + SOC15_REG_GOLDEN_VALUE(GC, 0, mmSDMA1_RLC4_RB_WPTR_POLL_CNTL, 0xfffffff7, 0x00403000), | |
| 164 | + SOC15_REG_GOLDEN_VALUE(GC, 0, mmSDMA1_RLC5_RB_WPTR_POLL_CNTL, 0xfffffff7, 0x00403000), | |
| 165 | + SOC15_REG_GOLDEN_VALUE(GC, 0, mmSDMA1_RLC6_RB_WPTR_POLL_CNTL, 0xfffffff7, 0x00403000), | |
| 166 | + SOC15_REG_GOLDEN_VALUE(GC, 0, mmSDMA1_RLC7_RB_WPTR_POLL_CNTL, 0xfffffff7, 0x00403000), | |
| 167 | + SOC15_REG_GOLDEN_VALUE(GC, 0, mmSDMA1_UTCL1_PAGE, 0x007fffff, 0x004c5c00) | |
| 168 | +}; | |
| 169 | + | |
| 133 | 170 | static u32 sdma_v5_0_get_reg_offset(struct amdgpu_device *adev, u32 instance, u32 internal_offset) |
| 134 | 171 | { |
| 135 | 172 | u32 base; |
| @@ -180,6 +217,11 @@ static void sdma_v5_0_init_golden_registers(struct amdgpu_device *adev) · 44 unmodified lines | ||
| 180 | 217 | golden_settings_sdma_nv12, |
| 181 | 218 | (const u32)ARRAY_SIZE(golden_settings_sdma_nv12)); |
| 182 | 219 | break; |
| 220 | + case CHIP_CYAN_SKILLFISH: | |
| 221 | + soc15_program_register_sequence(adev, | |
| 222 | + golden_settings_sdma_cyan_skillfish, | |
| 223 | + (const u32)ARRAY_SIZE(golden_settings_sdma_cyan_skillfish)); | |
| 224 | + break; | |
| 183 | 225 | default: |
| 184 | 226 | break; |
| 185 | 227 | } |
| @@ -200,7 +242,7 @@ static void sdma_v5_0_init_golden_registers(struct amdgpu_device *adev) · 14 unmodified lines | ||
| 200 | 242 | static int sdma_v5_0_init_microcode(struct amdgpu_device *adev) |
| 201 | 243 | { |
| 202 | 244 | const char *chip_name; |
| 203 | − char fw_name[30]; | |
| 245 | + char fw_name[40]; | |
| 204 | 246 | int err = 0, i; |
| 205 | 247 | struct amdgpu_firmware_info *info = NULL; |
| 206 | 248 | const struct common_firmware_header *header = NULL; |
| @@ -221,6 +263,12 @@ static int sdma_v5_0_init_microcode(struct amdgpu_device *adev) · 14 unmodified lines | ||
| 221 | 263 | case CHIP_NAVI12: |
| 222 | 264 | chip_name = "navi12"; |
| 223 | 265 | break; |
| 266 | + case CHIP_CYAN_SKILLFISH: | |
| 267 | + if (adev->apu_flags & AMD_APU_IS_CYAN_SKILLFISH2) | |
| 268 | + chip_name = "cyan_skillfish2"; | |
| 269 | + else | |
| 270 | + chip_name = "cyan_skillfish"; | |
| 271 | + break; | |
| 224 | 272 | default: |
| 225 | 273 | BUG(); |
| 226 | 274 | } |
| @@ -87,21 +87,6 @@ static u32 sdma_v5_2_get_reg_offset(struct amdgpu_device *adev, u32 instance, u3 · 86 unmodified lines | ||
| 87 | 87 | return base + internal_offset; |
| 88 | 88 | } |
| 89 | 89 | |
| 90 | −static void sdma_v5_2_init_golden_registers(struct amdgpu_device *adev) | |
| 91 | −{ | |
| 92 | − switch (adev->asic_type) { | |
| 93 | − case CHIP_SIENNA_CICHLID: | |
| 94 | − case CHIP_NAVY_FLOUNDER: | |
| 95 | − case CHIP_VANGOGH: | |
| 96 | − case CHIP_DIMGREY_CAVEFISH: | |
| 97 | − case CHIP_BEIGE_GOBY: | |
| 98 | − case CHIP_YELLOW_CARP: | |
| 99 | − break; | |
| 100 | − default: | |
| 101 | − break; | |
| 102 | − } | |
| 103 | −} | |
| 104 | − | |
| 105 | 90 | static int sdma_v5_2_init_inst_ctx(struct amdgpu_sdma_instance *sdma_inst) |
| 106 | 91 | { |
| 107 | 92 | int err = 0; |
| @@ -1345,8 +1330,6 @@ static int sdma_v5_2_hw_init(void *handle) · 1237 unmodified lines | ||
| 1345 | 1330 | int r; |
| 1346 | 1331 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; |
| 1347 | 1332 | |
| 1348 | − sdma_v5_2_init_golden_registers(adev); | |
| 1349 | − | |
| 1350 | 1333 | r = sdma_v5_2_start(adev); |
| 1351 | 1334 | |
| 1352 | 1335 | return r; |
| @@ -44,7 +44,7 @@ · 43 unmodified lines | ||
| 44 | 44 | #include "dce_v6_0.h" |
| 45 | 45 | #include "si.h" |
| 46 | 46 | #include "uvd_v3_1.h" |
| 47 | −#include "dce_virtual.h" | |
| 47 | +#include "amdgpu_vkms.h" | |
| 48 | 48 | #include "gca/gfx_6_0_d.h" |
| 49 | 49 | #include "oss/oss_1_0_d.h" |
| 50 | 50 | #include "oss/oss_1_0_sh_mask.h" |
| @@ -2759,7 +2759,7 @@ int si_set_ip_blocks(struct amdgpu_device *adev) · 2708 unmodified lines | ||
| 2759 | 2759 | amdgpu_device_ip_block_add(adev, &si_dma_ip_block); |
| 2760 | 2760 | amdgpu_device_ip_block_add(adev, &si_smu_ip_block); |
| 2761 | 2761 | if (adev->enable_virtual_display) |
| 2762 | − amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block); | |
| 2762 | + amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block); | |
| 2763 | 2763 | #if defined(CONFIG_DRM_AMD_DC) && defined(CONFIG_DRM_AMD_DC_SI) |
| 2764 | 2764 | else if (amdgpu_device_has_dc_support(adev)) |
| 2765 | 2765 | amdgpu_device_ip_block_add(adev, &dm_ip_block); |
| @@ -2777,7 +2777,7 @@ int si_set_ip_blocks(struct amdgpu_device *adev) · 11 unmodified lines | ||
| 2777 | 2777 | amdgpu_device_ip_block_add(adev, &si_dma_ip_block); |
| 2778 | 2778 | amdgpu_device_ip_block_add(adev, &si_smu_ip_block); |
| 2779 | 2779 | if (adev->enable_virtual_display) |
| 2780 | − amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block); | |
| 2780 | + amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block); | |
| 2781 | 2781 | #if defined(CONFIG_DRM_AMD_DC) && defined(CONFIG_DRM_AMD_DC_SI) |
| 2782 | 2782 | else if (amdgpu_device_has_dc_support(adev)) |
| 2783 | 2783 | amdgpu_device_ip_block_add(adev, &dm_ip_block); |
| @@ -2795,7 +2795,7 @@ int si_set_ip_blocks(struct amdgpu_device *adev) · 11 unmodified lines | ||
| 2795 | 2795 | amdgpu_device_ip_block_add(adev, &si_dma_ip_block); |
| 2796 | 2796 | amdgpu_device_ip_block_add(adev, &si_smu_ip_block); |
| 2797 | 2797 | if (adev->enable_virtual_display) |
| 2798 | − amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block); | |
| 2798 | + amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block); | |
| 2799 | 2799 | break; |
| 2800 | 2800 | default: |
| 2801 | 2801 | BUG(); |
| @@ -41,9 +41,7 @@ · 40 unmodified lines | ||
| 41 | 41 | #define I2C_SW_TIMEOUT 8 |
| 42 | 42 | #define I2C_ABORT 0x10 |
| 43 | 43 | |
| 44 | −/* I2C transaction flags */ | |
| 45 | −#define I2C_NO_STOP 1 | |
| 46 | −#define I2C_RESTART 2 | |
| 44 | +#define I2C_X_RESTART BIT(31) | |
| 47 | 45 | |
| 48 | 46 | #define to_amdgpu_device(x) (container_of(x, struct amdgpu_device, pm.smu_i2c)) |
| 49 | 47 | |
| @@ -56,12 +54,48 @@ static void smu_v11_0_i2c_set_clock_gating(struct i2c_adapter *control, bool en) · 6 unmodified lines | ||
| 56 | 54 | WREG32_SOC15(SMUIO, 0, mmSMUIO_PWRMGT, reg); |
| 57 | 55 | } |
| 58 | 56 | |
| 57 | +/* The T_I2C_POLL_US is defined as follows: | |
| 58 | + * | |
| 59 | + * "Define a timer interval (t_i2c_poll) equal to 10 times the | |
| 60 | + * signalling period for the highest I2C transfer speed used in the | |
| 61 | + * system and supported by DW_apb_i2c. For instance, if the highest | |
| 62 | + * I2C data transfer mode is 400 kb/s, then t_i2c_poll is 25 us." -- | |
| 63 | + * DesignWare DW_apb_i2c Databook, Version 1.21a, section 3.8.3.1, | |
| 64 | + * page 56, with grammar and syntax corrections. | |
| 65 | + * | |
| 66 | + * Vcc for our device is at 1.8V which puts it at 400 kHz, | |
| 67 | + * see Atmel AT24CM02 datasheet, section 8.3 DC Characteristics table, page 14. | |
| 68 | + * | |
| 69 | + * The procedure to disable the IP block is described in section | |
| 70 | + * 3.8.3 Disabling DW_apb_i2c on page 56. | |
| 71 | + */ | |
| 72 | +#define I2C_SPEED_MODE_FAST 2 | |
| 73 | +#define T_I2C_POLL_US 25 | |
| 74 | +#define I2C_MAX_T_POLL_COUNT 1000 | |
| 59 | 75 | |
| 60 | −static void smu_v11_0_i2c_enable(struct i2c_adapter *control, bool enable) | |
| 76 | +static int smu_v11_0_i2c_enable(struct i2c_adapter *control, bool enable) | |
| 61 | 77 | { |
| 62 | 78 | struct amdgpu_device *adev = to_amdgpu_device(control); |
| 63 | 79 | |
| 64 | 80 | WREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_ENABLE, enable ? 1 : 0); |
| 81 | + | |
| 82 | + if (!enable) { | |
| 83 | + int ii; | |
| 84 | + | |
| 85 | + for (ii = I2C_MAX_T_POLL_COUNT; ii > 0; ii--) { | |
| 86 | + u32 en_stat = RREG32_SOC15(SMUIO, | |
| 87 | + 0, | |
| 88 | + mmCKSVII2C_IC_ENABLE_STATUS); | |
| 89 | + if (REG_GET_FIELD(en_stat, CKSVII2C_IC_ENABLE_STATUS, IC_EN)) | |
| 90 | + udelay(T_I2C_POLL_US); | |
| 91 | + else | |
| 92 | + return I2C_OK; | |
| 93 | + } | |
| 94 | + | |
| 95 | + return I2C_ABORT; | |
| 96 | + } | |
| 97 | + | |
| 98 | + return I2C_OK; | |
| 65 | 99 | } |
| 66 | 100 | |
| 67 | 101 | static void smu_v11_0_i2c_clear_status(struct i2c_adapter *control) |
| @@ -83,8 +117,13 @@ static void smu_v11_0_i2c_configure(struct i2c_adapter *control) · 15 unmodified lines | ||
| 83 | 117 | reg = REG_SET_FIELD(reg, CKSVII2C_IC_CON, IC_RESTART_EN, 1); |
| 84 | 118 | reg = REG_SET_FIELD(reg, CKSVII2C_IC_CON, IC_10BITADDR_MASTER, 0); |
| 85 | 119 | reg = REG_SET_FIELD(reg, CKSVII2C_IC_CON, IC_10BITADDR_SLAVE, 0); |
| 86 | − /* Standard mode */ | |
| 87 | − reg = REG_SET_FIELD(reg, CKSVII2C_IC_CON, IC_MAX_SPEED_MODE, 2); | |
| 120 | + /* The values of IC_MAX_SPEED_MODE are, | |
| 121 | + * 1: standard mode, 0 - 100 Kb/s, | |
| 122 | + * 2: fast mode, <= 400 Kb/s, or fast mode plus, <= 1000 Kb/s, | |
| 123 | + * 3: high speed mode, <= 3.4 Mb/s. | |
| 124 | + */ | |
| 125 | + reg = REG_SET_FIELD(reg, CKSVII2C_IC_CON, IC_MAX_SPEED_MODE, | |
| 126 | + I2C_SPEED_MODE_FAST); | |
| 88 | 127 | reg = REG_SET_FIELD(reg, CKSVII2C_IC_CON, IC_MASTER_MODE, 1); |
| 89 | 128 | |
| 90 | 129 | WREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_CON, reg); |
| @@ -113,13 +152,15 @@ static void smu_v11_0_i2c_set_clock(struct i2c_adapter *control) · 22 unmodified lines | ||
| 113 | 152 | WREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_SDA_HOLD, 20); |
| 114 | 153 | } |
| 115 | 154 | |
| 116 | −static void smu_v11_0_i2c_set_address(struct i2c_adapter *control, uint8_t address) | |
| 155 | +static void smu_v11_0_i2c_set_address(struct i2c_adapter *control, u16 address) | |
| 117 | 156 | { |
| 118 | 157 | struct amdgpu_device *adev = to_amdgpu_device(control); |
| 119 | 158 | |
| 120 | − /* Convert fromr 8-bit to 7-bit address */ | |
| 121 | − address >>= 1; | |
| 122 | − WREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_TAR, (address & 0xFF)); | |
| 159 | + /* The IC_TAR::IC_TAR field is 10-bits wide. | |
| 160 | + * It takes a 7-bit or 10-bit addresses as an address, | |
| 161 | + * i.e. no read/write bit--no wire format, just the address. | |
| 162 | + */ | |
| 163 | + WREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_TAR, address & 0x3FF); | |
| 123 | 164 | } |
| 124 | 165 | |
| 125 | 166 | static uint32_t smu_v11_0_i2c_poll_tx_status(struct i2c_adapter *control) |
| @@ -206,9 +247,6 @@ static uint32_t smu_v11_0_i2c_poll_rx_status(struct i2c_adapter *control) · 80 unmodified lines | ||
| 206 | 247 | return ret; |
| 207 | 248 | } |
| 208 | 249 | |
| 209 | − | |
| 210 | − | |
| 211 | − | |
| 212 | 250 | /** |
| 213 | 251 | * smu_v11_0_i2c_transmit - Send a block of data over the I2C bus to a slave device. |
| 214 | 252 | * |
| @@ -221,17 +259,17 @@ static uint32_t smu_v11_0_i2c_poll_rx_status(struct i2c_adapter *control) · 6 unmodified lines | ||
| 221 | 259 | * Returns 0 on success or error. |
| 222 | 260 | */ |
| 223 | 261 | static uint32_t smu_v11_0_i2c_transmit(struct i2c_adapter *control, |
| 224 | − uint8_t address, uint8_t *data, | |
| 225 | − uint32_t numbytes, uint32_t i2c_flag) | |
| 262 | + u16 address, u8 *data, | |
| 263 | + u32 numbytes, u32 i2c_flag) | |
| 226 | 264 | { |
| 227 | 265 | struct amdgpu_device *adev = to_amdgpu_device(control); |
| 228 | − uint32_t bytes_sent, reg, ret = 0; | |
| 266 | + u32 bytes_sent, reg, ret = I2C_OK; | |
| 229 | 267 | unsigned long timeout_counter; |
| 230 | 268 | |
| 231 | 269 | bytes_sent = 0; |
| 232 | 270 | |
| 233 | 271 | DRM_DEBUG_DRIVER("I2C_Transmit(), address = %x, bytes = %d , data: ", |
| 234 | − (uint16_t)address, numbytes); | |
| 272 | + address, numbytes); | |
| 235 | 273 | |
| 236 | 274 | if (drm_debug_enabled(DRM_UT_DRIVER)) { |
| 237 | 275 | print_hex_dump(KERN_INFO, "data: ", DUMP_PREFIX_NONE, |
| @@ -246,53 +284,49 @@ static uint32_t smu_v11_0_i2c_transmit(struct i2c_adapter *control, · 8 unmodified lines | ||
| 246 | 284 | /* Clear status bits */ |
| 247 | 285 | smu_v11_0_i2c_clear_status(control); |
| 248 | 286 | |
| 249 | − | |
| 250 | 287 | timeout_counter = jiffies + msecs_to_jiffies(20); |
| 251 | 288 | |
| 252 | 289 | while (numbytes > 0) { |
| 253 | 290 | reg = RREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_STATUS); |
| 254 | − if (REG_GET_FIELD(reg, CKSVII2C_IC_STATUS, TFNF)) { | |
| 255 | − do { | |
| 256 | − reg = 0; | |
| 257 | − /* | |
| 258 | − * Prepare transaction, no need to set RESTART. I2C engine will send | |
| 259 | − * START as soon as it sees data in TXFIFO | |
| 260 | − */ | |
| 261 | − if (bytes_sent == 0) | |
| 262 | − reg = REG_SET_FIELD(reg, CKSVII2C_IC_DATA_CMD, RESTART, | |
| 263 | − (i2c_flag & I2C_RESTART) ? 1 : 0); | |
| 264 | − reg = REG_SET_FIELD(reg, CKSVII2C_IC_DATA_CMD, DAT, data[bytes_sent]); | |
| 265 | − | |
| 266 | − /* determine if we need to send STOP bit or not */ | |
| 267 | − if (numbytes == 1) | |
| 268 | − /* Final transaction, so send stop unless I2C_NO_STOP */ | |
| 269 | − reg = REG_SET_FIELD(reg, CKSVII2C_IC_DATA_CMD, STOP, | |
| 270 | − (i2c_flag & I2C_NO_STOP) ? 0 : 1); | |
| 271 | − /* Write */ | |
| 272 | − reg = REG_SET_FIELD(reg, CKSVII2C_IC_DATA_CMD, CMD, 0); | |
| 273 | − WREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_DATA_CMD, reg); | |
| 274 | − | |
| 275 | − /* Record that the bytes were transmitted */ | |
| 276 | − bytes_sent++; | |
| 277 | − numbytes--; | |
| 278 | − | |
| 279 | − reg = RREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_STATUS); | |
| 280 | − | |
| 281 | − } while (numbytes && REG_GET_FIELD(reg, CKSVII2C_IC_STATUS, TFNF)); | |
| 282 | − } | |
| 283 | − | |
| 284 | − /* | |
| 285 | − * We waited too long for the transmission FIFO to become not-full. | |
| 286 | − * Exit the loop with error. | |
| 287 | − */ | |
| 288 | − if (time_after(jiffies, timeout_counter)) { | |
| 289 | − ret |= I2C_SW_TIMEOUT; | |
| 290 | − goto Err; | |
| 291 | + if (!REG_GET_FIELD(reg, CKSVII2C_IC_STATUS, TFNF)) { | |
| 292 | + /* | |
| 293 | + * We waited for too long for the transmission | |
| 294 | + * FIFO to become not-full. Exit the loop | |
| 295 | + * with error. | |
| 296 | + */ | |
| 297 | + if (time_after(jiffies, timeout_counter)) { | |
| 298 | + ret |= I2C_SW_TIMEOUT; | |
| 299 | + goto Err; | |
| 300 | + } | |
| 301 | + } else { | |
| 302 | + reg = REG_SET_FIELD(reg, CKSVII2C_IC_DATA_CMD, DAT, | |
| 303 | + data[bytes_sent]); | |
| 304 | + | |
| 305 | + /* Final message, final byte, must generate a | |
| 306 | + * STOP to release the bus, i.e. don't hold | |
| 307 | + * SCL low. | |
| 308 | + */ | |
| 309 | + if (numbytes == 1 && i2c_flag & I2C_M_STOP) | |
| 310 | + reg = REG_SET_FIELD(reg, | |
| 311 | + CKSVII2C_IC_DATA_CMD, | |
| 312 | + STOP, 1); | |
| 313 | + | |
| 314 | + if (bytes_sent == 0 && i2c_flag & I2C_X_RESTART) | |
| 315 | + reg = REG_SET_FIELD(reg, | |
| 316 | + CKSVII2C_IC_DATA_CMD, | |
| 317 | + RESTART, 1); | |
| 318 | + | |
| 319 | + /* Write */ | |
| 320 | + reg = REG_SET_FIELD(reg, CKSVII2C_IC_DATA_CMD, CMD, 0); | |
| 321 | + WREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_DATA_CMD, reg); | |
| 322 | + | |
| 323 | + /* Record that the bytes were transmitted */ | |
| 324 | + bytes_sent++; | |
| 325 | + numbytes--; | |
| 291 | 326 | } |
| 292 | 327 | } |
| 293 | 328 | |
| 294 | 329 | ret = smu_v11_0_i2c_poll_tx_status(control); |
| 295 | − | |
| 296 | 330 | Err: |
| 297 | 331 | /* Any error, no point in proceeding */ |
| 298 | 332 | if (ret != I2C_OK) { |
| @@ -323,8 +357,8 @@ Err: · 24 unmodified lines | ||
| 323 | 357 | * Returns 0 on success or error. |
| 324 | 358 | */ |
| 325 | 359 | static uint32_t smu_v11_0_i2c_receive(struct i2c_adapter *control, |
| 326 | − uint8_t address, uint8_t *data, | |
| 327 | − uint32_t numbytes, uint8_t i2c_flag) | |
| 360 | + u16 address, u8 *data, | |
| 361 | + u32 numbytes, u32 i2c_flag) | |
| 328 | 362 | { |
| 329 | 363 | struct amdgpu_device *adev = to_amdgpu_device(control); |
| 330 | 364 | uint32_t bytes_received, ret = I2C_OK; |
| @@ -342,23 +376,21 @@ static uint32_t smu_v11_0_i2c_receive(struct i2c_adapter *control, · 11 unmodified lines | ||
| 342 | 376 | |
| 343 | 377 | smu_v11_0_i2c_clear_status(control); |
| 344 | 378 | |
| 345 | − | |
| 346 | 379 | /* Prepare transaction */ |
| 347 | − | |
| 348 | − /* Each time we disable I2C, so this is not a restart */ | |
| 349 | − if (bytes_received == 0) | |
| 350 | − reg = REG_SET_FIELD(reg, CKSVII2C_IC_DATA_CMD, RESTART, | |
| 351 | − (i2c_flag & I2C_RESTART) ? 1 : 0); | |
| 352 | − | |
| 353 | 380 | reg = REG_SET_FIELD(reg, CKSVII2C_IC_DATA_CMD, DAT, 0); |
| 354 | 381 | /* Read */ |
| 355 | 382 | reg = REG_SET_FIELD(reg, CKSVII2C_IC_DATA_CMD, CMD, 1); |
| 356 | 383 | |
| 357 | − /* Transmitting last byte */ | |
| 358 | − if (numbytes == 1) | |
| 359 | − /* Final transaction, so send stop if requested */ | |
| 360 | − reg = REG_SET_FIELD(reg, CKSVII2C_IC_DATA_CMD, STOP, | |
| 361 | − (i2c_flag & I2C_NO_STOP) ? 0 : 1); | |
| 384 | + /* Final message, final byte, must generate a STOP | |
| 385 | + * to release the bus, i.e. don't hold SCL low. | |
| 386 | + */ | |
| 387 | + if (numbytes == 1 && i2c_flag & I2C_M_STOP) | |
| 388 | + reg = REG_SET_FIELD(reg, CKSVII2C_IC_DATA_CMD, | |
| 389 | + STOP, 1); | |
| 390 | + | |
| 391 | + if (bytes_received == 0 && i2c_flag & I2C_X_RESTART) | |
| 392 | + reg = REG_SET_FIELD(reg, CKSVII2C_IC_DATA_CMD, | |
| 393 | + RESTART, 1); | |
| 362 | 394 | |
| 363 | 395 | WREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_DATA_CMD, reg); |
| 364 | 396 | |
| @@ -413,7 +445,6 @@ static void smu_v11_0_i2c_abort(struct i2c_adapter *control) · 48 unmodified lines | ||
| 413 | 445 | DRM_DEBUG_DRIVER("I2C_Abort() Done."); |
| 414 | 446 | } |
| 415 | 447 | |
| 416 | − | |
| 417 | 448 | static bool smu_v11_0_i2c_activity_done(struct i2c_adapter *control) |
| 418 | 449 | { |
| 419 | 450 | struct amdgpu_device *adev = to_amdgpu_device(control); |
| @@ -425,7 +456,6 @@ static bool smu_v11_0_i2c_activity_done(struct i2c_adapter *control) · 5 unmodified lines | ||
| 425 | 456 | reg_ic_enable_status = RREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_ENABLE_STATUS); |
| 426 | 457 | reg_ic_enable = RREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_ENABLE); |
| 427 | 458 | |
| 428 | − | |
| 429 | 459 | if ((REG_GET_FIELD(reg_ic_enable, CKSVII2C_IC_ENABLE, ENABLE) == 0) && |
| 430 | 460 | (REG_GET_FIELD(reg_ic_enable_status, CKSVII2C_IC_ENABLE_STATUS, IC_EN) == 1)) { |
| 431 | 461 | /* |
| @@ -455,6 +485,8 @@ static bool smu_v11_0_i2c_activity_done(struct i2c_adapter *control) · 23 unmodified lines | ||
| 455 | 485 | |
| 456 | 486 | static void smu_v11_0_i2c_init(struct i2c_adapter *control) |
| 457 | 487 | { |
| 488 | + int res; | |
| 489 | + | |
| 458 | 490 | /* Disable clock gating */ |
| 459 | 491 | smu_v11_0_i2c_set_clock_gating(control, false); |
| 460 | 492 | |
| @@ -462,7 +494,9 @@ static void smu_v11_0_i2c_init(struct i2c_adapter *control) · 1 unmodified line | ||
| 462 | 494 | DRM_WARN("I2C busy !"); |
| 463 | 495 | |
| 464 | 496 | /* Disable I2C */ |
| 465 | − smu_v11_0_i2c_enable(control, false); | |
| 497 | + res = smu_v11_0_i2c_enable(control, false); | |
| 498 | + if (res != I2C_OK) | |
| 499 | + smu_v11_0_i2c_abort(control); | |
| 466 | 500 | |
| 467 | 501 | /* Configure I2C to operate as master and in standard mode */ |
| 468 | 502 | smu_v11_0_i2c_configure(control); |
| @@ -475,21 +509,22 @@ static void smu_v11_0_i2c_init(struct i2c_adapter *control) · 6 unmodified lines | ||
| 475 | 509 | static void smu_v11_0_i2c_fini(struct i2c_adapter *control) |
| 476 | 510 | { |
| 477 | 511 | struct amdgpu_device *adev = to_amdgpu_device(control); |
| 478 | − uint32_t reg_ic_enable_status, reg_ic_enable; | |
| 512 | + u32 status, enable, en_stat; | |
| 513 | + int res; | |
| 479 | 514 | |
| 480 | − smu_v11_0_i2c_enable(control, false); | |
| 515 | + res = smu_v11_0_i2c_enable(control, false); | |
| 516 | + if (res != I2C_OK) { | |
| 517 | + status = RREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_STATUS); | |
| 518 | + enable = RREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_ENABLE); | |
| 519 | + en_stat = RREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_ENABLE_STATUS); | |
| 481 | 520 | |
| 482 | − /* Double check if disabled, else force abort */ | |
| 483 | − reg_ic_enable_status = RREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_ENABLE_STATUS); | |
| 484 | − reg_ic_enable = RREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_ENABLE); | |
| 485 | − | |
| 486 | − if ((REG_GET_FIELD(reg_ic_enable, CKSVII2C_IC_ENABLE, ENABLE) == 0) && | |
| 487 | − (REG_GET_FIELD(reg_ic_enable_status, | |
| 488 | − CKSVII2C_IC_ENABLE_STATUS, IC_EN) == 1)) { | |
| 489 | − /* | |
| 490 | − * Nobody is using I2C engine, but engine remains active because | |
| 491 | − * someone missed to send STOP | |
| 521 | + /* Nobody is using the I2C engine, yet it remains | |
| 522 | + * active, possibly because someone missed to send | |
| 523 | + * STOP. | |
| 492 | 524 | */ |
| 525 | + DRM_DEBUG_DRIVER("Aborting from fini: status:0x%08x " | |
| 526 | + "enable:0x%08x enable_stat:0x%08x", | |
| 527 | + status, enable, en_stat); | |
| 493 | 528 | smu_v11_0_i2c_abort(control); |
| 494 | 529 | } |
| 495 | 530 | |
| @@ -531,22 +566,12 @@ static bool smu_v11_0_i2c_bus_unlock(struct i2c_adapter *control) · 35 unmodified lines | ||
| 531 | 566 | /***************************** I2C GLUE ****************************/ |
| 532 | 567 | |
| 533 | 568 | static uint32_t smu_v11_0_i2c_read_data(struct i2c_adapter *control, |
| 534 | − uint8_t address, | |
| 535 | − uint8_t *data, | |
| 536 | − uint32_t numbytes) | |
| 569 | + struct i2c_msg *msg, uint32_t i2c_flag) | |
| 537 | 570 | { |
| 538 | − uint32_t ret = 0; | |
| 539 | − | |
| 540 | − /* First 2 bytes are dummy write to set EEPROM address */ | |
| 541 | − ret = smu_v11_0_i2c_transmit(control, address, data, 2, I2C_NO_STOP); | |
| 542 | − if (ret != I2C_OK) | |
| 543 | − goto Fail; | |
| 571 | + uint32_t ret; | |
| 544 | 572 | |
| 545 | − /* Now read data starting with that address */ | |
| 546 | − ret = smu_v11_0_i2c_receive(control, address, data + 2, numbytes - 2, | |
| 547 | − I2C_RESTART); | |
| 573 | + ret = smu_v11_0_i2c_receive(control, msg->addr, msg->buf, msg->len, i2c_flag); | |
| 548 | 574 | |
| 549 | −Fail: | |
| 550 | 575 | if (ret != I2C_OK) |
| 551 | 576 | DRM_ERROR("ReadData() - I2C error occurred :%x", ret); |
| 552 | 577 | |
| @@ -554,28 +579,15 @@ Fail: · 1 unmodified line | ||
| 554 | 579 | } |
| 555 | 580 | |
| 556 | 581 | static uint32_t smu_v11_0_i2c_write_data(struct i2c_adapter *control, |
| 557 | − uint8_t address, | |
| 558 | − uint8_t *data, | |
| 559 | − uint32_t numbytes) | |
| 582 | + struct i2c_msg *msg, uint32_t i2c_flag) | |
| 560 | 583 | { |
| 561 | 584 | uint32_t ret; |
| 562 | 585 | |
| 563 | − ret = smu_v11_0_i2c_transmit(control, address, data, numbytes, 0); | |
| 586 | + ret = smu_v11_0_i2c_transmit(control, msg->addr, msg->buf, msg->len, i2c_flag); | |
| 564 | 587 | |
| 565 | 588 | if (ret != I2C_OK) |
| 566 | 589 | DRM_ERROR("WriteI2CData() - I2C error occurred :%x", ret); |
| 567 | − else | |
| 568 | − /* | |
| 569 | − * According to EEPROM spec there is a MAX of 10 ms required for | |
| 570 | − * EEPROM to flush internal RX buffer after STOP was issued at the | |
| 571 | − * end of write transaction. During this time the EEPROM will not be | |
| 572 | − * responsive to any more commands - so wait a bit more. | |
| 573 | − * | |
| 574 | − * TODO Improve to wait for first ACK for slave address after | |
| 575 | − * internal write cycle done. | |
| 576 | − */ | |
| 577 | − msleep(10); | |
| 578 | − | |
| 590 | + | |
| 579 | 591 | return ret; |
| 580 | 592 | |
| 581 | 593 | } |
| @@ -584,12 +596,11 @@ static void lock_bus(struct i2c_adapter *i2c, unsigned int flags) · 2 unmodified lines | ||
| 584 | 596 | { |
| 585 | 597 | struct amdgpu_device *adev = to_amdgpu_device(i2c); |
| 586 | 598 | |
| 587 | − if (!smu_v11_0_i2c_bus_lock(i2c)) { | |
| 599 | + mutex_lock(&adev->pm.smu_i2c_mutex); | |
| 600 | + if (!smu_v11_0_i2c_bus_lock(i2c)) | |
| 588 | 601 | DRM_ERROR("Failed to lock the bus from SMU"); |
| 589 | − return; | |
| 590 | − } | |
| 591 | − | |
| 592 | − adev->pm.bus_locked = true; | |
| 602 | + else | |
| 603 | + adev->pm.bus_locked = true; | |
| 593 | 604 | } |
| 594 | 605 | |
| 595 | 606 | static int trylock_bus(struct i2c_adapter *i2c, unsigned int flags) |
| @@ -602,12 +613,11 @@ static void unlock_bus(struct i2c_adapter *i2c, unsigned int flags) · 6 unmodified lines | ||
| 602 | 613 | { |
| 603 | 614 | struct amdgpu_device *adev = to_amdgpu_device(i2c); |
| 604 | 615 | |
| 605 | − if (!smu_v11_0_i2c_bus_unlock(i2c)) { | |
| 616 | + if (!smu_v11_0_i2c_bus_unlock(i2c)) | |
| 606 | 617 | DRM_ERROR("Failed to unlock the bus from SMU"); |
| 607 | − return; | |
| 608 | − } | |
| 609 | − | |
| 610 | − adev->pm.bus_locked = false; | |
| 618 | + else | |
| 619 | + adev->pm.bus_locked = false; | |
| 620 | + mutex_unlock(&adev->pm.smu_i2c_mutex); | |
| 611 | 621 | } |
| 612 | 622 | |
| 613 | 623 | static const struct i2c_lock_operations smu_v11_0_i2c_i2c_lock_ops = { |
| @@ -617,27 +627,60 @@ static const struct i2c_lock_operations smu_v11_0_i2c_i2c_lock_ops = { · 3 unmodified lines | ||
| 617 | 627 | }; |
| 618 | 628 | |
| 619 | 629 | static int smu_v11_0_i2c_xfer(struct i2c_adapter *i2c_adap, |
| 620 | − struct i2c_msg *msgs, int num) | |
| 630 | + struct i2c_msg *msg, int num) | |
| 621 | 631 | { |
| 622 | 632 | int i, ret; |
| 623 | − struct amdgpu_device *adev = to_amdgpu_device(i2c_adap); | |
| 624 | − | |
| 625 | − if (!adev->pm.bus_locked) { | |
| 626 | − DRM_ERROR("I2C bus unlocked, stopping transaction!"); | |
| 627 | − return -EIO; | |
| 628 | − } | |
| 633 | + u16 addr, dir; | |
| 629 | 634 | |
| 630 | 635 | smu_v11_0_i2c_init(i2c_adap); |
| 631 | 636 | |
| 637 | + /* From the client's point of view, this sequence of | |
| 638 | + * messages-- the array i2c_msg *msg, is a single transaction | |
| 639 | + * on the bus, starting with START and ending with STOP. | |
| 640 | + * | |
| 641 | + * The client is welcome to send any sequence of messages in | |
| 642 | + * this array, as processing under this function here is | |
| 643 | + * striving to be agnostic. | |
| 644 | + * | |
| 645 | + * Record the first address and direction we see. If either | |
| 646 | + * changes for a subsequent message, generate ReSTART. The | |
| 647 | + * DW_apb_i2c databook, v1.21a, specifies that ReSTART is | |
| 648 | + * generated when the direction changes, with the default IP | |
| 649 | + * block parameter settings, but it doesn't specify if ReSTART | |
| 650 | + * is generated when the address changes (possibly...). We | |
| 651 | + * don't rely on the default IP block parameter settings as | |
| 652 | + * the block is shared and they may change. | |
| 653 | + */ | |
| 654 | + if (num > 0) { | |
| 655 | + addr = msg[0].addr; | |
| 656 | + dir = msg[0].flags & I2C_M_RD; | |
| 657 | + } | |
| 658 | + | |
| 632 | 659 | for (i = 0; i < num; i++) { |
| 633 | − if (msgs[i].flags & I2C_M_RD) | |
| 660 | + u32 i2c_flag = 0; | |
| 661 | + | |
| 662 | + if (msg[i].addr != addr || (msg[i].flags ^ dir) & I2C_M_RD) { | |
| 663 | + addr = msg[i].addr; | |
| 664 | + dir = msg[i].flags & I2C_M_RD; | |
| 665 | + i2c_flag |= I2C_X_RESTART; | |
| 666 | + } | |
| 667 | + | |
| 668 | + if (i == num - 1) { | |
| 669 | + /* Set the STOP bit on the last message, so | |
| 670 | + * that the IP block generates a STOP after | |
| 671 | + * the last byte of the message. | |
| 672 | + */ | |
| 673 | + i2c_flag |= I2C_M_STOP; | |
| 674 | + } | |
| 675 | + | |
| 676 | + if (msg[i].flags & I2C_M_RD) | |
| 634 | 677 | ret = smu_v11_0_i2c_read_data(i2c_adap, |
| 635 | − (uint8_t)msgs[i].addr, | |
| 636 | − msgs[i].buf, msgs[i].len); | |
| 678 | + msg + i, | |
| 679 | + i2c_flag); | |
| 637 | 680 | else |
| 638 | 681 | ret = smu_v11_0_i2c_write_data(i2c_adap, |
| 639 | − (uint8_t)msgs[i].addr, | |
| 640 | − msgs[i].buf, msgs[i].len); | |
| 682 | + msg + i, | |
| 683 | + i2c_flag); | |
| 641 | 684 | |
| 642 | 685 | if (ret != I2C_OK) { |
| 643 | 686 | num = -EIO; |
| @@ -654,23 +697,28 @@ static u32 smu_v11_0_i2c_func(struct i2c_adapter *adap) · 10 unmodified lines | ||
| 654 | 697 | return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; |
| 655 | 698 | } |
| 656 | 699 | |
| 657 | − | |
| 658 | 700 | static const struct i2c_algorithm smu_v11_0_i2c_algo = { |
| 659 | 701 | .master_xfer = smu_v11_0_i2c_xfer, |
| 660 | 702 | .functionality = smu_v11_0_i2c_func, |
| 661 | 703 | }; |
| 662 | 704 | |
| 705 | +static const struct i2c_adapter_quirks smu_v11_0_i2c_control_quirks = { | |
| 706 | + .flags = I2C_AQ_NO_ZERO_LEN, | |
| 707 | +}; | |
| 708 | + | |
| 663 | 709 | int smu_v11_0_i2c_control_init(struct i2c_adapter *control) |
| 664 | 710 | { |
| 665 | 711 | struct amdgpu_device *adev = to_amdgpu_device(control); |
| 666 | 712 | int res; |
| 667 | 713 | |
| 714 | + mutex_init(&adev->pm.smu_i2c_mutex); | |
| 668 | 715 | control->owner = THIS_MODULE; |
| 669 | − control->class = I2C_CLASS_SPD; | |
| 716 | + control->class = I2C_CLASS_HWMON; | |
| 670 | 717 | control->dev.parent = &adev->pdev->dev; |
| 671 | 718 | control->algo = &smu_v11_0_i2c_algo; |
| 672 | 719 | snprintf(control->name, sizeof(control->name), "AMDGPU SMU"); |
| 673 | 720 | control->lock_ops = &smu_v11_0_i2c_i2c_lock_ops; |
| 721 | + control->quirks = &smu_v11_0_i2c_control_quirks; | |
| 674 | 722 | |
| 675 | 723 | res = i2c_add_adapter(control); |
| 676 | 724 | if (res) |
| @@ -74,7 +74,7 @@ · 73 unmodified lines | ||
| 74 | 74 | #include "smuio_v9_0.h" |
| 75 | 75 | #include "smuio_v11_0.h" |
| 76 | 76 | #include "smuio_v13_0.h" |
| 77 | −#include "dce_virtual.h" | |
| 77 | +#include "amdgpu_vkms.h" | |
| 78 | 78 | #include "mxgpu_ai.h" |
| 79 | 79 | #include "amdgpu_ras.h" |
| 80 | 80 | #include "amdgpu_xgmi.h" |
| @@ -575,7 +575,7 @@ soc15_asic_reset_method(struct amdgpu_device *adev) · 494 unmodified lines | ||
| 575 | 575 | baco_reset = amdgpu_dpm_is_baco_supported(adev); |
| 576 | 576 | break; |
| 577 | 577 | case CHIP_VEGA20: |
| 578 | − if (adev->psp.sos_fw_version >= 0x80067) | |
| 578 | + if (adev->psp.sos.fw_version >= 0x80067) | |
| 579 | 579 | baco_reset = amdgpu_dpm_is_baco_supported(adev); |
| 580 | 580 | |
| 581 | 581 | /* |
| @@ -635,7 +635,7 @@ static bool soc15_supports_baco(struct amdgpu_device *adev) · 53 unmodified lines | ||
| 635 | 635 | case CHIP_ARCTURUS: |
| 636 | 636 | return amdgpu_dpm_is_baco_supported(adev); |
| 637 | 637 | case CHIP_VEGA20: |
| 638 | − if (adev->psp.sos_fw_version >= 0x80067) | |
| 638 | + if (adev->psp.sos.fw_version >= 0x80067) | |
| 639 | 639 | return amdgpu_dpm_is_baco_supported(adev); |
| 640 | 640 | return false; |
| 641 | 641 | default: |
| @@ -843,7 +843,7 @@ int soc15_set_ip_blocks(struct amdgpu_device *adev) · 201 unmodified lines | ||
| 843 | 843 | amdgpu_device_ip_block_add(adev, &pp_smu_ip_block); |
| 844 | 844 | } |
| 845 | 845 | if (adev->enable_virtual_display || amdgpu_sriov_vf(adev)) |
| 846 | − amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block); | |
| 846 | + amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block); | |
| 847 | 847 | #if defined(CONFIG_DRM_AMD_DC) |
| 848 | 848 | else if (amdgpu_device_has_dc_support(adev)) |
| 849 | 849 | amdgpu_device_ip_block_add(adev, &dm_ip_block); |
| @@ -863,7 +863,7 @@ int soc15_set_ip_blocks(struct amdgpu_device *adev) · 13 unmodified lines | ||
| 863 | 863 | amdgpu_device_ip_block_add(adev, &sdma_v4_0_ip_block); |
| 864 | 864 | amdgpu_device_ip_block_add(adev, &pp_smu_ip_block); |
| 865 | 865 | if (adev->enable_virtual_display || amdgpu_sriov_vf(adev)) |
| 866 | − amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block); | |
| 866 | + amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block); | |
| 867 | 867 | #if defined(CONFIG_DRM_AMD_DC) |
| 868 | 868 | else if (amdgpu_device_has_dc_support(adev)) |
| 869 | 869 | amdgpu_device_ip_block_add(adev, &dm_ip_block); |
| @@ -885,7 +885,7 @@ int soc15_set_ip_blocks(struct amdgpu_device *adev) · 15 unmodified lines | ||
| 885 | 885 | } |
| 886 | 886 | |
| 887 | 887 | if (adev->enable_virtual_display || amdgpu_sriov_vf(adev)) |
| 888 | − amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block); | |
| 888 | + amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block); | |
| 889 | 889 | amdgpu_device_ip_block_add(adev, &gfx_v9_0_ip_block); |
| 890 | 890 | amdgpu_device_ip_block_add(adev, &sdma_v4_0_ip_block); |
| 891 | 891 | amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block); |
| @@ -909,7 +909,7 @@ int soc15_set_ip_blocks(struct amdgpu_device *adev) · 17 unmodified lines | ||
| 909 | 909 | amdgpu_device_ip_block_add(adev, &gfx_v9_0_ip_block); |
| 910 | 910 | amdgpu_device_ip_block_add(adev, &sdma_v4_0_ip_block); |
| 911 | 911 | if (adev->enable_virtual_display || amdgpu_sriov_vf(adev)) |
| 912 | − amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block); | |
| 912 | + amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block); | |
| 913 | 913 | #if defined(CONFIG_DRM_AMD_DC) |
| 914 | 914 | else if (amdgpu_device_has_dc_support(adev)) |
| 915 | 915 | amdgpu_device_ip_block_add(adev, &dm_ip_block); |
| @@ -1353,8 +1353,6 @@ static int soc15_common_early_init(void *handle) · 437 unmodified lines | ||
| 1353 | 1353 | adev->asic_funcs = &vega20_asic_funcs; |
| 1354 | 1354 | adev->cg_flags = AMD_CG_SUPPORT_GFX_MGCG | |
| 1355 | 1355 | AMD_CG_SUPPORT_GFX_MGLS | |
| 1356 | − AMD_CG_SUPPORT_GFX_CGCG | | |
| 1357 | − AMD_CG_SUPPORT_GFX_CGLS | | |
| 1358 | 1356 | AMD_CG_SUPPORT_GFX_CP_LS | |
| 1359 | 1357 | AMD_CG_SUPPORT_HDP_LS | |
| 1360 | 1358 | AMD_CG_SUPPORT_SDMA_MGCG | |
| @@ -28,13 +28,13 @@ · 27 unmodified lines | ||
| 28 | 28 | #define SOC15_REG_OFFSET(ip, inst, reg) (adev->reg_offset[ip##_HWIP][inst][reg##_BASE_IDX] + reg) |
| 29 | 29 | |
| 30 | 30 | #define __WREG32_SOC15_RLC__(reg, value, flag, hwip) \ |
| 31 | − ((amdgpu_sriov_vf(adev) && adev->gfx.rlc.funcs && adev->gfx.rlc.funcs->rlcg_wreg) ? \ | |
| 32 | − adev->gfx.rlc.funcs->rlcg_wreg(adev, reg, value, flag, hwip) : \ | |
| 31 | + ((amdgpu_sriov_vf(adev) && adev->gfx.rlc.funcs && adev->gfx.rlc.funcs->sriov_wreg) ? \ | |
| 32 | + adev->gfx.rlc.funcs->sriov_wreg(adev, reg, value, flag, hwip) : \ | |
| 33 | 33 | WREG32(reg, value)) |
| 34 | 34 | |
| 35 | 35 | #define __RREG32_SOC15_RLC__(reg, flag, hwip) \ |
| 36 | − ((amdgpu_sriov_vf(adev) && adev->gfx.rlc.funcs && adev->gfx.rlc.funcs->rlcg_rreg) ? \ | |
| 37 | − adev->gfx.rlc.funcs->rlcg_rreg(adev, reg, flag, hwip) : \ | |
| 36 | + ((amdgpu_sriov_vf(adev) && adev->gfx.rlc.funcs && adev->gfx.rlc.funcs->sriov_rreg) ? \ | |
| 37 | + adev->gfx.rlc.funcs->sriov_rreg(adev, reg, flag, hwip) : \ | |
| 38 | 38 | RREG32(reg)) |
| 39 | 39 | |
| 40 | 40 | #define WREG32_FIELD15(ip, idx, reg, field, val) \ |
| @@ -33,7 +33,8 @@ enum ta_command_xgmi { · 32 unmodified lines | ||
| 33 | 33 | TA_COMMAND_XGMI__GET_NODE_ID = 0x01, |
| 34 | 34 | TA_COMMAND_XGMI__GET_HIVE_ID = 0x02, |
| 35 | 35 | TA_COMMAND_XGMI__GET_GET_TOPOLOGY_INFO = 0x03, |
| 36 | − TA_COMMAND_XGMI__SET_TOPOLOGY_INFO = 0x04 | |
| 36 | + TA_COMMAND_XGMI__SET_TOPOLOGY_INFO = 0x04, | |
| 37 | + TA_COMMAND_XGMI__GET_PEER_LINKS = 0x0B | |
| 37 | 38 | }; |
| 38 | 39 | |
| 39 | 40 | /* XGMI related enumerations */ |
| @@ -75,6 +76,11 @@ struct ta_xgmi_node_info { · 35 unmodified lines | ||
| 75 | 76 | enum ta_xgmi_assigned_sdma_engine sdma_engine; |
| 76 | 77 | }; |
| 77 | 78 | |
| 79 | +struct ta_xgmi_peer_link_info { | |
| 80 | + uint64_t node_id; | |
| 81 | + uint8_t num_links; | |
| 82 | +}; | |
| 83 | + | |
| 78 | 84 | struct ta_xgmi_cmd_initialize_output { |
| 79 | 85 | uint32_t status; |
| 80 | 86 | }; |
| @@ -97,6 +103,11 @@ struct ta_xgmi_cmd_get_topology_info_output { · 16 unmodified lines | ||
| 97 | 103 | struct ta_xgmi_node_info nodes[TA_XGMI__MAX_CONNECTED_NODES]; |
| 98 | 104 | }; |
| 99 | 105 | |
| 106 | +struct ta_xgmi_cmd_get_peer_link_info_output { | |
| 107 | + uint32_t num_nodes; | |
| 108 | + struct ta_xgmi_peer_link_info nodes[TA_XGMI__MAX_CONNECTED_NODES]; | |
| 109 | +}; | |
| 110 | + | |
| 100 | 111 | struct ta_xgmi_cmd_set_topology_info_input { |
| 101 | 112 | uint32_t num_nodes; |
| 102 | 113 | struct ta_xgmi_node_info nodes[TA_XGMI__MAX_CONNECTED_NODES]; |
| @@ -115,6 +126,7 @@ union ta_xgmi_cmd_output { · 12 unmodified lines | ||
| 115 | 126 | struct ta_xgmi_cmd_get_node_id_output get_node_id; |
| 116 | 127 | struct ta_xgmi_cmd_get_hive_id_output get_hive_id; |
| 117 | 128 | struct ta_xgmi_cmd_get_topology_info_output get_topology_info; |
| 129 | + struct ta_xgmi_cmd_get_peer_link_info_output get_link_info; | |
| 118 | 130 | }; |
| 119 | 131 | /**********************************************************/ |
| 120 | 132 | |
| @@ -122,7 +134,8 @@ struct ta_xgmi_shared_memory { · 1 unmodified line | ||
| 122 | 134 | uint32_t cmd_id; |
| 123 | 135 | uint32_t resp_id; |
| 124 | 136 | enum ta_xgmi_status xgmi_status; |
| 125 | − uint32_t reserved; | |
| 137 | + uint8_t flag_extend_link_record; | |
| 138 | + uint8_t reserved0[3]; | |
| 126 | 139 | union ta_xgmi_cmd_input xgmi_in_message; |
| 127 | 140 | union ta_xgmi_cmd_output xgmi_out_message; |
| 128 | 141 | }; |
| @@ -28,6 +28,21 @@ · 27 unmodified lines | ||
| 28 | 28 | #include "umc/umc_6_7_0_offset.h" |
| 29 | 29 | #include "umc/umc_6_7_0_sh_mask.h" |
| 30 | 30 | |
| 31 | +const uint32_t | |
| 32 | + umc_v6_7_channel_idx_tbl_second[UMC_V6_7_UMC_INSTANCE_NUM][UMC_V6_7_CHANNEL_INSTANCE_NUM] = { | |
| 33 | + {28, 20, 24, 16, 12, 4, 8, 0}, | |
| 34 | + {6, 30, 2, 26, 22, 14, 18, 10}, | |
| 35 | + {19, 11, 15, 7, 3, 27, 31, 23}, | |
| 36 | + {9, 1, 5, 29, 25, 17, 21, 13} | |
| 37 | +}; | |
| 38 | +const uint32_t | |
| 39 | + umc_v6_7_channel_idx_tbl_first[UMC_V6_7_UMC_INSTANCE_NUM][UMC_V6_7_CHANNEL_INSTANCE_NUM] = { | |
| 40 | + {19, 11, 15, 7, 3, 27, 31, 23}, | |
| 41 | + {9, 1, 5, 29, 25, 17, 21, 13}, | |
| 42 | + {28, 20, 24, 16, 12, 4, 8, 0}, | |
| 43 | + {6, 30, 2, 26, 22, 14, 18, 10}, | |
| 44 | +}; | |
| 45 | + | |
| 31 | 46 | static inline uint32_t get_umc_v6_7_reg_offset(struct amdgpu_device *adev, |
| 32 | 47 | uint32_t umc_inst, |
| 33 | 48 | uint32_t ch_inst) |
| @@ -23,6 +23,9 @@ · 22 unmodified lines | ||
| 23 | 23 | #ifndef __UMC_V6_7_H__ |
| 24 | 24 | #define __UMC_V6_7_H__ |
| 25 | 25 | |
| 26 | +#include "soc15_common.h" | |
| 27 | +#include "amdgpu.h" | |
| 28 | + | |
| 26 | 29 | /* EccErrCnt max value */ |
| 27 | 30 | #define UMC_V6_7_CE_CNT_MAX 0xffff |
| 28 | 31 | /* umc ce interrupt threshold */ |
| @@ -32,6 +35,18 @@ · 3 unmodified lines | ||
| 32 | 35 | |
| 33 | 36 | #define UMC_V6_7_INST_DIST 0x40000 |
| 34 | 37 | |
| 38 | +/* number of umc channel instance with memory map register access */ | |
| 39 | +#define UMC_V6_7_UMC_INSTANCE_NUM 4 | |
| 40 | +/* number of umc instance with memory map register access */ | |
| 41 | +#define UMC_V6_7_CHANNEL_INSTANCE_NUM 8 | |
| 42 | +/* total channel instances in one umc block */ | |
| 43 | +#define UMC_V6_7_TOTAL_CHANNEL_NUM (UMC_V6_7_CHANNEL_INSTANCE_NUM * UMC_V6_7_UMC_INSTANCE_NUM) | |
| 44 | +/* UMC regiser per channel offset */ | |
| 45 | +#define UMC_V6_7_PER_CHANNEL_OFFSET 0x400 | |
| 35 | 46 | extern const struct amdgpu_umc_ras_funcs umc_v6_7_ras_funcs; |
| 47 | +extern const uint32_t | |
| 48 | + umc_v6_7_channel_idx_tbl_second[UMC_V6_7_UMC_INSTANCE_NUM][UMC_V6_7_CHANNEL_INSTANCE_NUM]; | |
| 49 | +extern const uint32_t | |
| 50 | + umc_v6_7_channel_idx_tbl_first[UMC_V6_7_UMC_INSTANCE_NUM][UMC_V6_7_CHANNEL_INSTANCE_NUM]; | |
| 36 | 51 | |
| 37 | 52 | #endif |
| @@ -698,6 +698,30 @@ static int uvd_v3_1_hw_fini(void *handle) · 697 unmodified lines | ||
| 698 | 698 | { |
| 699 | 699 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; |
| 700 | 700 | |
| 701 | + /* | |
| 702 | + * Proper cleanups before halting the HW engine: | |
| 703 | + * - cancel the delayed idle work | |
| 704 | + * - enable powergating | |
| 705 | + * - enable clockgating | |
| 706 | + * - disable dpm | |
| 707 | + * | |
| 708 | + * TODO: to align with the VCN implementation, move the | |
| 709 | + * jobs for clockgating/powergating/dpm setting to | |
| 710 | + * ->set_powergating_state(). | |
| 711 | + */ | |
| 712 | + cancel_delayed_work_sync(&adev->uvd.idle_work); | |
| 713 | + | |
| 714 | + if (adev->pm.dpm_enabled) { | |
| 715 | + amdgpu_dpm_enable_uvd(adev, false); | |
| 716 | + } else { | |
| 717 | + amdgpu_asic_set_uvd_clocks(adev, 0, 0); | |
| 718 | + /* shutdown the UVD block */ | |
| 719 | + amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_UVD, | |
| 720 | + AMD_PG_STATE_GATE); | |
| 721 | + amdgpu_device_ip_set_clockgating_state(adev, AMD_IP_BLOCK_TYPE_UVD, | |
| 722 | + AMD_CG_STATE_GATE); | |
| 723 | + } | |
| 724 | + | |
| 701 | 725 | if (RREG32(mmUVD_STATUS) != 0) |
| 702 | 726 | uvd_v3_1_stop(adev); |
| 703 | 727 | |
| @@ -212,6 +212,30 @@ static int uvd_v4_2_hw_fini(void *handle) · 211 unmodified lines | ||
| 212 | 212 | { |
| 213 | 213 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; |
| 214 | 214 | |
| 215 | + /* | |
| 216 | + * Proper cleanups before halting the HW engine: | |
| 217 | + * - cancel the delayed idle work | |
| 218 | + * - enable powergating | |
| 219 | + * - enable clockgating | |
| 220 | + * - disable dpm | |
| 221 | + * | |
| 222 | + * TODO: to align with the VCN implementation, move the | |
| 223 | + * jobs for clockgating/powergating/dpm setting to | |
| 224 | + * ->set_powergating_state(). | |
| 225 | + */ | |
| 226 | + cancel_delayed_work_sync(&adev->uvd.idle_work); | |
| 227 | + | |
| 228 | + if (adev->pm.dpm_enabled) { | |
| 229 | + amdgpu_dpm_enable_uvd(adev, false); | |
| 230 | + } else { | |
| 231 | + amdgpu_asic_set_uvd_clocks(adev, 0, 0); | |
| 232 | + /* shutdown the UVD block */ | |
| 233 | + amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_UVD, | |
| 234 | + AMD_PG_STATE_GATE); | |
| 235 | + amdgpu_device_ip_set_clockgating_state(adev, AMD_IP_BLOCK_TYPE_UVD, | |
| 236 | + AMD_CG_STATE_GATE); | |
| 237 | + } | |
| 238 | + | |
| 215 | 239 | if (RREG32(mmUVD_STATUS) != 0) |
| 216 | 240 | uvd_v4_2_stop(adev); |
| 217 | 241 | |
| @@ -210,6 +210,30 @@ static int uvd_v5_0_hw_fini(void *handle) · 209 unmodified lines | ||
| 210 | 210 | { |
| 211 | 211 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; |
| 212 | 212 | |
| 213 | + /* | |
| 214 | + * Proper cleanups before halting the HW engine: | |
| 215 | + * - cancel the delayed idle work | |
| 216 | + * - enable powergating | |
| 217 | + * - enable clockgating | |
| 218 | + * - disable dpm | |
| 219 | + * | |
| 220 | + * TODO: to align with the VCN implementation, move the | |
| 221 | + * jobs for clockgating/powergating/dpm setting to | |
| 222 | + * ->set_powergating_state(). | |
| 223 | + */ | |
| 224 | + cancel_delayed_work_sync(&adev->uvd.idle_work); | |
| 225 | + | |
| 226 | + if (adev->pm.dpm_enabled) { | |
| 227 | + amdgpu_dpm_enable_uvd(adev, false); | |
| 228 | + } else { | |
| 229 | + amdgpu_asic_set_uvd_clocks(adev, 0, 0); | |
| 230 | + /* shutdown the UVD block */ | |
| 231 | + amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_UVD, | |
| 232 | + AMD_PG_STATE_GATE); | |
| 233 | + amdgpu_device_ip_set_clockgating_state(adev, AMD_IP_BLOCK_TYPE_UVD, | |
| 234 | + AMD_CG_STATE_GATE); | |
| 235 | + } | |
| 236 | + | |
| 213 | 237 | if (RREG32(mmUVD_STATUS) != 0) |
| 214 | 238 | uvd_v5_0_stop(adev); |
| 215 | 239 | |
| @@ -224,7 +248,6 @@ static int uvd_v5_0_suspend(void *handle) · 8 unmodified lines | ||
| 224 | 248 | r = uvd_v5_0_hw_fini(adev); |
| 225 | 249 | if (r) |
| 226 | 250 | return r; |
| 227 | − uvd_v5_0_set_clockgating_state(adev, AMD_CG_STATE_GATE); | |
| 228 | 251 | |
| 229 | 252 | return amdgpu_uvd_suspend(adev); |
| 230 | 253 | } |
| @@ -543,6 +543,30 @@ static int uvd_v6_0_hw_fini(void *handle) · 542 unmodified lines | ||
| 543 | 543 | { |
| 544 | 544 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; |
| 545 | 545 | |
| 546 | + /* | |
| 547 | + * Proper cleanups before halting the HW engine: | |
| 548 | + * - cancel the delayed idle work | |
| 549 | + * - enable powergating | |
| 550 | + * - enable clockgating | |
| 551 | + * - disable dpm | |
| 552 | + * | |
| 553 | + * TODO: to align with the VCN implementation, move the | |
| 554 | + * jobs for clockgating/powergating/dpm setting to | |
| 555 | + * ->set_powergating_state(). | |
| 556 | + */ | |
| 557 | + cancel_delayed_work_sync(&adev->uvd.idle_work); | |
| 558 | + | |
| 559 | + if (adev->pm.dpm_enabled) { | |
| 560 | + amdgpu_dpm_enable_uvd(adev, false); | |
| 561 | + } else { | |
| 562 | + amdgpu_asic_set_uvd_clocks(adev, 0, 0); | |
| 563 | + /* shutdown the UVD block */ | |
| 564 | + amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_UVD, | |
| 565 | + AMD_PG_STATE_GATE); | |
| 566 | + amdgpu_device_ip_set_clockgating_state(adev, AMD_IP_BLOCK_TYPE_UVD, | |
| 567 | + AMD_CG_STATE_GATE); | |
| 568 | + } | |
| 569 | + | |
| 546 | 570 | if (RREG32(mmUVD_STATUS) != 0) |
| 547 | 571 | uvd_v6_0_stop(adev); |
| 548 | 572 | |
| @@ -606,6 +606,30 @@ static int uvd_v7_0_hw_fini(void *handle) · 605 unmodified lines | ||
| 606 | 606 | { |
| 607 | 607 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; |
| 608 | 608 | |
| 609 | + /* | |
| 610 | + * Proper cleanups before halting the HW engine: | |
| 611 | + * - cancel the delayed idle work | |
| 612 | + * - enable powergating | |
| 613 | + * - enable clockgating | |
| 614 | + * - disable dpm | |
| 615 | + * | |
| 616 | + * TODO: to align with the VCN implementation, move the | |
| 617 | + * jobs for clockgating/powergating/dpm setting to | |
| 618 | + * ->set_powergating_state(). | |
| 619 | + */ | |
| 620 | + cancel_delayed_work_sync(&adev->uvd.idle_work); | |
| 621 | + | |
| 622 | + if (adev->pm.dpm_enabled) { | |
| 623 | + amdgpu_dpm_enable_uvd(adev, false); | |
| 624 | + } else { | |
| 625 | + amdgpu_asic_set_uvd_clocks(adev, 0, 0); | |
| 626 | + /* shutdown the UVD block */ | |
| 627 | + amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_UVD, | |
| 628 | + AMD_PG_STATE_GATE); | |
| 629 | + amdgpu_device_ip_set_clockgating_state(adev, AMD_IP_BLOCK_TYPE_UVD, | |
| 630 | + AMD_CG_STATE_GATE); | |
| 631 | + } | |
| 632 | + | |
| 609 | 633 | if (!amdgpu_sriov_vf(adev)) |
| 610 | 634 | uvd_v7_0_stop(adev); |
| 611 | 635 | else { |
| @@ -477,6 +477,31 @@ static int vce_v2_0_hw_init(void *handle) · 476 unmodified lines | ||
| 477 | 477 | |
| 478 | 478 | static int vce_v2_0_hw_fini(void *handle) |
| 479 | 479 | { |
| 480 | + struct amdgpu_device *adev = (struct amdgpu_device *)handle; | |
| 481 | + | |
| 482 | + /* | |
| 483 | + * Proper cleanups before halting the HW engine: | |
| 484 | + * - cancel the delayed idle work | |
| 485 | + * - enable powergating | |
| 486 | + * - enable clockgating | |
| 487 | + * - disable dpm | |
| 488 | + * | |
| 489 | + * TODO: to align with the VCN implementation, move the | |
| 490 | + * jobs for clockgating/powergating/dpm setting to | |
| 491 | + * ->set_powergating_state(). | |
| 492 | + */ | |
| 493 | + cancel_delayed_work_sync(&adev->vce.idle_work); | |
| 494 | + | |
| 495 | + if (adev->pm.dpm_enabled) { | |
| 496 | + amdgpu_dpm_enable_vce(adev, false); | |
| 497 | + } else { | |
| 498 | + amdgpu_asic_set_vce_clocks(adev, 0, 0); | |
| 499 | + amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_VCE, | |
| 500 | + AMD_PG_STATE_GATE); | |
| 501 | + amdgpu_device_ip_set_clockgating_state(adev, AMD_IP_BLOCK_TYPE_VCE, | |
| 502 | + AMD_CG_STATE_GATE); | |
| 503 | + } | |
| 504 | + | |
| 480 | 505 | return 0; |
| 481 | 506 | } |
| 482 | 507 | |
| @@ -490,6 +490,29 @@ static int vce_v3_0_hw_fini(void *handle) · 489 unmodified lines | ||
| 490 | 490 | int r; |
| 491 | 491 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; |
| 492 | 492 | |
| 493 | + /* | |
| 494 | + * Proper cleanups before halting the HW engine: | |
| 495 | + * - cancel the delayed idle work | |
| 496 | + * - enable powergating | |
| 497 | + * - enable clockgating | |
| 498 | + * - disable dpm | |
| 499 | + * | |
| 500 | + * TODO: to align with the VCN implementation, move the | |
| 501 | + * jobs for clockgating/powergating/dpm setting to | |
| 502 | + * ->set_powergating_state(). | |
| 503 | + */ | |
| 504 | + cancel_delayed_work_sync(&adev->vce.idle_work); | |
| 505 | + | |
| 506 | + if (adev->pm.dpm_enabled) { | |
| 507 | + amdgpu_dpm_enable_vce(adev, false); | |
| 508 | + } else { | |
| 509 | + amdgpu_asic_set_vce_clocks(adev, 0, 0); | |
| 510 | + amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_VCE, | |
| 511 | + AMD_PG_STATE_GATE); | |
| 512 | + amdgpu_device_ip_set_clockgating_state(adev, AMD_IP_BLOCK_TYPE_VCE, | |
| 513 | + AMD_CG_STATE_GATE); | |
| 514 | + } | |
| 515 | + | |
| 493 | 516 | r = vce_v3_0_wait_for_idle(handle); |
| 494 | 517 | if (r) |
| 495 | 518 | return r; |
| @@ -542,6 +542,29 @@ static int vce_v4_0_hw_fini(void *handle) · 541 unmodified lines | ||
| 542 | 542 | { |
| 543 | 543 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; |
| 544 | 544 | |
| 545 | + /* | |
| 546 | + * Proper cleanups before halting the HW engine: | |
| 547 | + * - cancel the delayed idle work | |
| 548 | + * - enable powergating | |
| 549 | + * - enable clockgating | |
| 550 | + * - disable dpm | |
| 551 | + * | |
| 552 | + * TODO: to align with the VCN implementation, move the | |
| 553 | + * jobs for clockgating/powergating/dpm setting to | |
| 554 | + * ->set_powergating_state(). | |
| 555 | + */ | |
| 556 | + cancel_delayed_work_sync(&adev->vce.idle_work); | |
| 557 | + | |
| 558 | + if (adev->pm.dpm_enabled) { | |
| 559 | + amdgpu_dpm_enable_vce(adev, false); | |
| 560 | + } else { | |
| 561 | + amdgpu_asic_set_vce_clocks(adev, 0, 0); | |
| 562 | + amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_VCE, | |
| 563 | + AMD_PG_STATE_GATE); | |
| 564 | + amdgpu_device_ip_set_clockgating_state(adev, AMD_IP_BLOCK_TYPE_VCE, | |
| 565 | + AMD_CG_STATE_GATE); | |
| 566 | + } | |
| 567 | + | |
| 545 | 568 | if (!amdgpu_sriov_vf(adev)) { |
| 546 | 569 | /* vce_v4_0_wait_for_idle(handle); */ |
| 547 | 570 | vce_v4_0_stop(adev); |
| @@ -119,7 +119,7 @@ static int vcn_v1_0_sw_init(void *handle) · 118 unmodified lines | ||
| 119 | 119 | adev->firmware.ucode[AMDGPU_UCODE_ID_VCN].fw = adev->vcn.fw; |
| 120 | 120 | adev->firmware.fw_size += |
| 121 | 121 | ALIGN(le32_to_cpu(hdr->ucode_size_bytes), PAGE_SIZE); |
| 122 | − DRM_INFO("PSP loading VCN firmware\n"); | |
| 122 | + dev_info(adev->dev, "Will use PSP to load VCN firmware\n"); | |
| 123 | 123 | } |
| 124 | 124 | |
| 125 | 125 | r = amdgpu_vcn_resume(adev); |
| @@ -122,7 +122,7 @@ static int vcn_v2_0_sw_init(void *handle) · 121 unmodified lines | ||
| 122 | 122 | adev->firmware.ucode[AMDGPU_UCODE_ID_VCN].fw = adev->vcn.fw; |
| 123 | 123 | adev->firmware.fw_size += |
| 124 | 124 | ALIGN(le32_to_cpu(hdr->ucode_size_bytes), PAGE_SIZE); |
| 125 | − DRM_INFO("PSP loading VCN firmware\n"); | |
| 125 | + dev_info(adev->dev, "Will use PSP to load VCN firmware\n"); | |
| 126 | 126 | } |
| 127 | 127 | |
| 128 | 128 | r = amdgpu_vcn_resume(adev); |
| @@ -152,7 +152,7 @@ static int vcn_v2_5_sw_init(void *handle) · 151 unmodified lines | ||
| 152 | 152 | adev->firmware.fw_size += |
| 153 | 153 | ALIGN(le32_to_cpu(hdr->ucode_size_bytes), PAGE_SIZE); |
| 154 | 154 | } |
| 155 | − DRM_INFO("PSP loading VCN firmware\n"); | |
| 155 | + dev_info(adev->dev, "Will use PSP to load VCN firmware\n"); | |
| 156 | 156 | } |
| 157 | 157 | |
| 158 | 158 | r = amdgpu_vcn_resume(adev); |
| @@ -90,9 +90,7 @@ static int vcn_v3_0_early_init(void *handle) · 89 unmodified lines | ||
| 90 | 90 | int i; |
| 91 | 91 | |
| 92 | 92 | if (amdgpu_sriov_vf(adev)) { |
| 93 | − for (i = 0; i < VCN_INSTANCES_SIENNA_CICHLID; i++) | |
| 94 | − if (amdgpu_vcn_is_disabled_vcn(adev, VCN_DECODE_RING, i)) | |
| 95 | − adev->vcn.num_vcn_inst++; | |
| 93 | + adev->vcn.num_vcn_inst = VCN_INSTANCES_SIENNA_CICHLID; | |
| 96 | 94 | adev->vcn.harvest_config = 0; |
| 97 | 95 | adev->vcn.num_enc_rings = 1; |
| 98 | 96 | |
| @@ -153,14 +151,13 @@ static int vcn_v3_0_sw_init(void *handle) · 54 unmodified lines | ||
| 153 | 151 | adev->firmware.fw_size += |
| 154 | 152 | ALIGN(le32_to_cpu(hdr->ucode_size_bytes), PAGE_SIZE); |
| 155 | 153 | |
| 156 | − if ((adev->vcn.num_vcn_inst == VCN_INSTANCES_SIENNA_CICHLID) || | |
| 157 | − (amdgpu_sriov_vf(adev) && adev->asic_type == CHIP_SIENNA_CICHLID)) { | |
| 154 | + if (adev->vcn.num_vcn_inst == VCN_INSTANCES_SIENNA_CICHLID) { | |
| 158 | 155 | adev->firmware.ucode[AMDGPU_UCODE_ID_VCN1].ucode_id = AMDGPU_UCODE_ID_VCN1; |
| 159 | 156 | adev->firmware.ucode[AMDGPU_UCODE_ID_VCN1].fw = adev->vcn.fw; |
| 160 | 157 | adev->firmware.fw_size += |
| 161 | 158 | ALIGN(le32_to_cpu(hdr->ucode_size_bytes), PAGE_SIZE); |
| 162 | 159 | } |
| 163 | − DRM_INFO("PSP loading VCN firmware\n"); | |
| 160 | + dev_info(adev->dev, "Will use PSP to load VCN firmware\n"); | |
| 164 | 161 | } |
| 165 | 162 | |
| 166 | 163 | r = amdgpu_vcn_resume(adev); |
| @@ -328,18 +325,28 @@ static int vcn_v3_0_hw_init(void *handle) · 161 unmodified lines | ||
| 328 | 325 | continue; |
| 329 | 326 | |
| 330 | 327 | ring = &adev->vcn.inst[i].ring_dec; |
| 331 | − ring->wptr = 0; | |
| 332 | − ring->wptr_old = 0; | |
| 333 | − vcn_v3_0_dec_ring_set_wptr(ring); | |
| 334 | − ring->sched.ready = true; | |
| 335 | − | |
| 336 | − for (j = 0; j < adev->vcn.num_enc_rings; ++j) { | |
| 337 | − ring = &adev->vcn.inst[i].ring_enc[j]; | |
| 328 | + if (amdgpu_vcn_is_disabled_vcn(adev, VCN_DECODE_RING, i)) { | |
| 329 | + ring->sched.ready = false; | |
| 330 | + dev_info(adev->dev, "ring %s is disabled by hypervisor\n", ring->name); | |
| 331 | + } else { | |
| 338 | 332 | ring->wptr = 0; |
| 339 | 333 | ring->wptr_old = 0; |
| 340 | − vcn_v3_0_enc_ring_set_wptr(ring); | |
| 334 | + vcn_v3_0_dec_ring_set_wptr(ring); | |
| 341 | 335 | ring->sched.ready = true; |
| 342 | 336 | } |
| 337 | + | |
| 338 | + for (j = 0; j < adev->vcn.num_enc_rings; ++j) { | |
| 339 | + ring = &adev->vcn.inst[i].ring_enc[j]; | |
| 340 | + if (amdgpu_vcn_is_disabled_vcn(adev, VCN_ENCODE_RING, i)) { | |
| 341 | + ring->sched.ready = false; | |
| 342 | + dev_info(adev->dev, "ring %s is disabled by hypervisor\n", ring->name); | |
| 343 | + } else { | |
| 344 | + ring->wptr = 0; | |
| 345 | + ring->wptr_old = 0; | |
| 346 | + vcn_v3_0_enc_ring_set_wptr(ring); | |
| 347 | + ring->sched.ready = true; | |
| 348 | + } | |
| 349 | + } | |
| 343 | 350 | } |
| 344 | 351 | } else { |
| 345 | 352 | for (i = 0; i < adev->vcn.num_vcn_inst; ++i) { |
| @@ -77,7 +77,7 @@ · 76 unmodified lines | ||
| 77 | 77 | #if defined(CONFIG_DRM_AMD_ACP) |
| 78 | 78 | #include "amdgpu_acp.h" |
| 79 | 79 | #endif |
| 80 | −#include "dce_virtual.h" | |
| 80 | +#include "amdgpu_vkms.h" | |
| 81 | 81 | #include "mxgpu_vi.h" |
| 82 | 82 | #include "amdgpu_dm.h" |
| 83 | 83 | |
| @@ -904,7 +904,14 @@ static bool vi_asic_supports_baco(struct amdgpu_device *adev) · 820 unmodified lines | ||
| 904 | 904 | case CHIP_POLARIS11: |
| 905 | 905 | case CHIP_POLARIS12: |
| 906 | 906 | case CHIP_TOPAZ: |
| 907 | − return amdgpu_dpm_is_baco_supported(adev); | |
| 907 | + /* Disable BACO support for the specific polaris12 SKU temporarily */ | |
| 908 | + if ((adev->pdev->device == 0x699F) && | |
| 909 | + (adev->pdev->revision == 0xC7) && | |
| 910 | + (adev->pdev->subsystem_vendor == 0x1028) && | |
| 911 | + (adev->pdev->subsystem_device == 0x0039)) | |
| 912 | + return false; | |
| 913 | + else | |
| 914 | + return amdgpu_dpm_is_baco_supported(adev); | |
| 908 | 915 | default: |
| 909 | 916 | return false; |
| 910 | 917 | } |
| @@ -2102,7 +2109,7 @@ int vi_set_ip_blocks(struct amdgpu_device *adev) · 1191 unmodified lines | ||
| 2102 | 2109 | amdgpu_device_ip_block_add(adev, &sdma_v2_4_ip_block); |
| 2103 | 2110 | amdgpu_device_ip_block_add(adev, &pp_smu_ip_block); |
| 2104 | 2111 | if (adev->enable_virtual_display) |
| 2105 | − amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block); | |
| 2112 | + amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block); | |
| 2106 | 2113 | break; |
| 2107 | 2114 | case CHIP_FIJI: |
| 2108 | 2115 | amdgpu_device_ip_block_add(adev, &vi_common_ip_block); |
| @@ -2112,7 +2119,7 @@ int vi_set_ip_blocks(struct amdgpu_device *adev) · 3 unmodified lines | ||
| 2112 | 2119 | amdgpu_device_ip_block_add(adev, &sdma_v3_0_ip_block); |
| 2113 | 2120 | amdgpu_device_ip_block_add(adev, &pp_smu_ip_block); |
| 2114 | 2121 | if (adev->enable_virtual_display || amdgpu_sriov_vf(adev)) |
| 2115 | − amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block); | |
| 2122 | + amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block); | |
| 2116 | 2123 | #if defined(CONFIG_DRM_AMD_DC) |
| 2117 | 2124 | else if (amdgpu_device_has_dc_support(adev)) |
| 2118 | 2125 | amdgpu_device_ip_block_add(adev, &dm_ip_block); |
| @@ -2132,7 +2139,7 @@ int vi_set_ip_blocks(struct amdgpu_device *adev) · 13 unmodified lines | ||
| 2132 | 2139 | amdgpu_device_ip_block_add(adev, &sdma_v3_0_ip_block); |
| 2133 | 2140 | amdgpu_device_ip_block_add(adev, &pp_smu_ip_block); |
| 2134 | 2141 | if (adev->enable_virtual_display || amdgpu_sriov_vf(adev)) |
| 2135 | − amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block); | |
| 2142 | + amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block); | |
| 2136 | 2143 | #if defined(CONFIG_DRM_AMD_DC) |
| 2137 | 2144 | else if (amdgpu_device_has_dc_support(adev)) |
| 2138 | 2145 | amdgpu_device_ip_block_add(adev, &dm_ip_block); |
| @@ -2155,7 +2162,7 @@ int vi_set_ip_blocks(struct amdgpu_device *adev) · 16 unmodified lines | ||
| 2155 | 2162 | amdgpu_device_ip_block_add(adev, &sdma_v3_1_ip_block); |
| 2156 | 2163 | amdgpu_device_ip_block_add(adev, &pp_smu_ip_block); |
| 2157 | 2164 | if (adev->enable_virtual_display) |
| 2158 | − amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block); | |
| 2165 | + amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block); | |
| 2159 | 2166 | #if defined(CONFIG_DRM_AMD_DC) |
| 2160 | 2167 | else if (amdgpu_device_has_dc_support(adev)) |
| 2161 | 2168 | amdgpu_device_ip_block_add(adev, &dm_ip_block); |
| @@ -2173,7 +2180,7 @@ int vi_set_ip_blocks(struct amdgpu_device *adev) · 11 unmodified lines | ||
| 2173 | 2180 | amdgpu_device_ip_block_add(adev, &sdma_v3_0_ip_block); |
| 2174 | 2181 | amdgpu_device_ip_block_add(adev, &pp_smu_ip_block); |
| 2175 | 2182 | if (adev->enable_virtual_display) |
| 2176 | − amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block); | |
| 2183 | + amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block); | |
| 2177 | 2184 | #if defined(CONFIG_DRM_AMD_DC) |
| 2178 | 2185 | else if (amdgpu_device_has_dc_support(adev)) |
| 2179 | 2186 | amdgpu_device_ip_block_add(adev, &dm_ip_block); |
| @@ -2194,7 +2201,7 @@ int vi_set_ip_blocks(struct amdgpu_device *adev) · 14 unmodified lines | ||
| 2194 | 2201 | amdgpu_device_ip_block_add(adev, &sdma_v3_0_ip_block); |
| 2195 | 2202 | amdgpu_device_ip_block_add(adev, &pp_smu_ip_block); |
| 2196 | 2203 | if (adev->enable_virtual_display) |
| 2197 | − amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block); | |
| 2204 | + amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block); | |
| 2198 | 2205 | #if defined(CONFIG_DRM_AMD_DC) |
| 2199 | 2206 | else if (amdgpu_device_has_dc_support(adev)) |
| 2200 | 2207 | amdgpu_device_ip_block_add(adev, &dm_ip_block); |
| @@ -1393,6 +1393,7 @@ static int kfd_ioctl_map_memory_to_gpu(struct file *filep, · 1392 unmodified lines | ||
| 1393 | 1393 | long err = 0; |
| 1394 | 1394 | int i; |
| 1395 | 1395 | uint32_t *devices_arr = NULL; |
| 1396 | + bool table_freed = false; | |
| 1396 | 1397 | |
| 1397 | 1398 | dev = kfd_device_by_id(GET_GPU_ID(args->handle)); |
| 1398 | 1399 | if (!dev) |
| @@ -1450,7 +1451,8 @@ static int kfd_ioctl_map_memory_to_gpu(struct file *filep, · 51 unmodified lines | ||
| 1450 | 1451 | goto get_mem_obj_from_handle_failed; |
| 1451 | 1452 | } |
| 1452 | 1453 | err = amdgpu_amdkfd_gpuvm_map_memory_to_gpu( |
| 1453 | − peer->kgd, (struct kgd_mem *)mem, peer_pdd->drm_priv); | |
| 1454 | + peer->kgd, (struct kgd_mem *)mem, | |
| 1455 | + peer_pdd->drm_priv, &table_freed); | |
| 1454 | 1456 | if (err) { |
| 1455 | 1457 | pr_err("Failed to map to gpu %d/%d\n", |
| 1456 | 1458 | i, args->n_devices); |
| @@ -1468,16 +1470,17 @@ static int kfd_ioctl_map_memory_to_gpu(struct file *filep, · 11 unmodified lines | ||
| 1468 | 1470 | } |
| 1469 | 1471 | |
| 1470 | 1472 | /* Flush TLBs after waiting for the page table updates to complete */ |
| 1471 | − for (i = 0; i < args->n_devices; i++) { | |
| 1472 | − peer = kfd_device_by_id(devices_arr[i]); | |
| 1473 | − if (WARN_ON_ONCE(!peer)) | |
| 1474 | − continue; | |
| 1475 | − peer_pdd = kfd_get_process_device_data(peer, p); | |
| 1476 | − if (WARN_ON_ONCE(!peer_pdd)) | |
| 1477 | − continue; | |
| 1478 | − kfd_flush_tlb(peer_pdd, TLB_FLUSH_LEGACY); | |
| 1473 | + if (table_freed) { | |
| 1474 | + for (i = 0; i < args->n_devices; i++) { | |
| 1475 | + peer = kfd_device_by_id(devices_arr[i]); | |
| 1476 | + if (WARN_ON_ONCE(!peer)) | |
| 1477 | + continue; | |
| 1478 | + peer_pdd = kfd_get_process_device_data(peer, p); | |
| 1479 | + if (WARN_ON_ONCE(!peer_pdd)) | |
| 1480 | + continue; | |
| 1481 | + kfd_flush_tlb(peer_pdd, TLB_FLUSH_LEGACY); | |
| 1482 | + } | |
| 1479 | 1483 | } |
| 1480 | − | |
| 1481 | 1484 | kfree(devices_arr); |
| 1482 | 1485 | |
| 1483 | 1486 | return err; |
| @@ -1565,10 +1568,29 @@ static int kfd_ioctl_unmap_memory_from_gpu(struct file *filep, · 81 unmodified lines | ||
| 1565 | 1568 | } |
| 1566 | 1569 | args->n_success = i+1; |
| 1567 | 1570 | } |
| 1568 | − kfree(devices_arr); | |
| 1569 | − | |
| 1570 | 1571 | mutex_unlock(&p->mutex); |
| 1571 | 1572 | |
| 1573 | + if (dev->device_info->asic_family == CHIP_ALDEBARAN) { | |
| 1574 | + err = amdgpu_amdkfd_gpuvm_sync_memory(dev->kgd, | |
| 1575 | + (struct kgd_mem *) mem, true); | |
| 1576 | + if (err) { | |
| 1577 | + pr_debug("Sync memory failed, wait interrupted by user signal\n"); | |
| 1578 | + goto sync_memory_failed; | |
| 1579 | + } | |
| 1580 | + | |
| 1581 | + /* Flush TLBs after waiting for the page table updates to complete */ | |
| 1582 | + for (i = 0; i < args->n_devices; i++) { | |
| 1583 | + peer = kfd_device_by_id(devices_arr[i]); | |
| 1584 | + if (WARN_ON_ONCE(!peer)) | |
| 1585 | + continue; | |
| 1586 | + peer_pdd = kfd_get_process_device_data(peer, p); | |
| 1587 | + if (WARN_ON_ONCE(!peer_pdd)) | |
| 1588 | + continue; | |
| 1589 | + kfd_flush_tlb(peer_pdd, TLB_FLUSH_HEAVYWEIGHT); | |
| 1590 | + } | |
| 1591 | + } | |
| 1592 | + kfree(devices_arr); | |
| 1593 | + | |
| 1572 | 1594 | return 0; |
| 1573 | 1595 | |
| 1574 | 1596 | bind_process_to_device_failed: |
| @@ -1576,6 +1598,7 @@ get_mem_obj_from_handle_failed: · 1 unmodified line | ||
| 1576 | 1598 | unmap_memory_from_gpu_failed: |
| 1577 | 1599 | mutex_unlock(&p->mutex); |
| 1578 | 1600 | copy_from_user_failed: |
| 1601 | +sync_memory_failed: | |
| 1579 | 1602 | kfree(devices_arr); |
| 1580 | 1603 | return err; |
| 1581 | 1604 | } |
| @@ -1404,6 +1404,7 @@ static int kfd_fill_gpu_cache_info(struct kfd_dev *kdev, · 1403 unmodified lines | ||
| 1404 | 1404 | break; |
| 1405 | 1405 | case CHIP_NAVI10: |
| 1406 | 1406 | case CHIP_NAVI12: |
| 1407 | + case CHIP_CYAN_SKILLFISH: | |
| 1407 | 1408 | pcache_info = navi10_cache_info; |
| 1408 | 1409 | num_of_cache_types = ARRAY_SIZE(navi10_cache_info); |
| 1409 | 1410 | break; |
| @@ -1989,8 +1990,19 @@ static int kfd_fill_gpu_direct_io_link_to_cpu(int *avail_size, · 579 unmodified lines | ||
| 1989 | 1990 | sub_type_hdr->flags |= CRAT_IOLINK_FLAGS_BI_DIRECTIONAL; |
| 1990 | 1991 | sub_type_hdr->io_interface_type = CRAT_IOLINK_TYPE_XGMI; |
| 1991 | 1992 | sub_type_hdr->num_hops_xgmi = 1; |
| 1993 | + if (adev->asic_type == CHIP_ALDEBARAN) { | |
| 1994 | + sub_type_hdr->minimum_bandwidth_mbs = | |
| 1995 | + amdgpu_amdkfd_get_xgmi_bandwidth_mbytes( | |
| 1996 | + kdev->kgd, NULL, true); | |
| 1997 | + sub_type_hdr->maximum_bandwidth_mbs = | |
| 1998 | + sub_type_hdr->minimum_bandwidth_mbs; | |
| 1999 | + } | |
| 1992 | 2000 | } else { |
| 1993 | 2001 | sub_type_hdr->io_interface_type = CRAT_IOLINK_TYPE_PCIEXPRESS; |
| 2002 | + sub_type_hdr->minimum_bandwidth_mbs = | |
| 2003 | + amdgpu_amdkfd_get_pcie_bandwidth_mbytes(kdev->kgd, true); | |
| 2004 | + sub_type_hdr->maximum_bandwidth_mbs = | |
| 2005 | + amdgpu_amdkfd_get_pcie_bandwidth_mbytes(kdev->kgd, false); | |
| 1994 | 2006 | } |
| 1995 | 2007 | |
| 1996 | 2008 | sub_type_hdr->proximity_domain_from = proximity_domain; |
| @@ -2033,6 +2045,11 @@ static int kfd_fill_gpu_xgmi_link_to_gpu(int *avail_size, · 36 unmodified lines | ||
| 2033 | 2045 | sub_type_hdr->proximity_domain_to = proximity_domain_to; |
| 2034 | 2046 | sub_type_hdr->num_hops_xgmi = |
| 2035 | 2047 | amdgpu_amdkfd_get_xgmi_hops_count(kdev->kgd, peer_kdev->kgd); |
| 2048 | + sub_type_hdr->maximum_bandwidth_mbs = | |
| 2049 | + amdgpu_amdkfd_get_xgmi_bandwidth_mbytes(kdev->kgd, peer_kdev->kgd, false); | |
| 2050 | + sub_type_hdr->minimum_bandwidth_mbs = sub_type_hdr->maximum_bandwidth_mbs ? | |
| 2051 | + amdgpu_amdkfd_get_xgmi_bandwidth_mbytes(kdev->kgd, NULL, true) : 0; | |
| 2052 | + | |
| 2036 | 2053 | return 0; |
| 2037 | 2054 | } |
| 2038 | 2055 | |
| @@ -84,12 +84,14 @@ static const struct kfd2kgd_calls *kfd2kgd_funcs[] = { · 83 unmodified lines | ||
| 84 | 84 | [CHIP_DIMGREY_CAVEFISH] = &gfx_v10_3_kfd2kgd, |
| 85 | 85 | [CHIP_BEIGE_GOBY] = &gfx_v10_3_kfd2kgd, |
| 86 | 86 | [CHIP_YELLOW_CARP] = &gfx_v10_3_kfd2kgd, |
| 87 | + [CHIP_CYAN_SKILLFISH] = &gfx_v10_kfd2kgd, | |
| 87 | 88 | }; |
| 88 | 89 | |
| 89 | 90 | #ifdef KFD_SUPPORT_IOMMU_V2 |
| 90 | 91 | static const struct kfd_device_info kaveri_device_info = { |
| 91 | 92 | .asic_family = CHIP_KAVERI, |
| 92 | 93 | .asic_name = "kaveri", |
| 94 | + .gfx_target_version = 70000, | |
| 93 | 95 | .max_pasid_bits = 16, |
| 94 | 96 | /* max num of queues for KV.TODO should be a dynamic value */ |
| 95 | 97 | .max_no_of_hqd = 24, |
| @@ -109,6 +111,7 @@ static const struct kfd_device_info kaveri_device_info = { · 13 unmodified lines | ||
| 109 | 111 | static const struct kfd_device_info carrizo_device_info = { |
| 110 | 112 | .asic_family = CHIP_CARRIZO, |
| 111 | 113 | .asic_name = "carrizo", |
| 114 | + .gfx_target_version = 80001, | |
| 112 | 115 | .max_pasid_bits = 16, |
| 113 | 116 | /* max num of queues for CZ.TODO should be a dynamic value */ |
| 114 | 117 | .max_no_of_hqd = 24, |
| @@ -129,6 +132,7 @@ static const struct kfd_device_info carrizo_device_info = { · 14 unmodified lines | ||
| 129 | 132 | static const struct kfd_device_info raven_device_info = { |
| 130 | 133 | .asic_family = CHIP_RAVEN, |
| 131 | 134 | .asic_name = "raven", |
| 135 | + .gfx_target_version = 90002, | |
| 132 | 136 | .max_pasid_bits = 16, |
| 133 | 137 | .max_no_of_hqd = 24, |
| 134 | 138 | .doorbell_size = 8, |
| @@ -147,6 +151,7 @@ static const struct kfd_device_info raven_device_info = { · 12 unmodified lines | ||
| 147 | 151 | static const struct kfd_device_info hawaii_device_info = { |
| 148 | 152 | .asic_family = CHIP_HAWAII, |
| 149 | 153 | .asic_name = "hawaii", |
| 154 | + .gfx_target_version = 70001, | |
| 150 | 155 | .max_pasid_bits = 16, |
| 151 | 156 | /* max num of queues for KV.TODO should be a dynamic value */ |
| 152 | 157 | .max_no_of_hqd = 24, |
| @@ -166,6 +171,7 @@ static const struct kfd_device_info hawaii_device_info = { · 13 unmodified lines | ||
| 166 | 171 | static const struct kfd_device_info tonga_device_info = { |
| 167 | 172 | .asic_family = CHIP_TONGA, |
| 168 | 173 | .asic_name = "tonga", |
| 174 | + .gfx_target_version = 80002, | |
| 169 | 175 | .max_pasid_bits = 16, |
| 170 | 176 | .max_no_of_hqd = 24, |
| 171 | 177 | .doorbell_size = 4, |
| @@ -184,6 +190,7 @@ static const struct kfd_device_info tonga_device_info = { · 12 unmodified lines | ||
| 184 | 190 | static const struct kfd_device_info fiji_device_info = { |
| 185 | 191 | .asic_family = CHIP_FIJI, |
| 186 | 192 | .asic_name = "fiji", |
| 193 | + .gfx_target_version = 80003, | |
| 187 | 194 | .max_pasid_bits = 16, |
| 188 | 195 | .max_no_of_hqd = 24, |
| 189 | 196 | .doorbell_size = 4, |
| @@ -202,6 +209,7 @@ static const struct kfd_device_info fiji_device_info = { · 12 unmodified lines | ||
| 202 | 209 | static const struct kfd_device_info fiji_vf_device_info = { |
| 203 | 210 | .asic_family = CHIP_FIJI, |
| 204 | 211 | .asic_name = "fiji", |
| 212 | + .gfx_target_version = 80003, | |
| 205 | 213 | .max_pasid_bits = 16, |
| 206 | 214 | .max_no_of_hqd = 24, |
| 207 | 215 | .doorbell_size = 4, |
| @@ -221,6 +229,7 @@ static const struct kfd_device_info fiji_vf_device_info = { · 13 unmodified lines | ||
| 221 | 229 | static const struct kfd_device_info polaris10_device_info = { |
| 222 | 230 | .asic_family = CHIP_POLARIS10, |
| 223 | 231 | .asic_name = "polaris10", |
| 232 | + .gfx_target_version = 80003, | |
| 224 | 233 | .max_pasid_bits = 16, |
| 225 | 234 | .max_no_of_hqd = 24, |
| 226 | 235 | .doorbell_size = 4, |
| @@ -239,6 +248,7 @@ static const struct kfd_device_info polaris10_device_info = { · 12 unmodified lines | ||
| 239 | 248 | static const struct kfd_device_info polaris10_vf_device_info = { |
| 240 | 249 | .asic_family = CHIP_POLARIS10, |
| 241 | 250 | .asic_name = "polaris10", |
| 251 | + .gfx_target_version = 80003, | |
| 242 | 252 | .max_pasid_bits = 16, |
| 243 | 253 | .max_no_of_hqd = 24, |
| 244 | 254 | .doorbell_size = 4, |
| @@ -257,6 +267,7 @@ static const struct kfd_device_info polaris10_vf_device_info = { · 12 unmodified lines | ||
| 257 | 267 | static const struct kfd_device_info polaris11_device_info = { |
| 258 | 268 | .asic_family = CHIP_POLARIS11, |
| 259 | 269 | .asic_name = "polaris11", |
| 270 | + .gfx_target_version = 80003, | |
| 260 | 271 | .max_pasid_bits = 16, |
| 261 | 272 | .max_no_of_hqd = 24, |
| 262 | 273 | .doorbell_size = 4, |
| @@ -275,6 +286,7 @@ static const struct kfd_device_info polaris11_device_info = { · 12 unmodified lines | ||
| 275 | 286 | static const struct kfd_device_info polaris12_device_info = { |
| 276 | 287 | .asic_family = CHIP_POLARIS12, |
| 277 | 288 | .asic_name = "polaris12", |
| 289 | + .gfx_target_version = 80003, | |
| 278 | 290 | .max_pasid_bits = 16, |
| 279 | 291 | .max_no_of_hqd = 24, |
| 280 | 292 | .doorbell_size = 4, |
| @@ -293,6 +305,7 @@ static const struct kfd_device_info polaris12_device_info = { · 12 unmodified lines | ||
| 293 | 305 | static const struct kfd_device_info vegam_device_info = { |
| 294 | 306 | .asic_family = CHIP_VEGAM, |
| 295 | 307 | .asic_name = "vegam", |
| 308 | + .gfx_target_version = 80003, | |
| 296 | 309 | .max_pasid_bits = 16, |
| 297 | 310 | .max_no_of_hqd = 24, |
| 298 | 311 | .doorbell_size = 4, |
| @@ -311,6 +324,7 @@ static const struct kfd_device_info vegam_device_info = { · 12 unmodified lines | ||
| 311 | 324 | static const struct kfd_device_info vega10_device_info = { |
| 312 | 325 | .asic_family = CHIP_VEGA10, |
| 313 | 326 | .asic_name = "vega10", |
| 327 | + .gfx_target_version = 90000, | |
| 314 | 328 | .max_pasid_bits = 16, |
| 315 | 329 | .max_no_of_hqd = 24, |
| 316 | 330 | .doorbell_size = 8, |
| @@ -329,6 +343,7 @@ static const struct kfd_device_info vega10_device_info = { · 12 unmodified lines | ||
| 329 | 343 | static const struct kfd_device_info vega10_vf_device_info = { |
| 330 | 344 | .asic_family = CHIP_VEGA10, |
| 331 | 345 | .asic_name = "vega10", |
| 346 | + .gfx_target_version = 90000, | |
| 332 | 347 | .max_pasid_bits = 16, |
| 333 | 348 | .max_no_of_hqd = 24, |
| 334 | 349 | .doorbell_size = 8, |
| @@ -347,6 +362,7 @@ static const struct kfd_device_info vega10_vf_device_info = { · 12 unmodified lines | ||
| 347 | 362 | static const struct kfd_device_info vega12_device_info = { |
| 348 | 363 | .asic_family = CHIP_VEGA12, |
| 349 | 364 | .asic_name = "vega12", |
| 365 | + .gfx_target_version = 90004, | |
| 350 | 366 | .max_pasid_bits = 16, |
| 351 | 367 | .max_no_of_hqd = 24, |
| 352 | 368 | .doorbell_size = 8, |
| @@ -365,6 +381,7 @@ static const struct kfd_device_info vega12_device_info = { · 12 unmodified lines | ||
| 365 | 381 | static const struct kfd_device_info vega20_device_info = { |
| 366 | 382 | .asic_family = CHIP_VEGA20, |
| 367 | 383 | .asic_name = "vega20", |
| 384 | + .gfx_target_version = 90006, | |
| 368 | 385 | .max_pasid_bits = 16, |
| 369 | 386 | .max_no_of_hqd = 24, |
| 370 | 387 | .doorbell_size = 8, |
| @@ -383,6 +400,7 @@ static const struct kfd_device_info vega20_device_info = { · 12 unmodified lines | ||
| 383 | 400 | static const struct kfd_device_info arcturus_device_info = { |
| 384 | 401 | .asic_family = CHIP_ARCTURUS, |
| 385 | 402 | .asic_name = "arcturus", |
| 403 | + .gfx_target_version = 90008, | |
| 386 | 404 | .max_pasid_bits = 16, |
| 387 | 405 | .max_no_of_hqd = 24, |
| 388 | 406 | .doorbell_size = 8, |
| @@ -401,6 +419,7 @@ static const struct kfd_device_info arcturus_device_info = { · 12 unmodified lines | ||
| 401 | 419 | static const struct kfd_device_info aldebaran_device_info = { |
| 402 | 420 | .asic_family = CHIP_ALDEBARAN, |
| 403 | 421 | .asic_name = "aldebaran", |
| 422 | + .gfx_target_version = 90010, | |
| 404 | 423 | .max_pasid_bits = 16, |
| 405 | 424 | .max_no_of_hqd = 24, |
| 406 | 425 | .doorbell_size = 8, |
| @@ -419,6 +438,7 @@ static const struct kfd_device_info aldebaran_device_info = { · 12 unmodified lines | ||
| 419 | 438 | static const struct kfd_device_info renoir_device_info = { |
| 420 | 439 | .asic_family = CHIP_RENOIR, |
| 421 | 440 | .asic_name = "renoir", |
| 441 | + .gfx_target_version = 90002, | |
| 422 | 442 | .max_pasid_bits = 16, |
| 423 | 443 | .max_no_of_hqd = 24, |
| 424 | 444 | .doorbell_size = 8, |
| @@ -437,6 +457,7 @@ static const struct kfd_device_info renoir_device_info = { · 12 unmodified lines | ||
| 437 | 457 | static const struct kfd_device_info navi10_device_info = { |
| 438 | 458 | .asic_family = CHIP_NAVI10, |
| 439 | 459 | .asic_name = "navi10", |
| 460 | + .gfx_target_version = 100100, | |
| 440 | 461 | .max_pasid_bits = 16, |
| 441 | 462 | .max_no_of_hqd = 24, |
| 442 | 463 | .doorbell_size = 8, |
| @@ -455,6 +476,7 @@ static const struct kfd_device_info navi10_device_info = { · 12 unmodified lines | ||
| 455 | 476 | static const struct kfd_device_info navi12_device_info = { |
| 456 | 477 | .asic_family = CHIP_NAVI12, |
| 457 | 478 | .asic_name = "navi12", |
| 479 | + .gfx_target_version = 100101, | |
| 458 | 480 | .max_pasid_bits = 16, |
| 459 | 481 | .max_no_of_hqd = 24, |
| 460 | 482 | .doorbell_size = 8, |
| @@ -473,6 +495,7 @@ static const struct kfd_device_info navi12_device_info = { · 12 unmodified lines | ||
| 473 | 495 | static const struct kfd_device_info navi14_device_info = { |
| 474 | 496 | .asic_family = CHIP_NAVI14, |
| 475 | 497 | .asic_name = "navi14", |
| 498 | + .gfx_target_version = 100102, | |
| 476 | 499 | .max_pasid_bits = 16, |
| 477 | 500 | .max_no_of_hqd = 24, |
| 478 | 501 | .doorbell_size = 8, |
| @@ -491,6 +514,7 @@ static const struct kfd_device_info navi14_device_info = { · 12 unmodified lines | ||
| 491 | 514 | static const struct kfd_device_info sienna_cichlid_device_info = { |
| 492 | 515 | .asic_family = CHIP_SIENNA_CICHLID, |
| 493 | 516 | .asic_name = "sienna_cichlid", |
| 517 | + .gfx_target_version = 100300, | |
| 494 | 518 | .max_pasid_bits = 16, |
| 495 | 519 | .max_no_of_hqd = 24, |
| 496 | 520 | .doorbell_size = 8, |
| @@ -509,6 +533,7 @@ static const struct kfd_device_info sienna_cichlid_device_info = { · 12 unmodified lines | ||
| 509 | 533 | static const struct kfd_device_info navy_flounder_device_info = { |
| 510 | 534 | .asic_family = CHIP_NAVY_FLOUNDER, |
| 511 | 535 | .asic_name = "navy_flounder", |
| 536 | + .gfx_target_version = 100301, | |
| 512 | 537 | .max_pasid_bits = 16, |
| 513 | 538 | .max_no_of_hqd = 24, |
| 514 | 539 | .doorbell_size = 8, |
| @@ -527,6 +552,7 @@ static const struct kfd_device_info navy_flounder_device_info = { · 12 unmodified lines | ||
| 527 | 552 | static const struct kfd_device_info vangogh_device_info = { |
| 528 | 553 | .asic_family = CHIP_VANGOGH, |
| 529 | 554 | .asic_name = "vangogh", |
| 555 | + .gfx_target_version = 100303, | |
| 530 | 556 | .max_pasid_bits = 16, |
| 531 | 557 | .max_no_of_hqd = 24, |
| 532 | 558 | .doorbell_size = 8, |
| @@ -545,6 +571,7 @@ static const struct kfd_device_info vangogh_device_info = { · 12 unmodified lines | ||
| 545 | 571 | static const struct kfd_device_info dimgrey_cavefish_device_info = { |
| 546 | 572 | .asic_family = CHIP_DIMGREY_CAVEFISH, |
| 547 | 573 | .asic_name = "dimgrey_cavefish", |
| 574 | + .gfx_target_version = 100302, | |
| 548 | 575 | .max_pasid_bits = 16, |
| 549 | 576 | .max_no_of_hqd = 24, |
| 550 | 577 | .doorbell_size = 8, |
| @@ -563,6 +590,7 @@ static const struct kfd_device_info dimgrey_cavefish_device_info = { · 12 unmodified lines | ||
| 563 | 590 | static const struct kfd_device_info beige_goby_device_info = { |
| 564 | 591 | .asic_family = CHIP_BEIGE_GOBY, |
| 565 | 592 | .asic_name = "beige_goby", |
| 593 | + .gfx_target_version = 100304, | |
| 566 | 594 | .max_pasid_bits = 16, |
| 567 | 595 | .max_no_of_hqd = 24, |
| 568 | 596 | .doorbell_size = 8, |
| @@ -581,6 +609,7 @@ static const struct kfd_device_info beige_goby_device_info = { · 12 unmodified lines | ||
| 581 | 609 | static const struct kfd_device_info yellow_carp_device_info = { |
| 582 | 610 | .asic_family = CHIP_YELLOW_CARP, |
| 583 | 611 | .asic_name = "yellow_carp", |
| 612 | + .gfx_target_version = 100305, | |
| 584 | 613 | .max_pasid_bits = 16, |
| 585 | 614 | .max_no_of_hqd = 24, |
| 586 | 615 | .doorbell_size = 8, |
| @@ -596,6 +625,25 @@ static const struct kfd_device_info yellow_carp_device_info = { · 9 unmodified lines | ||
| 596 | 625 | .num_sdma_queues_per_engine = 2, |
| 597 | 626 | }; |
| 598 | 627 | |
| 628 | +static const struct kfd_device_info cyan_skillfish_device_info = { | |
| 629 | + .asic_family = CHIP_CYAN_SKILLFISH, | |
| 630 | + .asic_name = "cyan_skillfish", | |
| 631 | + .gfx_target_version = 100103, | |
| 632 | + .max_pasid_bits = 16, | |
| 633 | + .max_no_of_hqd = 24, | |
| 634 | + .doorbell_size = 8, | |
| 635 | + .ih_ring_entry_size = 8 * sizeof(uint32_t), | |
| 636 | + .event_interrupt_class = &event_interrupt_class_v9, | |
| 637 | + .num_of_watch_points = 4, | |
| 638 | + .mqd_size_aligned = MQD_SIZE_ALIGNED, | |
| 639 | + .needs_iommu_device = false, | |
| 640 | + .supports_cwsr = true, | |
| 641 | + .needs_pci_atomics = true, | |
| 642 | + .num_sdma_engines = 2, | |
| 643 | + .num_xgmi_sdma_engines = 0, | |
| 644 | + .num_sdma_queues_per_engine = 8, | |
| 645 | +}; | |
| 646 | + | |
| 599 | 647 | /* For each entry, [0] is regular and [1] is virtualisation device. */ |
| 600 | 648 | static const struct kfd_device_info *kfd_supported_devices[][2] = { |
| 601 | 649 | #ifdef KFD_SUPPORT_IOMMU_V2 |
| @@ -625,6 +673,7 @@ static const struct kfd_device_info *kfd_supported_devices[][2] = { · 23 unmodified lines | ||
| 625 | 673 | [CHIP_DIMGREY_CAVEFISH] = {&dimgrey_cavefish_device_info, &dimgrey_cavefish_device_info}, |
| 626 | 674 | [CHIP_BEIGE_GOBY] = {&beige_goby_device_info, &beige_goby_device_info}, |
| 627 | 675 | [CHIP_YELLOW_CARP] = {&yellow_carp_device_info, NULL}, |
| 676 | + [CHIP_CYAN_SKILLFISH] = {&cyan_skillfish_device_info, NULL}, | |
| 628 | 677 | }; |
| 629 | 678 | |
| 630 | 679 | static int kfd_gtt_sa_init(struct kfd_dev *kfd, unsigned int buf_size, |
| @@ -1369,7 +1418,7 @@ void kfd_dec_compute_active(struct kfd_dev *kfd) · 738 unmodified lines | ||
| 1369 | 1418 | WARN_ONCE(count < 0, "Compute profile ref. count error"); |
| 1370 | 1419 | } |
| 1371 | 1420 | |
| 1372 | −void kgd2kfd_smi_event_throttle(struct kfd_dev *kfd, uint32_t throttle_bitmask) | |
| 1421 | +void kgd2kfd_smi_event_throttle(struct kfd_dev *kfd, uint64_t throttle_bitmask) | |
| 1373 | 1422 | { |
| 1374 | 1423 | if (kfd && kfd->init_complete) |
| 1375 | 1424 | kfd_smi_event_update_thermal_throttling(kfd, throttle_bitmask); |
| @@ -1382,18 +1431,12 @@ void kgd2kfd_smi_event_throttle(struct kfd_dev *kfd, uint32_t throttle_bitmask) · 6 unmodified lines | ||
| 1382 | 1431 | */ |
| 1383 | 1432 | int kfd_debugfs_hang_hws(struct kfd_dev *dev) |
| 1384 | 1433 | { |
| 1385 | − int r = 0; | |
| 1386 | − | |
| 1387 | 1434 | if (dev->dqm->sched_policy != KFD_SCHED_POLICY_HWS) { |
| 1388 | 1435 | pr_err("HWS is not enabled"); |
| 1389 | 1436 | return -EINVAL; |
| 1390 | 1437 | } |
| 1391 | 1438 | |
| 1392 | − r = pm_debugfs_hang_hws(&dev->dqm->packets); | |
| 1393 | − if (!r) | |
| 1394 | − r = dqm_debugfs_execute_queues(dev->dqm); | |
| 1395 | − | |
| 1396 | − return r; | |
| 1439 | + return dqm_debugfs_hang_hws(dev->dqm); | |
| 1397 | 1440 | } |
| 1398 | 1441 | |
| 1399 | 1442 | #endif |
| @@ -211,6 +211,15 @@ static void deallocate_doorbell(struct qcm_process_device *qpd, · 210 unmodified lines | ||
| 211 | 211 | WARN_ON(!old); |
| 212 | 212 | } |
| 213 | 213 | |
| 214 | +static void program_trap_handler_settings(struct device_queue_manager *dqm, | |
| 215 | + struct qcm_process_device *qpd) | |
| 216 | +{ | |
| 217 | + if (dqm->dev->kfd2kgd->program_trap_handler_settings) | |
| 218 | + dqm->dev->kfd2kgd->program_trap_handler_settings( | |
| 219 | + dqm->dev->kgd, qpd->vmid, | |
| 220 | + qpd->tba_addr, qpd->tma_addr); | |
| 221 | +} | |
| 222 | + | |
| 214 | 223 | static int allocate_vmid(struct device_queue_manager *dqm, |
| 215 | 224 | struct qcm_process_device *qpd, |
| 216 | 225 | struct queue *q) |
| @@ -241,6 +250,10 @@ static int allocate_vmid(struct device_queue_manager *dqm, · 24 unmodified lines | ||
| 241 | 250 | |
| 242 | 251 | program_sh_mem_settings(dqm, qpd); |
| 243 | 252 | |
| 253 | + if (dqm->dev->device_info->asic_family >= CHIP_VEGA10 && | |
| 254 | + dqm->dev->cwsr_enabled) | |
| 255 | + program_trap_handler_settings(dqm, qpd); | |
| 256 | + | |
| 244 | 257 | /* qpd->page_table_base is set earlier when register_process() |
| 245 | 258 | * is called, i.e. when the first queue is created. |
| 246 | 259 | */ |
| @@ -260,7 +273,7 @@ static int allocate_vmid(struct device_queue_manager *dqm, · 13 unmodified lines | ||
| 260 | 273 | static int flush_texture_cache_nocpsch(struct kfd_dev *kdev, |
| 261 | 274 | struct qcm_process_device *qpd) |
| 262 | 275 | { |
| 263 | − const struct packet_manager_funcs *pmf = qpd->dqm->packets.pmf; | |
| 276 | + const struct packet_manager_funcs *pmf = qpd->dqm->packet_mgr.pmf; | |
| 264 | 277 | int ret; |
| 265 | 278 | |
| 266 | 279 | if (!qpd->ib_kaddr) |
| @@ -582,7 +595,9 @@ static int update_queue(struct device_queue_manager *dqm, struct queue *q) · 315 unmodified lines | ||
| 582 | 595 | } |
| 583 | 596 | |
| 584 | 597 | retval = mqd_mgr->destroy_mqd(mqd_mgr, q->mqd, |
| 585 | − KFD_PREEMPT_TYPE_WAVEFRONT_DRAIN, | |
| 598 | + (dqm->dev->cwsr_enabled? | |
| 599 | + KFD_PREEMPT_TYPE_WAVEFRONT_SAVE: | |
| 600 | + KFD_PREEMPT_TYPE_WAVEFRONT_DRAIN), | |
| 586 | 601 | KFD_UNMAP_LATENCY_MS, q->pipe, q->queue); |
| 587 | 602 | if (retval) { |
| 588 | 603 | pr_err("destroy mqd failed\n"); |
| @@ -675,7 +690,9 @@ static int evict_process_queues_nocpsch(struct device_queue_manager *dqm, · 86 unmodified lines | ||
| 675 | 690 | continue; |
| 676 | 691 | |
| 677 | 692 | retval = mqd_mgr->destroy_mqd(mqd_mgr, q->mqd, |
| 678 | − KFD_PREEMPT_TYPE_WAVEFRONT_DRAIN, | |
| 693 | + (dqm->dev->cwsr_enabled? | |
| 694 | + KFD_PREEMPT_TYPE_WAVEFRONT_SAVE: | |
| 695 | + KFD_PREEMPT_TYPE_WAVEFRONT_DRAIN), | |
| 679 | 696 | KFD_UNMAP_LATENCY_MS, q->pipe, q->queue); |
| 680 | 697 | if (retval && !ret) |
| 681 | 698 | /* Return the first error, but keep going to |
| @@ -1000,7 +1017,7 @@ static int start_nocpsch(struct device_queue_manager *dqm) · 318 unmodified lines | ||
| 1000 | 1017 | init_interrupts(dqm); |
| 1001 | 1018 | |
| 1002 | 1019 | if (dqm->dev->device_info->asic_family == CHIP_HAWAII) |
| 1003 | − return pm_init(&dqm->packets, dqm); | |
| 1020 | + return pm_init(&dqm->packet_mgr, dqm); | |
| 1004 | 1021 | dqm->sched_running = true; |
| 1005 | 1022 | |
| 1006 | 1023 | return 0; |
| @@ -1009,7 +1026,7 @@ static int start_nocpsch(struct device_queue_manager *dqm) · 2 unmodified lines | ||
| 1009 | 1026 | static int stop_nocpsch(struct device_queue_manager *dqm) |
| 1010 | 1027 | { |
| 1011 | 1028 | if (dqm->dev->device_info->asic_family == CHIP_HAWAII) |
| 1012 | − pm_uninit(&dqm->packets, false); | |
| 1029 | + pm_uninit(&dqm->packet_mgr, false); | |
| 1013 | 1030 | dqm->sched_running = false; |
| 1014 | 1031 | |
| 1015 | 1032 | return 0; |
| @@ -1124,7 +1141,7 @@ static int set_sched_resources(struct device_queue_manager *dqm) · 108 unmodified lines | ||
| 1124 | 1141 | "queue mask: 0x%8llX\n", |
| 1125 | 1142 | res.vmid_mask, res.queue_mask); |
| 1126 | 1143 | |
| 1127 | − return pm_send_set_resources(&dqm->packets, &res); | |
| 1144 | + return pm_send_set_resources(&dqm->packet_mgr, &res); | |
| 1128 | 1145 | } |
| 1129 | 1146 | |
| 1130 | 1147 | static int initialize_cpsch(struct device_queue_manager *dqm) |
| @@ -1164,7 +1181,8 @@ static int start_cpsch(struct device_queue_manager *dqm) · 33 unmodified lines | ||
| 1164 | 1181 | |
| 1165 | 1182 | retval = 0; |
| 1166 | 1183 | |
| 1167 | − retval = pm_init(&dqm->packets, dqm); | |
| 1184 | + dqm_lock(dqm); | |
| 1185 | + retval = pm_init(&dqm->packet_mgr, dqm); | |
| 1168 | 1186 | if (retval) |
| 1169 | 1187 | goto fail_packet_manager_init; |
| 1170 | 1188 | |
| @@ -1186,7 +1204,6 @@ static int start_cpsch(struct device_queue_manager *dqm) · 15 unmodified lines | ||
| 1186 | 1204 | |
| 1187 | 1205 | init_interrupts(dqm); |
| 1188 | 1206 | |
| 1189 | − dqm_lock(dqm); | |
| 1190 | 1207 | /* clear hang status when driver try to start the hw scheduler */ |
| 1191 | 1208 | dqm->is_hws_hang = false; |
| 1192 | 1209 | dqm->is_resetting = false; |
| @@ -1197,8 +1214,9 @@ static int start_cpsch(struct device_queue_manager *dqm) · 4 unmodified lines | ||
| 1197 | 1214 | return 0; |
| 1198 | 1215 | fail_allocate_vidmem: |
| 1199 | 1216 | fail_set_sched_resources: |
| 1200 | − pm_uninit(&dqm->packets, false); | |
| 1217 | + pm_uninit(&dqm->packet_mgr, false); | |
| 1201 | 1218 | fail_packet_manager_init: |
| 1219 | + dqm_unlock(dqm); | |
| 1202 | 1220 | return retval; |
| 1203 | 1221 | } |
| 1204 | 1222 | |
| @@ -1211,12 +1229,12 @@ static int stop_cpsch(struct device_queue_manager *dqm) · 6 unmodified lines | ||
| 1211 | 1229 | unmap_queues_cpsch(dqm, KFD_UNMAP_QUEUES_FILTER_ALL_QUEUES, 0); |
| 1212 | 1230 | hanging = dqm->is_hws_hang || dqm->is_resetting; |
| 1213 | 1231 | dqm->sched_running = false; |
| 1214 | − dqm_unlock(dqm); | |
| 1215 | 1232 | |
| 1216 | − pm_release_ib(&dqm->packets); | |
| 1233 | + pm_release_ib(&dqm->packet_mgr); | |
| 1217 | 1234 | |
| 1218 | 1235 | kfd_gtt_sa_free(dqm->dev, dqm->fence_mem); |
| 1219 | − pm_uninit(&dqm->packets, hanging); | |
| 1236 | + pm_uninit(&dqm->packet_mgr, hanging); | |
| 1237 | + dqm_unlock(dqm); | |
| 1220 | 1238 | |
| 1221 | 1239 | return 0; |
| 1222 | 1240 | } |
| @@ -1390,7 +1408,7 @@ static int map_queues_cpsch(struct device_queue_manager *dqm) · 167 unmodified lines | ||
| 1390 | 1408 | if (dqm->active_runlist) |
| 1391 | 1409 | return 0; |
| 1392 | 1410 | |
| 1393 | − retval = pm_send_runlist(&dqm->packets, &dqm->queues); | |
| 1411 | + retval = pm_send_runlist(&dqm->packet_mgr, &dqm->queues); | |
| 1394 | 1412 | pr_debug("%s sent runlist\n", __func__); |
| 1395 | 1413 | if (retval) { |
| 1396 | 1414 | pr_err("failed to execute runlist\n"); |
| @@ -1416,13 +1434,13 @@ static int unmap_queues_cpsch(struct device_queue_manager *dqm, · 19 unmodified lines | ||
| 1416 | 1434 | if (!dqm->active_runlist) |
| 1417 | 1435 | return retval; |
| 1418 | 1436 | |
| 1419 | − retval = pm_send_unmap_queue(&dqm->packets, KFD_QUEUE_TYPE_COMPUTE, | |
| 1437 | + retval = pm_send_unmap_queue(&dqm->packet_mgr, KFD_QUEUE_TYPE_COMPUTE, | |
| 1420 | 1438 | filter, filter_param, false, 0); |
| 1421 | 1439 | if (retval) |
| 1422 | 1440 | return retval; |
| 1423 | 1441 | |
| 1424 | 1442 | *dqm->fence_addr = KFD_FENCE_INIT; |
| 1425 | − pm_send_query_status(&dqm->packets, dqm->fence_gpu_addr, | |
| 1443 | + pm_send_query_status(&dqm->packet_mgr, dqm->fence_gpu_addr, | |
| 1426 | 1444 | KFD_FENCE_COMPLETED); |
| 1427 | 1445 | /* should be timed out */ |
| 1428 | 1446 | retval = amdkfd_fence_wait_timeout(dqm->fence_addr, KFD_FENCE_COMPLETED, |
| @@ -1448,14 +1466,14 @@ static int unmap_queues_cpsch(struct device_queue_manager *dqm, · 19 unmodified lines | ||
| 1448 | 1466 | * check those fields |
| 1449 | 1467 | */ |
| 1450 | 1468 | mqd_mgr = dqm->mqd_mgrs[KFD_MQD_TYPE_HIQ]; |
| 1451 | − if (mqd_mgr->read_doorbell_id(dqm->packets.priv_queue->queue->mqd)) { | |
| 1469 | + if (mqd_mgr->read_doorbell_id(dqm->packet_mgr.priv_queue->queue->mqd)) { | |
| 1452 | 1470 | pr_err("HIQ MQD's queue_doorbell_id0 is not 0, Queue preemption time out\n"); |
| 1453 | 1471 | while (halt_if_hws_hang) |
| 1454 | 1472 | schedule(); |
| 1455 | 1473 | return -ETIME; |
| 1456 | 1474 | } |
| 1457 | 1475 | |
| 1458 | − pm_release_ib(&dqm->packets); | |
| 1476 | + pm_release_ib(&dqm->packet_mgr); | |
| 1459 | 1477 | dqm->active_runlist = false; |
| 1460 | 1478 | |
| 1461 | 1479 | return retval; |
| @@ -1946,6 +1964,7 @@ struct device_queue_manager *device_queue_manager_init(struct kfd_dev *dev) · 484 unmodified lines | ||
| 1946 | 1964 | case CHIP_DIMGREY_CAVEFISH: |
| 1947 | 1965 | case CHIP_BEIGE_GOBY: |
| 1948 | 1966 | case CHIP_YELLOW_CARP: |
| 1967 | + case CHIP_CYAN_SKILLFISH: | |
| 1949 | 1968 | device_queue_manager_init_v10_navi10(&dqm->asic_ops); |
| 1950 | 1969 | break; |
| 1951 | 1970 | default: |
| @@ -2099,11 +2118,16 @@ int dqm_debugfs_hqds(struct seq_file *m, void *data) · 147 unmodified lines | ||
| 2099 | 2118 | return r; |
| 2100 | 2119 | } |
| 2101 | 2120 | |
| 2102 | −int dqm_debugfs_execute_queues(struct device_queue_manager *dqm) | |
| 2121 | +int dqm_debugfs_hang_hws(struct device_queue_manager *dqm) | |
| 2103 | 2122 | { |
| 2104 | 2123 | int r = 0; |
| 2105 | 2124 | |
| 2106 | 2125 | dqm_lock(dqm); |
| 2126 | + r = pm_debugfs_hang_hws(&dqm->packet_mgr); | |
| 2127 | + if (r) { | |
| 2128 | + dqm_unlock(dqm); | |
| 2129 | + return r; | |
| 2130 | + } | |
| 2107 | 2131 | dqm->active_runlist = true; |
| 2108 | 2132 | r = execute_queues_cpsch(dqm, KFD_UNMAP_QUEUES_FILTER_ALL_QUEUES, 0); |
| 2109 | 2133 | dqm_unlock(dqm); |
| @@ -169,7 +169,7 @@ struct device_queue_manager { · 168 unmodified lines | ||
| 169 | 169 | struct device_queue_manager_asic_ops asic_ops; |
| 170 | 170 | |
| 171 | 171 | struct mqd_manager *mqd_mgrs[KFD_MQD_TYPE_MAX]; |
| 172 | − struct packet_manager packets; | |
| 172 | + struct packet_manager packet_mgr; | |
| 173 | 173 | struct kfd_dev *dev; |
| 174 | 174 | struct mutex lock_hidden; /* use dqm_lock/unlock(dqm) */ |
| 175 | 175 | struct list_head queues; |
| @@ -422,6 +422,7 @@ int kfd_init_apertures(struct kfd_process *process) · 421 unmodified lines | ||
| 422 | 422 | case CHIP_DIMGREY_CAVEFISH: |
| 423 | 423 | case CHIP_BEIGE_GOBY: |
| 424 | 424 | case CHIP_YELLOW_CARP: |
| 425 | + case CHIP_CYAN_SKILLFISH: | |
| 425 | 426 | kfd_init_apertures_v9(pdd, id); |
| 426 | 427 | break; |
| 427 | 428 | default: |
| @@ -98,36 +98,78 @@ void mqd_symmetrically_map_cu_mask(struct mqd_manager *mm, · 97 unmodified lines | ||
| 98 | 98 | uint32_t *se_mask) |
| 99 | 99 | { |
| 100 | 100 | struct kfd_cu_info cu_info; |
| 101 | − uint32_t cu_per_se[KFD_MAX_NUM_SE] = {0}; | |
| 102 | − int i, se, sh, cu = 0; | |
| 103 | − | |
| 101 | + uint32_t cu_per_sh[KFD_MAX_NUM_SE][KFD_MAX_NUM_SH_PER_SE] = {0}; | |
| 102 | + int i, se, sh, cu; | |
| 104 | 103 | amdgpu_amdkfd_get_cu_info(mm->dev->kgd, &cu_info); |
| 105 | 104 | |
| 106 | 105 | if (cu_mask_count > cu_info.cu_active_number) |
| 107 | 106 | cu_mask_count = cu_info.cu_active_number; |
| 108 | 107 | |
| 108 | + /* Exceeding these bounds corrupts the stack and indicates a coding error. | |
| 109 | + * Returning with no CU's enabled will hang the queue, which should be | |
| 110 | + * attention grabbing. | |
| 111 | + */ | |
| 112 | + if (cu_info.num_shader_engines > KFD_MAX_NUM_SE) { | |
| 113 | + pr_err("Exceeded KFD_MAX_NUM_SE, chip reports %d\n", cu_info.num_shader_engines); | |
| 114 | + return; | |
| 115 | + } | |
| 116 | + if (cu_info.num_shader_arrays_per_engine > KFD_MAX_NUM_SH_PER_SE) { | |
| 117 | + pr_err("Exceeded KFD_MAX_NUM_SH, chip reports %d\n", | |
| 118 | + cu_info.num_shader_arrays_per_engine * cu_info.num_shader_engines); | |
| 119 | + return; | |
| 120 | + } | |
| 121 | + /* Count active CUs per SH. | |
| 122 | + * | |
| 123 | + * Some CUs in an SH may be disabled. HW expects disabled CUs to be | |
| 124 | + * represented in the high bits of each SH's enable mask (the upper and lower | |
| 125 | + * 16 bits of se_mask) and will take care of the actual distribution of | |
| 126 | + * disabled CUs within each SH automatically. | |
| 127 | + * Each half of se_mask must be filled only on bits 0-cu_per_sh[se][sh]-1. | |
| 128 | + * | |
| 129 | + * See note on Arcturus cu_bitmap layout in gfx_v9_0_get_cu_info. | |
| 130 | + */ | |
| 109 | 131 | for (se = 0; se < cu_info.num_shader_engines; se++) |
| 110 | 132 | for (sh = 0; sh < cu_info.num_shader_arrays_per_engine; sh++) |
| 111 | − cu_per_se[se] += hweight32(cu_info.cu_bitmap[se % 4][sh + (se / 4)]); | |
| 112 | − | |
| 113 | − /* Symmetrically map cu_mask to all SEs: | |
| 114 | − * cu_mask[0] bit0 -> se_mask[0] bit0; | |
| 115 | − * cu_mask[0] bit1 -> se_mask[1] bit0; | |
| 116 | − * ... (if # SE is 4) | |
| 117 | − * cu_mask[0] bit4 -> se_mask[0] bit1; | |
| 133 | + cu_per_sh[se][sh] = hweight32(cu_info.cu_bitmap[se % 4][sh + (se / 4)]); | |
| 134 | + | |
| 135 | + /* Symmetrically map cu_mask to all SEs & SHs: | |
| 136 | + * se_mask programs up to 2 SH in the upper and lower 16 bits. | |
| 137 | + * | |
| 138 | + * Examples | |
| 139 | + * Assuming 1 SH/SE, 4 SEs: | |
| 140 | + * cu_mask[0] bit0 -> se_mask[0] bit0 | |
| 141 | + * cu_mask[0] bit1 -> se_mask[1] bit0 | |
| 142 | + * ... | |
| 143 | + * cu_mask[0] bit4 -> se_mask[0] bit1 | |
| 144 | + * ... | |
| 145 | + * | |
| 146 | + * Assuming 2 SH/SE, 4 SEs | |
| 147 | + * cu_mask[0] bit0 -> se_mask[0] bit0 (SE0,SH0,CU0) | |
| 148 | + * cu_mask[0] bit1 -> se_mask[1] bit0 (SE1,SH0,CU0) | |
| 149 | + * ... | |
| 150 | + * cu_mask[0] bit4 -> se_mask[0] bit16 (SE0,SH1,CU0) | |
| 151 | + * cu_mask[0] bit5 -> se_mask[1] bit16 (SE1,SH1,CU0) | |
| 152 | + * ... | |
| 153 | + * cu_mask[0] bit8 -> se_mask[0] bit1 (SE0,SH0,CU1) | |
| 118 | 154 | * ... |
| 155 | + * | |
| 156 | + * First ensure all CUs are disabled, then enable user specified CUs. | |
| 119 | 157 | */ |
| 120 | − se = 0; | |
| 121 | − for (i = 0; i < cu_mask_count; i++) { | |
| 122 | − if (cu_mask[i / 32] & (1 << (i % 32))) | |
| 123 | − se_mask[se] |= 1 << cu; | |
| 124 | − | |
| 125 | − do { | |
| 126 | − se++; | |
| 127 | − if (se == cu_info.num_shader_engines) { | |
| 128 | − se = 0; | |
| 129 | − cu++; | |
| 158 | + for (i = 0; i < cu_info.num_shader_engines; i++) | |
| 159 | + se_mask[i] = 0; | |
| 160 | + | |
| 161 | + i = 0; | |
| 162 | + for (cu = 0; cu < 16; cu++) { | |
| 163 | + for (sh = 0; sh < cu_info.num_shader_arrays_per_engine; sh++) { | |
| 164 | + for (se = 0; se < cu_info.num_shader_engines; se++) { | |
| 165 | + if (cu_per_sh[se][sh] > cu) { | |
| 166 | + if (cu_mask[i / 32] & (1 << (i % 32))) | |
| 167 | + se_mask[se] |= 1 << (cu + sh * 16); | |
| 168 | + i++; | |
| 169 | + if (i == cu_mask_count) | |
| 170 | + return; | |
| 171 | + } | |
| 130 | 172 | } |
| 131 | − } while (cu >= cu_per_se[se] && cu < 32); | |
| 173 | + } | |
| 132 | 174 | } |
| 133 | 175 | } |
| @@ -27,6 +27,7 @@ · 26 unmodified lines | ||
| 27 | 27 | #include "kfd_priv.h" |
| 28 | 28 | |
| 29 | 29 | #define KFD_MAX_NUM_SE 8 |
| 30 | +#define KFD_MAX_NUM_SH_PER_SE 2 | |
| 30 | 31 | |
| 31 | 32 | /** |
| 32 | 33 | * struct mqd_manager |
| @@ -251,6 +251,7 @@ int pm_init(struct packet_manager *pm, struct device_queue_manager *dqm) · 250 unmodified lines | ||
| 251 | 251 | case CHIP_DIMGREY_CAVEFISH: |
| 252 | 252 | case CHIP_BEIGE_GOBY: |
| 253 | 253 | case CHIP_YELLOW_CARP: |
| 254 | + case CHIP_CYAN_SKILLFISH: | |
| 254 | 255 | pm->pmf = &kfd_v9_pm_funcs; |
| 255 | 256 | break; |
| 256 | 257 | case CHIP_ALDEBARAN: |
| @@ -278,6 +279,7 @@ void pm_uninit(struct packet_manager *pm, bool hanging) · 21 unmodified lines | ||
| 278 | 279 | { |
| 279 | 280 | mutex_destroy(&pm->lock); |
| 280 | 281 | kernel_queue_uninit(pm->priv_queue, hanging); |
| 282 | + pm->priv_queue = NULL; | |
| 281 | 283 | } |
| 282 | 284 | |
| 283 | 285 | int pm_send_set_resources(struct packet_manager *pm, |
| @@ -447,6 +449,9 @@ int pm_debugfs_hang_hws(struct packet_manager *pm) · 163 unmodified lines | ||
| 447 | 449 | uint32_t *buffer, size; |
| 448 | 450 | int r = 0; |
| 449 | 451 | |
| 452 | + if (!pm->priv_queue) | |
| 453 | + return -EAGAIN; | |
| 454 | + | |
| 450 | 455 | size = pm->pmf->query_status_size; |
| 451 | 456 | mutex_lock(&pm->lock); |
| 452 | 457 | kq_acquire_packet_buffer(pm->priv_queue, |
| @@ -196,6 +196,7 @@ struct kfd_event_interrupt_class { · 195 unmodified lines | ||
| 196 | 196 | struct kfd_device_info { |
| 197 | 197 | enum amd_asic_type asic_family; |
| 198 | 198 | const char *asic_name; |
| 199 | + uint32_t gfx_target_version; | |
| 199 | 200 | const struct kfd_event_interrupt_class *event_interrupt_class; |
| 200 | 201 | unsigned int max_pasid_bits; |
| 201 | 202 | unsigned int max_no_of_hqd; |
| @@ -1194,7 +1195,7 @@ int pm_debugfs_runlist(struct seq_file *m, void *data); · 992 unmodified lines | ||
| 1194 | 1195 | |
| 1195 | 1196 | int kfd_debugfs_hang_hws(struct kfd_dev *dev); |
| 1196 | 1197 | int pm_debugfs_hang_hws(struct packet_manager *pm); |
| 1197 | −int dqm_debugfs_execute_queues(struct device_queue_manager *dqm); | |
| 1198 | +int dqm_debugfs_hang_hws(struct device_queue_manager *dqm); | |
| 1198 | 1199 | |
| 1199 | 1200 | #else |
| 1200 | 1201 | |
| @@ -714,7 +714,8 @@ static int kfd_process_alloc_gpuvm(struct kfd_process_device *pdd, · 713 unmodified lines | ||
| 714 | 714 | if (err) |
| 715 | 715 | goto err_alloc_mem; |
| 716 | 716 | |
| 717 | − err = amdgpu_amdkfd_gpuvm_map_memory_to_gpu(kdev->kgd, mem, pdd->drm_priv); | |
| 717 | + err = amdgpu_amdkfd_gpuvm_map_memory_to_gpu(kdev->kgd, mem, | |
| 718 | + pdd->drm_priv, NULL); | |
| 718 | 719 | if (err) |
| 719 | 720 | goto err_map_mem; |
| 720 | 721 | |
| @@ -205,23 +205,23 @@ void kfd_smi_event_update_gpu_reset(struct kfd_dev *dev, bool post_reset) · 204 unmodified lines | ||
| 205 | 205 | } |
| 206 | 206 | |
| 207 | 207 | void kfd_smi_event_update_thermal_throttling(struct kfd_dev *dev, |
| 208 | − uint32_t throttle_bitmask) | |
| 208 | + uint64_t throttle_bitmask) | |
| 209 | 209 | { |
| 210 | 210 | struct amdgpu_device *adev = (struct amdgpu_device *)dev->kgd; |
| 211 | 211 | /* |
| 212 | 212 | * ThermalThrottle msg = throttle_bitmask(8): |
| 213 | 213 | * thermal_interrupt_count(16): |
| 214 | − * 1 byte event + 1 byte space + 8 byte throttle_bitmask + | |
| 214 | + * 1 byte event + 1 byte space + 16 byte throttle_bitmask + | |
| 215 | 215 | * 1 byte : + 16 byte thermal_interupt_counter + 1 byte \n + |
| 216 | − * 1 byte \0 = 29 | |
| 216 | + * 1 byte \0 = 37 | |
| 217 | 217 | */ |
| 218 | − char fifo_in[29]; | |
| 218 | + char fifo_in[37]; | |
| 219 | 219 | int len; |
| 220 | 220 | |
| 221 | 221 | if (list_empty(&dev->smi_clients)) |
| 222 | 222 | return; |
| 223 | 223 | |
| 224 | − len = snprintf(fifo_in, sizeof(fifo_in), "%x %x:%llx\n", | |
| 224 | + len = snprintf(fifo_in, sizeof(fifo_in), "%x %llx:%llx\n", | |
| 225 | 225 | KFD_SMI_EVENT_THERMAL_THROTTLE, throttle_bitmask, |
| 226 | 226 | atomic64_read(&adev->smu.throttle_int_counter)); |
| 227 | 227 | |
| @@ -26,7 +26,7 @@ · 25 unmodified lines | ||
| 26 | 26 | int kfd_smi_event_open(struct kfd_dev *dev, uint32_t *fd); |
| 27 | 27 | void kfd_smi_event_update_vmfault(struct kfd_dev *dev, uint16_t pasid); |
| 28 | 28 | void kfd_smi_event_update_thermal_throttling(struct kfd_dev *dev, |
| 29 | − uint32_t throttle_bitmask); | |
| 29 | + uint64_t throttle_bitmask); | |
| 30 | 30 | void kfd_smi_event_update_gpu_reset(struct kfd_dev *dev, bool post_reset); |
| 31 | 31 | |
| 32 | 32 | #endif |
| @@ -120,6 +120,7 @@ static void svm_range_remove_notifier(struct svm_range *prange) · 119 unmodified lines | ||
| 120 | 120 | |
| 121 | 121 | static int |
| 122 | 122 | svm_range_dma_map_dev(struct amdgpu_device *adev, struct svm_range *prange, |
| 123 | + unsigned long offset, unsigned long npages, | |
| 123 | 124 | unsigned long *hmm_pfns, uint32_t gpuidx) |
| 124 | 125 | { |
| 125 | 126 | enum dma_data_direction dir = DMA_BIDIRECTIONAL; |
| @@ -136,7 +137,8 @@ svm_range_dma_map_dev(struct amdgpu_device *adev, struct svm_range *prange, · 10 unmodified lines | ||
| 136 | 137 | prange->dma_addr[gpuidx] = addr; |
| 137 | 138 | } |
| 138 | 139 | |
| 139 | − for (i = 0; i < prange->npages; i++) { | |
| 140 | + addr += offset; | |
| 141 | + for (i = 0; i < npages; i++) { | |
| 140 | 142 | if (WARN_ONCE(addr[i] && !dma_mapping_error(dev, addr[i]), |
| 141 | 143 | "leaking dma mapping\n")) |
| 142 | 144 | dma_unmap_page(dev, addr[i], PAGE_SIZE, dir); |
| @@ -167,6 +169,7 @@ svm_range_dma_map_dev(struct amdgpu_device *adev, struct svm_range *prange, · 24 unmodified lines | ||
| 167 | 169 | |
| 168 | 170 | static int |
| 169 | 171 | svm_range_dma_map(struct svm_range *prange, unsigned long *bitmap, |
| 172 | + unsigned long offset, unsigned long npages, | |
| 170 | 173 | unsigned long *hmm_pfns) |
| 171 | 174 | { |
| 172 | 175 | struct kfd_process *p; |
| @@ -187,7 +190,8 @@ svm_range_dma_map(struct svm_range *prange, unsigned long *bitmap, · 14 unmodified lines | ||
| 187 | 190 | } |
| 188 | 191 | adev = (struct amdgpu_device *)pdd->dev->kgd; |
| 189 | 192 | |
| 190 | − r = svm_range_dma_map_dev(adev, prange, hmm_pfns, gpuidx); | |
| 193 | + r = svm_range_dma_map_dev(adev, prange, offset, npages, | |
| 194 | + hmm_pfns, gpuidx); | |
| 191 | 195 | if (r) |
| 192 | 196 | break; |
| 193 | 197 | } |
| @@ -1088,11 +1092,6 @@ svm_range_get_pte_flags(struct amdgpu_device *adev, struct svm_range *prange, · 894 unmodified lines | ||
| 1088 | 1092 | pte_flags |= snoop ? AMDGPU_PTE_SNOOPED : 0; |
| 1089 | 1093 | |
| 1090 | 1094 | pte_flags |= amdgpu_gem_va_map_flags(adev, mapping_flags); |
| 1091 | − | |
| 1092 | − pr_debug("svms 0x%p [0x%lx 0x%lx] vram %d PTE 0x%llx mapping 0x%x\n", | |
| 1093 | − prange->svms, prange->start, prange->last, | |
| 1094 | − (domain == SVM_RANGE_VRAM_DOMAIN) ? 1:0, pte_flags, mapping_flags); | |
| 1095 | − | |
| 1096 | 1095 | return pte_flags; |
| 1097 | 1096 | } |
| 1098 | 1097 | |
| @@ -1156,7 +1155,8 @@ svm_range_unmap_from_gpus(struct svm_range *prange, unsigned long start, · 57 unmodified lines | ||
| 1156 | 1155 | |
| 1157 | 1156 | static int |
| 1158 | 1157 | svm_range_map_to_gpu(struct amdgpu_device *adev, struct amdgpu_vm *vm, |
| 1159 | − struct svm_range *prange, dma_addr_t *dma_addr, | |
| 1158 | + struct svm_range *prange, unsigned long offset, | |
| 1159 | + unsigned long npages, bool readonly, dma_addr_t *dma_addr, | |
| 1160 | 1160 | struct amdgpu_device *bo_adev, struct dma_fence **fence) |
| 1161 | 1161 | { |
| 1162 | 1162 | struct amdgpu_bo_va bo_va; |
| @@ -1167,14 +1167,15 @@ svm_range_map_to_gpu(struct amdgpu_device *adev, struct amdgpu_vm *vm, · 4 unmodified lines | ||
| 1167 | 1167 | int r = 0; |
| 1168 | 1168 | int64_t i; |
| 1169 | 1169 | |
| 1170 | − pr_debug("svms 0x%p [0x%lx 0x%lx]\n", prange->svms, prange->start, | |
| 1171 | − prange->last); | |
| 1170 | + last_start = prange->start + offset; | |
| 1171 | + | |
| 1172 | + pr_debug("svms 0x%p [0x%lx 0x%lx] readonly %d\n", prange->svms, | |
| 1173 | + last_start, last_start + npages - 1, readonly); | |
| 1172 | 1174 | |
| 1173 | 1175 | if (prange->svm_bo && prange->ttm_res) |
| 1174 | 1176 | bo_va.is_xgmi = amdgpu_xgmi_same_hive(adev, bo_adev); |
| 1175 | 1177 | |
| 1176 | − last_start = prange->start; | |
| 1177 | − for (i = 0; i < prange->npages; i++) { | |
| 1178 | + for (i = offset; i < offset + npages; i++) { | |
| 1178 | 1179 | last_domain = dma_addr[i] & SVM_RANGE_VRAM_DOMAIN; |
| 1179 | 1180 | dma_addr[i] &= ~SVM_RANGE_VRAM_DOMAIN; |
| 1180 | 1181 | if ((prange->start + i) < prange->last && |
| @@ -1183,13 +1184,21 @@ svm_range_map_to_gpu(struct amdgpu_device *adev, struct amdgpu_vm *vm, · 2 unmodified lines | ||
| 1183 | 1184 | |
| 1184 | 1185 | pr_debug("Mapping range [0x%lx 0x%llx] on domain: %s\n", |
| 1185 | 1186 | last_start, prange->start + i, last_domain ? "GPU" : "CPU"); |
| 1187 | + | |
| 1186 | 1188 | pte_flags = svm_range_get_pte_flags(adev, prange, last_domain); |
| 1187 | − r = amdgpu_vm_bo_update_mapping(adev, bo_adev, vm, false, false, NULL, | |
| 1188 | − last_start, | |
| 1189 | + if (readonly) | |
| 1190 | + pte_flags &= ~AMDGPU_PTE_WRITEABLE; | |
| 1191 | + | |
| 1192 | + pr_debug("svms 0x%p map [0x%lx 0x%llx] vram %d PTE 0x%llx\n", | |
| 1193 | + prange->svms, last_start, prange->start + i, | |
| 1194 | + (last_domain == SVM_RANGE_VRAM_DOMAIN) ? 1 : 0, | |
| 1195 | + pte_flags); | |
| 1196 | + | |
| 1197 | + r = amdgpu_vm_bo_update_mapping(adev, bo_adev, vm, false, false, | |
| 1198 | + NULL, last_start, | |
| 1189 | 1199 | prange->start + i, pte_flags, |
| 1190 | 1200 | last_start - prange->start, |
| 1191 | − NULL, | |
| 1192 | − dma_addr, | |
| 1201 | + NULL, dma_addr, | |
| 1193 | 1202 | &vm->last_update, |
| 1194 | 1203 | &table_freed); |
| 1195 | 1204 | if (r) { |
| @@ -1220,8 +1229,10 @@ out: · 24 unmodified lines | ||
| 1220 | 1229 | return r; |
| 1221 | 1230 | } |
| 1222 | 1231 | |
| 1223 | −static int svm_range_map_to_gpus(struct svm_range *prange, | |
| 1224 | − unsigned long *bitmap, bool wait) | |
| 1232 | +static int | |
| 1233 | +svm_range_map_to_gpus(struct svm_range *prange, unsigned long offset, | |
| 1234 | + unsigned long npages, bool readonly, | |
| 1235 | + unsigned long *bitmap, bool wait) | |
| 1225 | 1236 | { |
| 1226 | 1237 | struct kfd_process_device *pdd; |
| 1227 | 1238 | struct amdgpu_device *bo_adev; |
| @@ -1257,7 +1268,8 @@ static int svm_range_map_to_gpus(struct svm_range *prange, · 29 unmodified lines | ||
| 1257 | 1268 | } |
| 1258 | 1269 | |
| 1259 | 1270 | r = svm_range_map_to_gpu(adev, drm_priv_to_vm(pdd->drm_priv), |
| 1260 | − prange, prange->dma_addr[gpuidx], | |
| 1271 | + prange, offset, npages, readonly, | |
| 1272 | + prange->dma_addr[gpuidx], | |
| 1261 | 1273 | bo_adev, wait ? &fence : NULL); |
| 1262 | 1274 | if (r) |
| 1263 | 1275 | break; |
| @@ -1390,7 +1402,7 @@ static int svm_range_validate_and_map(struct mm_struct *mm, · 126 unmodified lines | ||
| 1390 | 1402 | int32_t gpuidx, bool intr, bool wait) |
| 1391 | 1403 | { |
| 1392 | 1404 | struct svm_validate_context ctx; |
| 1393 | − struct hmm_range *hmm_range; | |
| 1405 | + unsigned long start, end, addr; | |
| 1394 | 1406 | struct kfd_process *p; |
| 1395 | 1407 | void *owner; |
| 1396 | 1408 | int32_t idx; |
| @@ -1448,40 +1460,66 @@ static int svm_range_validate_and_map(struct mm_struct *mm, · 51 unmodified lines | ||
| 1448 | 1460 | break; |
| 1449 | 1461 | } |
| 1450 | 1462 | } |
| 1451 | − r = amdgpu_hmm_range_get_pages(&prange->notifier, mm, NULL, | |
| 1452 | − prange->start << PAGE_SHIFT, | |
| 1453 | − prange->npages, &hmm_range, | |
| 1454 | − false, true, owner); | |
| 1455 | − if (r) { | |
| 1456 | − pr_debug("failed %d to get svm range pages\n", r); | |
| 1457 | − goto unreserve_out; | |
| 1458 | − } | |
| 1459 | 1463 | |
| 1460 | − r = svm_range_dma_map(prange, ctx.bitmap, | |
| 1461 | − hmm_range->hmm_pfns); | |
| 1462 | − if (r) { | |
| 1463 | − pr_debug("failed %d to dma map range\n", r); | |
| 1464 | − goto unreserve_out; | |
| 1465 | − } | |
| 1464 | + start = prange->start << PAGE_SHIFT; | |
| 1465 | + end = (prange->last + 1) << PAGE_SHIFT; | |
| 1466 | + for (addr = start; addr < end && !r; ) { | |
| 1467 | + struct hmm_range *hmm_range; | |
| 1468 | + struct vm_area_struct *vma; | |
| 1469 | + unsigned long next; | |
| 1470 | + unsigned long offset; | |
| 1471 | + unsigned long npages; | |
| 1472 | + bool readonly; | |
| 1466 | 1473 | |
| 1467 | − prange->validated_once = true; | |
| 1474 | + vma = find_vma(mm, addr); | |
| 1475 | + if (!vma || addr < vma->vm_start) { | |
| 1476 | + r = -EFAULT; | |
| 1477 | + goto unreserve_out; | |
| 1478 | + } | |
| 1479 | + readonly = !(vma->vm_flags & VM_WRITE); | |
| 1468 | 1480 | |
| 1469 | − svm_range_lock(prange); | |
| 1470 | − if (amdgpu_hmm_range_get_pages_done(hmm_range)) { | |
| 1471 | − pr_debug("hmm update the range, need validate again\n"); | |
| 1472 | − r = -EAGAIN; | |
| 1473 | − goto unlock_out; | |
| 1474 | − } | |
| 1475 | − if (!list_empty(&prange->child_list)) { | |
| 1476 | − pr_debug("range split by unmap in parallel, validate again\n"); | |
| 1477 | − r = -EAGAIN; | |
| 1478 | − goto unlock_out; | |
| 1479 | − } | |
| 1481 | + next = min(vma->vm_end, end); | |
| 1482 | + npages = (next - addr) >> PAGE_SHIFT; | |
| 1483 | + r = amdgpu_hmm_range_get_pages(&prange->notifier, mm, NULL, | |
| 1484 | + addr, npages, &hmm_range, | |
| 1485 | + readonly, true, owner); | |
| 1486 | + if (r) { | |
| 1487 | + pr_debug("failed %d to get svm range pages\n", r); | |
| 1488 | + goto unreserve_out; | |
| 1489 | + } | |
| 1480 | 1490 | |
| 1481 | − r = svm_range_map_to_gpus(prange, ctx.bitmap, wait); | |
| 1491 | + offset = (addr - start) >> PAGE_SHIFT; | |
| 1492 | + r = svm_range_dma_map(prange, ctx.bitmap, offset, npages, | |
| 1493 | + hmm_range->hmm_pfns); | |
| 1494 | + if (r) { | |
| 1495 | + pr_debug("failed %d to dma map range\n", r); | |
| 1496 | + goto unreserve_out; | |
| 1497 | + } | |
| 1498 | + | |
| 1499 | + svm_range_lock(prange); | |
| 1500 | + if (amdgpu_hmm_range_get_pages_done(hmm_range)) { | |
| 1501 | + pr_debug("hmm update the range, need validate again\n"); | |
| 1502 | + r = -EAGAIN; | |
| 1503 | + goto unlock_out; | |
| 1504 | + } | |
| 1505 | + if (!list_empty(&prange->child_list)) { | |
| 1506 | + pr_debug("range split by unmap in parallel, validate again\n"); | |
| 1507 | + r = -EAGAIN; | |
| 1508 | + goto unlock_out; | |
| 1509 | + } | |
| 1510 | + | |
| 1511 | + r = svm_range_map_to_gpus(prange, offset, npages, readonly, | |
| 1512 | + ctx.bitmap, wait); | |
| 1482 | 1513 | |
| 1483 | 1514 | unlock_out: |
| 1484 | − svm_range_unlock(prange); | |
| 1515 | + svm_range_unlock(prange); | |
| 1516 | + | |
| 1517 | + addr = next; | |
| 1518 | + } | |
| 1519 | + | |
| 1520 | + if (addr == end) | |
| 1521 | + prange->validated_once = true; | |
| 1522 | + | |
| 1485 | 1523 | unreserve_out: |
| 1486 | 1524 | svm_range_unreserve_bos(&ctx); |
| 1487 | 1525 | |
| @@ -2400,9 +2438,29 @@ svm_range_count_fault(struct amdgpu_device *adev, struct kfd_process *p, · 912 unmodified lines | ||
| 2400 | 2438 | WRITE_ONCE(pdd->faults, pdd->faults + 1); |
| 2401 | 2439 | } |
| 2402 | 2440 | |
| 2441 | +static bool | |
| 2442 | +svm_fault_allowed(struct mm_struct *mm, uint64_t addr, bool write_fault) | |
| 2443 | +{ | |
| 2444 | + unsigned long requested = VM_READ; | |
| 2445 | + struct vm_area_struct *vma; | |
| 2446 | + | |
| 2447 | + if (write_fault) | |
| 2448 | + requested |= VM_WRITE; | |
| 2449 | + | |
| 2450 | + vma = find_vma(mm, addr << PAGE_SHIFT); | |
| 2451 | + if (!vma || (addr << PAGE_SHIFT) < vma->vm_start) { | |
| 2452 | + pr_debug("address 0x%llx VMA is removed\n", addr); | |
| 2453 | + return true; | |
| 2454 | + } | |
| 2455 | + | |
| 2456 | + pr_debug("requested 0x%lx, vma permission flags 0x%lx\n", requested, | |
| 2457 | + vma->vm_flags); | |
| 2458 | + return (vma->vm_flags & requested) == requested; | |
| 2459 | +} | |
| 2460 | + | |
| 2403 | 2461 | int |
| 2404 | 2462 | svm_range_restore_pages(struct amdgpu_device *adev, unsigned int pasid, |
| 2405 | − uint64_t addr) | |
| 2463 | + uint64_t addr, bool write_fault) | |
| 2406 | 2464 | { |
| 2407 | 2465 | struct mm_struct *mm = NULL; |
| 2408 | 2466 | struct svm_range_list *svms; |
| @@ -2484,6 +2542,13 @@ retry_write_locked: · 75 unmodified lines | ||
| 2484 | 2542 | goto out_unlock_range; |
| 2485 | 2543 | } |
| 2486 | 2544 | |
| 2545 | + if (!svm_fault_allowed(mm, addr, write_fault)) { | |
| 2546 | + pr_debug("fault addr 0x%llx no %s permission\n", addr, | |
| 2547 | + write_fault ? "write" : "read"); | |
| 2548 | + r = -EPERM; | |
| 2549 | + goto out_unlock_range; | |
| 2550 | + } | |
| 2551 | + | |
| 2487 | 2552 | best_loc = svm_range_best_restore_location(prange, adev, &gpuidx); |
| 2488 | 2553 | if (best_loc == -1) { |
| 2489 | 2554 | pr_debug("svms %p failed get best restore loc [0x%lx 0x%lx]\n", |
| @@ -2675,22 +2740,26 @@ svm_range_add(struct kfd_process *p, uint64_t start, uint64_t size, · 185 unmodified lines | ||
| 2675 | 2740 | return 0; |
| 2676 | 2741 | } |
| 2677 | 2742 | |
| 2678 | −/* svm_range_best_prefetch_location - decide the best prefetch location | |
| 2743 | +/** | |
| 2744 | + * svm_range_best_prefetch_location - decide the best prefetch location | |
| 2679 | 2745 | * @prange: svm range structure |
| 2680 | 2746 | * |
| 2681 | 2747 | * For xnack off: |
| 2682 | − * If range map to single GPU, the best acutal location is prefetch loc, which | |
| 2748 | + * If range map to single GPU, the best prefetch location is prefetch_loc, which | |
| 2683 | 2749 | * can be CPU or GPU. |
| 2684 | 2750 | * |
| 2685 | − * If range map to multiple GPUs, only if mGPU connection on xgmi same hive, | |
| 2686 | − * the best actual location could be prefetch_loc GPU. If mGPU connection on | |
| 2687 | − * PCIe, the best actual location is always CPU, because GPU cannot access vram | |
| 2688 | − * of other GPUs, assuming PCIe small bar (large bar support is not upstream). | |
| 2751 | + * If range is ACCESS or ACCESS_IN_PLACE by mGPUs, only if mGPU connection on | |
| 2752 | + * XGMI same hive, the best prefetch location is prefetch_loc GPU, othervise | |
| 2753 | + * the best prefetch location is always CPU, because GPU can not have coherent | |
| 2754 | + * mapping VRAM of other GPUs even with large-BAR PCIe connection. | |
| 2689 | 2755 | * |
| 2690 | 2756 | * For xnack on: |
| 2691 | − * The best actual location is prefetch location. If mGPU connection on xgmi | |
| 2692 | − * same hive, range map to multiple GPUs. Otherwise, the range only map to | |
| 2693 | − * actual location GPU. Other GPU access vm fault will trigger migration. | |
| 2757 | + * If range is not ACCESS_IN_PLACE by mGPUs, the best prefetch location is | |
| 2758 | + * prefetch_loc, other GPU access will generate vm fault and trigger migration. | |
| 2759 | + * | |
| 2760 | + * If range is ACCESS_IN_PLACE by mGPUs, only if mGPU connection on XGMI same | |
| 2761 | + * hive, the best prefetch location is prefetch_loc GPU, otherwise the best | |
| 2762 | + * prefetch location is always CPU. | |
| 2694 | 2763 | * |
| 2695 | 2764 | * Context: Process context |
| 2696 | 2765 | * |
| @@ -2710,11 +2779,6 @@ svm_range_best_prefetch_location(struct svm_range *prange) · 13 unmodified lines | ||
| 2710 | 2779 | |
| 2711 | 2780 | p = container_of(prange->svms, struct kfd_process, svms); |
| 2712 | 2781 | |
| 2713 | − /* xnack on */ | |
| 2714 | − if (p->xnack_enabled) | |
| 2715 | − goto out; | |
| 2716 | − | |
| 2717 | − /* xnack off */ | |
| 2718 | 2782 | if (!best_loc || best_loc == KFD_IOCTL_SVM_LOCATION_UNDEFINED) |
| 2719 | 2783 | goto out; |
| 2720 | 2784 | |
| @@ -2724,8 +2788,12 @@ svm_range_best_prefetch_location(struct svm_range *prange) · 3 unmodified lines | ||
| 2724 | 2788 | best_loc = 0; |
| 2725 | 2789 | goto out; |
| 2726 | 2790 | } |
| 2727 | − bitmap_or(bitmap, prange->bitmap_access, prange->bitmap_aip, | |
| 2728 | − MAX_GPU_INSTANCE); | |
| 2791 | + | |
| 2792 | + if (p->xnack_enabled) | |
| 2793 | + bitmap_copy(bitmap, prange->bitmap_aip, MAX_GPU_INSTANCE); | |
| 2794 | + else | |
| 2795 | + bitmap_or(bitmap, prange->bitmap_access, prange->bitmap_aip, | |
| 2796 | + MAX_GPU_INSTANCE); | |
| 2729 | 2797 | |
| 2730 | 2798 | for_each_set_bit(gpuidx, bitmap, MAX_GPU_INSTANCE) { |
| 2731 | 2799 | pdd = kfd_process_device_from_gpuidx(p, gpuidx); |
| @@ -3019,7 +3087,8 @@ svm_range_get_attr(struct kfd_process *p, uint64_t start, uint64_t size, · 287 unmodified lines | ||
| 3019 | 3087 | struct svm_range *prange; |
| 3020 | 3088 | uint32_t prefetch_loc = KFD_IOCTL_SVM_LOCATION_UNDEFINED; |
| 3021 | 3089 | uint32_t location = KFD_IOCTL_SVM_LOCATION_UNDEFINED; |
| 3022 | − uint32_t flags = 0xffffffff; | |
| 3090 | + uint32_t flags_and = 0xffffffff; | |
| 3091 | + uint32_t flags_or = 0; | |
| 3023 | 3092 | int gpuidx; |
| 3024 | 3093 | uint32_t i; |
| 3025 | 3094 | |
| @@ -3054,12 +3123,12 @@ svm_range_get_attr(struct kfd_process *p, uint64_t start, uint64_t size, · 28 unmodified lines | ||
| 3054 | 3123 | get_accessible = true; |
| 3055 | 3124 | break; |
| 3056 | 3125 | case KFD_IOCTL_SVM_ATTR_SET_FLAGS: |
| 3126 | + case KFD_IOCTL_SVM_ATTR_CLR_FLAGS: | |
| 3057 | 3127 | get_flags = true; |
| 3058 | 3128 | break; |
| 3059 | 3129 | case KFD_IOCTL_SVM_ATTR_GRANULARITY: |
| 3060 | 3130 | get_granularity = true; |
| 3061 | 3131 | break; |
| 3062 | − case KFD_IOCTL_SVM_ATTR_CLR_FLAGS: | |
| 3063 | 3132 | case KFD_IOCTL_SVM_ATTR_ACCESS_IN_PLACE: |
| 3064 | 3133 | case KFD_IOCTL_SVM_ATTR_NO_ACCESS: |
| 3065 | 3134 | fallthrough; |
| @@ -3077,7 +3146,8 @@ svm_range_get_attr(struct kfd_process *p, uint64_t start, uint64_t size, · 11 unmodified lines | ||
| 3077 | 3146 | if (!node) { |
| 3078 | 3147 | pr_debug("range attrs not found return default values\n"); |
| 3079 | 3148 | svm_range_set_default_attributes(&location, &prefetch_loc, |
| 3080 | − &granularity, &flags); | |
| 3149 | + &granularity, &flags_and); | |
| 3150 | + flags_or = flags_and; | |
| 3081 | 3151 | if (p->xnack_enabled) |
| 3082 | 3152 | bitmap_copy(bitmap_access, svms->bitmap_supported, |
| 3083 | 3153 | MAX_GPU_INSTANCE); |
| @@ -3123,8 +3193,10 @@ svm_range_get_attr(struct kfd_process *p, uint64_t start, uint64_t size, · 39 unmodified lines | ||
| 3123 | 3193 | bitmap_and(bitmap_aip, bitmap_aip, |
| 3124 | 3194 | prange->bitmap_aip, MAX_GPU_INSTANCE); |
| 3125 | 3195 | } |
| 3126 | − if (get_flags) | |
| 3127 | − flags &= prange->flags; | |
| 3196 | + if (get_flags) { | |
| 3197 | + flags_and &= prange->flags; | |
| 3198 | + flags_or |= prange->flags; | |
| 3199 | + } | |
| 3128 | 3200 | |
| 3129 | 3201 | if (get_granularity && prange->granularity < granularity) |
| 3130 | 3202 | granularity = prange->granularity; |
| @@ -3158,7 +3230,10 @@ fill_values: · 27 unmodified lines | ||
| 3158 | 3230 | attrs[i].type = KFD_IOCTL_SVM_ATTR_NO_ACCESS; |
| 3159 | 3231 | break; |
| 3160 | 3232 | case KFD_IOCTL_SVM_ATTR_SET_FLAGS: |
| 3161 | − attrs[i].value = flags; | |
| 3233 | + attrs[i].value = flags_and; | |
| 3234 | + break; | |
| 3235 | + case KFD_IOCTL_SVM_ATTR_CLR_FLAGS: | |
| 3236 | + attrs[i].value = ~flags_or; | |
| 3162 | 3237 | break; |
| 3163 | 3238 | case KFD_IOCTL_SVM_ATTR_GRANULARITY: |
| 3164 | 3239 | attrs[i].value = (uint32_t)granularity; |
| @@ -175,7 +175,7 @@ int svm_range_split_by_granularity(struct kfd_process *p, struct mm_struct *mm, · 174 unmodified lines | ||
| 175 | 175 | unsigned long addr, struct svm_range *parent, |
| 176 | 176 | struct svm_range *prange); |
| 177 | 177 | int svm_range_restore_pages(struct amdgpu_device *adev, |
| 178 | − unsigned int pasid, uint64_t addr); | |
| 178 | + unsigned int pasid, uint64_t addr, bool write_fault); | |
| 179 | 179 | int svm_range_schedule_evict_svm_bo(struct amdgpu_amdkfd_fence *fence); |
| 180 | 180 | void svm_range_add_list_work(struct svm_range_list *svms, |
| 181 | 181 | struct svm_range *prange, struct mm_struct *mm, |
| @@ -209,7 +209,8 @@ static inline void svm_range_list_fini(struct kfd_process *p) · 27 unmodified lines | ||
| 209 | 209 | } |
| 210 | 210 | |
| 211 | 211 | static inline int svm_range_restore_pages(struct amdgpu_device *adev, |
| 212 | − unsigned int pasid, uint64_t addr) | |
| 212 | + unsigned int pasid, uint64_t addr, | |
| 213 | + bool write_fault) | |
| 213 | 214 | { |
| 214 | 215 | return -EFAULT; |
| 215 | 216 | } |
| @@ -478,6 +478,8 @@ static ssize_t node_show(struct kobject *kobj, struct attribute *attr, · 477 unmodified lines | ||
| 478 | 478 | dev->node_props.simd_per_cu); |
| 479 | 479 | sysfs_show_32bit_prop(buffer, offs, "max_slots_scratch_cu", |
| 480 | 480 | dev->node_props.max_slots_scratch_cu); |
| 481 | + sysfs_show_32bit_prop(buffer, offs, "gfx_target_version", | |
| 482 | + dev->node_props.gfx_target_version); | |
| 481 | 483 | sysfs_show_32bit_prop(buffer, offs, "vendor_id", |
| 482 | 484 | dev->node_props.vendor_id); |
| 483 | 485 | sysfs_show_32bit_prop(buffer, offs, "device_id", |
| @@ -1360,6 +1362,7 @@ int kfd_topology_add_device(struct kfd_dev *gpu) · 876 unmodified lines | ||
| 1360 | 1362 | dev->node_props.simd_arrays_per_engine = |
| 1361 | 1363 | cu_info.num_shader_arrays_per_engine; |
| 1362 | 1364 | |
| 1365 | + dev->node_props.gfx_target_version = gpu->device_info->gfx_target_version; | |
| 1363 | 1366 | dev->node_props.vendor_id = gpu->pdev->vendor; |
| 1364 | 1367 | dev->node_props.device_id = gpu->pdev->device; |
| 1365 | 1368 | dev->node_props.capability |= |
| @@ -1424,6 +1427,7 @@ int kfd_topology_add_device(struct kfd_dev *gpu) · 58 unmodified lines | ||
| 1424 | 1427 | case CHIP_DIMGREY_CAVEFISH: |
| 1425 | 1428 | case CHIP_BEIGE_GOBY: |
| 1426 | 1429 | case CHIP_YELLOW_CARP: |
| 1430 | + case CHIP_CYAN_SKILLFISH: | |
| 1427 | 1431 | dev->node_props.capability |= ((HSA_CAP_DOORBELL_TYPE_2_0 << |
| 1428 | 1432 | HSA_CAP_DOORBELL_TYPE_TOTALBITS_SHIFT) & |
| 1429 | 1433 | HSA_CAP_DOORBELL_TYPE_TOTALBITS_MASK); |
| @@ -1630,7 +1634,7 @@ int kfd_debugfs_rls_by_device(struct seq_file *m, void *data) · 200 unmodified lines | ||
| 1630 | 1634 | } |
| 1631 | 1635 | |
| 1632 | 1636 | seq_printf(m, "Node %u, gpu_id %x:\n", i++, dev->gpu->id); |
| 1633 | − r = pm_debugfs_runlist(m, &dev->gpu->dqm->packets); | |
| 1637 | + r = pm_debugfs_runlist(m, &dev->gpu->dqm->packet_mgr); | |
| 1634 | 1638 | if (r) |
| 1635 | 1639 | break; |
| 1636 | 1640 | } |
| @@ -78,6 +78,7 @@ struct kfd_node_properties { · 77 unmodified lines | ||
| 78 | 78 | uint32_t simd_per_cu; |
| 79 | 79 | uint32_t max_slots_scratch_cu; |
| 80 | 80 | uint32_t engine_id; |
| 81 | + uint32_t gfx_target_version; | |
| 81 | 82 | uint32_t vendor_id; |
| 82 | 83 | uint32_t device_id; |
| 83 | 84 | uint32_t location_id; |
| @@ -27,6 +27,10 @@ · 26 unmodified lines | ||
| 27 | 27 | |
| 28 | 28 | AMDGPUDM = amdgpu_dm.o amdgpu_dm_irq.o amdgpu_dm_mst_types.o amdgpu_dm_color.o |
| 29 | 29 | |
| 30 | +ifdef CONFIG_DRM_AMD_DC_DCN | |
| 31 | +AMDGPUDM += dc_fpu.o | |
| 32 | +endif | |
| 33 | + | |
| 30 | 34 | ifneq ($(CONFIG_DRM_AMD_DC),) |
| 31 | 35 | AMDGPUDM += amdgpu_dm_services.o amdgpu_dm_helpers.o amdgpu_dm_pp_smu.o amdgpu_dm_psr.o |
| 32 | 36 | endif |
| @@ -618,6 +618,7 @@ static void dm_dcn_vertical_interrupt0_high_irq(void *interrupt_params) · 617 unmodified lines | ||
| 618 | 618 | } |
| 619 | 619 | #endif |
| 620 | 620 | |
| 621 | +#define DMUB_TRACE_MAX_READ 64 | |
| 621 | 622 | /** |
| 622 | 623 | * dm_dmub_outbox1_low_irq() - Handles Outbox interrupt |
| 623 | 624 | * @interrupt_params: used for determining the Outbox instance |
| @@ -625,7 +626,6 @@ static void dm_dcn_vertical_interrupt0_high_irq(void *interrupt_params) · 1 unmodified line | ||
| 625 | 626 | * Handles the Outbox Interrupt |
| 626 | 627 | * event handler. |
| 627 | 628 | */ |
| 628 | −#define DMUB_TRACE_MAX_READ 64 | |
| 629 | 629 | static void dm_dmub_outbox1_low_irq(void *interrupt_params) |
| 630 | 630 | { |
| 631 | 631 | struct dmub_notification notify; |
| @@ -1044,10 +1044,10 @@ static void mmhub_read_system_context(struct amdgpu_device *adev, struct dc_phy_ · 412 unmodified lines | ||
| 1044 | 1044 | } |
| 1045 | 1045 | #endif |
| 1046 | 1046 | #if defined(CONFIG_DRM_AMD_DC_DCN) |
| 1047 | −static void event_mall_stutter(struct work_struct *work) | |
| 1047 | +static void vblank_control_worker(struct work_struct *work) | |
| 1048 | 1048 | { |
| 1049 | − | |
| 1050 | − struct vblank_workqueue *vblank_work = container_of(work, struct vblank_workqueue, mall_work); | |
| 1049 | + struct vblank_control_work *vblank_work = | |
| 1050 | + container_of(work, struct vblank_control_work, work); | |
| 1051 | 1051 | struct amdgpu_display_manager *dm = vblank_work->dm; |
| 1052 | 1052 | |
| 1053 | 1053 | mutex_lock(&dm->dc_lock); |
| @@ -1061,27 +1061,25 @@ static void event_mall_stutter(struct work_struct *work) · 7 unmodified lines | ||
| 1061 | 1061 | |
| 1062 | 1062 | DRM_DEBUG_KMS("Allow idle optimizations (MALL): %d\n", dm->active_vblank_irq_count == 0); |
| 1063 | 1063 | |
| 1064 | − mutex_unlock(&dm->dc_lock); | |
| 1065 | −} | |
| 1066 | − | |
| 1067 | −static struct vblank_workqueue *vblank_create_workqueue(struct amdgpu_device *adev, struct dc *dc) | |
| 1068 | −{ | |
| 1069 | − | |
| 1070 | − int max_caps = dc->caps.max_links; | |
| 1071 | − struct vblank_workqueue *vblank_work; | |
| 1072 | − int i = 0; | |
| 1073 | − | |
| 1074 | − vblank_work = kcalloc(max_caps, sizeof(*vblank_work), GFP_KERNEL); | |
| 1075 | − if (ZERO_OR_NULL_PTR(vblank_work)) { | |
| 1076 | − kfree(vblank_work); | |
| 1077 | − return NULL; | |
| 1064 | + /* Control PSR based on vblank requirements from OS */ | |
| 1065 | + if (vblank_work->stream && vblank_work->stream->link) { | |
| 1066 | + if (vblank_work->enable) { | |
| 1067 | + if (vblank_work->stream->link->psr_settings.psr_allow_active) | |
| 1068 | + amdgpu_dm_psr_disable(vblank_work->stream); | |
| 1069 | + } else if (vblank_work->stream->link->psr_settings.psr_feature_enabled && | |
| 1070 | + !vblank_work->stream->link->psr_settings.psr_allow_active && | |
| 1071 | + vblank_work->acrtc->dm_irq_params.allow_psr_entry) { | |
| 1072 | + amdgpu_dm_psr_enable(vblank_work->stream); | |
| 1073 | + } | |
| 1078 | 1074 | } |
| 1079 | 1075 | |
| 1080 | − for (i = 0; i < max_caps; i++) | |
| 1081 | − INIT_WORK(&vblank_work[i].mall_work, event_mall_stutter); | |
| 1076 | + mutex_unlock(&dm->dc_lock); | |
| 1077 | + | |
| 1078 | + dc_stream_release(vblank_work->stream); | |
| 1082 | 1079 | |
| 1083 | − return vblank_work; | |
| 1080 | + kfree(vblank_work); | |
| 1084 | 1081 | } |
| 1082 | + | |
| 1085 | 1083 | #endif |
| 1086 | 1084 | static int amdgpu_dm_init(struct amdgpu_device *adev) |
| 1087 | 1085 | { |
| @@ -1224,12 +1222,10 @@ static int amdgpu_dm_init(struct amdgpu_device *adev) · 136 unmodified lines | ||
| 1224 | 1222 | |
| 1225 | 1223 | #if defined(CONFIG_DRM_AMD_DC_DCN) |
| 1226 | 1224 | if (adev->dm.dc->caps.max_links > 0) { |
| 1227 | − adev->dm.vblank_workqueue = vblank_create_workqueue(adev, adev->dm.dc); | |
| 1228 | − | |
| 1229 | − if (!adev->dm.vblank_workqueue) | |
| 1225 | + adev->dm.vblank_control_workqueue = | |
| 1226 | + create_singlethread_workqueue("dm_vblank_control_workqueue"); | |
| 1227 | + if (!adev->dm.vblank_control_workqueue) | |
| 1230 | 1228 | DRM_ERROR("amdgpu: failed to initialize vblank_workqueue.\n"); |
| 1231 | − else | |
| 1232 | − DRM_DEBUG_DRIVER("amdgpu: vblank_workqueue init done %p.\n", adev->dm.vblank_workqueue); | |
| 1233 | 1229 | } |
| 1234 | 1230 | #endif |
| 1235 | 1231 | |
| @@ -1302,6 +1298,13 @@ static void amdgpu_dm_fini(struct amdgpu_device *adev) · 66 unmodified lines | ||
| 1302 | 1298 | { |
| 1303 | 1299 | int i; |
| 1304 | 1300 | |
| 1301 | +#if defined(CONFIG_DRM_AMD_DC_DCN) | |
| 1302 | + if (adev->dm.vblank_control_workqueue) { | |
| 1303 | + destroy_workqueue(adev->dm.vblank_control_workqueue); | |
| 1304 | + adev->dm.vblank_control_workqueue = NULL; | |
| 1305 | + } | |
| 1306 | +#endif | |
| 1307 | + | |
| 1305 | 1308 | for (i = 0; i < adev->dm.display_indexes_num; i++) { |
| 1306 | 1309 | drm_encoder_cleanup(&adev->dm.mst_encoders[i].base); |
| 1307 | 1310 | } |
| @@ -1325,14 +1328,6 @@ static void amdgpu_dm_fini(struct amdgpu_device *adev) · 17 unmodified lines | ||
| 1325 | 1328 | dc_deinit_callbacks(adev->dm.dc); |
| 1326 | 1329 | #endif |
| 1327 | 1330 | |
| 1328 | −#if defined(CONFIG_DRM_AMD_DC_DCN) | |
| 1329 | − if (adev->dm.vblank_workqueue) { | |
| 1330 | − adev->dm.vblank_workqueue->dm = NULL; | |
| 1331 | − kfree(adev->dm.vblank_workqueue); | |
| 1332 | − adev->dm.vblank_workqueue = NULL; | |
| 1333 | − } | |
| 1334 | −#endif | |
| 1335 | − | |
| 1336 | 1331 | dc_dmub_srv_destroy(&adev->dm.dc->ctx->dmub_srv); |
| 1337 | 1332 | |
| 1338 | 1333 | if (dc_enable_dmub_notifications(adev->dm.dc)) { |
| @@ -2412,6 +2407,7 @@ static void update_connector_ext_caps(struct amdgpu_dm_connector *aconnector) · 1073 unmodified lines | ||
| 2412 | 2407 | static const u8 pre_computed_values[] = { |
| 2413 | 2408 | 50, 51, 52, 53, 55, 56, 57, 58, 59, 61, 62, 63, 65, 66, 68, 69, |
| 2414 | 2409 | 71, 72, 74, 75, 77, 79, 81, 82, 84, 86, 88, 90, 92, 94, 96, 98}; |
| 2410 | + int i; | |
| 2415 | 2411 | |
| 2416 | 2412 | if (!aconnector || !aconnector->dc_link) |
| 2417 | 2413 | return; |
| @@ -2423,7 +2419,13 @@ static void update_connector_ext_caps(struct amdgpu_dm_connector *aconnector) · 5 unmodified lines | ||
| 2423 | 2419 | conn_base = &aconnector->base; |
| 2424 | 2420 | adev = drm_to_adev(conn_base->dev); |
| 2425 | 2421 | dm = &adev->dm; |
| 2426 | − caps = &dm->backlight_caps; | |
| 2422 | + for (i = 0; i < dm->num_of_edps; i++) { | |
| 2423 | + if (link == dm->backlight_link[i]) | |
| 2424 | + break; | |
| 2425 | + } | |
| 2426 | + if (i >= dm->num_of_edps) | |
| 2427 | + return; | |
| 2428 | + caps = &dm->backlight_caps[i]; | |
| 2427 | 2429 | caps->ext_caps = &aconnector->dc_link->dpcd_sink_ext_caps; |
| 2428 | 2430 | caps->aux_support = false; |
| 2429 | 2431 | max_cll = conn_base->hdr_sink_metadata.hdmi_type1.max_cll; |
| @@ -3423,35 +3425,36 @@ static int amdgpu_dm_mode_config_init(struct amdgpu_device *adev) · 993 unmodified lines | ||
| 3423 | 3425 | #if defined(CONFIG_BACKLIGHT_CLASS_DEVICE) ||\ |
| 3424 | 3426 | defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE) |
| 3425 | 3427 | |
| 3426 | −static void amdgpu_dm_update_backlight_caps(struct amdgpu_display_manager *dm) | |
| 3428 | +static void amdgpu_dm_update_backlight_caps(struct amdgpu_display_manager *dm, | |
| 3429 | + int bl_idx) | |
| 3427 | 3430 | { |
| 3428 | 3431 | #if defined(CONFIG_ACPI) |
| 3429 | 3432 | struct amdgpu_dm_backlight_caps caps; |
| 3430 | 3433 | |
| 3431 | 3434 | memset(&caps, 0, sizeof(caps)); |
| 3432 | 3435 | |
| 3433 | − if (dm->backlight_caps.caps_valid) | |
| 3436 | + if (dm->backlight_caps[bl_idx].caps_valid) | |
| 3434 | 3437 | return; |
| 3435 | 3438 | |
| 3436 | 3439 | amdgpu_acpi_get_backlight_caps(&caps); |
| 3437 | 3440 | if (caps.caps_valid) { |
| 3438 | − dm->backlight_caps.caps_valid = true; | |
| 3441 | + dm->backlight_caps[bl_idx].caps_valid = true; | |
| 3439 | 3442 | if (caps.aux_support) |
| 3440 | 3443 | return; |
| 3441 | − dm->backlight_caps.min_input_signal = caps.min_input_signal; | |
| 3442 | − dm->backlight_caps.max_input_signal = caps.max_input_signal; | |
| 3444 | + dm->backlight_caps[bl_idx].min_input_signal = caps.min_input_signal; | |
| 3445 | + dm->backlight_caps[bl_idx].max_input_signal = caps.max_input_signal; | |
| 3443 | 3446 | } else { |
| 3444 | − dm->backlight_caps.min_input_signal = | |
| 3447 | + dm->backlight_caps[bl_idx].min_input_signal = | |
| 3445 | 3448 | AMDGPU_DM_DEFAULT_MIN_BACKLIGHT; |
| 3446 | − dm->backlight_caps.max_input_signal = | |
| 3449 | + dm->backlight_caps[bl_idx].max_input_signal = | |
| 3447 | 3450 | AMDGPU_DM_DEFAULT_MAX_BACKLIGHT; |
| 3448 | 3451 | } |
| 3449 | 3452 | #else |
| 3450 | − if (dm->backlight_caps.aux_support) | |
| 3453 | + if (dm->backlight_caps[bl_idx].aux_support) | |
| 3451 | 3454 | return; |
| 3452 | 3455 | |
| 3453 | − dm->backlight_caps.min_input_signal = AMDGPU_DM_DEFAULT_MIN_BACKLIGHT; | |
| 3454 | − dm->backlight_caps.max_input_signal = AMDGPU_DM_DEFAULT_MAX_BACKLIGHT; | |
| 3456 | + dm->backlight_caps[bl_idx].min_input_signal = AMDGPU_DM_DEFAULT_MIN_BACKLIGHT; | |
| 3457 | + dm->backlight_caps[bl_idx].max_input_signal = AMDGPU_DM_DEFAULT_MAX_BACKLIGHT; | |
| 3455 | 3458 | #endif |
| 3456 | 3459 | } |
| 3457 | 3460 | |
| @@ -3502,41 +3505,31 @@ static u32 convert_brightness_to_user(const struct amdgpu_dm_backlight_caps *cap · 44 unmodified lines | ||
| 3502 | 3505 | } |
| 3503 | 3506 | |
| 3504 | 3507 | static int amdgpu_dm_backlight_set_level(struct amdgpu_display_manager *dm, |
| 3508 | + int bl_idx, | |
| 3505 | 3509 | u32 user_brightness) |
| 3506 | 3510 | { |
| 3507 | 3511 | struct amdgpu_dm_backlight_caps caps; |
| 3508 | − struct dc_link *link[AMDGPU_DM_MAX_NUM_EDP]; | |
| 3509 | − u32 brightness[AMDGPU_DM_MAX_NUM_EDP]; | |
| 3512 | + struct dc_link *link; | |
| 3513 | + u32 brightness; | |
| 3510 | 3514 | bool rc; |
| 3511 | − int i; | |
| 3512 | 3515 | |
| 3513 | − amdgpu_dm_update_backlight_caps(dm); | |
| 3514 | − caps = dm->backlight_caps; | |
| 3516 | + amdgpu_dm_update_backlight_caps(dm, bl_idx); | |
| 3517 | + caps = dm->backlight_caps[bl_idx]; | |
| 3515 | 3518 | |
| 3516 | − for (i = 0; i < dm->num_of_edps; i++) { | |
| 3517 | − dm->brightness[i] = user_brightness; | |
| 3518 | − brightness[i] = convert_brightness_from_user(&caps, dm->brightness[i]); | |
| 3519 | − link[i] = (struct dc_link *)dm->backlight_link[i]; | |
| 3520 | − } | |
| 3519 | + dm->brightness[bl_idx] = user_brightness; | |
| 3520 | + brightness = convert_brightness_from_user(&caps, dm->brightness[bl_idx]); | |
| 3521 | + link = (struct dc_link *)dm->backlight_link[bl_idx]; | |
| 3521 | 3522 | |
| 3522 | 3523 | /* Change brightness based on AUX property */ |
| 3523 | 3524 | if (caps.aux_support) { |
| 3524 | − for (i = 0; i < dm->num_of_edps; i++) { | |
| 3525 | − rc = dc_link_set_backlight_level_nits(link[i], true, brightness[i], | |
| 3526 | − AUX_BL_DEFAULT_TRANSITION_TIME_MS); | |
| 3527 | − if (!rc) { | |
| 3528 | − DRM_DEBUG("DM: Failed to update backlight via AUX on eDP[%d]\n", i); | |
| 3529 | − break; | |
| 3530 | − } | |
| 3531 | − } | |
| 3525 | + rc = dc_link_set_backlight_level_nits(link, true, brightness, | |
| 3526 | + AUX_BL_DEFAULT_TRANSITION_TIME_MS); | |
| 3527 | + if (!rc) | |
| 3528 | + DRM_DEBUG("DM: Failed to update backlight via AUX on eDP[%d]\n", bl_idx); | |
| 3532 | 3529 | } else { |
| 3533 | − for (i = 0; i < dm->num_of_edps; i++) { | |
| 3534 | − rc = dc_link_set_backlight_level(dm->backlight_link[i], brightness[i], 0); | |
| 3535 | − if (!rc) { | |
| 3536 | − DRM_DEBUG("DM: Failed to update backlight on eDP[%d]\n", i); | |
| 3537 | − break; | |
| 3538 | − } | |
| 3539 | − } | |
| 3530 | + rc = dc_link_set_backlight_level(link, brightness, 0); | |
| 3531 | + if (!rc) | |
| 3532 | + DRM_DEBUG("DM: Failed to update backlight on eDP[%d]\n", bl_idx); | |
| 3540 | 3533 | } |
| 3541 | 3534 | |
| 3542 | 3535 | return rc ? 0 : 1; |
| @@ -3545,33 +3538,41 @@ static int amdgpu_dm_backlight_set_level(struct amdgpu_display_manager *dm, · 2 unmodified lines | ||
| 3545 | 3538 | static int amdgpu_dm_backlight_update_status(struct backlight_device *bd) |
| 3546 | 3539 | { |
| 3547 | 3540 | struct amdgpu_display_manager *dm = bl_get_data(bd); |
| 3541 | + int i; | |
| 3548 | 3542 | |
| 3549 | − amdgpu_dm_backlight_set_level(dm, bd->props.brightness); | |
| 3543 | + for (i = 0; i < dm->num_of_edps; i++) { | |
| 3544 | + if (bd == dm->backlight_dev[i]) | |
| 3545 | + break; | |
| 3546 | + } | |
| 3547 | + if (i >= AMDGPU_DM_MAX_NUM_EDP) | |
| 3548 | + i = 0; | |
| 3549 | + amdgpu_dm_backlight_set_level(dm, i, bd->props.brightness); | |
| 3550 | 3550 | |
| 3551 | 3551 | return 0; |
| 3552 | 3552 | } |
| 3553 | 3553 | |
| 3554 | −static u32 amdgpu_dm_backlight_get_level(struct amdgpu_display_manager *dm) | |
| 3554 | +static u32 amdgpu_dm_backlight_get_level(struct amdgpu_display_manager *dm, | |
| 3555 | + int bl_idx) | |
| 3555 | 3556 | { |
| 3556 | 3557 | struct amdgpu_dm_backlight_caps caps; |
| 3558 | + struct dc_link *link = (struct dc_link *)dm->backlight_link[bl_idx]; | |
| 3557 | 3559 | |
| 3558 | − amdgpu_dm_update_backlight_caps(dm); | |
| 3559 | − caps = dm->backlight_caps; | |
| 3560 | + amdgpu_dm_update_backlight_caps(dm, bl_idx); | |
| 3561 | + caps = dm->backlight_caps[bl_idx]; | |
| 3560 | 3562 | |
| 3561 | 3563 | if (caps.aux_support) { |
| 3562 | − struct dc_link *link = (struct dc_link *)dm->backlight_link[0]; | |
| 3563 | 3564 | u32 avg, peak; |
| 3564 | 3565 | bool rc; |
| 3565 | 3566 | |
| 3566 | 3567 | rc = dc_link_get_backlight_level_nits(link, &avg, &peak); |
| 3567 | 3568 | if (!rc) |
| 3568 | − return dm->brightness[0]; | |
| 3569 | + return dm->brightness[bl_idx]; | |
| 3569 | 3570 | return convert_brightness_to_user(&caps, avg); |
| 3570 | 3571 | } else { |
| 3571 | − int ret = dc_link_get_backlight_level(dm->backlight_link[0]); | |
| 3572 | + int ret = dc_link_get_backlight_level(link); | |
| 3572 | 3573 | |
| 3573 | 3574 | if (ret == DC_ERROR_UNEXPECTED) |
| 3574 | − return dm->brightness[0]; | |
| 3575 | + return dm->brightness[bl_idx]; | |
| 3575 | 3576 | return convert_brightness_to_user(&caps, ret); |
| 3576 | 3577 | } |
| 3577 | 3578 | } |
| @@ -3579,8 +3580,15 @@ static u32 amdgpu_dm_backlight_get_level(struct amdgpu_display_manager *dm) · 1 unmodified line | ||
| 3579 | 3580 | static int amdgpu_dm_backlight_get_brightness(struct backlight_device *bd) |
| 3580 | 3581 | { |
| 3581 | 3582 | struct amdgpu_display_manager *dm = bl_get_data(bd); |
| 3583 | + int i; | |
| 3582 | 3584 | |
| 3583 | − return amdgpu_dm_backlight_get_level(dm); | |
| 3585 | + for (i = 0; i < dm->num_of_edps; i++) { | |
| 3586 | + if (bd == dm->backlight_dev[i]) | |
| 3587 | + break; | |
| 3588 | + } | |
| 3589 | + if (i >= AMDGPU_DM_MAX_NUM_EDP) | |
| 3590 | + i = 0; | |
| 3591 | + return amdgpu_dm_backlight_get_level(dm, i); | |
| 3584 | 3592 | } |
| 3585 | 3593 | |
| 3586 | 3594 | static const struct backlight_ops amdgpu_dm_backlight_ops = { |
| @@ -3594,31 +3602,28 @@ amdgpu_dm_register_backlight_device(struct amdgpu_display_manager *dm) · 7 unmodified lines | ||
| 3594 | 3602 | { |
| 3595 | 3603 | char bl_name[16]; |
| 3596 | 3604 | struct backlight_properties props = { 0 }; |
| 3597 | − int i; | |
| 3598 | 3605 | |
| 3599 | − amdgpu_dm_update_backlight_caps(dm); | |
| 3600 | − for (i = 0; i < dm->num_of_edps; i++) | |
| 3601 | − dm->brightness[i] = AMDGPU_MAX_BL_LEVEL; | |
| 3606 | + amdgpu_dm_update_backlight_caps(dm, dm->num_of_edps); | |
| 3607 | + dm->brightness[dm->num_of_edps] = AMDGPU_MAX_BL_LEVEL; | |
| 3602 | 3608 | |
| 3603 | 3609 | props.max_brightness = AMDGPU_MAX_BL_LEVEL; |
| 3604 | 3610 | props.brightness = AMDGPU_MAX_BL_LEVEL; |
| 3605 | 3611 | props.type = BACKLIGHT_RAW; |
| 3606 | 3612 | |
| 3607 | 3613 | snprintf(bl_name, sizeof(bl_name), "amdgpu_bl%d", |
| 3608 | − adev_to_drm(dm->adev)->primary->index); | |
| 3614 | + adev_to_drm(dm->adev)->primary->index + dm->num_of_edps); | |
| 3609 | 3615 | |
| 3610 | − dm->backlight_dev = backlight_device_register(bl_name, | |
| 3611 | − adev_to_drm(dm->adev)->dev, | |
| 3612 | − dm, | |
| 3613 | − &amdgpu_dm_backlight_ops, | |
| 3614 | − &props); | |
| 3616 | + dm->backlight_dev[dm->num_of_edps] = backlight_device_register(bl_name, | |
| 3617 | + adev_to_drm(dm->adev)->dev, | |
| 3618 | + dm, | |
| 3619 | + &amdgpu_dm_backlight_ops, | |
| 3620 | + &props); | |
| 3615 | 3621 | |
| 3616 | − if (IS_ERR(dm->backlight_dev)) | |
| 3622 | + if (IS_ERR(dm->backlight_dev[dm->num_of_edps])) | |
| 3617 | 3623 | DRM_ERROR("DM: Backlight registration failed!\n"); |
| 3618 | 3624 | else |
| 3619 | 3625 | DRM_DEBUG_DRIVER("DM: Registered Backlight device: %s\n", bl_name); |
| 3620 | 3626 | } |
| 3621 | − | |
| 3622 | 3627 | #endif |
| 3623 | 3628 | |
| 3624 | 3629 | static int initialize_plane(struct amdgpu_display_manager *dm, |
| @@ -3675,10 +3680,10 @@ static void register_backlight_device(struct amdgpu_display_manager *dm, · 50 unmodified lines | ||
| 3675 | 3680 | * DM initialization because not having a backlight control |
| 3676 | 3681 | * is better then a black screen. |
| 3677 | 3682 | */ |
| 3678 | − if (!dm->backlight_dev) | |
| 3683 | + if (!dm->backlight_dev[dm->num_of_edps]) | |
| 3679 | 3684 | amdgpu_dm_register_backlight_device(dm); |
| 3680 | 3685 | |
| 3681 | − if (dm->backlight_dev) { | |
| 3686 | + if (dm->backlight_dev[dm->num_of_edps]) { | |
| 3682 | 3687 | dm->backlight_link[dm->num_of_edps] = link; |
| 3683 | 3688 | dm->num_of_edps++; |
| 3684 | 3689 | } |
| @@ -4747,7 +4752,7 @@ fill_gfx9_plane_attributes_from_modifiers(struct amdgpu_device *adev, · 1062 unmodified lines | ||
| 4747 | 4752 | const bool force_disable_dcc) |
| 4748 | 4753 | { |
| 4749 | 4754 | const uint64_t modifier = afb->base.modifier; |
| 4750 | − int ret; | |
| 4755 | + int ret = 0; | |
| 4751 | 4756 | |
| 4752 | 4757 | fill_gfx9_tiling_info_from_modifier(adev, tiling_info, modifier); |
| 4753 | 4758 | tiling_info->gfx9.swizzle = modifier_gfx9_swizzle_mode(modifier); |
| @@ -4765,9 +4770,9 @@ fill_gfx9_plane_attributes_from_modifiers(struct amdgpu_device *adev, · 11 unmodified lines | ||
| 4765 | 4770 | |
| 4766 | 4771 | ret = validate_dcc(adev, format, rotation, tiling_info, dcc, address, plane_size); |
| 4767 | 4772 | if (ret) |
| 4768 | − return ret; | |
| 4773 | + drm_dbg_kms(adev_to_drm(adev), "validate_dcc: returned error: %d\n", ret); | |
| 4769 | 4774 | |
| 4770 | − return 0; | |
| 4775 | + return ret; | |
| 4771 | 4776 | } |
| 4772 | 4777 | |
| 4773 | 4778 | static int |
| @@ -5994,7 +5999,7 @@ static inline int dm_set_vblank(struct drm_crtc *crtc, bool enable) · 1220 unmodified lines | ||
| 5994 | 5999 | struct dm_crtc_state *acrtc_state = to_dm_crtc_state(crtc->state); |
| 5995 | 6000 | #if defined(CONFIG_DRM_AMD_DC_DCN) |
| 5996 | 6001 | struct amdgpu_display_manager *dm = &adev->dm; |
| 5997 | − unsigned long flags; | |
| 6002 | + struct vblank_control_work *work; | |
| 5998 | 6003 | #endif |
| 5999 | 6004 | int rc = 0; |
| 6000 | 6005 | |
| @@ -6019,12 +6024,21 @@ static inline int dm_set_vblank(struct drm_crtc *crtc, bool enable) · 18 unmodified lines | ||
| 6019 | 6024 | return 0; |
| 6020 | 6025 | |
| 6021 | 6026 | #if defined(CONFIG_DRM_AMD_DC_DCN) |
| 6022 | − spin_lock_irqsave(&dm->vblank_lock, flags); | |
| 6023 | − dm->vblank_workqueue->dm = dm; | |
| 6024 | − dm->vblank_workqueue->otg_inst = acrtc->otg_inst; | |
| 6025 | − dm->vblank_workqueue->enable = enable; | |
| 6026 | − spin_unlock_irqrestore(&dm->vblank_lock, flags); | |
| 6027 | − schedule_work(&dm->vblank_workqueue->mall_work); | |
| 6027 | + work = kzalloc(sizeof(*work), GFP_ATOMIC); | |
| 6028 | + if (!work) | |
| 6029 | + return -ENOMEM; | |
| 6030 | + | |
| 6031 | + INIT_WORK(&work->work, vblank_control_worker); | |
| 6032 | + work->dm = dm; | |
| 6033 | + work->acrtc = acrtc; | |
| 6034 | + work->enable = enable; | |
| 6035 | + | |
| 6036 | + if (acrtc_state->stream) { | |
| 6037 | + dc_stream_retain(acrtc_state->stream); | |
| 6038 | + work->stream = acrtc_state->stream; | |
| 6039 | + } | |
| 6040 | + | |
| 6041 | + queue_work(dm->vblank_control_workqueue, &work->work); | |
| 6028 | 6042 | #endif |
| 6029 | 6043 | |
| 6030 | 6044 | return 0; |
| @@ -6198,6 +6212,7 @@ static void amdgpu_dm_connector_destroy(struct drm_connector *connector) · 167 unmodified lines | ||
| 6198 | 6212 | const struct dc_link *link = aconnector->dc_link; |
| 6199 | 6213 | struct amdgpu_device *adev = drm_to_adev(connector->dev); |
| 6200 | 6214 | struct amdgpu_display_manager *dm = &adev->dm; |
| 6215 | + int i; | |
| 6201 | 6216 | |
| 6202 | 6217 | /* |
| 6203 | 6218 | * Call only if mst_mgr was iniitalized before since it's not done |
| @@ -6208,12 +6223,11 @@ static void amdgpu_dm_connector_destroy(struct drm_connector *connector) · 4 unmodified lines | ||
| 6208 | 6223 | |
| 6209 | 6224 | #if defined(CONFIG_BACKLIGHT_CLASS_DEVICE) ||\ |
| 6210 | 6225 | defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE) |
| 6211 | − | |
| 6212 | − if ((link->connector_signal & (SIGNAL_TYPE_EDP | SIGNAL_TYPE_LVDS)) && | |
| 6213 | − link->type != dc_connection_none && | |
| 6214 | − dm->backlight_dev) { | |
| 6215 | − backlight_device_unregister(dm->backlight_dev); | |
| 6216 | − dm->backlight_dev = NULL; | |
| 6226 | + for (i = 0; i < dm->num_of_edps; i++) { | |
| 6227 | + if ((link == dm->backlight_link[i]) && dm->backlight_dev[i]) { | |
| 6228 | + backlight_device_unregister(dm->backlight_dev[i]); | |
| 6229 | + dm->backlight_dev[i] = NULL; | |
| 6230 | + } | |
| 6217 | 6231 | } |
| 6218 | 6232 | #endif |
| 6219 | 6233 | |
| @@ -7570,8 +7584,10 @@ static uint add_fs_modes(struct amdgpu_dm_connector *aconnector) · 1350 unmodified lines | ||
| 7570 | 7584 | * 60 - Commonly used |
| 7571 | 7585 | * 48,72,96 - Multiples of 24 |
| 7572 | 7586 | */ |
| 7573 | − const uint32_t common_rates[] = { 23976, 24000, 25000, 29970, 30000, | |
| 7574 | − 48000, 50000, 60000, 72000, 96000 }; | |
| 7587 | + static const uint32_t common_rates[] = { | |
| 7588 | + 23976, 24000, 25000, 29970, 30000, | |
| 7589 | + 48000, 50000, 60000, 72000, 96000 | |
| 7590 | + }; | |
| 7575 | 7591 | |
| 7576 | 7592 | /* |
| 7577 | 7593 | * Find mode with highest refresh rate with the same resolution |
| @@ -8627,6 +8643,14 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state, · 1049 unmodified lines | ||
| 8627 | 8643 | /* Update the planes if changed or disable if we don't have any. */ |
| 8628 | 8644 | if ((planes_count || acrtc_state->active_planes == 0) && |
| 8629 | 8645 | acrtc_state->stream) { |
| 8646 | +#if defined(CONFIG_DRM_AMD_DC_DCN) | |
| 8647 | + /* | |
| 8648 | + * If PSR or idle optimizations are enabled then flush out | |
| 8649 | + * any pending work before hardware programming. | |
| 8650 | + */ | |
| 8651 | + flush_workqueue(dm->vblank_control_workqueue); | |
| 8652 | +#endif | |
| 8653 | + | |
| 8630 | 8654 | bundle->stream_update.stream = acrtc_state->stream; |
| 8631 | 8655 | if (new_pcrtc_state->mode_changed) { |
| 8632 | 8656 | bundle->stream_update.src = acrtc_state->stream->src; |
| @@ -8695,16 +8719,20 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state, · 62 unmodified lines | ||
| 8695 | 8719 | acrtc_state->stream->link->psr_settings.psr_version != DC_PSR_VERSION_UNSUPPORTED && |
| 8696 | 8720 | !acrtc_state->stream->link->psr_settings.psr_feature_enabled) |
| 8697 | 8721 | amdgpu_dm_link_setup_psr(acrtc_state->stream); |
| 8698 | − else if ((acrtc_state->update_type == UPDATE_TYPE_FAST) && | |
| 8699 | − acrtc_state->stream->link->psr_settings.psr_feature_enabled && | |
| 8700 | − !acrtc_state->stream->link->psr_settings.psr_allow_active) { | |
| 8701 | − struct amdgpu_dm_connector *aconn = (struct amdgpu_dm_connector *) | |
| 8702 | − acrtc_state->stream->dm_stream_context; | |
| 8722 | + | |
| 8723 | + /* Decrement skip count when PSR is enabled and we're doing fast updates. */ | |
| 8724 | + if (acrtc_state->update_type == UPDATE_TYPE_FAST && | |
| 8725 | + acrtc_state->stream->link->psr_settings.psr_feature_enabled) { | |
| 8726 | + struct amdgpu_dm_connector *aconn = | |
| 8727 | + (struct amdgpu_dm_connector *)acrtc_state->stream->dm_stream_context; | |
| 8703 | 8728 | |
| 8704 | 8729 | if (aconn->psr_skip_count > 0) |
| 8705 | 8730 | aconn->psr_skip_count--; |
| 8706 | − else | |
| 8707 | − amdgpu_dm_psr_enable(acrtc_state->stream); | |
| 8731 | + | |
| 8732 | + /* Allow PSR when skip count is 0. */ | |
| 8733 | + acrtc_attach->dm_irq_params.allow_psr_entry = !aconn->psr_skip_count; | |
| 8734 | + } else { | |
| 8735 | + acrtc_attach->dm_irq_params.allow_psr_entry = false; | |
| 8708 | 8736 | } |
| 8709 | 8737 | |
| 8710 | 8738 | mutex_unlock(&dm->dc_lock); |
| @@ -8953,8 +8981,12 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state) · 242 unmodified lines | ||
| 8953 | 8981 | |
| 8954 | 8982 | if (dc_state) { |
| 8955 | 8983 | /* if there mode set or reset, disable eDP PSR */ |
| 8956 | − if (mode_set_reset_required) | |
| 8984 | + if (mode_set_reset_required) { | |
| 8985 | +#if defined(CONFIG_DRM_AMD_DC_DCN) | |
| 8986 | + flush_workqueue(dm->vblank_control_workqueue); | |
| 8987 | +#endif | |
| 8957 | 8988 | amdgpu_dm_psr_disable_all(dm); |
| 8989 | + } | |
| 8958 | 8990 | |
| 8959 | 8991 | dm_enable_per_frame_crtc_master_sync(dc_state); |
| 8960 | 8992 | mutex_lock(&dm->dc_lock); |
| @@ -9191,8 +9223,11 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state) · 230 unmodified lines | ||
| 9191 | 9223 | #if defined(CONFIG_BACKLIGHT_CLASS_DEVICE) || \ |
| 9192 | 9224 | defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE) |
| 9193 | 9225 | /* restore the backlight level */ |
| 9194 | − if (dm->backlight_dev && (amdgpu_dm_backlight_get_level(dm) != dm->brightness[0])) | |
| 9195 | − amdgpu_dm_backlight_set_level(dm, dm->brightness[0]); | |
| 9226 | + for (i = 0; i < dm->num_of_edps; i++) { | |
| 9227 | + if (dm->backlight_dev[i] && | |
| 9228 | + (amdgpu_dm_backlight_get_level(dm, i) != dm->brightness[i])) | |
| 9229 | + amdgpu_dm_backlight_set_level(dm, i, dm->brightness[i]); | |
| 9230 | + } | |
| 9196 | 9231 | #endif |
| 9197 | 9232 | /* |
| 9198 | 9233 | * send vblank event on all events not handled in flip and |
| @@ -10554,13 +10589,68 @@ static bool is_dp_capable_without_timing_msa(struct dc *dc, · 1355 unmodified lines | ||
| 10554 | 10589 | return capable; |
| 10555 | 10590 | } |
| 10556 | 10591 | |
| 10557 | −static bool parse_edid_cea(struct amdgpu_dm_connector *aconnector, | |
| 10592 | +static bool dm_edid_parser_send_cea(struct amdgpu_display_manager *dm, | |
| 10593 | + unsigned int offset, | |
| 10594 | + unsigned int total_length, | |
| 10595 | + uint8_t *data, | |
| 10596 | + unsigned int length, | |
| 10597 | + struct amdgpu_hdmi_vsdb_info *vsdb) | |
| 10598 | +{ | |
| 10599 | + bool res; | |
| 10600 | + union dmub_rb_cmd cmd; | |
| 10601 | + struct dmub_cmd_send_edid_cea *input; | |
| 10602 | + struct dmub_cmd_edid_cea_output *output; | |
| 10603 | + | |
| 10604 | + if (length > DMUB_EDID_CEA_DATA_CHUNK_BYTES) | |
| 10605 | + return false; | |
| 10606 | + | |
| 10607 | + memset(&cmd, 0, sizeof(cmd)); | |
| 10608 | + | |
| 10609 | + input = &cmd.edid_cea.data.input; | |
| 10610 | + | |
| 10611 | + cmd.edid_cea.header.type = DMUB_CMD__EDID_CEA; | |
| 10612 | + cmd.edid_cea.header.sub_type = 0; | |
| 10613 | + cmd.edid_cea.header.payload_bytes = | |
| 10614 | + sizeof(cmd.edid_cea) - sizeof(cmd.edid_cea.header); | |
| 10615 | + input->offset = offset; | |
| 10616 | + input->length = length; | |
| 10617 | + input->total_length = total_length; | |
| 10618 | + memcpy(input->payload, data, length); | |
| 10619 | + | |
| 10620 | + res = dc_dmub_srv_cmd_with_reply_data(dm->dc->ctx->dmub_srv, &cmd); | |
| 10621 | + if (!res) { | |
| 10622 | + DRM_ERROR("EDID CEA parser failed\n"); | |
| 10623 | + return false; | |
| 10624 | + } | |
| 10625 | + | |
| 10626 | + output = &cmd.edid_cea.data.output; | |
| 10627 | + | |
| 10628 | + if (output->type == DMUB_CMD__EDID_CEA_ACK) { | |
| 10629 | + if (!output->ack.success) { | |
| 10630 | + DRM_ERROR("EDID CEA ack failed at offset %d\n", | |
| 10631 | + output->ack.offset); | |
| 10632 | + } | |
| 10633 | + } else if (output->type == DMUB_CMD__EDID_CEA_AMD_VSDB) { | |
| 10634 | + if (!output->amd_vsdb.vsdb_found) | |
| 10635 | + return false; | |
| 10636 | + | |
| 10637 | + vsdb->freesync_supported = output->amd_vsdb.freesync_supported; | |
| 10638 | + vsdb->amd_vsdb_version = output->amd_vsdb.amd_vsdb_version; | |
| 10639 | + vsdb->min_refresh_rate_hz = output->amd_vsdb.min_frame_rate; | |
| 10640 | + vsdb->max_refresh_rate_hz = output->amd_vsdb.max_frame_rate; | |
| 10641 | + } else { | |
| 10642 | + DRM_WARN("Unknown EDID CEA parser results\n"); | |
| 10643 | + return false; | |
| 10644 | + } | |
| 10645 | + | |
| 10646 | + return true; | |
| 10647 | +} | |
| 10648 | + | |
| 10649 | +static bool parse_edid_cea_dmcu(struct amdgpu_display_manager *dm, | |
| 10558 | 10650 | uint8_t *edid_ext, int len, |
| 10559 | 10651 | struct amdgpu_hdmi_vsdb_info *vsdb_info) |
| 10560 | 10652 | { |
| 10561 | 10653 | int i; |
| 10562 | − struct amdgpu_device *adev = drm_to_adev(aconnector->base.dev); | |
| 10563 | − struct dc *dc = adev->dm.dc; | |
| 10564 | 10654 | |
| 10565 | 10655 | /* send extension block to DMCU for parsing */ |
| 10566 | 10656 | for (i = 0; i < len; i += 8) { |
| @@ -10568,14 +10658,14 @@ static bool parse_edid_cea(struct amdgpu_dm_connector *aconnector, · 1 unmodified line | ||
| 10568 | 10658 | int offset; |
| 10569 | 10659 | |
| 10570 | 10660 | /* send 8 bytes a time */ |
| 10571 | − if (!dc_edid_parser_send_cea(dc, i, len, &edid_ext[i], 8)) | |
| 10661 | + if (!dc_edid_parser_send_cea(dm->dc, i, len, &edid_ext[i], 8)) | |
| 10572 | 10662 | return false; |
| 10573 | 10663 | |
| 10574 | 10664 | if (i+8 == len) { |
| 10575 | 10665 | /* EDID block sent completed, expect result */ |
| 10576 | 10666 | int version, min_rate, max_rate; |
| 10577 | 10667 | |
| 10578 | − res = dc_edid_parser_recv_amd_vsdb(dc, &version, &min_rate, &max_rate); | |
| 10668 | + res = dc_edid_parser_recv_amd_vsdb(dm->dc, &version, &min_rate, &max_rate); | |
| 10579 | 10669 | if (res) { |
| 10580 | 10670 | /* amd vsdb found */ |
| 10581 | 10671 | vsdb_info->freesync_supported = 1; |
| @@ -10589,7 +10679,7 @@ static bool parse_edid_cea(struct amdgpu_dm_connector *aconnector, · 7 unmodified lines | ||
| 10589 | 10679 | } |
| 10590 | 10680 | |
| 10591 | 10681 | /* check for ack*/ |
| 10592 | − res = dc_edid_parser_recv_cea_ack(dc, &offset); | |
| 10682 | + res = dc_edid_parser_recv_cea_ack(dm->dc, &offset); | |
| 10593 | 10683 | if (!res) |
| 10594 | 10684 | return false; |
| 10595 | 10685 | } |
| @@ -10597,6 +10687,34 @@ static bool parse_edid_cea(struct amdgpu_dm_connector *aconnector, · 1 unmodified line | ||
| 10597 | 10687 | return false; |
| 10598 | 10688 | } |
| 10599 | 10689 | |
| 10690 | +static bool parse_edid_cea_dmub(struct amdgpu_display_manager *dm, | |
| 10691 | + uint8_t *edid_ext, int len, | |
| 10692 | + struct amdgpu_hdmi_vsdb_info *vsdb_info) | |
| 10693 | +{ | |
| 10694 | + int i; | |
| 10695 | + | |
| 10696 | + /* send extension block to DMCU for parsing */ | |
| 10697 | + for (i = 0; i < len; i += 8) { | |
| 10698 | + /* send 8 bytes a time */ | |
| 10699 | + if (!dm_edid_parser_send_cea(dm, i, len, &edid_ext[i], 8, vsdb_info)) | |
| 10700 | + return false; | |
| 10701 | + } | |
| 10702 | + | |
| 10703 | + return vsdb_info->freesync_supported; | |
| 10704 | +} | |
| 10705 | + | |
| 10706 | +static bool parse_edid_cea(struct amdgpu_dm_connector *aconnector, | |
| 10707 | + uint8_t *edid_ext, int len, | |
| 10708 | + struct amdgpu_hdmi_vsdb_info *vsdb_info) | |
| 10709 | +{ | |
| 10710 | + struct amdgpu_device *adev = drm_to_adev(aconnector->base.dev); | |
| 10711 | + | |
| 10712 | + if (adev->dm.dmub_srv) | |
| 10713 | + return parse_edid_cea_dmub(&adev->dm, edid_ext, len, vsdb_info); | |
| 10714 | + else | |
| 10715 | + return parse_edid_cea_dmcu(&adev->dm, edid_ext, len, vsdb_info); | |
| 10716 | +} | |
| 10717 | + | |
| 10600 | 10718 | static int parse_hdmi_amd_vsdb(struct amdgpu_dm_connector *aconnector, |
| 10601 | 10719 | struct edid *edid, struct amdgpu_hdmi_vsdb_info *vsdb_info) |
| 10602 | 10720 | { |
| @@ -60,6 +60,7 @@ enum aux_return_code_type; · 59 unmodified lines | ||
| 60 | 60 | |
| 61 | 61 | /* Forward declarations */ |
| 62 | 62 | struct amdgpu_device; |
| 63 | +struct amdgpu_crtc; | |
| 63 | 64 | struct drm_device; |
| 64 | 65 | struct dc; |
| 65 | 66 | struct amdgpu_bo; |
| @@ -86,16 +87,18 @@ struct dm_compressor_info { · 20 unmodified lines | ||
| 86 | 87 | }; |
| 87 | 88 | |
| 88 | 89 | /** |
| 89 | − * struct vblank_workqueue - Works to be executed in a separate thread during vblank | |
| 90 | − * @mall_work: work for mall stutter | |
| 90 | + * struct vblank_control_work - Work data for vblank control | |
| 91 | + * @work: Kernel work data for the work event | |
| 91 | 92 | * @dm: amdgpu display manager device |
| 92 | − * @otg_inst: otg instance of which vblank is being set | |
| 93 | − * @enable: true if enable vblank | |
| 93 | + * @acrtc: amdgpu CRTC instance for which the event has occurred | |
| 94 | + * @stream: DC stream for which the event has occurred | |
| 95 | + * @enable: true if enabling vblank | |
| 94 | 96 | */ |
| 95 | −struct vblank_workqueue { | |
| 96 | − struct work_struct mall_work; | |
| 97 | +struct vblank_control_work { | |
| 98 | + struct work_struct work; | |
| 97 | 99 | struct amdgpu_display_manager *dm; |
| 98 | − int otg_inst; | |
| 100 | + struct amdgpu_crtc *acrtc; | |
| 101 | + struct dc_stream_state *stream; | |
| 99 | 102 | bool enable; |
| 100 | 103 | }; |
| 101 | 104 | |
| @@ -365,13 +368,13 @@ struct amdgpu_display_manager { · 263 unmodified lines | ||
| 365 | 368 | |
| 366 | 369 | spinlock_t irq_handler_list_table_lock; |
| 367 | 370 | |
| 368 | − struct backlight_device *backlight_dev; | |
| 371 | + struct backlight_device *backlight_dev[AMDGPU_DM_MAX_NUM_EDP]; | |
| 369 | 372 | |
| 370 | 373 | const struct dc_link *backlight_link[AMDGPU_DM_MAX_NUM_EDP]; |
| 371 | 374 | |
| 372 | 375 | uint8_t num_of_edps; |
| 373 | 376 | |
| 374 | − struct amdgpu_dm_backlight_caps backlight_caps; | |
| 377 | + struct amdgpu_dm_backlight_caps backlight_caps[AMDGPU_DM_MAX_NUM_EDP]; | |
| 375 | 378 | |
| 376 | 379 | struct mod_freesync *freesync_module; |
| 377 | 380 | #ifdef CONFIG_DRM_AMD_DC_HDCP |
| @@ -380,11 +383,11 @@ struct amdgpu_display_manager { · 2 unmodified lines | ||
| 380 | 383 | |
| 381 | 384 | #if defined(CONFIG_DRM_AMD_DC_DCN) |
| 382 | 385 | /** |
| 383 | − * @vblank_workqueue: | |
| 386 | + * @vblank_control_workqueue: | |
| 384 | 387 | * |
| 385 | − * amdgpu workqueue during vblank | |
| 388 | + * Deferred work for vblank control events. | |
| 386 | 389 | */ |
| 387 | − struct vblank_workqueue *vblank_workqueue; | |
| 390 | + struct workqueue_struct *vblank_control_workqueue; | |
| 388 | 391 | #endif |
| 389 | 392 | |
| 390 | 393 | struct drm_atomic_state *cached_state; |
| @@ -197,29 +197,29 @@ static ssize_t dp_link_settings_read(struct file *f, char __user *buf, · 196 unmodified lines | ||
| 197 | 197 | |
| 198 | 198 | rd_buf_ptr = rd_buf; |
| 199 | 199 | |
| 200 | − str_len = strlen("Current: %d %d %d "); | |
| 201 | − snprintf(rd_buf_ptr, str_len, "Current: %d %d %d ", | |
| 200 | + str_len = strlen("Current: %d 0x%x %d "); | |
| 201 | + snprintf(rd_buf_ptr, str_len, "Current: %d 0x%x %d ", | |
| 202 | 202 | link->cur_link_settings.lane_count, |
| 203 | 203 | link->cur_link_settings.link_rate, |
| 204 | 204 | link->cur_link_settings.link_spread); |
| 205 | 205 | rd_buf_ptr += str_len; |
| 206 | 206 | |
| 207 | − str_len = strlen("Verified: %d %d %d "); | |
| 208 | − snprintf(rd_buf_ptr, str_len, "Verified: %d %d %d ", | |
| 207 | + str_len = strlen("Verified: %d 0x%x %d "); | |
| 208 | + snprintf(rd_buf_ptr, str_len, "Verified: %d 0x%x %d ", | |
| 209 | 209 | link->verified_link_cap.lane_count, |
| 210 | 210 | link->verified_link_cap.link_rate, |
| 211 | 211 | link->verified_link_cap.link_spread); |
| 212 | 212 | rd_buf_ptr += str_len; |
| 213 | 213 | |
| 214 | − str_len = strlen("Reported: %d %d %d "); | |
| 215 | − snprintf(rd_buf_ptr, str_len, "Reported: %d %d %d ", | |
| 214 | + str_len = strlen("Reported: %d 0x%x %d "); | |
| 215 | + snprintf(rd_buf_ptr, str_len, "Reported: %d 0x%x %d ", | |
| 216 | 216 | link->reported_link_cap.lane_count, |
| 217 | 217 | link->reported_link_cap.link_rate, |
| 218 | 218 | link->reported_link_cap.link_spread); |
| 219 | 219 | rd_buf_ptr += str_len; |
| 220 | 220 | |
| 221 | − str_len = strlen("Preferred: %d %d %d "); | |
| 222 | − snprintf(rd_buf_ptr, str_len, "Preferred: %d %d %d\n", | |
| 221 | + str_len = strlen("Preferred: %d 0x%x %d "); | |
| 222 | + snprintf(rd_buf_ptr, str_len, "Preferred: %d 0x%x %d\n", | |
| 223 | 223 | link->preferred_link_setting.lane_count, |
| 224 | 224 | link->preferred_link_setting.link_rate, |
| 225 | 225 | link->preferred_link_setting.link_spread); |
| @@ -377,7 +377,7 @@ static ssize_t dp_phy_settings_read(struct file *f, char __user *buf, · 151 unmodified lines | ||
| 377 | 377 | if (!rd_buf) |
| 378 | 378 | return -EINVAL; |
| 379 | 379 | |
| 380 | − snprintf(rd_buf, rd_buf_size, " %d %d %d ", | |
| 380 | + snprintf(rd_buf, rd_buf_size, " %d %d %d\n", | |
| 381 | 381 | link->cur_lane_setting.VOLTAGE_SWING, |
| 382 | 382 | link->cur_lane_setting.PRE_EMPHASIS, |
| 383 | 383 | link->cur_lane_setting.POST_CURSOR2); |
| @@ -79,12 +79,12 @@ static uint8_t *psp_get_srm(struct psp_context *psp, uint32_t *srm_version, uint · 78 unmodified lines | ||
| 79 | 79 | |
| 80 | 80 | struct ta_hdcp_shared_memory *hdcp_cmd; |
| 81 | 81 | |
| 82 | − if (!psp->hdcp_context.hdcp_initialized) { | |
| 82 | + if (!psp->hdcp_context.context.initialized) { | |
| 83 | 83 | DRM_WARN("Failed to get hdcp srm. HDCP TA is not initialized."); |
| 84 | 84 | return NULL; |
| 85 | 85 | } |
| 86 | 86 | |
| 87 | − hdcp_cmd = (struct ta_hdcp_shared_memory *)psp->hdcp_context.hdcp_shared_buf; | |
| 87 | + hdcp_cmd = (struct ta_hdcp_shared_memory *)psp->hdcp_context.context.mem_context.shared_buf; | |
| 88 | 88 | memset(hdcp_cmd, 0, sizeof(struct ta_hdcp_shared_memory)); |
| 89 | 89 | |
| 90 | 90 | hdcp_cmd->cmd_id = TA_HDCP_COMMAND__HDCP_GET_SRM; |
| @@ -105,12 +105,12 @@ static int psp_set_srm(struct psp_context *psp, uint8_t *srm, uint32_t srm_size, · 14 unmodified lines | ||
| 105 | 105 | |
| 106 | 106 | struct ta_hdcp_shared_memory *hdcp_cmd; |
| 107 | 107 | |
| 108 | − if (!psp->hdcp_context.hdcp_initialized) { | |
| 108 | + if (!psp->hdcp_context.context.initialized) { | |
| 109 | 109 | DRM_WARN("Failed to get hdcp srm. HDCP TA is not initialized."); |
| 110 | 110 | return -EINVAL; |
| 111 | 111 | } |
| 112 | 112 | |
| 113 | − hdcp_cmd = (struct ta_hdcp_shared_memory *)psp->hdcp_context.hdcp_shared_buf; | |
| 113 | + hdcp_cmd = (struct ta_hdcp_shared_memory *)psp->hdcp_context.context.mem_context.shared_buf; | |
| 114 | 114 | memset(hdcp_cmd, 0, sizeof(struct ta_hdcp_shared_memory)); |
| 115 | 115 | |
| 116 | 116 | memcpy(hdcp_cmd->in_msg.hdcp_set_srm.srm_buf, srm, srm_size); |
| @@ -414,12 +414,12 @@ static bool enable_assr(void *handle, struct dc_link *link) · 297 unmodified lines | ||
| 414 | 414 | struct ta_dtm_shared_memory *dtm_cmd; |
| 415 | 415 | bool res = true; |
| 416 | 416 | |
| 417 | − if (!psp->dtm_context.dtm_initialized) { | |
| 417 | + if (!psp->dtm_context.context.initialized) { | |
| 418 | 418 | DRM_INFO("Failed to enable ASSR, DTM TA is not initialized."); |
| 419 | 419 | return false; |
| 420 | 420 | } |
| 421 | 421 | |
| 422 | − dtm_cmd = (struct ta_dtm_shared_memory *)psp->dtm_context.dtm_shared_buf; | |
| 422 | + dtm_cmd = (struct ta_dtm_shared_memory *)psp->dtm_context.context.mem_context.shared_buf; | |
| 423 | 423 | |
| 424 | 424 | mutex_lock(&psp->dtm_context.mutex); |
| 425 | 425 | memset(dtm_cmd, 0, sizeof(struct ta_dtm_shared_memory)); |
| @@ -655,10 +655,8 @@ struct hdcp_workqueue *hdcp_create_workqueue(struct amdgpu_device *adev, struct · 229 unmodified lines | ||
| 655 | 655 | INIT_DELAYED_WORK(&hdcp_work[i].property_validate_dwork, event_property_validate); |
| 656 | 656 | |
| 657 | 657 | hdcp_work[i].hdcp.config.psp.handle = &adev->psp; |
| 658 | − if (dc->ctx->dce_version == DCN_VERSION_3_1) { | |
| 658 | + if (dc->ctx->dce_version == DCN_VERSION_3_1) | |
| 659 | 659 | hdcp_work[i].hdcp.config.psp.caps.dtm_v3_supported = 1; |
| 660 | − hdcp_work[i].hdcp.config.psp.caps.opm_state_query_supported = false; | |
| 661 | − } | |
| 662 | 660 | hdcp_work[i].hdcp.config.ddc.handle = dc_get_link_at_index(dc, i); |
| 663 | 661 | hdcp_work[i].hdcp.config.ddc.funcs.write_i2c = lp_write_i2c; |
| 664 | 662 | hdcp_work[i].hdcp.config.ddc.funcs.read_i2c = lp_read_i2c; |
| @@ -33,6 +33,7 @@ struct dm_irq_params { · 32 unmodified lines | ||
| 33 | 33 | struct mod_vrr_params vrr_params; |
| 34 | 34 | struct dc_stream_state *stream; |
| 35 | 35 | int active_planes; |
| 36 | + bool allow_psr_entry; | |
| 36 | 37 | struct mod_freesync_config freesync_config; |
| 37 | 38 | |
| 38 | 39 | #ifdef CONFIG_DEBUG_FS |
| @@ -213,6 +213,29 @@ static int dm_dp_mst_get_modes(struct drm_connector *connector) · 212 unmodified lines | ||
| 213 | 213 | drm_connector_update_edid_property( |
| 214 | 214 | &aconnector->base, |
| 215 | 215 | NULL); |
| 216 | + | |
| 217 | + DRM_DEBUG_KMS("Can't get EDID of %s. Add default remote sink.", connector->name); | |
| 218 | + if (!aconnector->dc_sink) { | |
| 219 | + struct dc_sink *dc_sink; | |
| 220 | + struct dc_sink_init_data init_params = { | |
| 221 | + .link = aconnector->dc_link, | |
| 222 | + .sink_signal = SIGNAL_TYPE_DISPLAY_PORT_MST }; | |
| 223 | + | |
| 224 | + dc_sink = dc_link_add_remote_sink( | |
| 225 | + aconnector->dc_link, | |
| 226 | + NULL, | |
| 227 | + 0, | |
| 228 | + &init_params); | |
| 229 | + | |
| 230 | + if (!dc_sink) { | |
| 231 | + DRM_ERROR("Unable to add a remote sink\n"); | |
| 232 | + return 0; | |
| 233 | + } | |
| 234 | + | |
| 235 | + dc_sink->priv = aconnector; | |
| 236 | + aconnector->dc_sink = dc_sink; | |
| 237 | + } | |
| 238 | + | |
| 216 | 239 | return ret; |
| 217 | 240 | } |
| 218 | 241 | |
| @@ -637,6 +637,30 @@ TRACE_EVENT(amdgpu_refresh_rate_track, · 636 unmodified lines | ||
| 637 | 637 | __entry->refresh_rate_ns) |
| 638 | 638 | ); |
| 639 | 639 | |
| 640 | +TRACE_EVENT(dcn_fpu, | |
| 641 | + TP_PROTO(bool begin, const char *function, const int line, const int recursion_depth), | |
| 642 | + TP_ARGS(begin, function, line, recursion_depth), | |
| 643 | + | |
| 644 | + TP_STRUCT__entry( | |
| 645 | + __field(bool, begin) | |
| 646 | + __field(const char *, function) | |
| 647 | + __field(int, line) | |
| 648 | + __field(int, recursion_depth) | |
| 649 | + ), | |
| 650 | + TP_fast_assign( | |
| 651 | + __entry->begin = begin; | |
| 652 | + __entry->function = function; | |
| 653 | + __entry->line = line; | |
| 654 | + __entry->recursion_depth = recursion_depth; | |
| 655 | + ), | |
| 656 | + TP_printk("%s: recursion_depth: %d: %s()+%d:", | |
| 657 | + __entry->begin ? "begin" : "end", | |
| 658 | + __entry->recursion_depth, | |
| 659 | + __entry->function, | |
| 660 | + __entry->line | |
| 661 | + ) | |
| 662 | +); | |
| 663 | + | |
| 640 | 664 | #endif /* _AMDGPU_DM_TRACE_H_ */ |
| 641 | 665 | |
| 642 | 666 | #undef TRACE_INCLUDE_PATH |
| @@ -0,0 +1,144 @@ | ||
| 1 | +// SPDX-License-Identifier: MIT | |
| 2 | +/* | |
| 3 | + * Copyright 2021 Advanced Micro Devices, Inc. | |
| 4 | + * | |
| 5 | + * Permission is hereby granted, free of charge, to any person obtaining a | |
| 6 | + * copy of this software and associated documentation files (the "Software"), | |
| 7 | + * to deal in the Software without restriction, including without limitation | |
| 8 | + * the rights to use, copy, modify, merge, publish, distribute, sublicense, | |
| 9 | + * and/or sell copies of the Software, and to permit persons to whom the | |
| 10 | + * Software is furnished to do so, subject to the following conditions: | |
| 11 | + * | |
| 12 | + * The above copyright notice and this permission notice shall be included in | |
| 13 | + * all copies or substantial portions of the Software. | |
| 14 | + * | |
| 15 | + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
| 16 | + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
| 17 | + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |
| 18 | + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR | |
| 19 | + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | |
| 20 | + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | |
| 21 | + * OTHER DEALINGS IN THE SOFTWARE. | |
| 22 | + * | |
| 23 | + * Authors: AMD | |
| 24 | + * | |
| 25 | + */ | |
| 26 | + | |
| 27 | +#include "dc_trace.h" | |
| 28 | + | |
| 29 | +#if defined(CONFIG_X86) | |
| 30 | +#include <asm/fpu/api.h> | |
| 31 | +#elif defined(CONFIG_PPC64) | |
| 32 | +#include <asm/switch_to.h> | |
| 33 | +#include <asm/cputable.h> | |
| 34 | +#endif | |
| 35 | + | |
| 36 | +/** | |
| 37 | + * DOC: DC FPU manipulation overview | |
| 38 | + * | |
| 39 | + * DC core uses FPU operations in multiple parts of the code, which requires a | |
| 40 | + * more specialized way to manage these areas' entrance. To fulfill this | |
| 41 | + * requirement, we created some wrapper functions that encapsulate | |
| 42 | + * kernel_fpu_begin/end to better fit our need in the display component. In | |
| 43 | + * summary, in this file, you can find functions related to FPU operation | |
| 44 | + * management. | |
| 45 | + */ | |
| 46 | + | |
| 47 | +static DEFINE_PER_CPU(int, fpu_recursion_depth); | |
| 48 | + | |
| 49 | +/** | |
| 50 | + * dc_assert_fp_enabled - Check if FPU protection is enabled | |
| 51 | + * | |
| 52 | + * This function tells if the code is already under FPU protection or not. A | |
| 53 | + * function that works as an API for a set of FPU operations can use this | |
| 54 | + * function for checking if the caller invoked it after DC_FP_START(). For | |
| 55 | + * example, take a look at dcn2x.c file. | |
| 56 | + */ | |
| 57 | +inline void dc_assert_fp_enabled(void) | |
| 58 | +{ | |
| 59 | + int *pcpu, depth = 0; | |
| 60 | + | |
| 61 | + pcpu = get_cpu_ptr(&fpu_recursion_depth); | |
| 62 | + depth = *pcpu; | |
| 63 | + put_cpu_ptr(&fpu_recursion_depth); | |
| 64 | + | |
| 65 | + ASSERT(depth > 1); | |
| 66 | +} | |
| 67 | + | |
| 68 | +/** | |
| 69 | + * dc_fpu_begin - Enables FPU protection | |
| 70 | + * @function_name: A string containing the function name for debug purposes | |
| 71 | + * (usually __func__) | |
| 72 | + * | |
| 73 | + * @line: A line number where DC_FP_START was invoked for debug purpose | |
| 74 | + * (usually __LINE__) | |
| 75 | + * | |
| 76 | + * This function is responsible for managing the use of kernel_fpu_begin() with | |
| 77 | + * the advantage of providing an event trace for debugging. | |
| 78 | + * | |
| 79 | + * Note: Do not call this function directly; always use DC_FP_START(). | |
| 80 | + */ | |
| 81 | +void dc_fpu_begin(const char *function_name, const int line) | |
| 82 | +{ | |
| 83 | + int *pcpu; | |
| 84 | + | |
| 85 | + pcpu = get_cpu_ptr(&fpu_recursion_depth); | |
| 86 | + *pcpu += 1; | |
| 87 | + | |
| 88 | + if (*pcpu == 1) { | |
| 89 | +#if defined(CONFIG_X86) | |
| 90 | + kernel_fpu_begin(); | |
| 91 | +#elif defined(CONFIG_PPC64) | |
| 92 | + if (cpu_has_feature(CPU_FTR_VSX_COMP)) { | |
| 93 | + preempt_disable(); | |
| 94 | + enable_kernel_vsx(); | |
| 95 | + } else if (cpu_has_feature(CPU_FTR_ALTIVEC_COMP)) { | |
| 96 | + preempt_disable(); | |
| 97 | + enable_kernel_altivec(); | |
| 98 | + } else if (!cpu_has_feature(CPU_FTR_FPU_UNAVAILABLE)) { | |
| 99 | + preempt_disable(); | |
| 100 | + enable_kernel_fp(); | |
| 101 | + } | |
| 102 | +#endif | |
| 103 | + } | |
| 104 | + | |
| 105 | + TRACE_DCN_FPU(true, function_name, line, *pcpu); | |
| 106 | + put_cpu_ptr(&fpu_recursion_depth); | |
| 107 | +} | |
| 108 | + | |
| 109 | +/** | |
| 110 | + * dc_fpu_end - Disable FPU protection | |
| 111 | + * @function_name: A string containing the function name for debug purposes | |
| 112 | + * @line: A-line number where DC_FP_END was invoked for debug purpose | |
| 113 | + * | |
| 114 | + * This function is responsible for managing the use of kernel_fpu_end() with | |
| 115 | + * the advantage of providing an event trace for debugging. | |
| 116 | + * | |
| 117 | + * Note: Do not call this function directly; always use DC_FP_END(). | |
| 118 | + */ | |
| 119 | +void dc_fpu_end(const char *function_name, const int line) | |
| 120 | +{ | |
| 121 | + int *pcpu; | |
| 122 | + | |
| 123 | + pcpu = get_cpu_ptr(&fpu_recursion_depth); | |
| 124 | + *pcpu -= 1; | |
| 125 | + if (*pcpu <= 0) { | |
| 126 | +#if defined(CONFIG_X86) | |
| 127 | + kernel_fpu_end(); | |
| 128 | +#elif defined(CONFIG_PPC64) | |
| 129 | + if (cpu_has_feature(CPU_FTR_VSX_COMP)) { | |
| 130 | + disable_kernel_vsx(); | |
| 131 | + preempt_enable(); | |
| 132 | + } else if (cpu_has_feature(CPU_FTR_ALTIVEC_COMP)) { | |
| 133 | + disable_kernel_altivec(); | |
| 134 | + preempt_enable(); | |
| 135 | + } else if (!cpu_has_feature(CPU_FTR_FPU_UNAVAILABLE)) { | |
| 136 | + disable_kernel_fp(); | |
| 137 | + preempt_enable(); | |
| 138 | + } | |
| 139 | +#endif | |
| 140 | + } | |
| 141 | + | |
| 142 | + TRACE_DCN_FPU(false, function_name, line, *pcpu); | |
| 143 | + put_cpu_ptr(&fpu_recursion_depth); | |
| 144 | +} | |
| @@ -0,0 +1,34 @@ | ||
| 1 | +/* SPDX-License-Identifier: MIT */ | |
| 2 | +/* | |
| 3 | + * Copyright 2021 Advanced Micro Devices, Inc. | |
| 4 | + * | |
| 5 | + * Permission is hereby granted, free of charge, to any person obtaining a | |
| 6 | + * copy of this software and associated documentation files (the "Software"), | |
| 7 | + * to deal in the Software without restriction, including without limitation | |
| 8 | + * the rights to use, copy, modify, merge, publish, distribute, sublicense, | |
| 9 | + * and/or sell copies of the Software, and to permit persons to whom the | |
| 10 | + * Software is furnished to do so, subject to the following conditions: | |
| 11 | + * | |
| 12 | + * The above copyright notice and this permission notice shall be included in | |
| 13 | + * all copies or substantial portions of the Software. | |
| 14 | + * | |
| 15 | + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
| 16 | + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
| 17 | + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |
| 18 | + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR | |
| 19 | + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | |
| 20 | + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | |
| 21 | + * OTHER DEALINGS IN THE SOFTWARE. | |
| 22 | + * | |
| 23 | + * Authors: AMD | |
| 24 | + * | |
| 25 | + */ | |
| 26 | + | |
| 27 | +#ifndef __DC_FPU_H__ | |
| 28 | +#define __DC_FPU_H__ | |
| 29 | + | |
| 30 | +void dc_assert_fp_enabled(void); | |
| 31 | +void dc_fpu_begin(const char *function_name, const int line); | |
| 32 | +void dc_fpu_end(const char *function_name, const int line); | |
| 33 | + | |
| 34 | +#endif /* __DC_FPU_H__ */ | |
| @@ -264,9 +264,9 @@ static void rv1_update_clocks(struct clk_mgr *clk_mgr_base, · 263 unmodified lines | ||
| 264 | 264 | if (pp_smu->set_hard_min_fclk_by_freq && |
| 265 | 265 | pp_smu->set_hard_min_dcfclk_by_freq && |
| 266 | 266 | pp_smu->set_min_deep_sleep_dcfclk) { |
| 267 | − pp_smu->set_hard_min_fclk_by_freq(&pp_smu->pp_smu, new_clocks->fclk_khz / 1000); | |
| 268 | − pp_smu->set_hard_min_dcfclk_by_freq(&pp_smu->pp_smu, new_clocks->dcfclk_khz / 1000); | |
| 269 | − pp_smu->set_min_deep_sleep_dcfclk(&pp_smu->pp_smu, (new_clocks->dcfclk_deep_sleep_khz + 999) / 1000); | |
| 267 | + pp_smu->set_hard_min_fclk_by_freq(&pp_smu->pp_smu, khz_to_mhz_ceil(new_clocks->fclk_khz)); | |
| 268 | + pp_smu->set_hard_min_dcfclk_by_freq(&pp_smu->pp_smu, khz_to_mhz_ceil(new_clocks->dcfclk_khz)); | |
| 269 | + pp_smu->set_min_deep_sleep_dcfclk(&pp_smu->pp_smu, khz_to_mhz_ceil(new_clocks->dcfclk_deep_sleep_khz)); | |
| 270 | 270 | } |
| 271 | 271 | } |
| 272 | 272 | |
| @@ -284,9 +284,9 @@ static void rv1_update_clocks(struct clk_mgr *clk_mgr_base, · 11 unmodified lines | ||
| 284 | 284 | if (pp_smu->set_hard_min_fclk_by_freq && |
| 285 | 285 | pp_smu->set_hard_min_dcfclk_by_freq && |
| 286 | 286 | pp_smu->set_min_deep_sleep_dcfclk) { |
| 287 | − pp_smu->set_hard_min_fclk_by_freq(&pp_smu->pp_smu, new_clocks->fclk_khz / 1000); | |
| 288 | − pp_smu->set_hard_min_dcfclk_by_freq(&pp_smu->pp_smu, new_clocks->dcfclk_khz / 1000); | |
| 289 | − pp_smu->set_min_deep_sleep_dcfclk(&pp_smu->pp_smu, (new_clocks->dcfclk_deep_sleep_khz + 999) / 1000); | |
| 287 | + pp_smu->set_hard_min_fclk_by_freq(&pp_smu->pp_smu, khz_to_mhz_ceil(new_clocks->fclk_khz)); | |
| 288 | + pp_smu->set_hard_min_dcfclk_by_freq(&pp_smu->pp_smu, khz_to_mhz_ceil(new_clocks->dcfclk_khz)); | |
| 289 | + pp_smu->set_min_deep_sleep_dcfclk(&pp_smu->pp_smu, khz_to_mhz_ceil(new_clocks->dcfclk_deep_sleep_khz)); | |
| 290 | 290 | } |
| 291 | 291 | } |
| 292 | 292 | } |
| @@ -130,7 +130,7 @@ int rv1_vbios_smu_set_dispclk(struct clk_mgr_internal *clk_mgr, int requested_di · 129 unmodified lines | ||
| 130 | 130 | actual_dispclk_set_mhz = rv1_vbios_smu_send_msg_with_param( |
| 131 | 131 | clk_mgr, |
| 132 | 132 | VBIOSSMC_MSG_SetDispclkFreq, |
| 133 | − requested_dispclk_khz / 1000); | |
| 133 | + khz_to_mhz_ceil(requested_dispclk_khz)); | |
| 134 | 134 | |
| 135 | 135 | if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) { |
| 136 | 136 | if (dmcu && dmcu->funcs->is_dmcu_initialized(dmcu)) { |
| @@ -150,7 +150,7 @@ int rv1_vbios_smu_set_dprefclk(struct clk_mgr_internal *clk_mgr) · 13 unmodified lines | ||
| 150 | 150 | actual_dprefclk_set_mhz = rv1_vbios_smu_send_msg_with_param( |
| 151 | 151 | clk_mgr, |
| 152 | 152 | VBIOSSMC_MSG_SetDprefclkFreq, |
| 153 | − clk_mgr->base.dprefclk_khz / 1000); | |
| 153 | + khz_to_mhz_ceil(clk_mgr->base.dprefclk_khz)); | |
| 154 | 154 | |
| 155 | 155 | /* TODO: add code for programing DP DTO, currently this is down by command table */ |
| 156 | 156 | |
| @@ -253,20 +253,20 @@ void dcn2_update_clocks(struct clk_mgr *clk_mgr_base, · 252 unmodified lines | ||
| 253 | 253 | if (should_set_clock(safe_to_lower, new_clocks->dcfclk_khz, clk_mgr_base->clks.dcfclk_khz)) { |
| 254 | 254 | clk_mgr_base->clks.dcfclk_khz = new_clocks->dcfclk_khz; |
| 255 | 255 | if (pp_smu && pp_smu->set_hard_min_dcfclk_by_freq) |
| 256 | − pp_smu->set_hard_min_dcfclk_by_freq(&pp_smu->pp_smu, clk_mgr_base->clks.dcfclk_khz / 1000); | |
| 256 | + pp_smu->set_hard_min_dcfclk_by_freq(&pp_smu->pp_smu, khz_to_mhz_ceil(clk_mgr_base->clks.dcfclk_khz)); | |
| 257 | 257 | } |
| 258 | 258 | |
| 259 | 259 | if (should_set_clock(safe_to_lower, |
| 260 | 260 | new_clocks->dcfclk_deep_sleep_khz, clk_mgr_base->clks.dcfclk_deep_sleep_khz)) { |
| 261 | 261 | clk_mgr_base->clks.dcfclk_deep_sleep_khz = new_clocks->dcfclk_deep_sleep_khz; |
| 262 | 262 | if (pp_smu && pp_smu->set_min_deep_sleep_dcfclk) |
| 263 | − pp_smu->set_min_deep_sleep_dcfclk(&pp_smu->pp_smu, clk_mgr_base->clks.dcfclk_deep_sleep_khz / 1000); | |
| 263 | + pp_smu->set_min_deep_sleep_dcfclk(&pp_smu->pp_smu, khz_to_mhz_ceil(clk_mgr_base->clks.dcfclk_deep_sleep_khz)); | |
| 264 | 264 | } |
| 265 | 265 | |
| 266 | 266 | if (should_set_clock(safe_to_lower, new_clocks->socclk_khz, clk_mgr_base->clks.socclk_khz)) { |
| 267 | 267 | clk_mgr_base->clks.socclk_khz = new_clocks->socclk_khz; |
| 268 | 268 | if (pp_smu && pp_smu->set_hard_min_socclk_by_freq) |
| 269 | − pp_smu->set_hard_min_socclk_by_freq(&pp_smu->pp_smu, clk_mgr_base->clks.socclk_khz / 1000); | |
| 269 | + pp_smu->set_hard_min_socclk_by_freq(&pp_smu->pp_smu, khz_to_mhz_ceil(clk_mgr_base->clks.socclk_khz)); | |
| 270 | 270 | } |
| 271 | 271 | |
| 272 | 272 | total_plane_count = clk_mgr_helper_get_active_plane_cnt(dc, context); |
| @@ -281,7 +281,7 @@ void dcn2_update_clocks(struct clk_mgr *clk_mgr_base, · 8 unmodified lines | ||
| 281 | 281 | if (should_set_clock(safe_to_lower, new_clocks->dramclk_khz, clk_mgr_base->clks.dramclk_khz)) { |
| 282 | 282 | clk_mgr_base->clks.dramclk_khz = new_clocks->dramclk_khz; |
| 283 | 283 | if (pp_smu && pp_smu->set_hard_min_uclk_by_freq) |
| 284 | − pp_smu->set_hard_min_uclk_by_freq(&pp_smu->pp_smu, clk_mgr_base->clks.dramclk_khz / 1000); | |
| 284 | + pp_smu->set_hard_min_uclk_by_freq(&pp_smu->pp_smu, khz_to_mhz_ceil(clk_mgr_base->clks.dramclk_khz)); | |
| 285 | 285 | } |
| 286 | 286 | |
| 287 | 287 | if (should_set_clock(safe_to_lower, new_clocks->dppclk_khz, clk_mgr->base.clks.dppclk_khz)) { |
| @@ -306,7 +306,7 @@ void dcn2_update_clocks(struct clk_mgr *clk_mgr_base, · 18 unmodified lines | ||
| 306 | 306 | |
| 307 | 307 | clk_mgr_base->clks.disp_dpp_voltage_level_khz = new_clocks->disp_dpp_voltage_level_khz; |
| 308 | 308 | if (pp_smu && pp_smu->set_voltage_by_freq) |
| 309 | − pp_smu->set_voltage_by_freq(&pp_smu->pp_smu, PP_SMU_NV_DISPCLK, clk_mgr_base->clks.disp_dpp_voltage_level_khz / 1000); | |
| 309 | + pp_smu->set_voltage_by_freq(&pp_smu->pp_smu, PP_SMU_NV_DISPCLK, khz_to_mhz_ceil(clk_mgr_base->clks.disp_dpp_voltage_level_khz)); | |
| 310 | 310 | } |
| 311 | 311 | |
| 312 | 312 | if (dc->config.forced_clocks == false || (force_reset && safe_to_lower)) { |
| @@ -502,7 +502,7 @@ static void dcn2_notify_link_rate_change(struct clk_mgr *clk_mgr_base, struct dc · 189 unmodified lines | ||
| 502 | 502 | |
| 503 | 503 | if (max_phyclk_req != clk_mgr_base->clks.phyclk_khz) { |
| 504 | 504 | clk_mgr_base->clks.phyclk_khz = max_phyclk_req; |
| 505 | − pp_smu->set_voltage_by_freq(&pp_smu->pp_smu, PP_SMU_NV_PHYCLK, clk_mgr_base->clks.phyclk_khz / 1000); | |
| 505 | + pp_smu->set_voltage_by_freq(&pp_smu->pp_smu, PP_SMU_NV_PHYCLK, khz_to_mhz_ceil(clk_mgr_base->clks.phyclk_khz)); | |
| 506 | 506 | } |
| 507 | 507 | } |
| 508 | 508 | |
| @@ -126,7 +126,7 @@ int rn_vbios_smu_set_dispclk(struct clk_mgr_internal *clk_mgr, int requested_dis · 125 unmodified lines | ||
| 126 | 126 | actual_dispclk_set_mhz = rn_vbios_smu_send_msg_with_param( |
| 127 | 127 | clk_mgr, |
| 128 | 128 | VBIOSSMC_MSG_SetDispclkFreq, |
| 129 | − requested_dispclk_khz / 1000); | |
| 129 | + khz_to_mhz_ceil(requested_dispclk_khz)); | |
| 130 | 130 | |
| 131 | 131 | if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) { |
| 132 | 132 | if (dmcu && dmcu->funcs->is_dmcu_initialized(dmcu)) { |
| @@ -138,7 +138,7 @@ int rn_vbios_smu_set_dispclk(struct clk_mgr_internal *clk_mgr, int requested_dis · 5 unmodified lines | ||
| 138 | 138 | |
| 139 | 139 | // pmfw always set clock more than or equal requested clock |
| 140 | 140 | if (!IS_DIAG_DC(dc->ctx->dce_environment)) |
| 141 | − ASSERT(actual_dispclk_set_mhz >= requested_dispclk_khz / 1000); | |
| 141 | + ASSERT(actual_dispclk_set_mhz >= khz_to_mhz_ceil(requested_dispclk_khz)); | |
| 142 | 142 | |
| 143 | 143 | return actual_dispclk_set_mhz * 1000; |
| 144 | 144 | } |
| @@ -150,7 +150,7 @@ int rn_vbios_smu_set_dprefclk(struct clk_mgr_internal *clk_mgr) · 5 unmodified lines | ||
| 150 | 150 | actual_dprefclk_set_mhz = rn_vbios_smu_send_msg_with_param( |
| 151 | 151 | clk_mgr, |
| 152 | 152 | VBIOSSMC_MSG_SetDprefclkFreq, |
| 153 | − clk_mgr->base.dprefclk_khz / 1000); | |
| 153 | + khz_to_mhz_ceil(clk_mgr->base.dprefclk_khz)); | |
| 154 | 154 | |
| 155 | 155 | /* TODO: add code for programing DP DTO, currently this is down by command table */ |
| 156 | 156 | |
| @@ -167,7 +167,7 @@ int rn_vbios_smu_set_hard_min_dcfclk(struct clk_mgr_internal *clk_mgr, int reque · 10 unmodified lines | ||
| 167 | 167 | actual_dcfclk_set_mhz = rn_vbios_smu_send_msg_with_param( |
| 168 | 168 | clk_mgr, |
| 169 | 169 | VBIOSSMC_MSG_SetHardMinDcfclkByFreq, |
| 170 | − requested_dcfclk_khz / 1000); | |
| 170 | + khz_to_mhz_ceil(requested_dcfclk_khz)); | |
| 171 | 171 | |
| 172 | 172 | return actual_dcfclk_set_mhz * 1000; |
| 173 | 173 | } |
| @@ -182,7 +182,7 @@ int rn_vbios_smu_set_min_deep_sleep_dcfclk(struct clk_mgr_internal *clk_mgr, int · 8 unmodified lines | ||
| 182 | 182 | actual_min_ds_dcfclk_mhz = rn_vbios_smu_send_msg_with_param( |
| 183 | 183 | clk_mgr, |
| 184 | 184 | VBIOSSMC_MSG_SetMinDeepSleepDcfclk, |
| 185 | − requested_min_ds_dcfclk_khz / 1000); | |
| 185 | + khz_to_mhz_ceil(requested_min_ds_dcfclk_khz)); | |
| 186 | 186 | |
| 187 | 187 | return actual_min_ds_dcfclk_mhz * 1000; |
| 188 | 188 | } |
| @@ -192,7 +192,7 @@ void rn_vbios_smu_set_phyclk(struct clk_mgr_internal *clk_mgr, int requested_phy · 3 unmodified lines | ||
| 192 | 192 | rn_vbios_smu_send_msg_with_param( |
| 193 | 193 | clk_mgr, |
| 194 | 194 | VBIOSSMC_MSG_SetPhyclkVoltageByFreq, |
| 195 | − requested_phyclk_khz / 1000); | |
| 195 | + khz_to_mhz_ceil(requested_phyclk_khz)); | |
| 196 | 196 | } |
| 197 | 197 | |
| 198 | 198 | int rn_vbios_smu_set_dppclk(struct clk_mgr_internal *clk_mgr, int requested_dpp_khz) |
| @@ -203,10 +203,10 @@ int rn_vbios_smu_set_dppclk(struct clk_mgr_internal *clk_mgr, int requested_dpp_ · 4 unmodified lines | ||
| 203 | 203 | actual_dppclk_set_mhz = rn_vbios_smu_send_msg_with_param( |
| 204 | 204 | clk_mgr, |
| 205 | 205 | VBIOSSMC_MSG_SetDppclkFreq, |
| 206 | − requested_dpp_khz / 1000); | |
| 206 | + khz_to_mhz_ceil(requested_dpp_khz)); | |
| 207 | 207 | |
| 208 | 208 | if (!IS_DIAG_DC(dc->ctx->dce_environment)) |
| 209 | − ASSERT(actual_dppclk_set_mhz >= requested_dpp_khz / 1000); | |
| 209 | + ASSERT(actual_dppclk_set_mhz >= khz_to_mhz_ceil(requested_dpp_khz)); | |
| 210 | 210 | |
| 211 | 211 | return actual_dppclk_set_mhz * 1000; |
| 212 | 212 | } |
| @@ -284,12 +284,12 @@ static void dcn3_update_clocks(struct clk_mgr *clk_mgr_base, · 283 unmodified lines | ||
| 284 | 284 | |
| 285 | 285 | if (should_set_clock(safe_to_lower, new_clocks->dcfclk_khz, clk_mgr_base->clks.dcfclk_khz)) { |
| 286 | 286 | clk_mgr_base->clks.dcfclk_khz = new_clocks->dcfclk_khz; |
| 287 | − dcn30_smu_set_hard_min_by_freq(clk_mgr, PPCLK_DCEFCLK, clk_mgr_base->clks.dcfclk_khz / 1000); | |
| 287 | + dcn30_smu_set_hard_min_by_freq(clk_mgr, PPCLK_DCEFCLK, khz_to_mhz_ceil(clk_mgr_base->clks.dcfclk_khz)); | |
| 288 | 288 | } |
| 289 | 289 | |
| 290 | 290 | if (should_set_clock(safe_to_lower, new_clocks->dcfclk_deep_sleep_khz, clk_mgr_base->clks.dcfclk_deep_sleep_khz)) { |
| 291 | 291 | clk_mgr_base->clks.dcfclk_deep_sleep_khz = new_clocks->dcfclk_deep_sleep_khz; |
| 292 | − dcn30_smu_set_min_deep_sleep_dcef_clk(clk_mgr, clk_mgr_base->clks.dcfclk_deep_sleep_khz / 1000); | |
| 292 | + dcn30_smu_set_min_deep_sleep_dcef_clk(clk_mgr, khz_to_mhz_ceil(clk_mgr_base->clks.dcfclk_deep_sleep_khz)); | |
| 293 | 293 | } |
| 294 | 294 | |
| 295 | 295 | if (should_set_clock(safe_to_lower, new_clocks->socclk_khz, clk_mgr_base->clks.socclk_khz)) |
| @@ -317,20 +317,20 @@ static void dcn3_update_clocks(struct clk_mgr *clk_mgr_base, · 21 unmodified lines | ||
| 317 | 317 | /* set UCLK to requested value if P-State switching is supported, or to re-enable P-State switching */ |
| 318 | 318 | if (clk_mgr_base->clks.p_state_change_support && |
| 319 | 319 | (update_uclk || !clk_mgr_base->clks.prev_p_state_change_support)) |
| 320 | − dcn30_smu_set_hard_min_by_freq(clk_mgr, PPCLK_UCLK, clk_mgr_base->clks.dramclk_khz / 1000); | |
| 320 | + dcn30_smu_set_hard_min_by_freq(clk_mgr, PPCLK_UCLK, khz_to_mhz_ceil(clk_mgr_base->clks.dramclk_khz)); | |
| 321 | 321 | |
| 322 | 322 | if (should_set_clock(safe_to_lower, new_clocks->dppclk_khz, clk_mgr_base->clks.dppclk_khz)) { |
| 323 | 323 | if (clk_mgr_base->clks.dppclk_khz > new_clocks->dppclk_khz) |
| 324 | 324 | dpp_clock_lowered = true; |
| 325 | 325 | |
| 326 | 326 | clk_mgr_base->clks.dppclk_khz = new_clocks->dppclk_khz; |
| 327 | − dcn30_smu_set_hard_min_by_freq(clk_mgr, PPCLK_PIXCLK, clk_mgr_base->clks.dppclk_khz / 1000); | |
| 327 | + dcn30_smu_set_hard_min_by_freq(clk_mgr, PPCLK_PIXCLK, khz_to_mhz_ceil(clk_mgr_base->clks.dppclk_khz)); | |
| 328 | 328 | update_dppclk = true; |
| 329 | 329 | } |
| 330 | 330 | |
| 331 | 331 | if (should_set_clock(safe_to_lower, new_clocks->dispclk_khz, clk_mgr_base->clks.dispclk_khz)) { |
| 332 | 332 | clk_mgr_base->clks.dispclk_khz = new_clocks->dispclk_khz; |
| 333 | − dcn30_smu_set_hard_min_by_freq(clk_mgr, PPCLK_DISPCLK, clk_mgr_base->clks.dispclk_khz / 1000); | |
| 333 | + dcn30_smu_set_hard_min_by_freq(clk_mgr, PPCLK_DISPCLK, khz_to_mhz_ceil(clk_mgr_base->clks.dispclk_khz)); | |
| 334 | 334 | update_dispclk = true; |
| 335 | 335 | } |
| 336 | 336 | |
| @@ -396,12 +396,17 @@ static void dcn3_set_hard_min_memclk(struct clk_mgr *clk_mgr_base, bool current_ · 59 unmodified lines | ||
| 396 | 396 | if (!clk_mgr->smu_present) |
| 397 | 397 | return; |
| 398 | 398 | |
| 399 | − if (current_mode) | |
| 400 | − dcn30_smu_set_hard_min_by_freq(clk_mgr, PPCLK_UCLK, | |
| 401 | − clk_mgr_base->clks.dramclk_khz / 1000); | |
| 402 | − else | |
| 399 | + if (current_mode) { | |
| 400 | + if (clk_mgr_base->clks.p_state_change_support) | |
| 401 | + dcn30_smu_set_hard_min_by_freq(clk_mgr, PPCLK_UCLK, | |
| 402 | + khz_to_mhz_ceil(clk_mgr_base->clks.dramclk_khz)); | |
| 403 | + else | |
| 404 | + dcn30_smu_set_hard_min_by_freq(clk_mgr, PPCLK_UCLK, | |
| 405 | + clk_mgr_base->bw_params->clk_table.entries[clk_mgr_base->bw_params->clk_table.num_entries - 1].memclk_mhz); | |
| 406 | + } else { | |
| 403 | 407 | dcn30_smu_set_hard_min_by_freq(clk_mgr, PPCLK_UCLK, |
| 404 | 408 | clk_mgr_base->bw_params->clk_table.entries[0].memclk_mhz); |
| 409 | + } | |
| 405 | 410 | } |
| 406 | 411 | |
| 407 | 412 | /* Set max memclk to highest DPM value */ |
| @@ -489,7 +494,7 @@ static void dcn30_notify_link_rate_change(struct clk_mgr *clk_mgr_base, struct d · 81 unmodified lines | ||
| 489 | 494 | |
| 490 | 495 | if (max_phyclk_req != clk_mgr_base->clks.phyclk_khz) { |
| 491 | 496 | clk_mgr_base->clks.phyclk_khz = max_phyclk_req; |
| 492 | − dcn30_smu_set_hard_min_by_freq(clk_mgr, PPCLK_PHYCLK, clk_mgr_base->clks.phyclk_khz / 1000); | |
| 497 | + dcn30_smu_set_hard_min_by_freq(clk_mgr, PPCLK_PHYCLK, khz_to_mhz_ceil(clk_mgr_base->clks.phyclk_khz)); | |
| 493 | 498 | } |
| 494 | 499 | } |
| 495 | 500 | |
| @@ -133,7 +133,7 @@ int dcn301_smu_set_dispclk(struct clk_mgr_internal *clk_mgr, int requested_dispc · 132 unmodified lines | ||
| 133 | 133 | actual_dispclk_set_mhz = dcn301_smu_send_msg_with_param( |
| 134 | 134 | clk_mgr, |
| 135 | 135 | VBIOSSMC_MSG_SetDispclkFreq, |
| 136 | − requested_dispclk_khz / 1000); | |
| 136 | + khz_to_mhz_ceil(requested_dispclk_khz)); | |
| 137 | 137 | |
| 138 | 138 | return actual_dispclk_set_mhz * 1000; |
| 139 | 139 | } |
| @@ -147,7 +147,7 @@ int dcn301_smu_set_dprefclk(struct clk_mgr_internal *clk_mgr) · 7 unmodified lines | ||
| 147 | 147 | actual_dprefclk_set_mhz = dcn301_smu_send_msg_with_param( |
| 148 | 148 | clk_mgr, |
| 149 | 149 | VBIOSSMC_MSG_SetDprefclkFreq, |
| 150 | − clk_mgr->base.dprefclk_khz / 1000); | |
| 150 | + khz_to_mhz_ceil(clk_mgr->base.dprefclk_khz)); | |
| 151 | 151 | |
| 152 | 152 | /* TODO: add code for programing DP DTO, currently this is down by command table */ |
| 153 | 153 | |
| @@ -163,7 +163,7 @@ int dcn301_smu_set_hard_min_dcfclk(struct clk_mgr_internal *clk_mgr, int request · 9 unmodified lines | ||
| 163 | 163 | actual_dcfclk_set_mhz = dcn301_smu_send_msg_with_param( |
| 164 | 164 | clk_mgr, |
| 165 | 165 | VBIOSSMC_MSG_SetHardMinDcfclkByFreq, |
| 166 | − requested_dcfclk_khz / 1000); | |
| 166 | + khz_to_mhz_ceil(requested_dcfclk_khz)); | |
| 167 | 167 | |
| 168 | 168 | return actual_dcfclk_set_mhz * 1000; |
| 169 | 169 | } |
| @@ -177,7 +177,7 @@ int dcn301_smu_set_min_deep_sleep_dcfclk(struct clk_mgr_internal *clk_mgr, int r · 7 unmodified lines | ||
| 177 | 177 | actual_min_ds_dcfclk_mhz = dcn301_smu_send_msg_with_param( |
| 178 | 178 | clk_mgr, |
| 179 | 179 | VBIOSSMC_MSG_SetMinDeepSleepDcfclk, |
| 180 | − requested_min_ds_dcfclk_khz / 1000); | |
| 180 | + khz_to_mhz_ceil(requested_min_ds_dcfclk_khz)); | |
| 181 | 181 | |
| 182 | 182 | return actual_min_ds_dcfclk_mhz * 1000; |
| 183 | 183 | } |
| @@ -191,7 +191,7 @@ int dcn301_smu_set_dppclk(struct clk_mgr_internal *clk_mgr, int requested_dpp_kh · 7 unmodified lines | ||
| 191 | 191 | actual_dppclk_set_mhz = dcn301_smu_send_msg_with_param( |
| 192 | 192 | clk_mgr, |
| 193 | 193 | VBIOSSMC_MSG_SetDppclkFreq, |
| 194 | − requested_dpp_khz / 1000); | |
| 194 | + khz_to_mhz_ceil(requested_dpp_khz)); | |
| 195 | 195 | |
| 196 | 196 | return actual_dppclk_set_mhz * 1000; |
| 197 | 197 | } |
| @@ -114,7 +114,7 @@ void vg_update_clocks(struct clk_mgr *clk_mgr_base, · 113 unmodified lines | ||
| 114 | 114 | |
| 115 | 115 | display_count = vg_get_active_display_cnt_wa(dc, context); |
| 116 | 116 | /* if we can go lower, go lower */ |
| 117 | − if (display_count == 0) { | |
| 117 | + if (display_count == 0 && !IS_DIAG_DC(dc->ctx->dce_environment)) { | |
| 118 | 118 | union display_idle_optimization_u idle_info = { 0 }; |
| 119 | 119 | |
| 120 | 120 | idle_info.idle_info.df_request_disabled = 1; |
| @@ -147,7 +147,7 @@ int dcn31_smu_set_dispclk(struct clk_mgr_internal *clk_mgr, int requested_dispcl · 146 unmodified lines | ||
| 147 | 147 | actual_dispclk_set_mhz = dcn31_smu_send_msg_with_param( |
| 148 | 148 | clk_mgr, |
| 149 | 149 | VBIOSSMC_MSG_SetDispclkFreq, |
| 150 | − (requested_dispclk_khz + 999) / 1000); | |
| 150 | + khz_to_mhz_ceil(requested_dispclk_khz)); | |
| 151 | 151 | |
| 152 | 152 | return actual_dispclk_set_mhz * 1000; |
| 153 | 153 | } |
| @@ -162,7 +162,7 @@ int dcn31_smu_set_dprefclk(struct clk_mgr_internal *clk_mgr) · 8 unmodified lines | ||
| 162 | 162 | actual_dprefclk_set_mhz = dcn31_smu_send_msg_with_param( |
| 163 | 163 | clk_mgr, |
| 164 | 164 | VBIOSSMC_MSG_SetDprefclkFreq, |
| 165 | − (clk_mgr->base.dprefclk_khz + 999) / 1000); | |
| 165 | + khz_to_mhz_ceil(clk_mgr->base.dprefclk_khz)); | |
| 166 | 166 | |
| 167 | 167 | /* TODO: add code for programing DP DTO, currently this is down by command table */ |
| 168 | 168 | |
| @@ -182,7 +182,7 @@ int dcn31_smu_set_hard_min_dcfclk(struct clk_mgr_internal *clk_mgr, int requeste · 13 unmodified lines | ||
| 182 | 182 | actual_dcfclk_set_mhz = dcn31_smu_send_msg_with_param( |
| 183 | 183 | clk_mgr, |
| 184 | 184 | VBIOSSMC_MSG_SetHardMinDcfclkByFreq, |
| 185 | − (requested_dcfclk_khz + 999) / 1000); | |
| 185 | + khz_to_mhz_ceil(requested_dcfclk_khz)); | |
| 186 | 186 | |
| 187 | 187 | return actual_dcfclk_set_mhz * 1000; |
| 188 | 188 | } |
| @@ -200,7 +200,7 @@ int dcn31_smu_set_min_deep_sleep_dcfclk(struct clk_mgr_internal *clk_mgr, int re · 11 unmodified lines | ||
| 200 | 200 | actual_min_ds_dcfclk_mhz = dcn31_smu_send_msg_with_param( |
| 201 | 201 | clk_mgr, |
| 202 | 202 | VBIOSSMC_MSG_SetMinDeepSleepDcfclk, |
| 203 | − (requested_min_ds_dcfclk_khz + 999) / 1000); | |
| 203 | + khz_to_mhz_ceil(requested_min_ds_dcfclk_khz)); | |
| 204 | 204 | |
| 205 | 205 | return actual_min_ds_dcfclk_mhz * 1000; |
| 206 | 206 | } |
| @@ -215,7 +215,7 @@ int dcn31_smu_set_dppclk(struct clk_mgr_internal *clk_mgr, int requested_dpp_khz · 8 unmodified lines | ||
| 215 | 215 | actual_dppclk_set_mhz = dcn31_smu_send_msg_with_param( |
| 216 | 216 | clk_mgr, |
| 217 | 217 | VBIOSSMC_MSG_SetDppclkFreq, |
| 218 | − (requested_dpp_khz + 999) / 1000); | |
| 218 | + khz_to_mhz_ceil(requested_dpp_khz)); | |
| 219 | 219 | |
| 220 | 220 | return actual_dppclk_set_mhz * 1000; |
| 221 | 221 | } |
| @@ -1481,6 +1481,22 @@ bool dc_validate_seamless_boot_timing(const struct dc *dc, · 1480 unmodified lines | ||
| 1481 | 1481 | return true; |
| 1482 | 1482 | } |
| 1483 | 1483 | |
| 1484 | +static inline bool should_update_pipe_for_stream( | |
| 1485 | + struct dc_state *context, | |
| 1486 | + struct pipe_ctx *pipe_ctx, | |
| 1487 | + struct dc_stream_state *stream) | |
| 1488 | +{ | |
| 1489 | + return (pipe_ctx->stream && pipe_ctx->stream == stream); | |
| 1490 | +} | |
| 1491 | + | |
| 1492 | +static inline bool should_update_pipe_for_plane( | |
| 1493 | + struct dc_state *context, | |
| 1494 | + struct pipe_ctx *pipe_ctx, | |
| 1495 | + struct dc_plane_state *plane_state) | |
| 1496 | +{ | |
| 1497 | + return (pipe_ctx->plane_state == plane_state); | |
| 1498 | +} | |
| 1499 | + | |
| 1484 | 1500 | void dc_enable_stereo( |
| 1485 | 1501 | struct dc *dc, |
| 1486 | 1502 | struct dc_state *context, |
| @@ -1491,12 +1507,15 @@ void dc_enable_stereo( · 4 unmodified lines | ||
| 1491 | 1507 | struct pipe_ctx *pipe; |
| 1492 | 1508 | |
| 1493 | 1509 | for (i = 0; i < MAX_PIPES; i++) { |
| 1494 | − if (context != NULL) | |
| 1510 | + if (context != NULL) { | |
| 1495 | 1511 | pipe = &context->res_ctx.pipe_ctx[i]; |
| 1496 | − else | |
| 1512 | + } else { | |
| 1513 | + context = dc->current_state; | |
| 1497 | 1514 | pipe = &dc->current_state->res_ctx.pipe_ctx[i]; |
| 1498 | − for (j = 0 ; pipe && j < stream_count; j++) { | |
| 1499 | − if (streams[j] && streams[j] == pipe->stream && | |
| 1515 | + } | |
| 1516 | + | |
| 1517 | + for (j = 0; pipe && j < stream_count; j++) { | |
| 1518 | + if (should_update_pipe_for_stream(context, pipe, streams[j]) && | |
| 1500 | 1519 | dc->hwss.setup_stereo) |
| 1501 | 1520 | dc->hwss.setup_stereo(pipe, dc); |
| 1502 | 1521 | } |
| @@ -2629,6 +2648,7 @@ static void commit_planes_for_stream(struct dc *dc, · 1126 unmodified lines | ||
| 2629 | 2648 | { |
| 2630 | 2649 | int i, j; |
| 2631 | 2650 | struct pipe_ctx *top_pipe_to_program = NULL; |
| 2651 | + bool should_lock_all_pipes = (update_type != UPDATE_TYPE_FAST); | |
| 2632 | 2652 | |
| 2633 | 2653 | #if defined(CONFIG_DRM_AMD_DC_DCN) |
| 2634 | 2654 | dc_z10_restore(dc); |
| @@ -2700,7 +2720,7 @@ static void commit_planes_for_stream(struct dc *dc, · 65 unmodified lines | ||
| 2700 | 2720 | top_pipe_to_program->stream_res.tg); |
| 2701 | 2721 | } |
| 2702 | 2722 | |
| 2703 | − if ((update_type != UPDATE_TYPE_FAST) && dc->hwss.interdependent_update_lock) | |
| 2723 | + if (should_lock_all_pipes && dc->hwss.interdependent_update_lock) | |
| 2704 | 2724 | dc->hwss.interdependent_update_lock(dc, context, true); |
| 2705 | 2725 | else |
| 2706 | 2726 | /* Lock the top pipe while updating plane addrs, since freesync requires |
| @@ -2723,7 +2743,7 @@ static void commit_planes_for_stream(struct dc *dc, · 16 unmodified lines | ||
| 2723 | 2743 | if (dc->hwss.program_front_end_for_ctx) |
| 2724 | 2744 | dc->hwss.program_front_end_for_ctx(dc, context); |
| 2725 | 2745 | |
| 2726 | − if ((update_type != UPDATE_TYPE_FAST) && dc->hwss.interdependent_update_lock) | |
| 2746 | + if (should_lock_all_pipes && dc->hwss.interdependent_update_lock) | |
| 2727 | 2747 | dc->hwss.interdependent_update_lock(dc, context, false); |
| 2728 | 2748 | else |
| 2729 | 2749 | dc->hwss.pipe_control_lock(dc, top_pipe_to_program, false); |
| @@ -2739,14 +2759,14 @@ static void commit_planes_for_stream(struct dc *dc, · 9 unmodified lines | ||
| 2739 | 2759 | struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; |
| 2740 | 2760 | if (!pipe_ctx->plane_state) |
| 2741 | 2761 | continue; |
| 2742 | − if (pipe_ctx->plane_state != plane_state) | |
| 2762 | + if (should_update_pipe_for_plane(context, pipe_ctx, plane_state)) | |
| 2743 | 2763 | continue; |
| 2744 | − plane_state->triplebuffer_flips = false; | |
| 2764 | + pipe_ctx->plane_state->triplebuffer_flips = false; | |
| 2745 | 2765 | if (update_type == UPDATE_TYPE_FAST && |
| 2746 | 2766 | dc->hwss.program_triplebuffer != NULL && |
| 2747 | − !plane_state->flip_immediate && dc->debug.enable_tri_buf) { | |
| 2767 | + !pipe_ctx->plane_state->flip_immediate && dc->debug.enable_tri_buf) { | |
| 2748 | 2768 | /*triple buffer for VUpdate only*/ |
| 2749 | − plane_state->triplebuffer_flips = true; | |
| 2769 | + pipe_ctx->plane_state->triplebuffer_flips = true; | |
| 2750 | 2770 | } |
| 2751 | 2771 | } |
| 2752 | 2772 | if (update_type == UPDATE_TYPE_FULL) { |
| @@ -2762,8 +2782,7 @@ static void commit_planes_for_stream(struct dc *dc, · 9 unmodified lines | ||
| 2762 | 2782 | |
| 2763 | 2783 | if (!pipe_ctx->top_pipe && |
| 2764 | 2784 | !pipe_ctx->prev_odm_pipe && |
| 2765 | − pipe_ctx->stream && | |
| 2766 | − pipe_ctx->stream == stream) { | |
| 2785 | + should_update_pipe_for_stream(context, pipe_ctx, stream)) { | |
| 2767 | 2786 | struct dc_stream_status *stream_status = NULL; |
| 2768 | 2787 | |
| 2769 | 2788 | if (!pipe_ctx->plane_state) |
| @@ -2816,15 +2835,15 @@ static void commit_planes_for_stream(struct dc *dc, · 46 unmodified lines | ||
| 2816 | 2835 | for (j = 0; j < dc->res_pool->pipe_count; j++) { |
| 2817 | 2836 | struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; |
| 2818 | 2837 | |
| 2819 | − if (pipe_ctx->stream != stream) | |
| 2838 | + if (!should_update_pipe_for_stream(context, pipe_ctx, stream)) | |
| 2820 | 2839 | continue; |
| 2821 | 2840 | |
| 2822 | − if (pipe_ctx->plane_state != plane_state) | |
| 2841 | + if (!should_update_pipe_for_plane(context, pipe_ctx, plane_state)) | |
| 2823 | 2842 | continue; |
| 2824 | 2843 | |
| 2825 | 2844 | // GSL has to be used for flip immediate |
| 2826 | 2845 | dc->hwss.set_flip_control_gsl(pipe_ctx, |
| 2827 | − plane_state->flip_immediate); | |
| 2846 | + pipe_ctx->plane_state->flip_immediate); | |
| 2828 | 2847 | } |
| 2829 | 2848 | } |
| 2830 | 2849 | |
| @@ -2835,25 +2854,26 @@ static void commit_planes_for_stream(struct dc *dc, · 4 unmodified lines | ||
| 2835 | 2854 | for (j = 0; j < dc->res_pool->pipe_count; j++) { |
| 2836 | 2855 | struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; |
| 2837 | 2856 | |
| 2838 | − if (pipe_ctx->stream != stream) | |
| 2857 | + if (!should_update_pipe_for_stream(context, pipe_ctx, stream)) | |
| 2839 | 2858 | continue; |
| 2840 | 2859 | |
| 2841 | − if (pipe_ctx->plane_state != plane_state) | |
| 2860 | + if (!should_update_pipe_for_plane(context, pipe_ctx, plane_state)) | |
| 2842 | 2861 | continue; |
| 2862 | + | |
| 2843 | 2863 | /*program triple buffer after lock based on flip type*/ |
| 2844 | 2864 | if (dc->hwss.program_triplebuffer != NULL && dc->debug.enable_tri_buf) { |
| 2845 | 2865 | /*only enable triplebuffer for fast_update*/ |
| 2846 | 2866 | dc->hwss.program_triplebuffer( |
| 2847 | − dc, pipe_ctx, plane_state->triplebuffer_flips); | |
| 2867 | + dc, pipe_ctx, pipe_ctx->plane_state->triplebuffer_flips); | |
| 2848 | 2868 | } |
| 2849 | − if (srf_updates[i].flip_addr) | |
| 2869 | + if (pipe_ctx->plane_state->update_flags.bits.addr_update) | |
| 2850 | 2870 | dc->hwss.update_plane_addr(dc, pipe_ctx); |
| 2851 | 2871 | } |
| 2852 | 2872 | } |
| 2853 | 2873 | |
| 2854 | 2874 | } |
| 2855 | 2875 | |
| 2856 | − if ((update_type != UPDATE_TYPE_FAST) && dc->hwss.interdependent_update_lock) | |
| 2876 | + if (should_lock_all_pipes && dc->hwss.interdependent_update_lock) | |
| 2857 | 2877 | dc->hwss.interdependent_update_lock(dc, context, false); |
| 2858 | 2878 | else |
| 2859 | 2879 | dc->hwss.pipe_control_lock(dc, top_pipe_to_program, false); |
| @@ -2897,7 +2917,7 @@ static void commit_planes_for_stream(struct dc *dc, · 37 unmodified lines | ||
| 2897 | 2917 | continue; |
| 2898 | 2918 | |
| 2899 | 2919 | if (pipe_ctx->bottom_pipe || pipe_ctx->next_odm_pipe || |
| 2900 | − !pipe_ctx->stream || pipe_ctx->stream != stream || | |
| 2920 | + !pipe_ctx->stream || !should_update_pipe_for_stream(context, pipe_ctx, stream) || | |
| 2901 | 2921 | !pipe_ctx->plane_state->update_flags.bits.addr_update || |
| 2902 | 2922 | pipe_ctx->plane_state->skip_manual_trigger) |
| 2903 | 2923 | continue; |
| @@ -541,6 +541,7 @@ static void link_disconnect_sink(struct dc_link *link) · 540 unmodified lines | ||
| 541 | 541 | } |
| 542 | 542 | |
| 543 | 543 | link->dpcd_sink_count = 0; |
| 544 | + //link->dpcd_caps.dpcd_rev.raw = 0; | |
| 544 | 545 | } |
| 545 | 546 | |
| 546 | 547 | static void link_disconnect_remap(struct dc_sink *prev_sink, struct dc_link *link) |
| @@ -742,6 +743,7 @@ static bool detect_dp(struct dc_link *link, · 195 unmodified lines | ||
| 742 | 743 | sink_caps, |
| 743 | 744 | audio_support); |
| 744 | 745 | link->dpcd_caps.dongle_type = sink_caps->dongle_type; |
| 746 | + link->dpcd_caps.dpcd_rev.raw = 0; | |
| 745 | 747 | } |
| 746 | 748 | |
| 747 | 749 | return true; |
| @@ -1663,6 +1665,12 @@ struct dc_link *link_create(const struct link_init_data *init_params) · 915 unmodified lines | ||
| 1663 | 1665 | if (false == dc_link_construct(link, init_params)) |
| 1664 | 1666 | goto construct_fail; |
| 1665 | 1667 | |
| 1668 | + /* | |
| 1669 | + * Must use preferred_link_setting, not reported_link_cap or verified_link_cap, | |
| 1670 | + * since struct preferred_link_setting won't be reset after S3. | |
| 1671 | + */ | |
| 1672 | + link->preferred_link_setting.dpcd_source_device_specific_field_support = true; | |
| 1673 | + | |
| 1666 | 1674 | return link; |
| 1667 | 1675 | |
| 1668 | 1676 | construct_fail: |
| @@ -3509,61 +3517,6 @@ void dc_link_enable_hpd_filter(struct dc_link *link, bool enable) · 1840 unmodified lines | ||
| 3509 | 3517 | } |
| 3510 | 3518 | } |
| 3511 | 3519 | |
| 3512 | −uint32_t dc_bandwidth_in_kbps_from_timing( | |
| 3513 | − const struct dc_crtc_timing *timing) | |
| 3514 | −{ | |
| 3515 | − uint32_t bits_per_channel = 0; | |
| 3516 | − uint32_t kbps; | |
| 3517 | − | |
| 3518 | −#if defined(CONFIG_DRM_AMD_DC_DCN) | |
| 3519 | − if (timing->flags.DSC) | |
| 3520 | − return dc_dsc_stream_bandwidth_in_kbps(timing, | |
| 3521 | − timing->dsc_cfg.bits_per_pixel, | |
| 3522 | − timing->dsc_cfg.num_slices_h, | |
| 3523 | − timing->dsc_cfg.is_dp); | |
| 3524 | −#endif | |
| 3525 | − | |
| 3526 | − switch (timing->display_color_depth) { | |
| 3527 | − case COLOR_DEPTH_666: | |
| 3528 | − bits_per_channel = 6; | |
| 3529 | − break; | |
| 3530 | − case COLOR_DEPTH_888: | |
| 3531 | − bits_per_channel = 8; | |
| 3532 | − break; | |
| 3533 | − case COLOR_DEPTH_101010: | |
| 3534 | − bits_per_channel = 10; | |
| 3535 | − break; | |
| 3536 | − case COLOR_DEPTH_121212: | |
| 3537 | − bits_per_channel = 12; | |
| 3538 | − break; | |
| 3539 | − case COLOR_DEPTH_141414: | |
| 3540 | − bits_per_channel = 14; | |
| 3541 | − break; | |
| 3542 | − case COLOR_DEPTH_161616: | |
| 3543 | − bits_per_channel = 16; | |
| 3544 | − break; | |
| 3545 | − default: | |
| 3546 | − ASSERT(bits_per_channel != 0); | |
| 3547 | − bits_per_channel = 8; | |
| 3548 | − break; | |
| 3549 | − } | |
| 3550 | − | |
| 3551 | − kbps = timing->pix_clk_100hz / 10; | |
| 3552 | − kbps *= bits_per_channel; | |
| 3553 | − | |
| 3554 | − if (timing->flags.Y_ONLY != 1) { | |
| 3555 | − /*Only YOnly make reduce bandwidth by 1/3 compares to RGB*/ | |
| 3556 | − kbps *= 3; | |
| 3557 | − if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR420) | |
| 3558 | − kbps /= 2; | |
| 3559 | − else if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR422) | |
| 3560 | − kbps = kbps * 2 / 3; | |
| 3561 | − } | |
| 3562 | − | |
| 3563 | − return kbps; | |
| 3564 | − | |
| 3565 | −} | |
| 3566 | − | |
| 3567 | 3520 | void dc_link_set_drive_settings(struct dc *dc, |
| 3568 | 3521 | struct link_training_settings *lt_settings, |
| 3569 | 3522 | const struct dc_link *link) |
| @@ -3769,3 +3722,58 @@ bool dc_link_should_enable_fec(const struct dc_link *link) · 199 unmodified lines | ||
| 3769 | 3722 | |
| 3770 | 3723 | return ret; |
| 3771 | 3724 | } |
| 3725 | + | |
| 3726 | +uint32_t dc_bandwidth_in_kbps_from_timing( | |
| 3727 | + const struct dc_crtc_timing *timing) | |
| 3728 | +{ | |
| 3729 | + uint32_t bits_per_channel = 0; | |
| 3730 | + uint32_t kbps; | |
| 3731 | + | |
| 3732 | +#if defined(CONFIG_DRM_AMD_DC_DCN) | |
| 3733 | + if (timing->flags.DSC) | |
| 3734 | + return dc_dsc_stream_bandwidth_in_kbps(timing, | |
| 3735 | + timing->dsc_cfg.bits_per_pixel, | |
| 3736 | + timing->dsc_cfg.num_slices_h, | |
| 3737 | + timing->dsc_cfg.is_dp); | |
| 3738 | +#endif | |
| 3739 | + | |
| 3740 | + switch (timing->display_color_depth) { | |
| 3741 | + case COLOR_DEPTH_666: | |
| 3742 | + bits_per_channel = 6; | |
| 3743 | + break; | |
| 3744 | + case COLOR_DEPTH_888: | |
| 3745 | + bits_per_channel = 8; | |
| 3746 | + break; | |
| 3747 | + case COLOR_DEPTH_101010: | |
| 3748 | + bits_per_channel = 10; | |
| 3749 | + break; | |
| 3750 | + case COLOR_DEPTH_121212: | |
| 3751 | + bits_per_channel = 12; | |
| 3752 | + break; | |
| 3753 | + case COLOR_DEPTH_141414: | |
| 3754 | + bits_per_channel = 14; | |
| 3755 | + break; | |
| 3756 | + case COLOR_DEPTH_161616: | |
| 3757 | + bits_per_channel = 16; | |
| 3758 | + break; | |
| 3759 | + default: | |
| 3760 | + ASSERT(bits_per_channel != 0); | |
| 3761 | + bits_per_channel = 8; | |
| 3762 | + break; | |
| 3763 | + } | |
| 3764 | + | |
| 3765 | + kbps = timing->pix_clk_100hz / 10; | |
| 3766 | + kbps *= bits_per_channel; | |
| 3767 | + | |
| 3768 | + if (timing->flags.Y_ONLY != 1) { | |
| 3769 | + /*Only YOnly make reduce bandwidth by 1/3 compares to RGB*/ | |
| 3770 | + kbps *= 3; | |
| 3771 | + if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR420) | |
| 3772 | + kbps /= 2; | |
| 3773 | + else if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR422) | |
| 3774 | + kbps = kbps * 2 / 3; | |
| 3775 | + } | |
| 3776 | + | |
| 3777 | + return kbps; | |
| 3778 | + | |
| 3779 | +} | |
| @@ -1241,29 +1241,15 @@ enum link_training_result dp_check_link_loss_status( · 1240 unmodified lines | ||
| 1241 | 1241 | static inline void decide_8b_10b_training_settings( |
| 1242 | 1242 | struct dc_link *link, |
| 1243 | 1243 | const struct dc_link_settings *link_setting, |
| 1244 | − const struct dc_link_training_overrides *overrides, | |
| 1245 | 1244 | struct link_training_settings *lt_settings) |
| 1246 | 1245 | { |
| 1247 | − uint32_t lane; | |
| 1248 | − | |
| 1249 | 1246 | memset(lt_settings, '\0', sizeof(struct link_training_settings)); |
| 1250 | 1247 | |
| 1251 | 1248 | /* Initialize link settings */ |
| 1252 | 1249 | lt_settings->link_settings.use_link_rate_set = link_setting->use_link_rate_set; |
| 1253 | 1250 | lt_settings->link_settings.link_rate_set = link_setting->link_rate_set; |
| 1254 | − | |
| 1255 | − if (link->preferred_link_setting.link_rate != LINK_RATE_UNKNOWN) | |
| 1256 | − lt_settings->link_settings.link_rate = link->preferred_link_setting.link_rate; | |
| 1257 | − else | |
| 1258 | − lt_settings->link_settings.link_rate = link_setting->link_rate; | |
| 1259 | − | |
| 1260 | − if (link->preferred_link_setting.lane_count != LANE_COUNT_UNKNOWN) | |
| 1261 | − lt_settings->link_settings.lane_count = link->preferred_link_setting.lane_count; | |
| 1262 | − else | |
| 1263 | − lt_settings->link_settings.lane_count = link_setting->lane_count; | |
| 1264 | − | |
| 1265 | − /*@todo[vdevulap] move SS to LS, should not be handled by displaypath*/ | |
| 1266 | − | |
| 1251 | + lt_settings->link_settings.link_rate = link_setting->link_rate; | |
| 1252 | + lt_settings->link_settings.lane_count = link_setting->lane_count; | |
| 1267 | 1253 | /* TODO hard coded to SS for now |
| 1268 | 1254 | * lt_settings.link_settings.link_spread = |
| 1269 | 1255 | * dal_display_path_is_ss_supported( |
| @@ -1271,30 +1257,52 @@ static inline void decide_8b_10b_training_settings( · 1 unmodified line | ||
| 1271 | 1257 | * LINK_SPREAD_05_DOWNSPREAD_30KHZ : |
| 1272 | 1258 | * LINK_SPREAD_DISABLED; |
| 1273 | 1259 | */ |
| 1274 | − /* Initialize link spread */ | |
| 1275 | − if (link->dp_ss_off) | |
| 1276 | − lt_settings->link_settings.link_spread = LINK_SPREAD_DISABLED; | |
| 1277 | − else if (overrides->downspread != NULL) | |
| 1278 | − lt_settings->link_settings.link_spread | |
| 1279 | − = *overrides->downspread | |
| 1280 | − ? LINK_SPREAD_05_DOWNSPREAD_30KHZ | |
| 1281 | − : LINK_SPREAD_DISABLED; | |
| 1282 | − else | |
| 1283 | − lt_settings->link_settings.link_spread = LINK_SPREAD_05_DOWNSPREAD_30KHZ; | |
| 1284 | − | |
| 1260 | + lt_settings->link_settings.link_spread = link->dp_ss_off ? | |
| 1261 | + LINK_SPREAD_DISABLED : LINK_SPREAD_05_DOWNSPREAD_30KHZ; | |
| 1285 | 1262 | lt_settings->lttpr_mode = link->lttpr_mode; |
| 1263 | + lt_settings->cr_pattern_time = get_cr_training_aux_rd_interval(link, link_setting); | |
| 1264 | + lt_settings->eq_pattern_time = get_eq_training_aux_rd_interval(link, link_setting); | |
| 1265 | + lt_settings->pattern_for_cr = decide_cr_training_pattern(link_setting); | |
| 1266 | + lt_settings->pattern_for_eq = decide_eq_training_pattern(link, link_setting); | |
| 1267 | + lt_settings->enhanced_framing = 1; | |
| 1268 | + lt_settings->should_set_fec_ready = true; | |
| 1269 | +} | |
| 1270 | + | |
| 1271 | +void dp_decide_training_settings( | |
| 1272 | + struct dc_link *link, | |
| 1273 | + const struct dc_link_settings *link_settings, | |
| 1274 | + struct link_training_settings *lt_settings) | |
| 1275 | +{ | |
| 1276 | + if (dp_get_link_encoding_format(link_settings) == DP_8b_10b_ENCODING) | |
| 1277 | + decide_8b_10b_training_settings(link, link_settings, lt_settings); | |
| 1278 | +} | |
| 1279 | + | |
| 1280 | +static void override_training_settings( | |
| 1281 | + struct dc_link *link, | |
| 1282 | + const struct dc_link_training_overrides *overrides, | |
| 1283 | + struct link_training_settings *lt_settings) | |
| 1284 | +{ | |
| 1285 | + uint32_t lane; | |
| 1286 | + | |
| 1287 | + /* Override link settings */ | |
| 1288 | + if (link->preferred_link_setting.link_rate != LINK_RATE_UNKNOWN) | |
| 1289 | + lt_settings->link_settings.link_rate = link->preferred_link_setting.link_rate; | |
| 1290 | + if (link->preferred_link_setting.lane_count != LANE_COUNT_UNKNOWN) | |
| 1291 | + lt_settings->link_settings.lane_count = link->preferred_link_setting.lane_count; | |
| 1292 | + | |
| 1293 | + /* Override link spread */ | |
| 1294 | + if (!link->dp_ss_off && overrides->downspread != NULL) | |
| 1295 | + lt_settings->link_settings.link_spread = *overrides->downspread ? | |
| 1296 | + LINK_SPREAD_05_DOWNSPREAD_30KHZ | |
| 1297 | + : LINK_SPREAD_DISABLED; | |
| 1286 | 1298 | |
| 1287 | − /* Initialize lane settings overrides */ | |
| 1299 | + /* Override lane settings */ | |
| 1288 | 1300 | if (overrides->voltage_swing != NULL) |
| 1289 | 1301 | lt_settings->voltage_swing = overrides->voltage_swing; |
| 1290 | − | |
| 1291 | 1302 | if (overrides->pre_emphasis != NULL) |
| 1292 | 1303 | lt_settings->pre_emphasis = overrides->pre_emphasis; |
| 1293 | − | |
| 1294 | 1304 | if (overrides->post_cursor2 != NULL) |
| 1295 | 1305 | lt_settings->post_cursor2 = overrides->post_cursor2; |
| 1296 | − | |
| 1297 | − /* Initialize lane settings (VS/PE/PC2) */ | |
| 1298 | 1306 | for (lane = 0; lane < LANE_COUNT_DP_MAX; lane++) { |
| 1299 | 1307 | lt_settings->lane_settings[lane].VOLTAGE_SWING = |
| 1300 | 1308 | lt_settings->voltage_swing != NULL ? |
| @@ -1313,45 +1321,22 @@ static inline void decide_8b_10b_training_settings( · 12 unmodified lines | ||
| 1313 | 1321 | /* Initialize training timings */ |
| 1314 | 1322 | if (overrides->cr_pattern_time != NULL) |
| 1315 | 1323 | lt_settings->cr_pattern_time = *overrides->cr_pattern_time; |
| 1316 | − else | |
| 1317 | − lt_settings->cr_pattern_time = get_cr_training_aux_rd_interval(link, link_setting); | |
| 1318 | 1324 | |
| 1319 | 1325 | if (overrides->eq_pattern_time != NULL) |
| 1320 | 1326 | lt_settings->eq_pattern_time = *overrides->eq_pattern_time; |
| 1321 | − else | |
| 1322 | − lt_settings->eq_pattern_time = get_eq_training_aux_rd_interval(link, link_setting); | |
| 1323 | 1327 | |
| 1324 | 1328 | if (overrides->pattern_for_cr != NULL) |
| 1325 | 1329 | lt_settings->pattern_for_cr = *overrides->pattern_for_cr; |
| 1326 | − else | |
| 1327 | − lt_settings->pattern_for_cr = decide_cr_training_pattern(link_setting); | |
| 1328 | 1330 | if (overrides->pattern_for_eq != NULL) |
| 1329 | 1331 | lt_settings->pattern_for_eq = *overrides->pattern_for_eq; |
| 1330 | − else | |
| 1331 | − lt_settings->pattern_for_eq = decide_eq_training_pattern(link, link_setting); | |
| 1332 | 1332 | |
| 1333 | 1333 | if (overrides->enhanced_framing != NULL) |
| 1334 | 1334 | lt_settings->enhanced_framing = *overrides->enhanced_framing; |
| 1335 | − else | |
| 1336 | − lt_settings->enhanced_framing = 1; | |
| 1337 | 1335 | |
| 1338 | 1336 | if (link->preferred_training_settings.fec_enable != NULL) |
| 1339 | 1337 | lt_settings->should_set_fec_ready = *link->preferred_training_settings.fec_enable; |
| 1340 | − else | |
| 1341 | − lt_settings->should_set_fec_ready = true; | |
| 1342 | −} | |
| 1343 | − | |
| 1344 | −void dp_decide_training_settings( | |
| 1345 | − struct dc_link *link, | |
| 1346 | − const struct dc_link_settings *link_settings, | |
| 1347 | − const struct dc_link_training_overrides *overrides, | |
| 1348 | − struct link_training_settings *lt_settings) | |
| 1349 | −{ | |
| 1350 | − if (dp_get_link_encoding_format(link_settings) == DP_8b_10b_ENCODING) | |
| 1351 | − decide_8b_10b_training_settings(link, link_settings, overrides, lt_settings); | |
| 1352 | 1338 | } |
| 1353 | 1339 | |
| 1354 | − | |
| 1355 | 1340 | uint8_t dp_convert_to_count(uint8_t lttpr_repeater_count) |
| 1356 | 1341 | { |
| 1357 | 1342 | switch (lttpr_repeater_count) { |
| @@ -1581,6 +1566,9 @@ bool dc_link_dp_perform_link_training_skip_aux( · 223 unmodified lines | ||
| 1581 | 1566 | dp_decide_training_settings( |
| 1582 | 1567 | link, |
| 1583 | 1568 | link_setting, |
| 1569 | + <_settings); | |
| 1570 | + override_training_settings( | |
| 1571 | + link, | |
| 1584 | 1572 | &link->preferred_training_settings, |
| 1585 | 1573 | <_settings); |
| 1586 | 1574 | |
| @@ -1727,6 +1715,9 @@ enum link_training_result dc_link_dp_perform_link_training( · 140 unmodified lines | ||
| 1727 | 1715 | dp_decide_training_settings( |
| 1728 | 1716 | link, |
| 1729 | 1717 | link_settings, |
| 1718 | + <_settings); | |
| 1719 | + override_training_settings( | |
| 1720 | + link, | |
| 1730 | 1721 | &link->preferred_training_settings, |
| 1731 | 1722 | <_settings); |
| 1732 | 1723 | |
| @@ -1939,11 +1930,13 @@ enum link_training_result dc_link_dp_sync_lt_attempt( · 206 unmodified lines | ||
| 1939 | 1930 | bool fec_enable = false; |
| 1940 | 1931 | |
| 1941 | 1932 | dp_decide_training_settings( |
| 1942 | − link, | |
| 1943 | − link_settings, | |
| 1944 | − lt_overrides, | |
| 1945 | − <_settings); | |
| 1946 | − | |
| 1933 | + link, | |
| 1934 | + link_settings, | |
| 1935 | + <_settings); | |
| 1936 | + override_training_settings( | |
| 1937 | + link, | |
| 1938 | + lt_overrides, | |
| 1939 | + <_settings); | |
| 1947 | 1940 | /* Setup MST Mode */ |
| 1948 | 1941 | if (lt_overrides->mst_enable) |
| 1949 | 1942 | set_dp_mst_mode(link, *lt_overrides->mst_enable); |
| @@ -4776,10 +4769,18 @@ void dpcd_set_source_specific_data(struct dc_link *link) · 2826 unmodified lines | ||
| 4776 | 4769 | |
| 4777 | 4770 | uint8_t hblank_size = (uint8_t)link->dc->caps.min_horizontal_blanking_period; |
| 4778 | 4771 | |
| 4779 | − result_write_min_hblank = core_link_write_dpcd(link, | |
| 4780 | − DP_SOURCE_MINIMUM_HBLANK_SUPPORTED, (uint8_t *)(&hblank_size), | |
| 4781 | − sizeof(hblank_size)); | |
| 4772 | + if (link->preferred_link_setting.dpcd_source_device_specific_field_support) { | |
| 4773 | + result_write_min_hblank = core_link_write_dpcd(link, | |
| 4774 | + DP_SOURCE_MINIMUM_HBLANK_SUPPORTED, (uint8_t *)(&hblank_size), | |
| 4775 | + sizeof(hblank_size)); | |
| 4776 | + | |
| 4777 | + if (result_write_min_hblank == DC_ERROR_UNEXPECTED) | |
| 4778 | + link->preferred_link_setting.dpcd_source_device_specific_field_support = false; | |
| 4779 | + } else { | |
| 4780 | + DC_LOG_DC("Sink device does not support 00340h DPCD write. Skipping on purpose.\n"); | |
| 4781 | + } | |
| 4782 | 4782 | } |
| 4783 | + | |
| 4783 | 4784 | DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_INFORMATION, |
| 4784 | 4785 | WPP_BIT_FLAG_DC_DETECTION_DP_CAPS, |
| 4785 | 4786 | "result=%u link_index=%u enum dce_version=%d DPCD=0x%04X min_hblank=%u branch_dev_id=0x%x branch_dev_name='%c%c%c%c%c%c'", |
| @@ -1,3 +1,28 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright 2021 Advanced Micro Devices, Inc. | |
| 3 | + * | |
| 4 | + * Permission is hereby granted, free of charge, to any person obtaining a | |
| 5 | + * copy of this software and associated documentation files (the "Software"), | |
| 6 | + * to deal in the Software without restriction, including without limitation | |
| 7 | + * the rights to use, copy, modify, merge, publish, distribute, sublicense, | |
| 8 | + * and/or sell copies of the Software, and to permit persons to whom the | |
| 9 | + * Software is furnished to do so, subject to the following conditions: | |
| 10 | + * | |
| 11 | + * The above copyright notice and this permission notice shall be included in | |
| 12 | + * all copies or substantial portions of the Software. | |
| 13 | + * | |
| 14 | + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
| 15 | + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
| 16 | + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |
| 17 | + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR | |
| 18 | + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | |
| 19 | + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | |
| 20 | + * OTHER DEALINGS IN THE SOFTWARE. | |
| 21 | + * | |
| 22 | + * Authors: AMD | |
| 23 | + * | |
| 24 | + */ | |
| 25 | + | |
| 1 | 26 | #include <inc/core_status.h> |
| 2 | 27 | #include <dc_link.h> |
| 3 | 28 | #include <inc/link_hwss.h> |
| @@ -305,7 +305,7 @@ struct link_encoder *link_enc_cfg_get_next_avail_link_enc( · 304 unmodified lines | ||
| 305 | 305 | const struct dc_state *state) |
| 306 | 306 | { |
| 307 | 307 | struct link_encoder *link_enc = NULL; |
| 308 | − enum engine_id eng_id = ENGINE_ID_UNKNOWN; | |
| 308 | + enum engine_id eng_id; | |
| 309 | 309 | |
| 310 | 310 | eng_id = find_first_avail_link_enc(dc->ctx, state); |
| 311 | 311 | if (eng_id != ENGINE_ID_UNKNOWN) |
| @@ -1030,7 +1030,7 @@ bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx) · 1029 unmodified lines | ||
| 1030 | 1030 | |
| 1031 | 1031 | /* Timing borders are part of vactive that we are also supposed to skip in addition |
| 1032 | 1032 | * to any stream dst offset. Since dm logic assumes dst is in addressable |
| 1033 | − * space we need to add the the left and top borders to dst offsets temporarily. | |
| 1033 | + * space we need to add the left and top borders to dst offsets temporarily. | |
| 1034 | 1034 | * TODO: fix in DM, stream dst is supposed to be in vactive |
| 1035 | 1035 | */ |
| 1036 | 1036 | pipe_ctx->stream->dst.x += timing->h_border_left; |
| @@ -1051,6 +1051,11 @@ bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx) · 14 unmodified lines | ||
| 1051 | 1051 | /* depends on scaling ratios and recout, does not calculate offset yet */ |
| 1052 | 1052 | calculate_viewport_size(pipe_ctx); |
| 1053 | 1053 | |
| 1054 | + /* Stopgap for validation of ODM + MPO on one side of screen case */ | |
| 1055 | + if (pipe_ctx->plane_res.scl_data.viewport.height < 1 || | |
| 1056 | + pipe_ctx->plane_res.scl_data.viewport.width < 1) | |
| 1057 | + return false; | |
| 1058 | + | |
| 1054 | 1059 | /* |
| 1055 | 1060 | * LB calculations depend on vp size, h/v_active and scaling ratios |
| 1056 | 1061 | * Setting line buffer pixel depth to 24bpp yields banding |
| @@ -62,3 +62,27 @@ void dc_stat_get_dmub_notification(const struct dc *dc, struct dmub_notification · 61 unmodified lines | ||
| 62 | 62 | status = dmub_srv_stat_get_notification(dmub, notify); |
| 63 | 63 | ASSERT(status == DMUB_STATUS_OK); |
| 64 | 64 | } |
| 65 | + | |
| 66 | +/** | |
| 67 | + ***************************************************************************** | |
| 68 | + * Function: dc_stat_get_dmub_dataout | |
| 69 | + * | |
| 70 | + * @brief | |
| 71 | + * Calls dmub layer to retrieve dmub gpint dataout | |
| 72 | + * | |
| 73 | + * @param | |
| 74 | + * [in] dc: dc structure | |
| 75 | + * [in] dataout: dmub gpint dataout | |
| 76 | + * | |
| 77 | + * @return | |
| 78 | + * None | |
| 79 | + ***************************************************************************** | |
| 80 | + */ | |
| 81 | +void dc_stat_get_dmub_dataout(const struct dc *dc, uint32_t *dataout) | |
| 82 | +{ | |
| 83 | + struct dmub_srv *dmub = dc->ctx->dmub_srv->dmub; | |
| 84 | + enum dmub_status status; | |
| 85 | + | |
| 86 | + status = dmub_srv_get_gpint_dataout(dmub, dataout); | |
| 87 | + ASSERT(status == DMUB_STATUS_OK); | |
| 88 | +} | |
| @@ -221,6 +221,9 @@ struct dc_stream_status *dc_stream_get_status_from_state( · 220 unmodified lines | ||
| 221 | 221 | { |
| 222 | 222 | uint8_t i; |
| 223 | 223 | |
| 224 | + if (state == NULL) | |
| 225 | + return NULL; | |
| 226 | + | |
| 224 | 227 | for (i = 0; i < state->stream_count; i++) { |
| 225 | 228 | if (stream == state->streams[i]) |
| 226 | 229 | return &state->stream_status[i]; |
| @@ -243,6 +246,40 @@ struct dc_stream_status *dc_stream_get_status( · 16 unmodified lines | ||
| 243 | 246 | return dc_stream_get_status_from_state(dc->current_state, stream); |
| 244 | 247 | } |
| 245 | 248 | |
| 249 | +static void program_cursor_attributes( | |
| 250 | + struct dc *dc, | |
| 251 | + struct dc_stream_state *stream, | |
| 252 | + const struct dc_cursor_attributes *attributes) | |
| 253 | +{ | |
| 254 | + int i; | |
| 255 | + struct resource_context *res_ctx; | |
| 256 | + struct pipe_ctx *pipe_to_program = NULL; | |
| 257 | + | |
| 258 | + if (!stream) | |
| 259 | + return; | |
| 260 | + | |
| 261 | + res_ctx = &dc->current_state->res_ctx; | |
| 262 | + | |
| 263 | + for (i = 0; i < MAX_PIPES; i++) { | |
| 264 | + struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i]; | |
| 265 | + | |
| 266 | + if (pipe_ctx->stream != stream) | |
| 267 | + continue; | |
| 268 | + | |
| 269 | + if (!pipe_to_program) { | |
| 270 | + pipe_to_program = pipe_ctx; | |
| 271 | + dc->hwss.cursor_lock(dc, pipe_to_program, true); | |
| 272 | + } | |
| 273 | + | |
| 274 | + dc->hwss.set_cursor_attribute(pipe_ctx); | |
| 275 | + if (dc->hwss.set_cursor_sdr_white_level) | |
| 276 | + dc->hwss.set_cursor_sdr_white_level(pipe_ctx); | |
| 277 | + } | |
| 278 | + | |
| 279 | + if (pipe_to_program) | |
| 280 | + dc->hwss.cursor_lock(dc, pipe_to_program, false); | |
| 281 | +} | |
| 282 | + | |
| 246 | 283 | #ifndef TRIM_FSFT |
| 247 | 284 | /* |
| 248 | 285 | * dc_optimize_timing_for_fsft() - dc to optimize timing |
| @@ -267,10 +304,7 @@ bool dc_stream_set_cursor_attributes( · 18 unmodified lines | ||
| 267 | 304 | struct dc_stream_state *stream, |
| 268 | 305 | const struct dc_cursor_attributes *attributes) |
| 269 | 306 | { |
| 270 | − int i; | |
| 271 | 307 | struct dc *dc; |
| 272 | − struct resource_context *res_ctx; | |
| 273 | − struct pipe_ctx *pipe_to_program = NULL; | |
| 274 | 308 | #if defined(CONFIG_DRM_AMD_DC_DCN) |
| 275 | 309 | bool reset_idle_optimizations = false; |
| 276 | 310 | #endif |
| @@ -290,7 +324,6 @@ bool dc_stream_set_cursor_attributes( · 13 unmodified lines | ||
| 290 | 324 | } |
| 291 | 325 | |
| 292 | 326 | dc = stream->ctx->dc; |
| 293 | − res_ctx = &dc->current_state->res_ctx; | |
| 294 | 327 | stream->cursor_attributes = *attributes; |
| 295 | 328 | |
| 296 | 329 | #if defined(CONFIG_DRM_AMD_DC_DCN) |
| @@ -302,11 +335,39 @@ bool dc_stream_set_cursor_attributes( · 5 unmodified lines | ||
| 302 | 335 | } |
| 303 | 336 | |
| 304 | 337 | #endif |
| 338 | + program_cursor_attributes(dc, stream, attributes); | |
| 339 | + | |
| 340 | +#if defined(CONFIG_DRM_AMD_DC_DCN) | |
| 341 | + /* re-enable idle optimizations if necessary */ | |
| 342 | + if (reset_idle_optimizations) | |
| 343 | + dc_allow_idle_optimizations(dc, true); | |
| 344 | + | |
| 345 | +#endif | |
| 346 | + return true; | |
| 347 | +} | |
| 348 | + | |
| 349 | +static void program_cursor_position( | |
| 350 | + struct dc *dc, | |
| 351 | + struct dc_stream_state *stream, | |
| 352 | + const struct dc_cursor_position *position) | |
| 353 | +{ | |
| 354 | + int i; | |
| 355 | + struct resource_context *res_ctx; | |
| 356 | + struct pipe_ctx *pipe_to_program = NULL; | |
| 357 | + | |
| 358 | + if (!stream) | |
| 359 | + return; | |
| 360 | + | |
| 361 | + res_ctx = &dc->current_state->res_ctx; | |
| 305 | 362 | |
| 306 | 363 | for (i = 0; i < MAX_PIPES; i++) { |
| 307 | 364 | struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i]; |
| 308 | 365 | |
| 309 | − if (pipe_ctx->stream != stream) | |
| 366 | + if (pipe_ctx->stream != stream || | |
| 367 | + (!pipe_ctx->plane_res.mi && !pipe_ctx->plane_res.hubp) || | |
| 368 | + !pipe_ctx->plane_state || | |
| 369 | + (!pipe_ctx->plane_res.xfm && !pipe_ctx->plane_res.dpp) || | |
| 370 | + (!pipe_ctx->plane_res.ipp && !pipe_ctx->plane_res.dpp)) | |
| 310 | 371 | continue; |
| 311 | 372 | |
| 312 | 373 | if (!pipe_to_program) { |
| @@ -314,31 +375,18 @@ bool dc_stream_set_cursor_attributes( · 1 unmodified line | ||
| 314 | 375 | dc->hwss.cursor_lock(dc, pipe_to_program, true); |
| 315 | 376 | } |
| 316 | 377 | |
| 317 | − dc->hwss.set_cursor_attribute(pipe_ctx); | |
| 318 | − if (dc->hwss.set_cursor_sdr_white_level) | |
| 319 | − dc->hwss.set_cursor_sdr_white_level(pipe_ctx); | |
| 378 | + dc->hwss.set_cursor_position(pipe_ctx); | |
| 320 | 379 | } |
| 321 | 380 | |
| 322 | 381 | if (pipe_to_program) |
| 323 | 382 | dc->hwss.cursor_lock(dc, pipe_to_program, false); |
| 324 | − | |
| 325 | −#if defined(CONFIG_DRM_AMD_DC_DCN) | |
| 326 | − /* re-enable idle optimizations if necessary */ | |
| 327 | − if (reset_idle_optimizations) | |
| 328 | − dc_allow_idle_optimizations(dc, true); | |
| 329 | − | |
| 330 | −#endif | |
| 331 | − return true; | |
| 332 | 383 | } |
| 333 | 384 | |
| 334 | 385 | bool dc_stream_set_cursor_position( |
| 335 | 386 | struct dc_stream_state *stream, |
| 336 | 387 | const struct dc_cursor_position *position) |
| 337 | 388 | { |
| 338 | − int i; | |
| 339 | 389 | struct dc *dc; |
| 340 | − struct resource_context *res_ctx; | |
| 341 | − struct pipe_ctx *pipe_to_program = NULL; | |
| 342 | 390 | #if defined(CONFIG_DRM_AMD_DC_DCN) |
| 343 | 391 | bool reset_idle_optimizations = false; |
| 344 | 392 | #endif |
| @@ -354,7 +402,6 @@ bool dc_stream_set_cursor_position( · 9 unmodified lines | ||
| 354 | 402 | } |
| 355 | 403 | |
| 356 | 404 | dc = stream->ctx->dc; |
| 357 | − res_ctx = &dc->current_state->res_ctx; | |
| 358 | 405 | #if defined(CONFIG_DRM_AMD_DC_DCN) |
| 359 | 406 | dc_z10_restore(dc); |
| 360 | 407 | |
| @@ -367,27 +414,7 @@ bool dc_stream_set_cursor_position( · 6 unmodified lines | ||
| 367 | 414 | #endif |
| 368 | 415 | stream->cursor_position = *position; |
| 369 | 416 | |
| 370 | − for (i = 0; i < MAX_PIPES; i++) { | |
| 371 | − struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i]; | |
| 372 | − | |
| 373 | − if (pipe_ctx->stream != stream || | |
| 374 | − (!pipe_ctx->plane_res.mi && !pipe_ctx->plane_res.hubp) || | |
| 375 | − !pipe_ctx->plane_state || | |
| 376 | − (!pipe_ctx->plane_res.xfm && !pipe_ctx->plane_res.dpp) || | |
| 377 | − (!pipe_ctx->plane_res.ipp && !pipe_ctx->plane_res.dpp)) | |
| 378 | − continue; | |
| 379 | − | |
| 380 | − if (!pipe_to_program) { | |
| 381 | − pipe_to_program = pipe_ctx; | |
| 382 | − dc->hwss.cursor_lock(dc, pipe_to_program, true); | |
| 383 | − } | |
| 384 | − | |
| 385 | − dc->hwss.set_cursor_position(pipe_ctx); | |
| 386 | − } | |
| 387 | − | |
| 388 | − if (pipe_to_program) | |
| 389 | − dc->hwss.cursor_lock(dc, pipe_to_program, false); | |
| 390 | − | |
| 417 | + program_cursor_position(dc, stream, position); | |
| 391 | 418 | #if defined(CONFIG_DRM_AMD_DC_DCN) |
| 392 | 419 | /* re-enable idle optimizations if necessary */ |
| 393 | 420 | if (reset_idle_optimizations) |
| @@ -45,7 +45,7 @@ · 44 unmodified lines | ||
| 45 | 45 | /* forward declaration */ |
| 46 | 46 | struct aux_payload; |
| 47 | 47 | |
| 48 | −#define DC_VER "3.2.141" | |
| 48 | +#define DC_VER "3.2.149" | |
| 49 | 49 | |
| 50 | 50 | #define MAX_SURFACES 3 |
| 51 | 51 | #define MAX_PLANES 6 |
| @@ -460,7 +460,65 @@ union mem_low_power_enable_options { · 408 unmodified lines | ||
| 460 | 460 | uint32_t u32All; |
| 461 | 461 | }; |
| 462 | 462 | |
| 463 | +struct dc_debug_data { | |
| 464 | + uint32_t ltFailCount; | |
| 465 | + uint32_t i2cErrorCount; | |
| 466 | + uint32_t auxErrorCount; | |
| 467 | +}; | |
| 468 | + | |
| 469 | +struct dc_phy_addr_space_config { | |
| 470 | + struct { | |
| 471 | + uint64_t start_addr; | |
| 472 | + uint64_t end_addr; | |
| 473 | + uint64_t fb_top; | |
| 474 | + uint64_t fb_offset; | |
| 475 | + uint64_t fb_base; | |
| 476 | + uint64_t agp_top; | |
| 477 | + uint64_t agp_bot; | |
| 478 | + uint64_t agp_base; | |
| 479 | + } system_aperture; | |
| 480 | + | |
| 481 | + struct { | |
| 482 | + uint64_t page_table_start_addr; | |
| 483 | + uint64_t page_table_end_addr; | |
| 484 | + uint64_t page_table_base_addr; | |
| 485 | + bool base_addr_is_mc_addr; | |
| 486 | + } gart_config; | |
| 487 | + | |
| 488 | + bool valid; | |
| 489 | + bool is_hvm_enabled; | |
| 490 | + uint64_t page_table_default_page_addr; | |
| 491 | +}; | |
| 492 | + | |
| 493 | +struct dc_virtual_addr_space_config { | |
| 494 | + uint64_t page_table_base_addr; | |
| 495 | + uint64_t page_table_start_addr; | |
| 496 | + uint64_t page_table_end_addr; | |
| 497 | + uint32_t page_table_block_size_in_bytes; | |
| 498 | + uint8_t page_table_depth; // 1 = 1 level, 2 = 2 level, etc. 0 = invalid | |
| 499 | +}; | |
| 500 | + | |
| 501 | +struct dc_bounding_box_overrides { | |
| 502 | + int sr_exit_time_ns; | |
| 503 | + int sr_enter_plus_exit_time_ns; | |
| 504 | + int urgent_latency_ns; | |
| 505 | + int percent_of_ideal_drambw; | |
| 506 | + int dram_clock_change_latency_ns; | |
| 507 | + int dummy_clock_change_latency_ns; | |
| 508 | + /* This forces a hard min on the DCFCLK we use | |
| 509 | + * for DML. Unlike the debug option for forcing | |
| 510 | + * DCFCLK, this override affects watermark calculations | |
| 511 | + */ | |
| 512 | + int min_dcfclk_mhz; | |
| 513 | +}; | |
| 514 | + | |
| 515 | +struct dc_state; | |
| 516 | +struct resource_pool; | |
| 517 | +struct dce_hwseq; | |
| 518 | + | |
| 463 | 519 | struct dc_debug_options { |
| 520 | + bool native422_support; | |
| 521 | + bool disable_dsc; | |
| 464 | 522 | enum visual_confirm visual_confirm; |
| 465 | 523 | bool sanity_checks; |
| 466 | 524 | bool max_disp_clk; |
| @@ -486,7 +544,6 @@ struct dc_debug_options { · 19 unmodified lines | ||
| 486 | 544 | bool disable_dsc_power_gate; |
| 487 | 545 | int dsc_min_slice_height_override; |
| 488 | 546 | int dsc_bpp_increment_div; |
| 489 | − bool native422_support; | |
| 490 | 547 | bool disable_pplib_wm_range; |
| 491 | 548 | enum wm_report_mode pplib_wm_report_mode; |
| 492 | 549 | unsigned int min_disp_clk_khz; |
| @@ -556,7 +613,6 @@ struct dc_debug_options { · 63 unmodified lines | ||
| 556 | 613 | bool validate_dml_output; |
| 557 | 614 | bool enable_dmcub_surface_flip; |
| 558 | 615 | bool usbc_combo_phy_reset_wa; |
| 559 | − bool disable_dsc; | |
| 560 | 616 | bool enable_dram_clock_change_one_display_vactive; |
| 561 | 617 | union mem_low_power_enable_options enable_mem_low_power; |
| 562 | 618 | bool force_vblank_alignment; |
| @@ -574,69 +630,13 @@ struct dc_debug_options { · 11 unmodified lines | ||
| 574 | 630 | #endif |
| 575 | 631 | }; |
| 576 | 632 | |
| 577 | −struct dc_debug_data { | |
| 578 | − uint32_t ltFailCount; | |
| 579 | − uint32_t i2cErrorCount; | |
| 580 | − uint32_t auxErrorCount; | |
| 581 | −}; | |
| 582 | − | |
| 583 | −struct dc_phy_addr_space_config { | |
| 584 | − struct { | |
| 585 | − uint64_t start_addr; | |
| 586 | − uint64_t end_addr; | |
| 587 | − uint64_t fb_top; | |
| 588 | − uint64_t fb_offset; | |
| 589 | − uint64_t fb_base; | |
| 590 | − uint64_t agp_top; | |
| 591 | − uint64_t agp_bot; | |
| 592 | − uint64_t agp_base; | |
| 593 | − } system_aperture; | |
| 594 | − | |
| 595 | − struct { | |
| 596 | − uint64_t page_table_start_addr; | |
| 597 | − uint64_t page_table_end_addr; | |
| 598 | − uint64_t page_table_base_addr; | |
| 599 | −#if defined(CONFIG_DRM_AMD_DC_DCN) | |
| 600 | − bool base_addr_is_mc_addr; | |
| 601 | −#endif | |
| 602 | − } gart_config; | |
| 603 | − | |
| 604 | − bool valid; | |
| 605 | − bool is_hvm_enabled; | |
| 606 | − uint64_t page_table_default_page_addr; | |
| 607 | −}; | |
| 608 | − | |
| 609 | −struct dc_virtual_addr_space_config { | |
| 610 | − uint64_t page_table_base_addr; | |
| 611 | − uint64_t page_table_start_addr; | |
| 612 | − uint64_t page_table_end_addr; | |
| 613 | − uint32_t page_table_block_size_in_bytes; | |
| 614 | − uint8_t page_table_depth; // 1 = 1 level, 2 = 2 level, etc. 0 = invalid | |
| 615 | −}; | |
| 616 | − | |
| 617 | −struct dc_bounding_box_overrides { | |
| 618 | − int sr_exit_time_ns; | |
| 619 | − int sr_enter_plus_exit_time_ns; | |
| 620 | − int urgent_latency_ns; | |
| 621 | − int percent_of_ideal_drambw; | |
| 622 | − int dram_clock_change_latency_ns; | |
| 623 | − int dummy_clock_change_latency_ns; | |
| 624 | − /* This forces a hard min on the DCFCLK we use | |
| 625 | − * for DML. Unlike the debug option for forcing | |
| 626 | − * DCFCLK, this override affects watermark calculations | |
| 627 | − */ | |
| 628 | − int min_dcfclk_mhz; | |
| 629 | −}; | |
| 630 | − | |
| 631 | −struct resource_pool; | |
| 632 | −struct dce_hwseq; | |
| 633 | 633 | struct gpu_info_soc_bounding_box_v1_0; |
| 634 | 634 | struct dc { |
| 635 | + struct dc_debug_options debug; | |
| 635 | 636 | struct dc_versions versions; |
| 636 | 637 | struct dc_caps caps; |
| 637 | 638 | struct dc_cap_funcs cap_funcs; |
| 638 | 639 | struct dc_config config; |
| 639 | − struct dc_debug_options debug; | |
| 640 | 640 | struct dc_bounding_box_overrides bb_overrides; |
| 641 | 641 | struct dc_bug_wa work_arounds; |
| 642 | 642 | struct dc_context *ctx; |
| @@ -109,6 +109,7 @@ struct dc_link_settings { · 108 unmodified lines | ||
| 109 | 109 | enum dc_link_spread link_spread; |
| 110 | 110 | bool use_link_rate_set; |
| 111 | 111 | uint8_t link_rate_set; |
| 112 | + bool dpcd_source_device_specific_field_support; | |
| 112 | 113 | }; |
| 113 | 114 | |
| 114 | 115 | struct dc_lane_settings { |
| @@ -38,5 +38,6 @@ · 37 unmodified lines | ||
| 38 | 38 | #include "dmub/dmub_srv.h" |
| 39 | 39 | |
| 40 | 40 | void dc_stat_get_dmub_notification(const struct dc *dc, struct dmub_notification *notify); |
| 41 | +void dc_stat_get_dmub_dataout(const struct dc *dc, uint32_t *dataout); | |
| 41 | 42 | |
| 42 | 43 | #endif /* _DC_STAT_H_ */ |
| @@ -37,3 +37,6 @@ · 36 unmodified lines | ||
| 37 | 37 | |
| 38 | 38 | #define TRACE_DCN_CLOCK_STATE(dcn_clocks) \ |
| 39 | 39 | trace_amdgpu_dm_dc_clocks_state(dcn_clocks) |
| 40 | + | |
| 41 | +#define TRACE_DCN_FPU(begin, function, line, ref_count) \ | |
| 42 | + trace_dcn_fpu(begin, function, line, ref_count) | |
| @@ -75,18 +75,6 @@ enum dce_environment { · 74 unmodified lines | ||
| 75 | 75 | #define IS_DIAG_DC(dce_environment) \ |
| 76 | 76 | (IS_FPGA_MAXIMUS_DC(dce_environment) || (dce_environment == DCE_ENV_DIAG)) |
| 77 | 77 | |
| 78 | −struct hw_asic_id { | |
| 79 | − uint32_t chip_id; | |
| 80 | − uint32_t chip_family; | |
| 81 | − uint32_t pci_revision_id; | |
| 82 | − uint32_t hw_internal_rev; | |
| 83 | − uint32_t vram_type; | |
| 84 | − uint32_t vram_width; | |
| 85 | − uint32_t feature_flags; | |
| 86 | − uint32_t fake_paths_num; | |
| 87 | − void *atombios_base_address; | |
| 88 | −}; | |
| 89 | − | |
| 90 | 78 | struct dc_perf_trace { |
| 91 | 79 | unsigned long read_count; |
| 92 | 80 | unsigned long write_count; |
| @@ -94,36 +82,7 @@ struct dc_perf_trace { · 1 unmodified line | ||
| 94 | 82 | unsigned long last_entry_write; |
| 95 | 83 | }; |
| 96 | 84 | |
| 97 | −struct dc_context { | |
| 98 | − struct dc *dc; | |
| 99 | − | |
| 100 | − void *driver_context; /* e.g. amdgpu_device */ | |
| 101 | − struct dc_perf_trace *perf_trace; | |
| 102 | − void *cgs_device; | |
| 103 | − | |
| 104 | − enum dce_environment dce_environment; | |
| 105 | − struct hw_asic_id asic_id; | |
| 106 | − | |
| 107 | − /* todo: below should probably move to dc. to facilitate removal | |
| 108 | − * of AS we will store these here | |
| 109 | − */ | |
| 110 | − enum dce_version dce_version; | |
| 111 | − struct dc_bios *dc_bios; | |
| 112 | − bool created_bios; | |
| 113 | − struct gpio_service *gpio_service; | |
| 114 | − uint32_t dc_sink_id_count; | |
| 115 | − uint32_t dc_stream_id_count; | |
| 116 | − uint32_t dc_edp_id_count; | |
| 117 | − uint64_t fbc_gpu_addr; | |
| 118 | − struct dc_dmub_srv *dmub_srv; | |
| 119 | − | |
| 120 | −#ifdef CONFIG_DRM_AMD_DC_HDCP | |
| 121 | − struct cp_psp cp_psp; | |
| 122 | −#endif | |
| 123 | −}; | |
| 124 | − | |
| 125 | − | |
| 126 | −#define DC_MAX_EDID_BUFFER_SIZE 1280 | |
| 85 | +#define DC_MAX_EDID_BUFFER_SIZE 2048 | |
| 127 | 86 | #define DC_EDID_BLOCK_SIZE 128 |
| 128 | 87 | #define MAX_SURFACE_NUM 4 |
| 129 | 88 | #define NUM_PIXEL_FORMATS 10 |
| @@ -836,6 +795,46 @@ struct dc_clock_config { · 706 unmodified lines | ||
| 836 | 795 | uint32_t current_clock_khz;/*current clock in use*/ |
| 837 | 796 | }; |
| 838 | 797 | |
| 798 | +struct hw_asic_id { | |
| 799 | + uint32_t chip_id; | |
| 800 | + uint32_t chip_family; | |
| 801 | + uint32_t pci_revision_id; | |
| 802 | + uint32_t hw_internal_rev; | |
| 803 | + uint32_t vram_type; | |
| 804 | + uint32_t vram_width; | |
| 805 | + uint32_t feature_flags; | |
| 806 | + uint32_t fake_paths_num; | |
| 807 | + void *atombios_base_address; | |
| 808 | +}; | |
| 809 | + | |
| 810 | +struct dc_context { | |
| 811 | + struct dc *dc; | |
| 812 | + | |
| 813 | + void *driver_context; /* e.g. amdgpu_device */ | |
| 814 | + struct dc_perf_trace *perf_trace; | |
| 815 | + void *cgs_device; | |
| 816 | + | |
| 817 | + enum dce_environment dce_environment; | |
| 818 | + struct hw_asic_id asic_id; | |
| 819 | + | |
| 820 | + /* todo: below should probably move to dc. to facilitate removal | |
| 821 | + * of AS we will store these here | |
| 822 | + */ | |
| 823 | + enum dce_version dce_version; | |
| 824 | + struct dc_bios *dc_bios; | |
| 825 | + bool created_bios; | |
| 826 | + struct gpio_service *gpio_service; | |
| 827 | + uint32_t dc_sink_id_count; | |
| 828 | + uint32_t dc_stream_id_count; | |
| 829 | + uint32_t dc_edp_id_count; | |
| 830 | + uint64_t fbc_gpu_addr; | |
| 831 | + struct dc_dmub_srv *dmub_srv; | |
| 832 | +#ifdef CONFIG_DRM_AMD_DC_HDCP | |
| 833 | + struct cp_psp cp_psp; | |
| 834 | +#endif | |
| 835 | + | |
| 836 | +}; | |
| 837 | + | |
| 839 | 838 | /* DSC DPCD capabilities */ |
| 840 | 839 | union dsc_slice_caps1 { |
| 841 | 840 | struct { |
| @@ -42,6 +42,11 @@ · 41 unmodified lines | ||
| 42 | 42 | #define DC_LOGGER \ |
| 43 | 43 | engine->ctx->logger |
| 44 | 44 | |
| 45 | +#define DC_TRACE_LEVEL_MESSAGE(...) /* do nothing */ | |
| 46 | +#define IS_DC_I2CAUX_LOGGING_ENABLED() (false) | |
| 47 | +#define LOG_FLAG_Error_I2cAux LOG_ERROR | |
| 48 | +#define LOG_FLAG_I2cAux_DceAux LOG_I2C_AUX | |
| 49 | + | |
| 45 | 50 | #include "reg_helper.h" |
| 46 | 51 | |
| 47 | 52 | #undef FN |
| @@ -71,6 +76,8 @@ enum { · 23 unmodified lines | ||
| 71 | 76 | #define DEFAULT_AUX_ENGINE_MULT 0 |
| 72 | 77 | #define DEFAULT_AUX_ENGINE_LENGTH 69 |
| 73 | 78 | |
| 79 | +#define DC_TRACE_LEVEL_MESSAGE(...) /* do nothing */ | |
| 80 | + | |
| 74 | 81 | static void release_engine( |
| 75 | 82 | struct dce_aux *engine) |
| 76 | 83 | { |
| @@ -621,6 +628,58 @@ int dce_aux_transfer_dmub_raw(struct ddc_service *ddc, · 544 unmodified lines | ||
| 621 | 628 | #define AUX_MAX_INVALID_REPLY_RETRIES 2 |
| 622 | 629 | #define AUX_MAX_TIMEOUT_RETRIES 3 |
| 623 | 630 | |
| 631 | +static void dce_aux_log_payload(const char *payload_name, | |
| 632 | + unsigned char *payload, uint32_t length, uint32_t max_length_to_log) | |
| 633 | +{ | |
| 634 | + if (!IS_DC_I2CAUX_LOGGING_ENABLED()) | |
| 635 | + return; | |
| 636 | + | |
| 637 | + if (payload && length) { | |
| 638 | + char hex_str[128] = {0}; | |
| 639 | + char *hex_str_ptr = &hex_str[0]; | |
| 640 | + uint32_t hex_str_remaining = sizeof(hex_str); | |
| 641 | + unsigned char *payload_ptr = payload; | |
| 642 | + unsigned char *payload_max_to_log_ptr = payload_ptr + min(max_length_to_log, length); | |
| 643 | + unsigned int count; | |
| 644 | + char *padding = ""; | |
| 645 | + | |
| 646 | + while (payload_ptr < payload_max_to_log_ptr) { | |
| 647 | + count = snprintf_count(hex_str_ptr, hex_str_remaining, "%s%02X", padding, *payload_ptr); | |
| 648 | + padding = " "; | |
| 649 | + hex_str_remaining -= count; | |
| 650 | + hex_str_ptr += count; | |
| 651 | + payload_ptr++; | |
| 652 | + } | |
| 653 | + | |
| 654 | + count = snprintf_count(hex_str_ptr, hex_str_remaining, " "); | |
| 655 | + hex_str_remaining -= count; | |
| 656 | + hex_str_ptr += count; | |
| 657 | + | |
| 658 | + payload_ptr = payload; | |
| 659 | + while (payload_ptr < payload_max_to_log_ptr) { | |
| 660 | + count = snprintf_count(hex_str_ptr, hex_str_remaining, "%c", | |
| 661 | + *payload_ptr >= ' ' ? *payload_ptr : '.'); | |
| 662 | + hex_str_remaining -= count; | |
| 663 | + hex_str_ptr += count; | |
| 664 | + payload_ptr++; | |
| 665 | + } | |
| 666 | + | |
| 667 | + DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_VERBOSE, | |
| 668 | + LOG_FLAG_I2cAux_DceAux, | |
| 669 | + "dce_aux_log_payload: %s: length=%u: data: %s%s", | |
| 670 | + payload_name, | |
| 671 | + length, | |
| 672 | + hex_str, | |
| 673 | + (length > max_length_to_log ? " (...)" : " ")); | |
| 674 | + } else { | |
| 675 | + DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_VERBOSE, | |
| 676 | + LOG_FLAG_I2cAux_DceAux, | |
| 677 | + "dce_aux_log_payload: %s: length=%u: data: <empty payload>", | |
| 678 | + payload_name, | |
| 679 | + length); | |
| 680 | + } | |
| 681 | +} | |
| 682 | + | |
| 624 | 683 | bool dce_aux_transfer_with_retries(struct ddc_service *ddc, |
| 625 | 684 | struct aux_payload *payload) |
| 626 | 685 | { |
| @@ -646,7 +705,34 @@ bool dce_aux_transfer_with_retries(struct ddc_service *ddc, · 19 unmodified lines | ||
| 646 | 705 | } |
| 647 | 706 | |
| 648 | 707 | for (i = 0; i < AUX_MAX_RETRIES; i++) { |
| 708 | + DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_INFORMATION, | |
| 709 | + LOG_FLAG_I2cAux_DceAux, | |
| 710 | + "dce_aux_transfer_with_retries: link_index=%u: START: retry %d of %d: address=0x%04x length=%u write=%d mot=%d", | |
| 711 | + ddc && ddc->link ? ddc->link->link_index : UINT_MAX, | |
| 712 | + i + 1, | |
| 713 | + (int)AUX_MAX_RETRIES, | |
| 714 | + payload->address, | |
| 715 | + payload->length, | |
| 716 | + (unsigned int) payload->write, | |
| 717 | + (unsigned int) payload->mot); | |
| 718 | + if (payload->write) | |
| 719 | + dce_aux_log_payload(" write", payload->data, payload->length, 16); | |
| 649 | 720 | ret = dce_aux_transfer_raw(ddc, payload, &operation_result); |
| 721 | + DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_INFORMATION, | |
| 722 | + LOG_FLAG_I2cAux_DceAux, | |
| 723 | + "dce_aux_transfer_with_retries: link_index=%u: END: retry %d of %d: address=0x%04x length=%u write=%d mot=%d: ret=%d operation_result=%d payload->reply=%u", | |
| 724 | + ddc && ddc->link ? ddc->link->link_index : UINT_MAX, | |
| 725 | + i + 1, | |
| 726 | + (int)AUX_MAX_RETRIES, | |
| 727 | + payload->address, | |
| 728 | + payload->length, | |
| 729 | + (unsigned int) payload->write, | |
| 730 | + (unsigned int) payload->mot, | |
| 731 | + ret, | |
| 732 | + (int)operation_result, | |
| 733 | + (unsigned int) *payload->reply); | |
| 734 | + if (!payload->write) | |
| 735 | + dce_aux_log_payload(" read", payload->data, ret > 0 ? ret : 0, 16); | |
| 650 | 736 | |
| 651 | 737 | switch (operation_result) { |
| 652 | 738 | case AUX_RET_SUCCESS: |
| @@ -655,30 +741,64 @@ bool dce_aux_transfer_with_retries(struct ddc_service *ddc, · 2 unmodified lines | ||
| 655 | 741 | |
| 656 | 742 | switch (*payload->reply) { |
| 657 | 743 | case AUX_TRANSACTION_REPLY_AUX_ACK: |
| 744 | + DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_INFORMATION, | |
| 745 | + LOG_FLAG_I2cAux_DceAux, | |
| 746 | + "dce_aux_transfer_with_retries: AUX_RET_SUCCESS: AUX_TRANSACTION_REPLY_AUX_ACK"); | |
| 658 | 747 | if (!payload->write && payload->length != ret) { |
| 659 | − if (++aux_ack_retries >= AUX_MAX_RETRIES) | |
| 748 | + if (++aux_ack_retries >= AUX_MAX_RETRIES) { | |
| 749 | + DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_ERROR, | |
| 750 | + LOG_FLAG_Error_I2cAux, | |
| 751 | + "dce_aux_transfer_with_retries: FAILURE: aux_ack_retries=%d >= AUX_MAX_RETRIES=%d", | |
| 752 | + aux_defer_retries, | |
| 753 | + AUX_MAX_RETRIES); | |
| 660 | 754 | goto fail; |
| 661 | − else | |
| 755 | + } else { | |
| 662 | 756 | udelay(300); |
| 757 | + } | |
| 663 | 758 | } else |
| 664 | 759 | return true; |
| 665 | 760 | break; |
| 666 | 761 | |
| 667 | 762 | case AUX_TRANSACTION_REPLY_AUX_DEFER: |
| 763 | + DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_INFORMATION, | |
| 764 | + LOG_FLAG_I2cAux_DceAux, | |
| 765 | + "dce_aux_transfer_with_retries: AUX_RET_SUCCESS: AUX_TRANSACTION_REPLY_AUX_DEFER"); | |
| 766 | + | |
| 668 | 767 | /* polling_timeout_period is in us */ |
| 669 | 768 | defer_time_in_ms += aux110->polling_timeout_period / 1000; |
| 670 | 769 | ++aux_defer_retries; |
| 671 | 770 | fallthrough; |
| 672 | 771 | case AUX_TRANSACTION_REPLY_I2C_OVER_AUX_DEFER: |
| 772 | + if (*payload->reply == AUX_TRANSACTION_REPLY_I2C_OVER_AUX_DEFER) | |
| 773 | + DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_INFORMATION, | |
| 774 | + LOG_FLAG_I2cAux_DceAux, | |
| 775 | + "dce_aux_transfer_with_retries: AUX_RET_SUCCESS: AUX_TRANSACTION_REPLY_I2C_OVER_AUX_DEFER"); | |
| 776 | + | |
| 673 | 777 | retry_on_defer = true; |
| 674 | 778 | fallthrough; |
| 675 | 779 | case AUX_TRANSACTION_REPLY_I2C_OVER_AUX_NACK: |
| 780 | + if (*payload->reply == AUX_TRANSACTION_REPLY_I2C_OVER_AUX_NACK) | |
| 781 | + DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_INFORMATION, | |
| 782 | + LOG_FLAG_I2cAux_DceAux, | |
| 783 | + "dce_aux_transfer_with_retries: AUX_RET_SUCCESS: AUX_TRANSACTION_REPLY_I2C_OVER_AUX_NACK"); | |
| 784 | + | |
| 676 | 785 | if (aux_defer_retries >= AUX_MIN_DEFER_RETRIES |
| 677 | 786 | && defer_time_in_ms >= AUX_MAX_DEFER_TIMEOUT_MS) { |
| 787 | + DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_ERROR, | |
| 788 | + LOG_FLAG_Error_I2cAux, | |
| 789 | + "dce_aux_transfer_with_retries: FAILURE: aux_defer_retries=%d >= AUX_MIN_DEFER_RETRIES=%d && defer_time_in_ms=%d >= AUX_MAX_DEFER_TIMEOUT_MS=%d", | |
| 790 | + aux_defer_retries, | |
| 791 | + AUX_MIN_DEFER_RETRIES, | |
| 792 | + defer_time_in_ms, | |
| 793 | + AUX_MAX_DEFER_TIMEOUT_MS); | |
| 678 | 794 | goto fail; |
| 679 | 795 | } else { |
| 680 | 796 | if ((*payload->reply == AUX_TRANSACTION_REPLY_AUX_DEFER) || |
| 681 | 797 | (*payload->reply == AUX_TRANSACTION_REPLY_I2C_OVER_AUX_DEFER)) { |
| 798 | + DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_INFORMATION, | |
| 799 | + LOG_FLAG_I2cAux_DceAux, | |
| 800 | + "dce_aux_transfer_with_retries: payload->defer_delay=%u", | |
| 801 | + payload->defer_delay); | |
| 682 | 802 | if (payload->defer_delay > 1) { |
| 683 | 803 | msleep(payload->defer_delay); |
| 684 | 804 | defer_time_in_ms += payload->defer_delay; |
| @@ -691,37 +811,86 @@ bool dce_aux_transfer_with_retries(struct ddc_service *ddc, · 6 unmodified lines | ||
| 691 | 811 | break; |
| 692 | 812 | |
| 693 | 813 | case AUX_TRANSACTION_REPLY_I2C_DEFER: |
| 814 | + DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_INFORMATION, | |
| 815 | + LOG_FLAG_I2cAux_DceAux, | |
| 816 | + "dce_aux_transfer_with_retries: AUX_RET_SUCCESS: AUX_TRANSACTION_REPLY_I2C_DEFER"); | |
| 817 | + | |
| 694 | 818 | aux_defer_retries = 0; |
| 695 | − if (++aux_i2c_defer_retries >= AUX_MAX_I2C_DEFER_RETRIES) | |
| 819 | + if (++aux_i2c_defer_retries >= AUX_MAX_I2C_DEFER_RETRIES) { | |
| 820 | + DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_ERROR, | |
| 821 | + LOG_FLAG_Error_I2cAux, | |
| 822 | + "dce_aux_transfer_with_retries: FAILURE: aux_i2c_defer_retries=%d >= AUX_MAX_I2C_DEFER_RETRIES=%d", | |
| 823 | + aux_i2c_defer_retries, | |
| 824 | + AUX_MAX_I2C_DEFER_RETRIES); | |
| 696 | 825 | goto fail; |
| 826 | + } | |
| 697 | 827 | break; |
| 698 | 828 | |
| 699 | 829 | case AUX_TRANSACTION_REPLY_AUX_NACK: |
| 830 | + DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_INFORMATION, | |
| 831 | + LOG_FLAG_I2cAux_DceAux, | |
| 832 | + "dce_aux_transfer_with_retries: AUX_RET_SUCCESS: AUX_TRANSACTION_REPLY_AUX_NACK"); | |
| 833 | + goto fail; | |
| 834 | + | |
| 700 | 835 | case AUX_TRANSACTION_REPLY_HPD_DISCON: |
| 836 | + DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_INFORMATION, | |
| 837 | + LOG_FLAG_I2cAux_DceAux, | |
| 838 | + "dce_aux_transfer_with_retries: AUX_RET_SUCCESS: AUX_TRANSACTION_REPLY_HPD_DISCON"); | |
| 839 | + goto fail; | |
| 840 | + | |
| 701 | 841 | default: |
| 842 | + DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_ERROR, | |
| 843 | + LOG_FLAG_Error_I2cAux, | |
| 844 | + "dce_aux_transfer_with_retries: AUX_RET_SUCCESS: FAILURE: AUX_TRANSACTION_REPLY_* unknown, default case."); | |
| 702 | 845 | goto fail; |
| 703 | 846 | } |
| 704 | 847 | break; |
| 705 | 848 | |
| 706 | 849 | case AUX_RET_ERROR_INVALID_REPLY: |
| 707 | − if (++aux_invalid_reply_retries >= AUX_MAX_INVALID_REPLY_RETRIES) | |
| 850 | + DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_INFORMATION, | |
| 851 | + LOG_FLAG_I2cAux_DceAux, | |
| 852 | + "dce_aux_transfer_with_retries: AUX_RET_ERROR_INVALID_REPLY"); | |
| 853 | + if (++aux_invalid_reply_retries >= AUX_MAX_INVALID_REPLY_RETRIES) { | |
| 854 | + DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_ERROR, | |
| 855 | + LOG_FLAG_Error_I2cAux, | |
| 856 | + "dce_aux_transfer_with_retries: FAILURE: aux_invalid_reply_retries=%d >= AUX_MAX_INVALID_REPLY_RETRIES=%d", | |
| 857 | + aux_invalid_reply_retries, | |
| 858 | + AUX_MAX_INVALID_REPLY_RETRIES); | |
| 708 | 859 | goto fail; |
| 709 | − else | |
| 860 | + } else | |
| 710 | 861 | udelay(400); |
| 711 | 862 | break; |
| 712 | 863 | |
| 713 | 864 | case AUX_RET_ERROR_TIMEOUT: |
| 865 | + DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_INFORMATION, | |
| 866 | + LOG_FLAG_I2cAux_DceAux, | |
| 867 | + "dce_aux_transfer_with_retries: AUX_RET_ERROR_TIMEOUT"); | |
| 714 | 868 | // Check whether a DEFER had occurred before the timeout. |
| 715 | 869 | // If so, treat timeout as a DEFER. |
| 716 | 870 | if (retry_on_defer) { |
| 717 | − if (++aux_defer_retries >= AUX_MIN_DEFER_RETRIES) | |
| 871 | + if (++aux_defer_retries >= AUX_MIN_DEFER_RETRIES) { | |
| 872 | + DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_ERROR, | |
| 873 | + LOG_FLAG_Error_I2cAux, | |
| 874 | + "dce_aux_transfer_with_retries: FAILURE: aux_defer_retries=%d >= AUX_MIN_DEFER_RETRIES=%d", | |
| 875 | + aux_defer_retries, | |
| 876 | + AUX_MIN_DEFER_RETRIES); | |
| 718 | 877 | goto fail; |
| 719 | − else if (payload->defer_delay > 0) | |
| 878 | + } else if (payload->defer_delay > 0) { | |
| 879 | + DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_INFORMATION, | |
| 880 | + LOG_FLAG_I2cAux_DceAux, | |
| 881 | + "dce_aux_transfer_with_retries: payload->defer_delay=%u", | |
| 882 | + payload->defer_delay); | |
| 720 | 883 | msleep(payload->defer_delay); |
| 884 | + } | |
| 721 | 885 | } else { |
| 722 | − if (++aux_timeout_retries >= AUX_MAX_TIMEOUT_RETRIES) | |
| 886 | + if (++aux_timeout_retries >= AUX_MAX_TIMEOUT_RETRIES) { | |
| 887 | + DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_ERROR, | |
| 888 | + LOG_FLAG_Error_I2cAux, | |
| 889 | + "dce_aux_transfer_with_retries: FAILURE: aux_timeout_retries=%d >= AUX_MAX_TIMEOUT_RETRIES=%d", | |
| 890 | + aux_timeout_retries, | |
| 891 | + AUX_MAX_TIMEOUT_RETRIES); | |
| 723 | 892 | goto fail; |
| 724 | − else { | |
| 893 | + } else { | |
| 725 | 894 | /* |
| 726 | 895 | * DP 1.4, 2.8.2: AUX Transaction Response/Reply Timeouts |
| 727 | 896 | * According to the DP spec there should be 3 retries total |
| @@ -736,12 +905,25 @@ bool dce_aux_transfer_with_retries(struct ddc_service *ddc, · 8 unmodified lines | ||
| 736 | 905 | case AUX_RET_ERROR_ENGINE_ACQUIRE: |
| 737 | 906 | case AUX_RET_ERROR_UNKNOWN: |
| 738 | 907 | default: |
| 908 | + DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_INFORMATION, | |
| 909 | + LOG_FLAG_I2cAux_DceAux, | |
| 910 | + "dce_aux_transfer_with_retries: Failure: operation_result=%d", | |
| 911 | + (int)operation_result); | |
| 739 | 912 | goto fail; |
| 740 | 913 | } |
| 741 | 914 | } |
| 742 | 915 | |
| 743 | 916 | fail: |
| 917 | + DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_ERROR, | |
12 more lines aren’t shown here.
This diff is large: its 50 lines aren’t shown here.
This diff is large: its 40 lines aren’t shown here.
This diff is large: its 50 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 97 lines aren’t shown here.
This diff is large: its 13 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 45 lines aren’t shown here.
This diff is large: its 35 lines aren’t shown here.
This diff is large: its 59 lines aren’t shown here.
This diff is large: its 31 lines aren’t shown here.
This diff is large: its 22 lines aren’t shown here.
This diff is large: its 93 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 21 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 19 lines aren’t shown here.
This diff is large: its 159 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 21 lines aren’t shown here.
This diff is large: its 58 lines aren’t shown here.
This diff is large: its 15 lines aren’t shown here.
This diff is large: its 100 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 55 lines aren’t shown here.
This diff is large: its 29 lines aren’t shown here.
This diff is large: its 42 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 25 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 44 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 103 lines aren’t shown here.
This diff is large: its 35 lines aren’t shown here.
This diff is large: its 88 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 43 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 69 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 477 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 12 lines aren’t shown here.
This diff is large: its 25 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 29 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 42 lines aren’t shown here.
This diff is large: its 32 lines aren’t shown here.
This diff is large: its 168 lines aren’t shown here.
This diff is large: its 85 lines aren’t shown here.
This diff is large: its 31 lines aren’t shown here.
This diff is large: its 31 lines aren’t shown here.
This diff is large: its 144 lines aren’t shown here.
This diff is large: its 31 lines aren’t shown here.
This diff is large: its 20 lines aren’t shown here.
This diff is large: its 36 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 81 lines aren’t shown here.
This diff is large: its 79 lines aren’t shown here.
This diff is large: its 358 lines aren’t shown here.
This diff is large: its 41 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 32 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 61 lines aren’t shown here.
This diff is large: its 353 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 180 lines aren’t shown here.
This diff is large: its 715 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 156 lines aren’t shown here.
This diff is large: its 24 lines aren’t shown here.
This diff is large: its 85 lines aren’t shown here.
This diff is large: its 13 lines aren’t shown here.
This diff is large: its 96 lines aren’t shown here.
This diff is large: its 86 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 42 lines aren’t shown here.
This diff is large: its 153 lines aren’t shown here.
This diff is large: its 71 lines aren’t shown here.
This diff is large: its 57 lines aren’t shown here.
This diff is large: its 74 lines aren’t shown here.
This diff is large: its 152 lines aren’t shown here.
This diff is large: its 59 lines aren’t shown here.
This diff is large: its 13 lines aren’t shown here.
This diff is large: its 28 lines aren’t shown here.
This diff is large: its 144 lines aren’t shown here.
This diff is large: its 58 lines aren’t shown here.
This diff is large: its 15 lines aren’t shown here.
This diff is large: its 53 lines aren’t shown here.
This diff is large: its 261 lines aren’t shown here.
This diff is large: its 60 lines aren’t shown here.
This diff is large: its 12 lines aren’t shown here.
This diff is large: its 59 lines aren’t shown here.
This diff is large: its 210 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 651 lines aren’t shown here.
This diff is large: its 77 lines aren’t shown here.
This diff is large: its 40 lines aren’t shown here.
This diff is large: its 461 lines aren’t shown here.
This diff is large: its 842 lines aren’t shown here.
This diff is large: its 203 lines aren’t shown here.
This diff is large: its 119 lines aren’t shown here.
This diff is large: its 63 lines aren’t shown here.
This diff is large: its 433 lines aren’t shown here.
This diff is large: its 130 lines aren’t shown here.
This diff is large: its 39 lines aren’t shown here.
This diff is large: its 362 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 33 lines aren’t shown here.
This diff is large: its 223 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 25 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 43 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 20 lines aren’t shown here.
This diff is large: its 12 lines aren’t shown here.
This diff is large: its 146 lines aren’t shown here.
This diff is large: its 112 lines aren’t shown here.
This diff is large: its 119 lines aren’t shown here.
This diff is large: its 12 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 99 lines aren’t shown here.
This diff is large: its 206 lines aren’t shown here.
This diff is large: its 324 lines aren’t shown here.
This diff is large: its 179 lines aren’t shown here.
This diff is large: its 25 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 23 lines aren’t shown here.
This diff is large: its 86 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 22 lines aren’t shown here.
This diff is large: its 90 lines aren’t shown here.
This diff is large: its 118 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 332 lines aren’t shown here.
This diff is large: its 1029 lines aren’t shown here.
This diff is large: its 84 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 69 lines aren’t shown here.
This diff is large: its 27 lines aren’t shown here.
This diff is large: its 167 lines aren’t shown here.
This diff is large: its 33 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 21 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 86 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 15 lines aren’t shown here.
This diff is large: its 324 lines aren’t shown here.
This diff is large: its 505 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 35 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 67 lines aren’t shown here.
This diff is large: its 73 lines aren’t shown here.
This diff is large: its 179 lines aren’t shown here.
This diff is large: its 250 lines aren’t shown here.
This diff is large: its 25 lines aren’t shown here.
This diff is large: its 40 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 158 lines aren’t shown here.
This diff is large: its 495 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 116 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 21 lines aren’t shown here.
This diff is large: its 120 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 82 lines aren’t shown here.
This diff is large: its 31 lines aren’t shown here.
This diff is large: its 97 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 28 lines aren’t shown here.
This diff is large: its 13 lines aren’t shown here.
This diff is large: its 41 lines aren’t shown here.
This diff is large: its 20 lines aren’t shown here.
This diff is large: its 13 lines aren’t shown here.
This diff is large: its 38 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 13 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 20 lines aren’t shown here.
This diff is large: its 63 lines aren’t shown here.
This diff is large: its 13 lines aren’t shown here.
This diff is large: its 137 lines aren’t shown here.
This diff is large: its 15 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 36 lines aren’t shown here.
This diff is large: its 12 lines aren’t shown here.
This diff is large: its 67 lines aren’t shown here.
This diff is large: its 12 lines aren’t shown here.
This diff is large: its 104 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 156 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 59 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 25 lines aren’t shown here.
This diff is large: its 93 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 97 lines aren’t shown here.
This diff is large: its 33 lines aren’t shown here.
This diff is large: its 15 lines aren’t shown here.
This diff is large: its 14 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 25 lines aren’t shown here.
This diff is large: its 300 lines aren’t shown here.
This diff is large: its 262 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 188 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 26 lines aren’t shown here.
This diff is large: its 37 lines aren’t shown here.
This diff is large: its 1194 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 2766 lines aren’t shown here.
This diff is large: its 95 lines aren’t shown here.
This diff is large: its 740 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 219 lines aren’t shown here.
This diff is large: its 810 lines aren’t shown here.
This diff is large: its 43 lines aren’t shown here.
This diff is large: its 103 lines aren’t shown here.
This diff is large: its 416 lines aren’t shown here.
This diff is large: its 36 lines aren’t shown here.
This diff is large: its 128 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 419 lines aren’t shown here.
This diff is large: its 100 lines aren’t shown here.
This diff is large: its 27 lines aren’t shown here.
This diff is large: its 718 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 356 lines aren’t shown here.
This diff is large: its 167 lines aren’t shown here.
This diff is large: its 71 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 160 lines aren’t shown here.
This diff is large: its 15 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 465 lines aren’t shown here.
This diff is large: its 55 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 863 lines aren’t shown here.
This diff is large: its 36 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 83 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 55 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 12 lines aren’t shown here.
This diff is large: its 46 lines aren’t shown here.
This diff is large: its 143 lines aren’t shown here.
This diff is large: its 112 lines aren’t shown here.
This diff is large: its 41 lines aren’t shown here.
This diff is large: its 15 lines aren’t shown here.
This diff is large: its 356 lines aren’t shown here.
This diff is large: its 22 lines aren’t shown here.
This diff is large: its 3487 lines aren’t shown here.
This diff is large: its 20 lines aren’t shown here.
This diff is large: its 290 lines aren’t shown here.
This diff is large: its 351 lines aren’t shown here.
This diff is large: its 115 lines aren’t shown here.
This diff is large: its 39 lines aren’t shown here.
This diff is large: its 704 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 189 lines aren’t shown here.
This diff is large: its 22 lines aren’t shown here.
This diff is large: its 200 lines aren’t shown here.
This diff is large: its 437 lines aren’t shown here.
This diff is large: its 166 lines aren’t shown here.
This diff is large: its 462 lines aren’t shown here.
This diff is large: its 40 lines aren’t shown here.
This diff is large: its 321 lines aren’t shown here.
This diff is large: its 111 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 55 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 79 lines aren’t shown here.
This diff is large: its 25 lines aren’t shown here.
This diff is large: its 966 lines aren’t shown here.
This diff is large: its 50 lines aren’t shown here.
This diff is large: its 261 lines aren’t shown here.
This diff is large: its 34 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 22 lines aren’t shown here.
This diff is large: its 135 lines aren’t shown here.
This diff is large: its 153 lines aren’t shown here.
This diff is large: its 221 lines aren’t shown here.
This diff is large: its 244 lines aren’t shown here.
This diff is large: its 377 lines aren’t shown here.
This diff is large: its 598 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 140 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 42 lines aren’t shown here.
This diff is large: its 59 lines aren’t shown here.
This diff is large: its 91 lines aren’t shown here.
This diff is large: its 109 lines aren’t shown here.
This diff is large: its 35 lines aren’t shown here.
This diff is large: its 33 lines aren’t shown here.
This diff is large: its 187 lines aren’t shown here.
This diff is large: its 98 lines aren’t shown here.
This diff is large: its 64 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 114 lines aren’t shown here.
This diff is large: its 148 lines aren’t shown here.
This diff is large: its 730 lines aren’t shown here.
This diff is large: its 111 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 15 lines aren’t shown here.
This diff is large: its 211 lines aren’t shown here.
This diff is large: its 26 lines aren’t shown here.
This diff is large: its 1376 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 25 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 272 lines aren’t shown here.
This diff is large: its 24 lines aren’t shown here.
This diff is large: its 25 lines aren’t shown here.
This diff is large: its 29 lines aren’t shown here.
This diff is large: its 53 lines aren’t shown here.
This diff is large: its 36 lines aren’t shown here.
This diff is large: its 29 lines aren’t shown here.
This diff is large: its 67 lines aren’t shown here.
This diff is large: its 41 lines aren’t shown here.
This diff is large: its 39 lines aren’t shown here.
This diff is large: its 195 lines aren’t shown here.
This diff is large: its 12 lines aren’t shown here.
This diff is large: its 689 lines aren’t shown here.
This diff is large: its 66 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 81 lines aren’t shown here.
This diff is large: its 28 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 159 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 130 lines aren’t shown here.
This diff is large: its 288 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 157 lines aren’t shown here.
This diff is large: its 27 lines aren’t shown here.
This diff is large: its 24 lines aren’t shown here.
This diff is large: its 904 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 108 lines aren’t shown here.
This diff is large: its 26 lines aren’t shown here.
This diff is large: its 26 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 560 lines aren’t shown here.
This diff is large: its 745 lines aren’t shown here.
This diff is large: its 24 lines aren’t shown here.
This diff is large: its 670 lines aren’t shown here.
This diff is large: its 112 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 312 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 302 lines aren’t shown here.
This diff is large: its 149 lines aren’t shown here.
This diff is large: its 236 lines aren’t shown here.
This diff is large: its 141 lines aren’t shown here.
This diff is large: its 78 lines aren’t shown here.
This diff is large: its 220 lines aren’t shown here.
This diff is large: its 329 lines aren’t shown here.
This diff is large: its 193 lines aren’t shown here.
This diff is large: its 591 lines aren’t shown here.
This diff is large: its 14 lines aren’t shown here.
This diff is large: its 1080 lines aren’t shown here.
This diff is large: its 86 lines aren’t shown here.
This diff is large: its 70 lines aren’t shown here.
This diff is large: its 264 lines aren’t shown here.
This diff is large: its 70 lines aren’t shown here.
This diff is large: its 15 lines aren’t shown here.
This diff is large: its 81 lines aren’t shown here.
This diff is large: its 32 lines aren’t shown here.
This diff is large: its 627 lines aren’t shown here.
This diff is large: its 43 lines aren’t shown here.
This diff is large: its 30 lines aren’t shown here.
This diff is large: its 3170 lines aren’t shown here.
This diff is large: its 35 lines aren’t shown here.
This diff is large: its 252 lines aren’t shown here.
This diff is large: its 48 lines aren’t shown here.
This diff is large: its 34 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 14 lines aren’t shown here.
This diff is large: its 98 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 422 lines aren’t shown here.
This diff is large: its 136 lines aren’t shown here.
This diff is large: its 85 lines aren’t shown here.
This diff is large: its 33 lines aren’t shown here.
This diff is large: its 65 lines aren’t shown here.
This diff is large: its 47 lines aren’t shown here.
This diff is large: its 481 lines aren’t shown here.
This diff is large: its 85 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 64 lines aren’t shown here.
This diff is large: its 51 lines aren’t shown here.
This diff is large: its 28 lines aren’t shown here.
This diff is large: its 161 lines aren’t shown here.
This diff is large: its 38 lines aren’t shown here.
This diff is large: its 51 lines aren’t shown here.
This diff is large: its 328 lines aren’t shown here.
This diff is large: its 125 lines aren’t shown here.
This diff is large: its 313 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 130 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 27 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 868 lines aren’t shown here.
This diff is large: its 635 lines aren’t shown here.
This diff is large: its 64 lines aren’t shown here.
This diff is large: its 94 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 385 lines aren’t shown here.
This diff is large: its 71 lines aren’t shown here.
This diff is large: its 116 lines aren’t shown here.
This diff is large: its 13 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 141 lines aren’t shown here.
This diff is large: its 244 lines aren’t shown here.
This diff is large: its 259 lines aren’t shown here.
This diff is large: its 57 lines aren’t shown here.
This diff is large: its 77 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 96 lines aren’t shown here.
This diff is large: its 78 lines aren’t shown here.
This diff is large: its 99 lines aren’t shown here.
This diff is large: its 117 lines aren’t shown here.
This diff is large: its 80 lines aren’t shown here.
This diff is large: its 36 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 493 lines aren’t shown here.
This diff is large: its 251 lines aren’t shown here.
This diff is large: its 37 lines aren’t shown here.
This diff is large: its 27 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 208 lines aren’t shown here.
This diff is large: its 50 lines aren’t shown here.
This diff is large: its 524 lines aren’t shown here.
This diff is large: its 46 lines aren’t shown here.
This diff is large: its 31 lines aren’t shown here.
This diff is large: its 788 lines aren’t shown here.
This diff is large: its 25 lines aren’t shown here.
This diff is large: its 7 lines aren’t shown here.
This diff is large: its 7 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 43 lines aren’t shown here.
This diff is large: its 21 lines aren’t shown here.
This diff is large: its 444 lines aren’t shown here.
This diff is large: its 89 lines aren’t shown here.
This diff is large: its 34 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 67 lines aren’t shown here.
This diff is large: its 30 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 12 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 13 lines aren’t shown here.
This diff is large: its 105 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 59 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 32 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 170 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 14 lines aren’t shown here.
This diff is large: its 12 lines aren’t shown here.
This diff is large: its 289 lines aren’t shown here.
This diff is large: its 79 lines aren’t shown here.
This diff is large: its 175 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 74 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 13 lines aren’t shown here.
This diff is large: its 54 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 6 lines aren’t shown here.
This diff is large: its 111 lines aren’t shown here.
This diff is large: its 118 lines aren’t shown here.
This diff is large: its 892 lines aren’t shown here.
This diff is large: its 993 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 21 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 77 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 21 lines aren’t shown here.
This diff is large: its 67 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 340 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 51 lines aren’t shown here.
This diff is large: its 68 lines aren’t shown here.
This diff is large: its 20 lines aren’t shown here.
This diff is large: its 59 lines aren’t shown here.
This diff is large: its 64 lines aren’t shown here.
This diff is large: its 44 lines aren’t shown here.
This diff is large: its 40 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 159 lines aren’t shown here.
This diff is large: its 24 lines aren’t shown here.
This diff is large: its 155 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 32 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 50 lines aren’t shown here.
This diff is large: its 327 lines aren’t shown here.
This diff is large: its 255 lines aren’t shown here.
This diff is large: its 62 lines aren’t shown here.
This diff is large: its 23 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 44 lines aren’t shown here.
This diff is large: its 65 lines aren’t shown here.
This diff is large: its 95 lines aren’t shown here.
This diff is large: its 86 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 384 lines aren’t shown here.
This diff is large: its 405 lines aren’t shown here.
This diff is large: its 159 lines aren’t shown here.
This diff is large: its 32 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 36 lines aren’t shown here.
This diff is large: its 307 lines aren’t shown here.
This diff is large: its 242 lines aren’t shown here.
This diff is large: its 39 lines aren’t shown here.
This diff is large: its 41 lines aren’t shown here.
This diff is large: its 81 lines aren’t shown here.
This diff is large: its 61 lines aren’t shown here.
This diff is large: its 241 lines aren’t shown here.
This diff is large: its 119 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 602 lines aren’t shown here.
This diff is large: its 409 lines aren’t shown here.
This diff is large: its 181 lines aren’t shown here.
This diff is large: its 204 lines aren’t shown here.
This diff is large: its 19 lines aren’t shown here.
This diff is large: its 21 lines aren’t shown here.
This diff is large: its 109 lines aren’t shown here.
This diff is large: its 28 lines aren’t shown here.
This diff is large: its 101 lines aren’t shown here.
This diff is large: its 145 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 145 lines aren’t shown here.
This diff is large: its 29 lines aren’t shown here.
This diff is large: its 79 lines aren’t shown here.
This diff is large: its 220 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 26 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 30 lines aren’t shown here.
This diff is large: its 14 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 36 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 96 lines aren’t shown here.
This diff is large: its 25 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 793 lines aren’t shown here.
This diff is large: its 290 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 367 lines aren’t shown here.
This diff is large: its 348 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 31 lines aren’t shown here.
This diff is large: its 113 lines aren’t shown here.
This diff is large: its 83 lines aren’t shown here.
This diff is large: its 40 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 571 lines aren’t shown here.
This diff is large: its 150 lines aren’t shown here.
This diff is large: its 442 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 158 lines aren’t shown here.
This diff is large: its 139 lines aren’t shown here.
This diff is large: its 171 lines aren’t shown here.
This diff is large: its 61 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 901 lines aren’t shown here.
This diff is large: its 22 lines aren’t shown here.
This diff is large: its 303 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 20 lines aren’t shown here.
This diff is large: its 13 lines aren’t shown here.
This diff is large: its 33 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 25 lines aren’t shown here.
This diff is large: its 23 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 67 lines aren’t shown here.
This diff is large: its 20 lines aren’t shown here.
This diff is large: its 37 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 172 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 31 lines aren’t shown here.
This diff is large: its 31 lines aren’t shown here.
This diff is large: its 40 lines aren’t shown here.
This diff is large: its 46 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 199 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 458 lines aren’t shown here.
This diff is large: its 22 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 13 lines aren’t shown here.
This diff is large: its 13 lines aren’t shown here.
This diff is large: its 85 lines aren’t shown here.
This diff is large: its 538 lines aren’t shown here.
This diff is large: its 49 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 12 lines aren’t shown here.
This diff is large: its 28 lines aren’t shown here.
This diff is large: its 40 lines aren’t shown here.
This diff is large: its 12 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 12 lines aren’t shown here.
This diff is large: its 12 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 523 lines aren’t shown here.
This diff is large: its 51 lines aren’t shown here.
This diff is large: its 278 lines aren’t shown here.
This diff is large: its 33 lines aren’t shown here.
This diff is large: its 255 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 7 lines aren’t shown here.
This diff is large: its 149 lines aren’t shown here.
This diff is large: its 50 lines aren’t shown here.
This diff is large: its 13 lines aren’t shown here.
This diff is large: its 626 lines aren’t shown here.
This diff is large: its 22 lines aren’t shown here.
This diff is large: its 339 lines aren’t shown here.
This diff is large: its 59 lines aren’t shown here.
This diff is large: its 171 lines aren’t shown here.
This diff is large: its 52 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 76 lines aren’t shown here.
This diff is large: its 12 lines aren’t shown here.
This diff is large: its 12 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 93 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 12 lines aren’t shown here.
This diff is large: its 31 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 734 lines aren’t shown here.
This diff is large: its 27 lines aren’t shown here.
This diff is large: its 58 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 50 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 54 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 96 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 89 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 36 lines aren’t shown here.
This diff is large: its 95 lines aren’t shown here.
This diff is large: its 75 lines aren’t shown here.
This diff is large: its 214 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 89 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 44 lines aren’t shown here.
This diff is large: its 19 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 20 lines aren’t shown here.
This diff is large: its 22 lines aren’t shown here.
This diff is large: its 12 lines aren’t shown here.
This diff is large: its 708 lines aren’t shown here.
This diff is large: its 13 lines aren’t shown here.
This diff is large: its 99 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 37 lines aren’t shown here.
This diff is large: its 52 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 106 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 27 lines aren’t shown here.
This diff is large: its 84 lines aren’t shown here.
This diff is large: its 66 lines aren’t shown here.
This diff is large: its 51 lines aren’t shown here.
This diff is large: its 129 lines aren’t shown here.
This diff is large: its 58 lines aren’t shown here.
This diff is large: its 12 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 4 lines aren’t shown here.
This diff is large: its 112 lines aren’t shown here.
This diff is large: its 3716 lines aren’t shown here.
This diff is large: its 819 lines aren’t shown here.
This diff is large: its 3607 lines aren’t shown here.
This diff is large: its 140 lines aren’t shown here.
This diff is large: its 36 lines aren’t shown here.
This diff is large: its 3181 lines aren’t shown here.
This diff is large: its 3270 lines aren’t shown here.
This diff is large: its 86 lines aren’t shown here.
This diff is large: its 239 lines aren’t shown here.
This diff is large: its 3005 lines aren’t shown here.
This diff is large: its 52 lines aren’t shown here.
This diff is large: its 146 lines aren’t shown here.
This diff is large: its 3 lines aren’t shown here.
This diff is large: its 3 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 540 lines aren’t shown here.
This diff is large: its 98 lines aren’t shown here.
This diff is large: its 26 lines aren’t shown here.
This diff is large: its 30 lines aren’t shown here.
This diff is large: its 38 lines aren’t shown here.
This diff is large: its 21 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 143 lines aren’t shown here.
This diff is large: its 51 lines aren’t shown here.
This diff is large: its 730 lines aren’t shown here.
This diff is large: its 138 lines aren’t shown here.
This diff is large: its 65 lines aren’t shown here.
This diff is large: its 43 lines aren’t shown here.
This diff is large: its 164 lines aren’t shown here.
This diff is large: its 55 lines aren’t shown here.
This diff is large: its 60 lines aren’t shown here.
This diff is large: its 19 lines aren’t shown here.
This diff is large: its 145 lines aren’t shown here.
This diff is large: its 104 lines aren’t shown here.
This diff is large: its 629 lines aren’t shown here.
This diff is large: its 39 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 26 lines aren’t shown here.
This diff is large: its 262 lines aren’t shown here.
This diff is large: its 51 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 763 lines aren’t shown here.
This diff is large: its 71 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 13 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 96 lines aren’t shown here.
This diff is large: its 169 lines aren’t shown here.
This diff is large: its 14 lines aren’t shown here.
This diff is large: its 130 lines aren’t shown here.
This diff is large: its 71 lines aren’t shown here.
This diff is large: its 27 lines aren’t shown here.
This diff is large: its 34 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 29 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 234 lines aren’t shown here.
This diff is large: its 23 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 24 lines aren’t shown here.
This diff is large: its 151 lines aren’t shown here.
This diff is large: its 35 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 27 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 22 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 232 lines aren’t shown here.
This diff is large: its 24 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 40 lines aren’t shown here.
This diff is large: its 95 lines aren’t shown here.
This diff is large: its 61 lines aren’t shown here.
This diff is large: its 24 lines aren’t shown here.
This diff is large: its 30 lines aren’t shown here.
This diff is large: its 32 lines aren’t shown here.
This diff is large: its 58 lines aren’t shown here.
This diff is large: its 222 lines aren’t shown here.
This diff is large: its 65 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 35 lines aren’t shown here.
This diff is large: its 48 lines aren’t shown here.
This diff is large: its 41 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 38 lines aren’t shown here.
This diff is large: its 27 lines aren’t shown here.
This diff is large: its 30 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 14 lines aren’t shown here.
This diff is large: its 32 lines aren’t shown here.
This diff is large: its 14 lines aren’t shown here.
This diff is large: its 22 lines aren’t shown here.
This diff is large: its 54 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 23 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 48 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 65 lines aren’t shown here.
This diff is large: its 14 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 251 lines aren’t shown here.
This diff is large: its 79 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 63 lines aren’t shown here.
This diff is large: its 60 lines aren’t shown here.
This diff is large: its 61 lines aren’t shown here.
This diff is large: its 141 lines aren’t shown here.
This diff is large: its 28 lines aren’t shown here.
This diff is large: its 123 lines aren’t shown here.
This diff is large: its 128 lines aren’t shown here.
This diff is large: its 623 lines aren’t shown here.
This diff is large: its 32 lines aren’t shown here.
This diff is large: its 450 lines aren’t shown here.
This diff is large: its 171 lines aren’t shown here.
This diff is large: its 55 lines aren’t shown here.
This diff is large: its 58 lines aren’t shown here.
This diff is large: its 38 lines aren’t shown here.