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 | - ti,ths8134a | 22 | - ti,ths8134a |
| 23 | - ti,ths8134b | 23 | - ti,ths8134b |
| 24 | - const: ti,ths8134 | 24 | - const: ti,ths8134 |
| 25 | - items: | ||
| 26 | - const: corpro,gm7123 | ||
| 27 | - const: adi,adv7123 | ||
| 25 | - enum: | 28 | - enum: |
| 26 | - adi,adv7123 | 29 | - adi,adv7123 |
| 27 | - dumb-vga-dac | 30 | - dumb-vga-dac |
| @@ -70,6 +70,9 @@ properties: · 69 unmodified lines | |||
| 70 | const: 1 | 70 | const: 1 |
| 71 | description: See ../../pwm/pwm.yaml for description of the cell formats. | 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 | ports: | 76 | ports: |
| 74 | $ref: /schemas/graph.yaml#/properties/ports | 77 | $ref: /schemas/graph.yaml#/properties/ports |
| 75 | 78 | ||
| @@ -150,7 +153,6 @@ properties: · 74 unmodified lines | |||
| 150 | required: | 153 | required: |
| 151 | - compatible | 154 | - compatible |
| 152 | - reg | 155 | - reg |
| 153 | - enable-gpios | ||
| 154 | - vccio-supply | 156 | - vccio-supply |
| 155 | - vpll-supply | 157 | - vpll-supply |
| 156 | - vcca-supply | 158 | - vcca-supply |
| @@ -201,11 +203,26 @@ examples: · 44 unmodified lines | |||
| 201 | 203 | ||
| 202 | port@1 { | 204 | port@1 { |
| 203 | reg = <1>; | 205 | reg = <1>; |
| 204 | endpoint { | 206 | sn65dsi86_out: endpoint { |
| 205 | remote-endpoint = <&panel_in_edp>; | 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 | Required properties: | 8 | Required properties: |
| 9 | - compatible: "mediatek,<chip>-dsi" | 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 | - reg: Physical base address and length of the controller's registers | 11 | - reg: Physical base address and length of the controller's registers |
| 12 | - interrupts: The interrupt signal from the function block. | 12 | - interrupts: The interrupt signal from the function block. |
| 13 | - clocks: device clocks | 13 | - clocks: device clocks |
| @@ -64,6 +64,18 @@ properties: · 63 unmodified lines | |||
| 64 | Indicates if the DSI controller is driving a panel which needs | 64 | Indicates if the DSI controller is driving a panel which needs |
| 65 | 2 DSI links. | 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 | power-domains: | 79 | power-domains: |
| 68 | maxItems: 1 | 80 | maxItems: 1 |
| 69 | 81 | ||
| @@ -119,6 +131,8 @@ required: · 49 unmodified lines | |||
| 119 | - clock-names | 131 | - clock-names |
| 120 | - phys | 132 | - phys |
| 121 | - phy-names | 133 | - phy-names |
| 134 | - assigned-clocks | ||
| 135 | - assigned-clock-parents | ||
| 122 | - power-domains | 136 | - power-domains |
| 123 | - operating-points-v2 | 137 | - operating-points-v2 |
| 124 | - ports | 138 | - ports |
| @@ -159,6 +173,9 @@ examples: · 34 unmodified lines | |||
| 159 | phys = <&dsi0_phy>; | 173 | phys = <&dsi0_phy>; |
| 160 | phy-names = "dsi"; | 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 | power-domains = <&rpmhpd SC7180_CX>; | 179 | power-domains = <&rpmhpd SC7180_CX>; |
| 163 | operating-points-v2 = <&dsi_opp_table>; | 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 | # AU Optronics Corporation 11.6" HD (1366x768) color TFT-LCD panel | 46 | # AU Optronics Corporation 11.6" HD (1366x768) color TFT-LCD panel |
| 47 | - auo,b116xw03 | 47 | - auo,b116xw03 |
| 48 | # AU Optronics Corporation 13.3" FHD (1920x1080) color TFT-LCD panel | 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 | - auo,b133htn01 | 51 | - auo,b133htn01 |
| 50 | # AU Optronics Corporation 13.3" WXGA (1366x768) TFT LCD panel | 52 | # AU Optronics Corporation 13.3" WXGA (1366x768) TFT LCD panel |
| 51 | - auo,b133xtn01 | 53 | - auo,b133xtn01 |
| 54 | # AU Optronics Corporation 14.0" FHD (1920x1080) color TFT-LCD panel | ||
| 55 | - auo,b140han06 | ||
| 52 | # AU Optronics Corporation 7.0" FHD (800 x 480) TFT LCD panel | 56 | # AU Optronics Corporation 7.0" FHD (800 x 480) TFT LCD panel |
| 53 | - auo,g070vvn01 | 57 | - auo,g070vvn01 |
| 54 | # AU Optronics Corporation 10.1" (1280x800) color TFT LCD panel | 58 | # AU Optronics Corporation 10.1" (1280x800) color TFT LCD panel |
| @@ -110,6 +114,9 @@ properties: · 55 unmodified lines | |||
| 110 | # Emerging Display Technology Corp. 5.7" VGA TFT LCD panel | 114 | # Emerging Display Technology Corp. 5.7" VGA TFT LCD panel |
| 111 | - edt,et057090dhu | 115 | - edt,et057090dhu |
| 112 | - edt,et070080dh6 | 116 | - edt,et070080dh6 |
| 117 | # Emerging Display Technology Corp. 3.5" WVGA TFT LCD panel with | ||
| 118 | # capacitive multitouch | ||
| 119 | - edt,etm0350g0dh6 | ||
| 113 | # Emerging Display Technology Corp. 480x272 TFT Display with capacitive touch | 120 | # Emerging Display Technology Corp. 480x272 TFT Display with capacitive touch |
| 114 | - edt,etm043080dh6gp | 121 | - edt,etm043080dh6gp |
| 115 | # Emerging Display Technology Corp. 480x272 TFT Display | 122 | # Emerging Display Technology Corp. 480x272 TFT Display |
| @@ -128,6 +135,11 @@ properties: · 12 unmodified lines | |||
| 128 | # Emerging Display Technology Corp. WVGA TFT Display with capacitive touch | 135 | # Emerging Display Technology Corp. WVGA TFT Display with capacitive touch |
| 129 | - edt,etm0700g0dh6 | 136 | - edt,etm0700g0dh6 |
| 130 | - edt,etm0700g0edh6 | 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 | # Evervision Electronics Co. Ltd. VGG804821 5.0" WVGA TFT LCD Panel | 143 | # Evervision Electronics Co. Ltd. VGG804821 5.0" WVGA TFT LCD Panel |
| 132 | - evervision,vgg804821 | 144 | - evervision,vgg804821 |
| 133 | # Foxlink Group 5" WVGA TFT LCD panel | 145 | # Foxlink Group 5" WVGA TFT LCD panel |
| @@ -202,8 +214,14 @@ properties: · 68 unmodified lines | |||
| 202 | - logictechno,lt161010-2nhr | 214 | - logictechno,lt161010-2nhr |
| 203 | # Logic Technologies LT170410-2WHC 10.1" 1280x800 IPS TFT Cap Touch Mod. | 215 | # Logic Technologies LT170410-2WHC 10.1" 1280x800 IPS TFT Cap Touch Mod. |
| 204 | - logictechno,lt170410-2whc | 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 | # Mitsubishi "AA070MC01 7.0" WVGA TFT LCD panel | 221 | # Mitsubishi "AA070MC01 7.0" WVGA TFT LCD panel |
| 206 | - mitsubishi,aa070mc01-ca1 | 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 | # NEC LCD Technologies, Ltd. 12.1" WXGA (1280x800) LVDS TFT LCD panel | 225 | # NEC LCD Technologies, Ltd. 12.1" WXGA (1280x800) LVDS TFT LCD panel |
| 208 | - nec,nl12880bc20-05 | 226 | - nec,nl12880bc20-05 |
| 209 | # NEC LCD Technologies,Ltd. WQVGA TFT LCD panel | 227 | # NEC LCD Technologies,Ltd. WQVGA TFT LCD panel |
| @@ -238,10 +256,14 @@ properties: · 28 unmodified lines | |||
| 238 | - powertip,ph800480t013-idf02 | 256 | - powertip,ph800480t013-idf02 |
| 239 | # QiaoDian XianShi Corporation 4"3 TFT LCD panel | 257 | # QiaoDian XianShi Corporation 4"3 TFT LCD panel |
| 240 | - qiaodian,qd43003c0-40 | 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 | # Rocktech Displays Ltd. RK101II01D-CT 10.1" TFT 1280x800 | 261 | # Rocktech Displays Ltd. RK101II01D-CT 10.1" TFT 1280x800 |
| 242 | - rocktech,rk101ii01d-ct | 262 | - rocktech,rk101ii01d-ct |
| 243 | # Rocktech Display Ltd. RK070ER9427 800(RGB)x480 TFT LCD panel | 263 | # Rocktech Display Ltd. RK070ER9427 800(RGB)x480 TFT LCD panel |
| 244 | - rocktech,rk070er9427 | 264 | - rocktech,rk070er9427 |
| 265 | # Samsung 13.3" FHD (1920x1080 pixels) eDP AMOLED panel | ||
| 266 | - samsung,atna33xc20 | ||
| 245 | # Samsung 12.2" (2560x1600 pixels) TFT LCD panel | 267 | # Samsung 12.2" (2560x1600 pixels) TFT LCD panel |
| 246 | - samsung,lsn122dl01-c01 | 268 | - samsung,lsn122dl01-c01 |
| 247 | # Samsung Electronics 10.1" WSVGA TFT LCD panel | 269 | # Samsung Electronics 10.1" WSVGA TFT LCD panel |
| @@ -298,6 +320,8 @@ properties: · 50 unmodified lines | |||
| 298 | enable-gpios: true | 320 | enable-gpios: true |
| 299 | port: true | 321 | port: true |
| 300 | power-supply: true | 322 | power-supply: true |
| 323 | no-hpd: true | ||
| 324 | hpd-gpios: true | ||
| 301 | 325 | ||
| 302 | additionalProperties: false | 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 | backlight: true | 34 | backlight: true |
| 35 | 35 | ||
| 36 | spi-cpha: true | ||
| 37 | |||
| 38 | spi-cpol: true | ||
| 39 | |||
| 36 | spi-max-frequency: | 40 | spi-max-frequency: |
| 37 | $ref: /schemas/types.yaml#/definitions/uint32 | ||
| 38 | description: inherited as a SPI client node, the datasheet specifies | 41 | description: inherited as a SPI client node, the datasheet specifies |
| 39 | maximum 300 ns minimum cycle which gives around 3 MHz max frequency | 42 | maximum 300 ns minimum cycle which gives around 3 MHz max frequency |
| 40 | maximum: 3000000 | 43 | maximum: 3000000 |
| @@ -44,6 +47,9 @@ properties: · 3 unmodified lines | |||
| 44 | required: | 47 | required: |
| 45 | - compatible | 48 | - compatible |
| 46 | - reg | 49 | - reg |
| 50 | - spi-cpha | ||
| 51 | - spi-cpol | ||
| 52 | - port | ||
| 47 | 53 | ||
| 48 | additionalProperties: false | 54 | additionalProperties: false |
| 49 | 55 | ||
| @@ -52,15 +58,23 @@ examples: · 2 unmodified lines | |||
| 52 | #include <dt-bindings/gpio/gpio.h> | 58 | #include <dt-bindings/gpio/gpio.h> |
| 53 | 59 | ||
| 54 | spi { | 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 | #address-cells = <1>; | 67 | #address-cells = <1>; |
| 56 | #size-cells = <0>; | 68 | #size-cells = <0>; |
| 57 | panel@0 { | 69 | panel@0 { |
| 58 | compatible = "samsung,lms397kf04"; | 70 | compatible = "samsung,lms397kf04"; |
| 59 | spi-max-frequency = <3000000>; | 71 | spi-max-frequency = <3000000>; |
| 72 | spi-cpha; | ||
| 73 | spi-cpol; | ||
| 60 | reg = <0>; | 74 | reg = <0>; |
| 61 | vci-supply = <&lcd_3v0_reg>; | 75 | vci-supply = <&lcd_3v0_reg>; |
| 62 | vccio-supply = <&lcd_1v8_reg>; | 76 | vccio-supply = <&lcd_1v8_reg>; |
| 63 | reset-gpios = <&gpio 1 GPIO_ACTIVE_LOW>; | 77 | reset-gpios = <&gpio 4 GPIO_ACTIVE_LOW>; |
| 64 | backlight = <&ktd259>; | 78 | backlight = <&ktd259>; |
| 65 | 79 | ||
| 66 | port { | 80 | port { |
| @@ -23,6 +23,7 @@ Required properties: · 22 unmodified lines | |||
| 23 | Optional properties: | 23 | Optional properties: |
| 24 | - phys: from general PHY binding: the phandle for the PHY device. | 24 | - phys: from general PHY binding: the phandle for the PHY device. |
| 25 | - phy-names: Should be "dphy" if phys references an external phy. | 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 | - power-domains: a phandle to mipi dsi power domain node. | 27 | - power-domains: a phandle to mipi dsi power domain node. |
| 27 | - resets: list of phandle + reset specifier pairs, as described in [3]. | 28 | - resets: list of phandle + reset specifier pairs, as described in [3]. |
| 28 | - reset-names: string reset name, must be "apb". | 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 | description: eGalax_eMPIA Technology Inc | 341 | description: eGalax_eMPIA Technology Inc |
| 342 | "^einfochips,.*": | 342 | "^einfochips,.*": |
| 343 | description: Einfochips | 343 | description: Einfochips |
| 344 | "^eink,.*": | ||
| 345 | description: E Ink Corporation | ||
| 344 | "^elan,.*": | 346 | "^elan,.*": |
| 345 | description: Elan Microelectronic Corp. | 347 | description: Elan Microelectronic Corp. |
| 346 | "^element14,.*": | 348 | "^element14,.*": |
| @@ -938,6 +940,8 @@ patternProperties: · 591 unmodified lines | |||
| 938 | description: Chengdu Kaixuan Information Technology Co., Ltd. | 940 | description: Chengdu Kaixuan Information Technology Co., Ltd. |
| 939 | "^qiaodian,.*": | 941 | "^qiaodian,.*": |
| 940 | description: QiaoDian XianShi Corporation | 942 | description: QiaoDian XianShi Corporation |
| 943 | "^qishenglong,.*": | ||
| 944 | description: Shenzhen QiShenglong Industrialist Co., Ltd. | ||
| 941 | "^qnap,.*": | 945 | "^qnap,.*": |
| 942 | description: QNAP Systems, Inc. | 946 | description: QNAP Systems, Inc. |
| 943 | "^radxa,.*": | 947 | "^radxa,.*": |
| @@ -88,6 +88,9 @@ consider though: · 87 unmodified lines | |||
| 88 | - The DMA buffer FD is also pollable, see `Implicit Fence Poll Support`_ below for | 88 | - The DMA buffer FD is also pollable, see `Implicit Fence Poll Support`_ below for |
| 89 | details. | 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 | Basic Operation and Device DMA Access | 94 | Basic Operation and Device DMA Access |
| 92 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | 95 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 93 | 96 | ||
| @@ -106,6 +109,16 @@ Implicit Fence Poll Support · 12 unmodified lines | |||
| 106 | .. kernel-doc:: drivers/dma-buf/dma-buf.c | 109 | .. kernel-doc:: drivers/dma-buf/dma-buf.c |
| 107 | :doc: implicit fence polling | 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 | Kernel Functions and Structures Reference | 122 | Kernel Functions and Structures Reference |
| 110 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | 123 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 111 | 124 | ||
| @@ -90,7 +90,7 @@ Bug reports · 89 unmodified lines | |||
| 90 | ----------- | 90 | ----------- |
| 91 | 91 | ||
| 92 | Thermal management on Nouveau is new and may not work on all cards. If you have | 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 | Bug reports should be filled on Freedesktop's bug tracker. Please follow | 95 | Bug reports should be filled on Freedesktop's bug tracker. Please follow |
| 96 | https://nouveau.freedesktop.org/wiki/Bugs | 96 | https://nouveau.freedesktop.org/wiki/Bugs |
| @@ -159,6 +159,8 @@ KMS Core Structures and Functions · 158 unmodified lines | |||
| 159 | .. kernel-doc:: drivers/gpu/drm/drm_mode_config.c | 159 | .. kernel-doc:: drivers/gpu/drm/drm_mode_config.c |
| 160 | :export: | 160 | :export: |
| 161 | 161 | ||
| 162 | .. _kms_base_object_abstraction: | ||
| 163 | |||
| 162 | Modeset Base Object Abstraction | 164 | Modeset Base Object Abstraction |
| 163 | =============================== | 165 | =============================== |
| 164 | 166 | ||
| @@ -463,6 +465,35 @@ KMS Properties · 298 unmodified lines | |||
| 463 | This section of the documentation is primarily aimed at user-space developers. | 465 | This section of the documentation is primarily aimed at user-space developers. |
| 464 | For the driver APIs, see the other sections. | 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 | Property Types and Blob Property Support | 497 | Property Types and Blob Property Support |
| 467 | ---------------------------------------- | 498 | ---------------------------------------- |
| 468 | 499 | ||
| @@ -508,8 +539,8 @@ Plane Composition Properties · 39 unmodified lines | |||
| 508 | Damage Tracking Properties | 539 | Damage Tracking Properties |
| 509 | -------------------------- | 540 | -------------------------- |
| 510 | 541 | ||
| 511 | .. kernel-doc:: drivers/gpu/drm/drm_damage_helper.c | 542 | .. kernel-doc:: drivers/gpu/drm/drm_plane.c |
| 512 | :doc: overview | 543 | :doc: damage tracking |
| 513 | 544 | ||
| 514 | Color Management Properties | 545 | Color Management Properties |
| 515 | --------------------------- | 546 | --------------------------- |
| @@ -37,6 +37,15 @@ Primary Nodes, DRM Master and Authentication · 36 unmodified lines | |||
| 37 | .. kernel-doc:: include/drm/drm_auth.h | 37 | .. kernel-doc:: include/drm/drm_auth.h |
| 38 | :internal: | 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 | Open-Source Userspace Requirements | 49 | Open-Source Userspace Requirements |
| 41 | ================================== | 50 | ================================== |
| 42 | 51 | ||
| @@ -457,6 +466,19 @@ Userspace API Structures · 414 unmodified lines | |||
| 457 | .. kernel-doc:: include/uapi/drm/drm_mode.h | 466 | .. kernel-doc:: include/uapi/drm/drm_mode.h |
| 458 | :doc: overview | 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 | .. kernel-doc:: include/uapi/drm/drm.h | 482 | .. kernel-doc:: include/uapi/drm/drm.h |
| 461 | :internal: | 483 | :internal: |
| 462 | 484 | ||
| @@ -422,9 +422,16 @@ Batchbuffer Parsing · 421 unmodified lines | |||
| 422 | User Batchbuffer Execution | 422 | User Batchbuffer Execution |
| 423 | -------------------------- | 423 | -------------------------- |
| 424 | 424 | ||
| 425 | .. kernel-doc:: drivers/gpu/drm/i915/gem/i915_gem_context_types.h | ||
| 426 | |||
| 425 | .. kernel-doc:: drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c | 427 | .. kernel-doc:: drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c |
| 426 | :doc: User command execution | 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 | Logical Rings, Logical Ring Contexts and Execlists | 435 | Logical Rings, Logical Ring Contexts and Execlists |
| 429 | -------------------------------------------------- | 436 | -------------------------------------------------- |
| 430 | 437 | ||
| @@ -518,6 +525,14 @@ GuC-based command submission · 87 unmodified lines | |||
| 518 | .. kernel-doc:: drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c | 525 | .. kernel-doc:: drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c |
| 519 | :doc: GuC-based command submission | 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 | HuC | 536 | HuC |
| 522 | --- | 537 | --- |
| 523 | .. kernel-doc:: drivers/gpu/drm/i915/gt/uc/intel_huc.c | 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 | .. toctree:: | 19 | .. toctree:: |
| 20 | 20 | ||
| 21 | i915_gem_lmem.rst | 21 | i915_gem_lmem.rst |
| 22 | |||
| 23 | .. toctree:: | ||
| 24 | |||
| 25 | i915_scheduler.rst | ||
| @@ -98,9 +98,17 @@ with VKMS maintainers. · 97 unmodified lines | |||
| 98 | IGT better support | 98 | IGT better support |
| 99 | ------------------ | 99 | ------------------ |
| 100 | 100 | ||
| 101 | - Investigate: (1) test cases on kms_plane that are failing due to timeout on | 101 | Debugging: |
| 102 | capturing CRC; (2) when running kms_flip test cases in sequence, some | 102 | |
| 103 | successful individual test cases are failing randomly. | 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 | - VKMS already has support for vblanks simulated via hrtimers, which can be | 113 | - VKMS already has support for vblanks simulated via hrtimers, which can be |
| 106 | tested with kms_flip test; in some way, we can say that VKMS already mimics | 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 | There's lots of plane features we could add support for: | 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 | - Full alpha blending on all planes. | 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 | cursor api). | 147 | cursor api). |
| 130 | 148 | ||
| 131 | For all of these, we also want to review the igt test coverage and make sure | 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. | 150 | all relevant igt testcases work on vkms. They are good options for internship |
| 133 | 151 | project. | |
| 134 | Prime Buffer Sharing | ||
| 135 | -------------------- | ||
| 136 | |||
| 137 | - Syzbot report - WARNING in vkms_gem_free_object: | ||
| 138 | https://syzkaller.appspot.com/bug?extid=e7ad70d406e74d8fc9d0 | ||
| 139 | 152 | ||
| 140 | Runtime Configuration | 153 | Runtime Configuration |
| 141 | --------------------- | 154 | --------------------- |
| @@ -153,7 +166,7 @@ module. Use/Test-cases: · 11 unmodified lines | |||
| 153 | the refresh rate. | 166 | the refresh rate. |
| 154 | 167 | ||
| 155 | The currently proposed solution is to expose vkms configuration through | 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 | too. | 170 | too. |
| 158 | 171 | ||
| 159 | Writeback support | 172 | Writeback support |
| @@ -162,6 +175,7 @@ Writeback support · 2 unmodified lines | |||
| 162 | - The writeback and CRC capture operations share the use of composer_enabled | 175 | - The writeback and CRC capture operations share the use of composer_enabled |
| 163 | boolean to ensure vblanks. Probably, when these operations work together, | 176 | boolean to ensure vblanks. Probably, when these operations work together, |
| 164 | composer_enabled needs to refcounting the composer state to proper work. | 177 | composer_enabled needs to refcounting the composer state to proper work. |
| 178 | [Good to get started] | ||
| 165 | 179 | ||
| 166 | - Add support for cloned writeback outputs and related test cases using a | 180 | - Add support for cloned writeback outputs and related test cases using a |
| 167 | cloned output in the IGT kms_writeback. | 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 | S: Maintained | 1703 | S: Maintained |
| 1704 | W: https://asahilinux.org | 1704 | W: https://asahilinux.org |
| 1705 | B: https://github.com/AsahiLinux/linux/issues | 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 | T: git https://github.com/AsahiLinux/linux.git | 1707 | T: git https://github.com/AsahiLinux/linux.git |
| 1708 | F: Documentation/devicetree/bindings/arm/apple.yaml | 1708 | F: Documentation/devicetree/bindings/arm/apple.yaml |
| 1709 | F: Documentation/devicetree/bindings/interrupt-controller/apple,aic.yaml | 1709 | F: Documentation/devicetree/bindings/interrupt-controller/apple,aic.yaml |
| @@ -5799,7 +5799,7 @@ M: Gerd Hoffmann <kraxel@redhat.com> · 4089 unmodified lines | |||
| 5799 | L: virtualization@lists.linux-foundation.org | 5799 | L: virtualization@lists.linux-foundation.org |
| 5800 | S: Maintained | 5800 | S: Maintained |
| 5801 | T: git git://anongit.freedesktop.org/drm/drm-misc | 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 | DRM DRIVER FOR BOE HIMAX8279D PANELS | 5804 | DRM DRIVER FOR BOE HIMAX8279D PANELS |
| 5805 | M: Jerry Han <hanxu5@huaqin.corp-partner.google.com> | 5805 | M: Jerry Han <hanxu5@huaqin.corp-partner.google.com> |
| @@ -5984,6 +5984,13 @@ S: Maintained · 178 unmodified lines | |||
| 5984 | F: Documentation/devicetree/bindings/display/panel/raydium,rm67191.yaml | 5984 | F: Documentation/devicetree/bindings/display/panel/raydium,rm67191.yaml |
| 5985 | F: drivers/gpu/drm/panel/panel-raydium-rm67191.c | 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 | DRM DRIVER FOR SITRONIX ST7703 PANELS | 5994 | DRM DRIVER FOR SITRONIX ST7703 PANELS |
| 5988 | M: Guido Günther <agx@sigxcpu.org> | 5995 | M: Guido Günther <agx@sigxcpu.org> |
| 5989 | R: Purism Kernel Team <kernel@puri.sm> | 5996 | R: Purism Kernel Team <kernel@puri.sm> |
| @@ -6082,21 +6089,27 @@ F: drivers/gpu/drm/vboxvideo/ · 92 unmodified lines | |||
| 6082 | 6089 | ||
| 6083 | DRM DRIVER FOR VMWARE VIRTUAL GPU | 6090 | DRM DRIVER FOR VMWARE VIRTUAL GPU |
| 6084 | M: "VMware Graphics" <linux-graphics-maintainer@vmware.com> | 6091 | M: "VMware Graphics" <linux-graphics-maintainer@vmware.com> |
| 6085 | M: Roland Scheidegger <sroland@vmware.com> | ||
| 6086 | M: Zack Rusin <zackr@vmware.com> | 6092 | M: Zack Rusin <zackr@vmware.com> |
| 6087 | L: dri-devel@lists.freedesktop.org | 6093 | L: dri-devel@lists.freedesktop.org |
| 6088 | S: Supported | 6094 | S: Supported |
| 6089 | T: git git://people.freedesktop.org/~sroland/linux | 6095 | T: git git://anongit.freedesktop.org/drm/drm-misc |
| 6090 | F: drivers/gpu/drm/vmwgfx/ | 6096 | F: drivers/gpu/drm/vmwgfx/ |
| 6091 | F: include/uapi/drm/vmwgfx_drm.h | 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 | DRM DRIVERS | 6106 | DRM DRIVERS |
| 6094 | M: David Airlie <airlied@linux.ie> | 6107 | M: David Airlie <airlied@linux.ie> |
| 6095 | M: Daniel Vetter <daniel@ffwll.ch> | 6108 | M: Daniel Vetter <daniel@ffwll.ch> |
| 6096 | L: dri-devel@lists.freedesktop.org | 6109 | L: dri-devel@lists.freedesktop.org |
| 6097 | S: Maintained | 6110 | S: Maintained |
| 6098 | B: https://gitlab.freedesktop.org/drm | 6111 | B: https://gitlab.freedesktop.org/drm |
| 6099 | C: irc://chat.freenode.net/dri-devel | 6112 | C: irc://irc.oftc.net/dri-devel |
| 6100 | T: git git://anongit.freedesktop.org/drm/drm | 6113 | T: git git://anongit.freedesktop.org/drm/drm |
| 6101 | F: Documentation/devicetree/bindings/display/ | 6114 | F: Documentation/devicetree/bindings/display/ |
| 6102 | F: Documentation/devicetree/bindings/gpu/ | 6115 | F: Documentation/devicetree/bindings/gpu/ |
| @@ -9288,7 +9301,7 @@ S: Supported · 3185 unmodified lines | |||
| 9288 | W: https://01.org/linuxgraphics/ | 9301 | W: https://01.org/linuxgraphics/ |
| 9289 | Q: http://patchwork.freedesktop.org/project/intel-gfx/ | 9302 | Q: http://patchwork.freedesktop.org/project/intel-gfx/ |
| 9290 | B: https://gitlab.freedesktop.org/drm/intel/-/wikis/How-to-file-i915-bugs | 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 | T: git git://anongit.freedesktop.org/drm-intel | 9305 | T: git git://anongit.freedesktop.org/drm-intel |
| 9293 | F: Documentation/gpu/i915.rst | 9306 | F: Documentation/gpu/i915.rst |
| 9294 | F: drivers/gpu/drm/i915/ | 9307 | F: drivers/gpu/drm/i915/ |
| @@ -17,6 +17,7 @@ · 16 unmodified lines | |||
| 17 | 17 | ||
| 18 | #ifdef CONFIG_EFI | 18 | #ifdef CONFIG_EFI |
| 19 | void efi_init(void); | 19 | void efi_init(void); |
| 20 | extern void efifb_setup_from_dmi(struct screen_info *si, const char *opt); | ||
| 20 | 21 | ||
| 21 | int efi_create_mapping(struct mm_struct *mm, efi_memory_desc_t *md); | 22 | int efi_create_mapping(struct mm_struct *mm, efi_memory_desc_t *md); |
| 22 | int efi_set_mapping_permissions(struct mm_struct *mm, efi_memory_desc_t *md); | 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 | struct screen_info *alloc_screen_info(void); | 53 | struct screen_info *alloc_screen_info(void); |
| 53 | void free_screen_info(struct screen_info *si); | 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 | * A reasonable upper bound for the uncompressed kernel size is 32 MBytes, | 57 | * A reasonable upper bound for the uncompressed kernel size is 32 MBytes, |
| 61 | * so we will reserve that amount of memory. We have no easy way to tell what | 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 | #sound-dai-cells = <0>; | 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 | pwmleds { | 258 | pwmleds { |
| 274 | compatible = "pwm-leds"; | 259 | compatible = "pwm-leds"; |
| 275 | keyboard_backlight: keyboard-backlight { | 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 | #ifdef CONFIG_EFI | 15 | #ifdef CONFIG_EFI |
| 16 | extern void efi_init(void); | 16 | extern void efi_init(void); |
| 17 | extern void efifb_setup_from_dmi(struct screen_info *si, const char *opt); | ||
| 17 | #else | 18 | #else |
| 18 | #define efi_init() | 19 | #define efi_init() |
| 19 | #endif | 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 | #define EFI_ALLOC_ALIGN SZ_64K | 89 | #define EFI_ALLOC_ALIGN SZ_64K |
| 93 | 90 | ||
| 94 | /* | 91 | /* |
| @@ -13,6 +13,7 @@ · 12 unmodified lines | |||
| 13 | 13 | ||
| 14 | #ifdef CONFIG_EFI | 14 | #ifdef CONFIG_EFI |
| 15 | extern void efi_init(void); | 15 | extern void efi_init(void); |
| 16 | extern void efifb_setup_from_dmi(struct screen_info *si, const char *opt); | ||
| 16 | #else | 17 | #else |
| 17 | #define efi_init() | 18 | #define efi_init() |
| 18 | #endif | 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 | void efi_virtmap_load(void); | 43 | void efi_virtmap_load(void); |
| 47 | void efi_virtmap_unload(void); | 44 | void efi_virtmap_unload(void); |
| 48 | 45 | ||
| @@ -2767,32 +2767,6 @@ config AMD_NB · 2766 unmodified lines | |||
| 2767 | def_bool y | 2767 | def_bool y |
| 2768 | depends on CPU_SUP_AMD && PCI | 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 | endmenu | 2770 | endmenu |
| 2797 | 2771 | ||
| 2798 | 2772 | ||
| @@ -136,9 +136,6 @@ obj-$(CONFIG_X86_CHECK_BIOS_CORRUPTION) += check.o · 135 unmodified lines | |||
| 136 | obj-$(CONFIG_SWIOTLB) += pci-swiotlb.o | 136 | obj-$(CONFIG_SWIOTLB) += pci-swiotlb.o |
| 137 | obj-$(CONFIG_OF) += devicetree.o | 137 | obj-$(CONFIG_OF) += devicetree.o |
| 138 | obj-$(CONFIG_UPROBES) += uprobes.o | 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 | obj-$(CONFIG_PERF_EVENTS) += perf_regs.o | 140 | obj-$(CONFIG_PERF_EVENTS) += perf_regs.o |
| 144 | obj-$(CONFIG_TRACING) += tracepoint.o | 141 | obj-$(CONFIG_TRACING) += tracepoint.o |
| @@ -72,6 +72,17 @@ menuconfig DMABUF_HEAPS · 71 unmodified lines | |||
| 72 | allows userspace to allocate dma-bufs that can be shared | 72 | allows userspace to allocate dma-bufs that can be shared |
| 73 | between drivers. | 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 | source "drivers/dma-buf/heaps/Kconfig" | 86 | source "drivers/dma-buf/heaps/Kconfig" |
| 76 | 87 | ||
| 77 | endmenu | 88 | endmenu |
| @@ -6,6 +6,7 @@ obj-$(CONFIG_DMABUF_HEAPS) += heaps/ · 5 unmodified lines | |||
| 6 | obj-$(CONFIG_SYNC_FILE) += sync_file.o | 6 | obj-$(CONFIG_SYNC_FILE) += sync_file.o |
| 7 | obj-$(CONFIG_SW_SYNC) += sw_sync.o sync_debug.o | 7 | obj-$(CONFIG_SW_SYNC) += sw_sync.o sync_debug.o |
| 8 | obj-$(CONFIG_UDMABUF) += udmabuf.o | 8 | obj-$(CONFIG_UDMABUF) += udmabuf.o |
| 9 | obj-$(CONFIG_DMABUF_SYSFS_STATS) += dma-buf-sysfs-stats.o | ||
| 9 | 10 | ||
| 10 | dmabuf_selftests-y := \ | 11 | dmabuf_selftests-y := \ |
| 11 | selftest.o \ | 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 | #include <uapi/linux/dma-buf.h> | 29 | #include <uapi/linux/dma-buf.h> |
| 30 | #include <uapi/linux/magic.h> | 30 | #include <uapi/linux/magic.h> |
| 31 | 31 | ||
| 32 | #include "dma-buf-sysfs-stats.h" | ||
| 33 | |||
| 32 | static inline int is_dma_buf_file(struct file *); | 34 | static inline int is_dma_buf_file(struct file *); |
| 33 | 35 | ||
| 34 | struct dma_buf_list { | 36 | struct dma_buf_list { |
| @@ -74,6 +76,7 @@ static void dma_buf_release(struct dentry *dentry) · 39 unmodified lines | |||
| 74 | */ | 76 | */ |
| 75 | BUG_ON(dmabuf->cb_shared.active || dmabuf->cb_excl.active); | 77 | BUG_ON(dmabuf->cb_shared.active || dmabuf->cb_excl.active); |
| 76 | 78 | ||
| 79 | dma_buf_stats_teardown(dmabuf); | ||
| 77 | dmabuf->ops->release(dmabuf); | 80 | dmabuf->ops->release(dmabuf); |
| 78 | 81 | ||
| 79 | if (dmabuf->resv == (struct dma_resv *)&dmabuf[1]) | 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 | file->f_mode |= FMODE_LSEEK; | 583 | file->f_mode |= FMODE_LSEEK; |
| 581 | dmabuf->file = file; | 584 | dmabuf->file = file; |
| 582 | 585 | ||
| 586 | ret = dma_buf_stats_setup(dmabuf); | ||
| 587 | if (ret) | ||
| 588 | goto err_sysfs; | ||
| 589 | |||
| 583 | mutex_init(&dmabuf->lock); | 590 | mutex_init(&dmabuf->lock); |
| 584 | INIT_LIST_HEAD(&dmabuf->attachments); | 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 | return dmabuf; | 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 | err_dmabuf: | 607 | err_dmabuf: |
| 593 | kfree(dmabuf); | 608 | kfree(dmabuf); |
| 594 | err_module: | 609 | err_module: |
| @@ -926,6 +941,9 @@ EXPORT_SYMBOL_GPL(dma_buf_unpin); · 331 unmodified lines | |||
| 926 | * the underlying backing storage is pinned for as long as a mapping exists, | 941 | * the underlying backing storage is pinned for as long as a mapping exists, |
| 927 | * therefore users/importers should not hold onto a mapping for undue amounts of | 942 | * therefore users/importers should not hold onto a mapping for undue amounts of |
| 928 | * time. | 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 | struct sg_table *dma_buf_map_attachment(struct dma_buf_attachment *attach, | 948 | struct sg_table *dma_buf_map_attachment(struct dma_buf_attachment *attach, |
| 931 | enum dma_data_direction direction) | 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 | #endif /* CONFIG_DMA_API_DEBUG */ | 1012 | #endif /* CONFIG_DMA_API_DEBUG */ |
| 995 | |||
| 996 | return sg_table; | 1013 | return sg_table; |
| 997 | } | 1014 | } |
| 998 | EXPORT_SYMBOL_GPL(dma_buf_map_attachment); | 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 | static int __init dma_buf_init(void) | 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 | dma_buf_mnt = kern_mount(&dma_buf_fs_type); | 1495 | dma_buf_mnt = kern_mount(&dma_buf_fs_type); |
| 1473 | if (IS_ERR(dma_buf_mnt)) | 1496 | if (IS_ERR(dma_buf_mnt)) |
| 1474 | return PTR_ERR(dma_buf_mnt); | 1497 | return PTR_ERR(dma_buf_mnt); |
| @@ -1484,5 +1507,6 @@ static void __exit dma_buf_deinit(void) · 9 unmodified lines | |||
| 1484 | { | 1507 | { |
| 1485 | dma_buf_uninit_debugfs(); | 1508 | dma_buf_uninit_debugfs(); |
| 1486 | kern_unmount(dma_buf_mnt); | 1509 | kern_unmount(dma_buf_mnt); |
| 1510 | dma_buf_uninit_sysfs_statistics(); | ||
| 1487 | } | 1511 | } |
| 1488 | __exitcall(dma_buf_deinit); | 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 | struct dma_fence_chain *chain; | 137 | struct dma_fence_chain *chain; |
| 138 | 138 | ||
| 139 | chain = container_of(cb, typeof(*chain), cb); | 139 | chain = container_of(cb, typeof(*chain), cb); |
| 140 | init_irq_work(&chain->work, dma_fence_chain_irq_work); | ||
| 140 | irq_work_queue(&chain->work); | 141 | irq_work_queue(&chain->work); |
| 141 | dma_fence_put(f); | 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 | rcu_assign_pointer(chain->prev, prev); | 240 | rcu_assign_pointer(chain->prev, prev); |
| 240 | chain->fence = fence; | 241 | chain->fence = fence; |
| 241 | chain->prev_seqno = 0; | 242 | chain->prev_seqno = 0; |
| 242 | init_irq_work(&chain->work, dma_fence_chain_irq_work); | ||
| 243 | 243 | ||
| 244 | /* Try to reuse the context of the previous chain node. */ | 244 | /* Try to reuse the context of the previous chain node. */ |
| 245 | if (prev_chain && __dma_fence_is_later(seqno, prev->seqno, prev->ops)) { | 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 | bool dma_resv_test_signaled(struct dma_resv *obj, bool test_all) | 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 | int ret; | 620 | int ret; |
| 620 | 621 | ||
| 621 | rcu_read_lock(); | 622 | rcu_read_lock(); |
| 622 | retry: | 623 | retry: |
| 623 | ret = true; | 624 | ret = true; |
| 624 | shared_count = 0; | ||
| 625 | seq = read_seqcount_begin(&obj->seq); | 625 | seq = read_seqcount_begin(&obj->seq); |
| 626 | 626 | ||
| 627 | if (test_all) { | 627 | if (test_all) { |
| 628 | struct dma_resv_list *fobj = dma_resv_shared_list(obj); | 628 | struct dma_resv_list *fobj = dma_resv_shared_list(obj); |
| 629 | unsigned int i; | 629 | unsigned int i, shared_count; |
| 630 | |||
| 631 | if (fobj) | ||
| 632 | shared_count = fobj->shared_count; | ||
| 633 | 630 | ||
| 631 | shared_count = fobj ? fobj->shared_count : 0; | ||
| 634 | for (i = 0; i < shared_count; ++i) { | 632 | for (i = 0; i < shared_count; ++i) { |
| 635 | struct dma_fence *fence; | ||
| 636 | |||
| 637 | fence = rcu_dereference(fobj->shared[i]); | 633 | fence = rcu_dereference(fobj->shared[i]); |
| 638 | ret = dma_resv_test_signaled_single(fence); | 634 | ret = dma_resv_test_signaled_single(fence); |
| 639 | if (ret < 0) | 635 | if (ret < 0) |
| @@ -641,24 +637,19 @@ retry: · 1 unmodified line | |||
| 641 | else if (!ret) | 637 | else if (!ret) |
| 642 | break; | 638 | break; |
| 643 | } | 639 | } |
| 644 | |||
| 645 | if (read_seqcount_retry(&obj->seq, seq)) | ||
| 646 | goto retry; | ||
| 647 | } | 640 | } |
| 648 | 641 | ||
| 649 | if (!shared_count) { | 642 | fence = dma_resv_excl_fence(obj); |
| 650 | struct dma_fence *fence_excl = dma_resv_excl_fence(obj); | 643 | if (ret && fence) { |
| 651 | 644 | ret = dma_resv_test_signaled_single(fence); | |
| 652 | if (fence_excl) { | 645 | if (ret < 0) |
| 653 | ret = dma_resv_test_signaled_single(fence_excl); | 646 | goto retry; |
| 654 | if (ret < 0) | ||
| 655 | 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 | rcu_read_unlock(); | 653 | rcu_read_unlock(); |
| 663 | return ret; | 654 | return ret; |
| 664 | } | 655 | } |
| @@ -58,28 +58,20 @@ static struct dma_fence *mock_fence(void) · 57 unmodified lines | |||
| 58 | return &f->base; | 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 | static struct dma_fence *mock_chain(struct dma_fence *prev, | 61 | static struct dma_fence *mock_chain(struct dma_fence *prev, |
| 68 | struct dma_fence *fence, | 62 | struct dma_fence *fence, |
| 69 | u64 seqno) | 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 | if (!f) | 68 | if (!f) |
| 75 | return NULL; | 69 | return NULL; |
| 76 | 70 | ||
| 77 | dma_fence_chain_init(&f->base, | 71 | dma_fence_chain_init(f, dma_fence_get(prev), dma_fence_get(fence), |
| 78 | dma_fence_get(prev), | ||
| 79 | dma_fence_get(fence), | ||
| 80 | seqno); | 72 | seqno); |
| 81 | 73 | ||
| 82 | return &f->base.base; | 74 | return &f->base; |
| 83 | } | 75 | } |
| 84 | 76 | ||
| 85 | static int sanitycheck(void *arg) | 77 | static int sanitycheck(void *arg) |
| @@ -11,9 +11,15 @@ · 10 unmodified lines | |||
| 11 | #include <linux/shmem_fs.h> | 11 | #include <linux/shmem_fs.h> |
| 12 | #include <linux/slab.h> | 12 | #include <linux/slab.h> |
| 13 | #include <linux/udmabuf.h> | 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 int list_limit = 1024; |
| 16 | static const size_t size_limit_mb = 64; /* total dmabuf size, in megabytes */ | 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 | struct udmabuf { | 24 | struct udmabuf { |
| 19 | pgoff_t pagecount; | 25 | pgoff_t pagecount; |
| @@ -160,10 +166,13 @@ static long udmabuf_create(struct miscdevice *device, · 140 unmodified lines | |||
| 160 | { | 166 | { |
| 161 | DEFINE_DMA_BUF_EXPORT_INFO(exp_info); | 167 | DEFINE_DMA_BUF_EXPORT_INFO(exp_info); |
| 162 | struct file *memfd = NULL; | 168 | struct file *memfd = NULL; |
| 169 | struct address_space *mapping = NULL; | ||
| 163 | struct udmabuf *ubuf; | 170 | struct udmabuf *ubuf; |
| 164 | struct dma_buf *buf; | 171 | struct dma_buf *buf; |
| 165 | pgoff_t pgoff, pgcnt, pgidx, pgbuf = 0, pglimit; | 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 | int seals, ret = -EINVAL; | 176 | int seals, ret = -EINVAL; |
| 168 | u32 i, flags; | 177 | u32 i, flags; |
| 169 | 178 | ||
| @@ -194,7 +203,8 @@ static long udmabuf_create(struct miscdevice *device, · 24 unmodified lines | |||
| 194 | memfd = fget(list[i].memfd); | 203 | memfd = fget(list[i].memfd); |
| 195 | if (!memfd) | 204 | if (!memfd) |
| 196 | goto err; | 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 | goto err; | 208 | goto err; |
| 199 | seals = memfd_fcntl(memfd, F_GET_SEALS, 0); | 209 | seals = memfd_fcntl(memfd, F_GET_SEALS, 0); |
| 200 | if (seals == -EINVAL) | 210 | if (seals == -EINVAL) |
| @@ -205,17 +215,48 @@ static long udmabuf_create(struct miscdevice *device, · 4 unmodified lines | |||
| 205 | goto err; | 215 | goto err; |
| 206 | pgoff = list[i].offset >> PAGE_SHIFT; | 216 | pgoff = list[i].offset >> PAGE_SHIFT; |
| 207 | pgcnt = list[i].size >> PAGE_SHIFT; | 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 | for (pgidx = 0; pgidx < pgcnt; pgidx++) { | 225 | for (pgidx = 0; pgidx < pgcnt; pgidx++) { |
| 209 | page = shmem_read_mapping_page( | 226 | if (is_file_hugepages(memfd)) { |
| 210 | file_inode(memfd)->i_mapping, pgoff + pgidx); | 227 | if (!hpage) { |
| 211 | if (IS_ERR(page)) { | 228 | hpage = find_get_page_flags(mapping, pgoff, |
| 212 | ret = PTR_ERR(page); | 229 | FGP_ACCESSED); |
| 213 | goto err; | 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 | ubuf->pages[pgbuf++] = page; | 252 | ubuf->pages[pgbuf++] = page; |
| 216 | } | 253 | } |
| 217 | fput(memfd); | 254 | fput(memfd); |
| 218 | memfd = NULL; | 255 | memfd = NULL; |
| 256 | if (hpage) { | ||
| 257 | put_page(hpage); | ||
| 258 | hpage = NULL; | ||
| 259 | } | ||
| 219 | } | 260 | } |
| 220 | 261 | ||
| 221 | exp_info.ops = &udmabuf_ops; | 262 | exp_info.ops = &udmabuf_ops; |
| @@ -251,6 +251,38 @@ config QCOM_SCM_DOWNLOAD_MODE_DEFAULT · 250 unmodified lines | |||
| 251 | 251 | ||
| 252 | Say Y here to enable "download mode" by default. | 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 | config TI_SCI_PROTOCOL | 286 | config TI_SCI_PROTOCOL |
| 255 | tristate "TI System Control Interface (TISCI) Message Protocol" | 287 | tristate "TI System Control Interface (TISCI) Message Protocol" |
| 256 | depends on TI_MESSAGE_MANAGER | 288 | depends on TI_MESSAGE_MANAGER |
| @@ -18,6 +18,8 @@ obj-$(CONFIG_FIRMWARE_MEMMAP) += memmap.o · 17 unmodified lines | |||
| 18 | obj-$(CONFIG_RASPBERRYPI_FIRMWARE) += raspberrypi.o | 18 | obj-$(CONFIG_RASPBERRYPI_FIRMWARE) += raspberrypi.o |
| 19 | obj-$(CONFIG_FW_CFG_SYSFS) += qemu_fw_cfg.o | 19 | obj-$(CONFIG_FW_CFG_SYSFS) += qemu_fw_cfg.o |
| 20 | obj-$(CONFIG_QCOM_SCM) += qcom_scm.o qcom_scm-smc.o qcom_scm-legacy.o | 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 | obj-$(CONFIG_TI_SCI_PROTOCOL) += ti_sci.o | 23 | obj-$(CONFIG_TI_SCI_PROTOCOL) += ti_sci.o |
| 22 | obj-$(CONFIG_TRUSTED_FOUNDATIONS) += trusted_foundations.o | 24 | obj-$(CONFIG_TRUSTED_FOUNDATIONS) += trusted_foundations.o |
| 23 | obj-$(CONFIG_TURRIS_MOX_RWTM) += turris-mox-rwtm.o | 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 | fake_map-y += fake_mem.o | 36 | fake_map-y += fake_mem.o |
| 37 | fake_map-$(CONFIG_X86) += x86_fake_mem.o | 37 | fake_map-$(CONFIG_X86) += x86_fake_mem.o |
| 38 | 38 | ||
| 39 | obj-$(CONFIG_SYSFB) += sysfb_efi.o | ||
| 40 | |||
| 39 | arm-obj-$(CONFIG_EFI) := efi-init.o arm-runtime.o | 41 | arm-obj-$(CONFIG_EFI) := efi-init.o arm-runtime.o |
| 40 | obj-$(CONFIG_ARM) += $(arm-obj-y) | 42 | obj-$(CONFIG_ARM) += $(arm-obj-y) |
| 41 | obj-$(CONFIG_ARM64) += $(arm-obj-y) | 43 | obj-$(CONFIG_ARM64) += $(arm-obj-y) |
| @@ -275,93 +275,3 @@ void __init efi_init(void) · 274 unmodified lines | |||
| 275 | } | 275 | } |
| 276 | #endif | 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 | // SPDX-License-Identifier: GPL-2.0-or-later | 1 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 2 | /* | 2 | /* |
| 3 | * Generic System Framebuffers on x86 | 3 | * Generic System Framebuffers |
| 4 | * Copyright (c) 2012-2013 David Herrmann <dh.herrmann@gmail.com> | 4 | * Copyright (c) 2012-2013 David Herrmann <dh.herrmann@gmail.com> |
| 5 | * | 5 | * |
| 6 | * EFI Quirks Copyright (c) 2006 Edgar Hucek <gimli@dark-green.com> | 6 | * EFI Quirks Copyright (c) 2006 Edgar Hucek <gimli@dark-green.com> |
| @@ -19,12 +19,14 @@ · 12 unmodified lines | |||
| 19 | #include <linux/init.h> | 19 | #include <linux/init.h> |
| 20 | #include <linux/kernel.h> | 20 | #include <linux/kernel.h> |
| 21 | #include <linux/mm.h> | 21 | #include <linux/mm.h> |
| 22 | #include <linux/of_address.h> | ||
| 22 | #include <linux/pci.h> | 23 | #include <linux/pci.h> |
| 24 | #include <linux/platform_device.h> | ||
| 23 | #include <linux/screen_info.h> | 25 | #include <linux/screen_info.h> |
| 26 | #include <linux/sysfb.h> | ||
| 24 | #include <video/vga.h> | 27 | #include <video/vga.h> |
| 25 | 28 | ||
| 26 | #include <asm/efi.h> | 29 | #include <asm/efi.h> |
| 27 | #include <asm/sysfb.h> | ||
| 28 | 30 | ||
| 29 | enum { | 31 | enum { |
| 30 | OVERRIDE_NONE = 0x0, | 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 | if (screen_info.orig_video_isVGA != VIDEO_TYPE_EFI || | 340 | if (screen_info.orig_video_isVGA != VIDEO_TYPE_EFI || |
| 273 | !(screen_info.capabilities & VIDEO_CAPABILITY_SKIP_QUIRKS)) | 341 | !(screen_info.capabilities & VIDEO_CAPABILITY_SKIP_QUIRKS)) |
| @@ -281,4 +349,10 @@ __init void sysfb_apply_efi_quirks(void) · 7 unmodified lines | |||
| 281 | screen_info.lfb_height = temp; | 349 | screen_info.lfb_height = temp; |
| 282 | screen_info.lfb_linelength = 4 * screen_info.lfb_width; | 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 | // SPDX-License-Identifier: GPL-2.0-or-later | 1 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 2 | /* | 2 | /* |
| 3 | * Generic System Framebuffers on x86 | 3 | * Generic System Framebuffers |
| 4 | * Copyright (c) 2012-2013 David Herrmann <dh.herrmann@gmail.com> | 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 | * Create a platform-device for any available boot framebuffer. The | 9 | * Create a platform-device for any available boot framebuffer. The |
| 10 | * simple-framebuffer platform device is already available on DT systems, so | 10 | * simple-framebuffer platform device is already available on DT systems, so |
| 11 | * this module parses the global "screen_info" object and creates a suitable | 11 | * this module parses the global "screen_info" object and creates a suitable |
| @@ -16,12 +16,12 @@ · 4 unmodified lines | |||
| 16 | * to pick these devices up without messing with simple-framebuffer drivers. | 16 | * to pick these devices up without messing with simple-framebuffer drivers. |
| 17 | * The global "screen_info" is still valid at all times. | 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 | * platform devices, but only use legacy framebuffer devices for | 20 | * platform devices, but only use legacy framebuffer devices for |
| 21 | * backwards compatibility. | 21 | * backwards compatibility. |
| 22 | * | 22 | * |
| 23 | * TODO: We set the dev_id field of all platform-devices to 0. This allows | 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 | * start at offset 1 for this to work. | 25 | * start at offset 1 for this to work. |
| 26 | */ | 26 | */ |
| 27 | 27 | ||
| @@ -32,7 +32,7 @@ · 4 unmodified lines | |||
| 32 | #include <linux/platform_data/simplefb.h> | 32 | #include <linux/platform_data/simplefb.h> |
| 33 | #include <linux/platform_device.h> | 33 | #include <linux/platform_device.h> |
| 34 | #include <linux/screen_info.h> | 34 | #include <linux/screen_info.h> |
| 35 | #include <asm/sysfb.h> | 35 | #include <linux/sysfb.h> |
| 36 | 36 | ||
| 37 | static __init int sysfb_init(void) | 37 | static __init int sysfb_init(void) |
| 38 | { | 38 | { |
| @@ -43,12 +43,10 @@ static __init int sysfb_init(void) · 4 unmodified lines | |||
| 43 | bool compatible; | 43 | bool compatible; |
| 44 | int ret; | 44 | int ret; |
| 45 | 45 | ||
| 46 | sysfb_apply_efi_quirks(); | ||
| 47 | |||
| 48 | /* try to create a simple-framebuffer device */ | 46 | /* try to create a simple-framebuffer device */ |
| 49 | compatible = parse_mode(si, &mode); | 47 | compatible = sysfb_parse_mode(si, &mode); |
| 50 | if (compatible) { | 48 | if (compatible) { |
| 51 | ret = create_simplefb(si, &mode); | 49 | ret = sysfb_create_simplefb(si, &mode); |
| 52 | if (!ret) | 50 | if (!ret) |
| 53 | return 0; | 51 | return 0; |
| 54 | } | 52 | } |
| @@ -61,9 +59,24 @@ static __init int sysfb_init(void) · 6 unmodified lines | |||
| 61 | else | 59 | else |
| 62 | name = "platform-framebuffer"; | 60 | name = "platform-framebuffer"; |
| 63 | 61 | ||
| 64 | pd = platform_device_register_resndata(NULL, name, 0, | 62 | pd = platform_device_alloc(name, 0); |
| 65 | NULL, 0, si, sizeof(*si)); | 63 | if (!pd) |
| 66 | return PTR_ERR_OR_ZERO(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 | /* must execute after PCI subsystem for EFI quirks */ | 82 | /* must execute after PCI subsystem for EFI quirks */ |
| @@ -1,6 +1,6 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0-or-later | 1 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 2 | /* | 2 | /* |
| 3 | * Generic System Framebuffers on x86 | 3 | * Generic System Framebuffers |
| 4 | * Copyright (c) 2012-2013 David Herrmann <dh.herrmann@gmail.com> | 4 | * Copyright (c) 2012-2013 David Herrmann <dh.herrmann@gmail.com> |
| 5 | */ | 5 | */ |
| 6 | 6 | ||
| @@ -18,14 +18,14 @@ · 11 unmodified lines | |||
| 18 | #include <linux/platform_data/simplefb.h> | 18 | #include <linux/platform_data/simplefb.h> |
| 19 | #include <linux/platform_device.h> | 19 | #include <linux/platform_device.h> |
| 20 | #include <linux/screen_info.h> | 20 | #include <linux/screen_info.h> |
| 21 | #include <asm/sysfb.h> | 21 | #include <linux/sysfb.h> |
| 22 | 22 | ||
| 23 | static const char simplefb_resname[] = "BOOTFB"; | 23 | static const char simplefb_resname[] = "BOOTFB"; |
| 24 | static const struct simplefb_format formats[] = SIMPLEFB_FORMATS; | 24 | static const struct simplefb_format formats[] = SIMPLEFB_FORMATS; |
| 25 | 25 | ||
| 26 | /* try parsing x86 screen_info into a simple-framebuffer mode struct */ | 26 | /* try parsing screen_info into a simple-framebuffer mode struct */ |
| 27 | __init bool parse_mode(const struct screen_info *si, | 27 | __init bool sysfb_parse_mode(const struct screen_info *si, |
| 28 | struct simplefb_platform_data *mode) | 28 | struct simplefb_platform_data *mode) |
| 29 | { | 29 | { |
| 30 | const struct simplefb_format *f; | 30 | const struct simplefb_format *f; |
| 31 | __u8 type; | 31 | __u8 type; |
| @@ -57,13 +57,14 @@ __init bool parse_mode(const struct screen_info *si, · 25 unmodified lines | |||
| 57 | return false; | 57 | return false; |
| 58 | } | 58 | } |
| 59 | 59 | ||
| 60 | __init int create_simplefb(const struct screen_info *si, | 60 | __init int sysfb_create_simplefb(const struct screen_info *si, |
| 61 | const struct simplefb_platform_data *mode) | 61 | const struct simplefb_platform_data *mode) |
| 62 | { | 62 | { |
| 63 | struct platform_device *pd; | 63 | struct platform_device *pd; |
| 64 | struct resource res; | 64 | struct resource res; |
| 65 | u64 base, size; | 65 | u64 base, size; |
| 66 | u32 length; | 66 | u32 length; |
| 67 | int ret; | ||
| 67 | 68 | ||
| 68 | /* | 69 | /* |
| 69 | * If the 64BIT_BASE capability is set, ext_lfb_base will contain the | 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 | if (res.end <= res.start) | 106 | if (res.end <= res.start) |
| 106 | return -EINVAL; | 107 | return -EINVAL; |
| 107 | 108 | ||
| 108 | pd = platform_device_register_resndata(NULL, "simple-framebuffer", 0, | 109 | pd = platform_device_alloc("simple-framebuffer", 0); |
| 109 | &res, 1, mode, sizeof(*mode)); | 110 | if (!pd) |
| 110 | return PTR_ERR_OR_ZERO(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 | bool | 35 | bool |
| 36 | depends on DRM | 36 | depends on DRM |
| 37 | 37 | ||
| 38 | config DRM_DP_AUX_BUS | ||
| 39 | tristate | ||
| 40 | depends on DRM | ||
| 41 | depends on OF | ||
| 42 | |||
| 38 | config DRM_DP_AUX_CHARDEV | 43 | config DRM_DP_AUX_CHARDEV |
| 39 | bool "DRM DP AUX Interface" | 44 | bool "DRM DP AUX Interface" |
| 40 | depends on DRM | 45 | depends on DRM |
| @@ -251,7 +256,6 @@ config DRM_AMDGPU · 210 unmodified lines | |||
| 251 | select HWMON | 256 | select HWMON |
| 252 | select BACKLIGHT_CLASS_DEVICE | 257 | select BACKLIGHT_CLASS_DEVICE |
| 253 | select INTERVAL_TREE | 258 | select INTERVAL_TREE |
| 254 | select CHASH | ||
| 255 | help | 259 | help |
| 256 | Choose this option if you have a recent AMD Radeon graphics card. | 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 | source "drivers/gpu/drm/qxl/Kconfig" | 322 | source "drivers/gpu/drm/qxl/Kconfig" |
| 319 | 323 | ||
| 320 | source "drivers/gpu/drm/bochs/Kconfig" | ||
| 321 | |||
| 322 | source "drivers/gpu/drm/virtio/Kconfig" | 324 | source "drivers/gpu/drm/virtio/Kconfig" |
| 323 | 325 | ||
| 324 | source "drivers/gpu/drm/msm/Kconfig" | 326 | source "drivers/gpu/drm/msm/Kconfig" |
| @@ -33,6 +33,8 @@ drm-$(CONFIG_PCI) += drm_pci.o · 32 unmodified lines | |||
| 33 | drm-$(CONFIG_DEBUG_FS) += drm_debugfs.o drm_debugfs_crc.o | 33 | drm-$(CONFIG_DEBUG_FS) += drm_debugfs.o drm_debugfs_crc.o |
| 34 | drm-$(CONFIG_DRM_LOAD_EDID_FIRMWARE) += drm_edid_load.o | 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 | drm_vram_helper-y := drm_gem_vram_helper.o | 38 | drm_vram_helper-y := drm_gem_vram_helper.o |
| 37 | obj-$(CONFIG_DRM_VRAM_HELPER) += drm_vram_helper.o | 39 | obj-$(CONFIG_DRM_VRAM_HELPER) += drm_vram_helper.o |
| 38 | 40 | ||
| @@ -96,7 +98,6 @@ obj-y += omapdrm/ · 57 unmodified lines | |||
| 96 | obj-$(CONFIG_DRM_SUN4I) += sun4i/ | 98 | obj-$(CONFIG_DRM_SUN4I) += sun4i/ |
| 97 | obj-y += tilcdc/ | 99 | obj-y += tilcdc/ |
| 98 | obj-$(CONFIG_DRM_QXL) += qxl/ | 100 | obj-$(CONFIG_DRM_QXL) += qxl/ |
| 99 | obj-$(CONFIG_DRM_BOCHS) += bochs/ | ||
| 100 | obj-$(CONFIG_DRM_VIRTIO_GPU) += virtio/ | 101 | obj-$(CONFIG_DRM_VIRTIO_GPU) += virtio/ |
| 101 | obj-$(CONFIG_DRM_MSM) += msm/ | 102 | obj-$(CONFIG_DRM_MSM) += msm/ |
| 102 | obj-$(CONFIG_DRM_TEGRA) += tegra/ | 103 | obj-$(CONFIG_DRM_TEGRA) += tegra/ |
| @@ -57,7 +57,8 @@ amdgpu-y += amdgpu_device.o amdgpu_kms.o \ · 56 unmodified lines | |||
| 57 | amdgpu_xgmi.o amdgpu_csa.o amdgpu_ras.o amdgpu_vm_cpu.o \ | 57 | amdgpu_xgmi.o amdgpu_csa.o amdgpu_ras.o amdgpu_vm_cpu.o \ |
| 58 | amdgpu_vm_sdma.o amdgpu_discovery.o amdgpu_ras_eeprom.o amdgpu_nbio.o \ | 58 | amdgpu_vm_sdma.o amdgpu_discovery.o amdgpu_ras_eeprom.o amdgpu_nbio.o \ |
| 59 | amdgpu_umc.o smu_v11_0_i2c.o amdgpu_fru_eeprom.o amdgpu_rap.o \ | 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 | amdgpu-$(CONFIG_PROC_FS) += amdgpu_fdinfo.o | 63 | amdgpu-$(CONFIG_PROC_FS) += amdgpu_fdinfo.o |
| 63 | 64 | ||
| @@ -75,7 +76,7 @@ amdgpu-y += \ · 11 unmodified lines | |||
| 75 | vega20_reg_init.o nbio_v7_4.o nbio_v2_3.o nv.o navi10_reg_init.o navi14_reg_init.o \ | 76 | vega20_reg_init.o nbio_v7_4.o nbio_v2_3.o nv.o navi10_reg_init.o navi14_reg_init.o \ |
| 76 | arct_reg_init.o navi12_reg_init.o mxgpu_nv.o sienna_cichlid_reg_init.o vangogh_reg_init.o \ | 77 | arct_reg_init.o navi12_reg_init.o mxgpu_nv.o sienna_cichlid_reg_init.o vangogh_reg_init.o \ |
| 77 | nbio_v7_2.o dimgrey_cavefish_reg_init.o hdp_v4_0.o hdp_v5_0.o aldebaran_reg_init.o aldebaran.o \ | 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 | # add DF block | 81 | # add DF block |
| 81 | amdgpu-y += \ | 82 | amdgpu-y += \ |
| @@ -111,6 +112,7 @@ amdgpu-y += \ · 29 unmodified lines | |||
| 111 | psp_v3_1.o \ | 112 | psp_v3_1.o \ |
| 112 | psp_v10_0.o \ | 113 | psp_v10_0.o \ |
| 113 | psp_v11_0.o \ | 114 | psp_v11_0.o \ |
| 115 | psp_v11_0_8.o \ | ||
| 114 | psp_v12_0.o \ | 116 | psp_v12_0.o \ |
| 115 | psp_v13_0.o | 117 | psp_v13_0.o |
| 116 | 118 | ||
| @@ -118,7 +120,7 @@ amdgpu-y += \ · 1 unmodified line | |||
| 118 | amdgpu-y += \ | 120 | amdgpu-y += \ |
| 119 | dce_v10_0.o \ | 121 | dce_v10_0.o \ |
| 120 | dce_v11_0.o \ | 122 | dce_v11_0.o \ |
| 121 | dce_virtual.o | 123 | amdgpu_vkms.o |
| 122 | 124 | ||
| 123 | # add GFX block | 125 | # add GFX block |
| 124 | amdgpu-y += \ | 126 | amdgpu-y += \ |
| @@ -187,6 +189,10 @@ amdgpu-y += \ · 62 unmodified lines | |||
| 187 | amdgpu-y += \ | 189 | amdgpu-y += \ |
| 188 | amdgpu_reset.o | 190 | amdgpu_reset.o |
| 189 | 191 | ||
| 192 | # add MCA block | ||
| 193 | amdgpu-y += \ | ||
| 194 | mca_v3_0.o | ||
| 195 | |||
| 190 | # add amdkfd interfaces | 196 | # add amdkfd interfaces |
| 191 | amdgpu-y += amdgpu_amdkfd.o | 197 | amdgpu-y += amdgpu_amdkfd.o |
| 192 | 198 | ||
| @@ -108,6 +108,7 @@ · 107 unmodified lines | |||
| 108 | #include "amdgpu_df.h" | 108 | #include "amdgpu_df.h" |
| 109 | #include "amdgpu_smuio.h" | 109 | #include "amdgpu_smuio.h" |
| 110 | #include "amdgpu_fdinfo.h" | 110 | #include "amdgpu_fdinfo.h" |
| 111 | #include "amdgpu_mca.h" | ||
| 111 | 112 | ||
| 112 | #define MAX_GPU_INSTANCE 16 | 113 | #define MAX_GPU_INSTANCE 16 |
| 113 | 114 | ||
| @@ -916,6 +917,7 @@ struct amdgpu_device { · 802 unmodified lines | |||
| 916 | 917 | ||
| 917 | /* display */ | 918 | /* display */ |
| 918 | bool enable_virtual_display; | 919 | bool enable_virtual_display; |
| 920 | struct amdgpu_vkms_output *amdgpu_vkms_output; | ||
| 919 | struct amdgpu_mode_info mode_info; | 921 | struct amdgpu_mode_info mode_info; |
| 920 | /* For pre-DCE11. DCE11 and later are in "struct amdgpu_device->dm" */ | 922 | /* For pre-DCE11. DCE11 and later are in "struct amdgpu_device->dm" */ |
| 921 | struct work_struct hotplug_work; | 923 | struct work_struct hotplug_work; |
| @@ -1008,6 +1010,9 @@ struct amdgpu_device { · 86 unmodified lines | |||
| 1008 | /* df */ | 1010 | /* df */ |
| 1009 | struct amdgpu_df df; | 1011 | struct amdgpu_df df; |
| 1010 | 1012 | ||
| 1013 | /* MCA */ | ||
| 1014 | struct amdgpu_mca mca; | ||
| 1015 | |||
| 1011 | struct amdgpu_ip_block ip_blocks[AMDGPU_MAX_IP_NUM]; | 1016 | struct amdgpu_ip_block ip_blocks[AMDGPU_MAX_IP_NUM]; |
| 1012 | uint32_t harvest_ip_mask; | 1017 | uint32_t harvest_ip_mask; |
| 1013 | int num_ip_blocks; | 1018 | int num_ip_blocks; |
| @@ -1108,8 +1113,13 @@ void amdgpu_device_fini_sw(struct amdgpu_device *adev); · 94 unmodified lines | |||
| 1108 | 1113 | ||
| 1109 | int amdgpu_gpu_wait_for_idle(struct amdgpu_device *adev); | 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 | void amdgpu_device_vram_access(struct amdgpu_device *adev, loff_t pos, | 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 | uint32_t amdgpu_device_rreg(struct amdgpu_device *adev, | 1123 | uint32_t amdgpu_device_rreg(struct amdgpu_device *adev, |
| 1114 | uint32_t reg, uint32_t acc_flags); | 1124 | uint32_t reg, uint32_t acc_flags); |
| 1115 | void amdgpu_device_wreg(struct amdgpu_device *adev, | 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 | #define amdgpu_inc_vram_lost(adev) atomic_inc(&((adev)->vram_lost_counter)); | 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 | /* Common functions */ | 1280 | /* Common functions */ |
| 1269 | bool amdgpu_device_has_job_running(struct amdgpu_device *adev); | 1281 | bool amdgpu_device_has_job_running(struct amdgpu_device *adev); |
| 1270 | bool amdgpu_device_should_recover_gpu(struct amdgpu_device *adev); | 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 | int amdgpu_acpi_pcie_notify_device_ready(struct amdgpu_device *adev); | 1397 | int amdgpu_acpi_pcie_notify_device_ready(struct amdgpu_device *adev); |
| 1386 | 1398 | ||
| 1387 | void amdgpu_acpi_get_backlight_caps(struct amdgpu_dm_backlight_caps *caps); | 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 | void amdgpu_acpi_detect(void); | 1401 | void amdgpu_acpi_detect(void); |
| 1390 | #else | 1402 | #else |
| 1391 | static inline int amdgpu_acpi_init(struct amdgpu_device *adev) { return 0; } | 1403 | static inline int amdgpu_acpi_init(struct amdgpu_device *adev) { return 0; } |
| 1392 | static inline void amdgpu_acpi_fini(struct amdgpu_device *adev) { } | 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 | static inline void amdgpu_acpi_detect(void) { } | 1406 | static inline void amdgpu_acpi_detect(void) { } |
| 1395 | static inline bool amdgpu_acpi_is_power_shift_control_supported(void) { return false; } | 1407 | static inline bool amdgpu_acpi_is_power_shift_control_supported(void) { return false; } |
| 1396 | static inline int amdgpu_acpi_power_shift_control(struct amdgpu_device *adev, | 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 | return 0; | 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]; | 165 | struct generic_pm_domain *gpd = data; |
| 166 | struct device *dev; | 166 | int ret; |
| 167 | 167 | ||
| 168 | snprintf(auto_dev_name, sizeof(auto_dev_name), | 168 | ret = pm_genpd_add_device(gpd, dev); |
| 169 | "%s.%d.auto", device_name, r); | 169 | if (ret) |
| 170 | dev = bus_find_device_by_name(&platform_bus_type, NULL, auto_dev_name); | 170 | dev_err(dev, "Failed to add dev to genpd %d\n", ret); |
| 171 | dev_info(dev, "device %s added to pm domain\n", auto_dev_name); | ||
| 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 | static int acp_hw_init(void *handle) | 193 | static int acp_hw_init(void *handle) |
| 183 | { | 194 | { |
| 184 | int r, i; | 195 | int r; |
| 185 | uint64_t acp_base; | 196 | uint64_t acp_base; |
| 186 | u32 val = 0; | 197 | u32 val = 0; |
| 187 | u32 count = 0; | 198 | u32 count = 0; |
| 188 | struct device *dev; | ||
| 189 | struct i2s_platform_data *i2s_pdata = NULL; | 199 | struct i2s_platform_data *i2s_pdata = NULL; |
| 190 | 200 | ||
| 191 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; | 201 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; |
| @@ -341,15 +351,10 @@ static int acp_hw_init(void *handle) · 149 unmodified lines | |||
| 341 | if (r) | 351 | if (r) |
| 342 | goto failure; | 352 | goto failure; |
| 343 | 353 | ||
| 344 | for (i = 0; i < ACP_DEVS ; i++) { | 354 | r = device_for_each_child(adev->acp.parent, &adev->acp.acp_genpd->gpd, |
| 345 | dev = get_mfd_cell_dev(adev->acp.acp_cell[i].name, i); | 355 | acp_genpd_add_device); |
| 346 | r = pm_genpd_add_device(&adev->acp.acp_genpd->gpd, dev); | 356 | if (r) |
| 347 | if (r) { | 357 | goto failure; |
| 348 | dev_err(dev, "Failed to add dev to genpd\n"); | ||
| 349 | goto failure; | ||
| 350 | } | ||
| 351 | } | ||
| 352 | |||
| 353 | 358 | ||
| 354 | /* Assert Soft reset of ACP */ | 359 | /* Assert Soft reset of ACP */ |
| 355 | val = cgs_read_register(adev->acp.cgs_device, mmACP_SOFT_RESET); | 360 | val = cgs_read_register(adev->acp.cgs_device, mmACP_SOFT_RESET); |
| @@ -410,10 +415,8 @@ failure: · 54 unmodified lines | |||
| 410 | */ | 415 | */ |
| 411 | static int acp_hw_fini(void *handle) | 416 | static int acp_hw_fini(void *handle) |
| 412 | { | 417 | { |
| 413 | int i, ret; | ||
| 414 | u32 val = 0; | 418 | u32 val = 0; |
| 415 | u32 count = 0; | 419 | u32 count = 0; |
| 416 | struct device *dev; | ||
| 417 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; | 420 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; |
| 418 | 421 | ||
| 419 | /* return early if no ACP */ | 422 | /* return early if no ACP */ |
| @@ -458,13 +461,8 @@ static int acp_hw_fini(void *handle) · 38 unmodified lines | |||
| 458 | udelay(100); | 461 | udelay(100); |
| 459 | } | 462 | } |
| 460 | 463 | ||
| 461 | for (i = 0; i < ACP_DEVS ; i++) { | 464 | device_for_each_child(adev->acp.parent, NULL, |
| 462 | dev = get_mfd_cell_dev(adev->acp.acp_cell[i].name, i); | 465 | acp_genpd_remove_device); |
| 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 | } | ||
| 468 | 466 | ||
| 469 | mfd_remove_devices(adev->acp.parent); | 467 | mfd_remove_devices(adev->acp.parent); |
| 470 | kfree(adev->acp.acp_res); | 468 | kfree(adev->acp.acp_res); |
| @@ -854,8 +854,8 @@ int amdgpu_acpi_init(struct amdgpu_device *adev) · 853 unmodified lines | |||
| 854 | if (amdgpu_device_has_dc_support(adev)) { | 854 | if (amdgpu_device_has_dc_support(adev)) { |
| 855 | #if defined(CONFIG_DRM_AMD_DC) | 855 | #if defined(CONFIG_DRM_AMD_DC) |
| 856 | struct amdgpu_display_manager *dm = &adev->dm; | 856 | struct amdgpu_display_manager *dm = &adev->dm; |
| 857 | if (dm->backlight_dev) | 857 | if (dm->backlight_dev[0]) |
| 858 | atif->bd = dm->backlight_dev; | 858 | atif->bd = dm->backlight_dev[0]; |
| 859 | #endif | 859 | #endif |
| 860 | } else { | 860 | } else { |
| 861 | struct drm_encoder *tmp; | 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 | * @adev: amdgpu_device_pointer | 1037 | * @adev: amdgpu_device_pointer |
| 1038 | * | 1038 | * |
| 1039 | * returns true if supported, false if not. | 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 | #if IS_ENABLED(CONFIG_AMD_PMC) && IS_ENABLED(CONFIG_SUSPEND) | 1043 | #if IS_ENABLED(CONFIG_AMD_PMC) && IS_ENABLED(CONFIG_SUSPEND) |
| 1044 | if (acpi_gbl_FADT.flags & ACPI_FADT_LOW_POWER_S0) { | 1044 | if (acpi_gbl_FADT.flags & ACPI_FADT_LOW_POWER_S0) { |
| @@ -21,6 +21,7 @@ · 20 unmodified lines | |||
| 21 | */ | 21 | */ |
| 22 | 22 | ||
| 23 | #include "amdgpu_amdkfd.h" | 23 | #include "amdgpu_amdkfd.h" |
| 24 | #include "amd_pcie.h" | ||
| 24 | #include "amd_shared.h" | 25 | #include "amd_shared.h" |
| 25 | 26 | ||
| 26 | #include "amdgpu.h" | 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 | return (uint8_t)ret; | 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 | uint64_t amdgpu_amdkfd_get_mmio_remap_phys_addr(struct kgd_dev *kgd) | 639 | uint64_t amdgpu_amdkfd_get_mmio_remap_phys_addr(struct kgd_dev *kgd) |
| 557 | { | 640 | { |
| 558 | struct amdgpu_device *adev = (struct amdgpu_device *)kgd; | 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 | ret = dma_fence_wait(f, false); | 714 | ret = dma_fence_wait(f, false); |
| 632 | 715 | ||
| 633 | err_ib_sched: | 716 | err_ib_sched: |
| 634 | dma_fence_put(f); | ||
| 635 | amdgpu_job_free(job); | 717 | amdgpu_job_free(job); |
| 636 | err: | 718 | err: |
| 637 | return ret; | 719 | return ret; |
| @@ -226,6 +226,8 @@ uint32_t amdgpu_amdkfd_get_num_gws(struct kgd_dev *kgd); · 225 unmodified lines | |||
| 226 | uint32_t amdgpu_amdkfd_get_asic_rev_id(struct kgd_dev *kgd); | 226 | uint32_t amdgpu_amdkfd_get_asic_rev_id(struct kgd_dev *kgd); |
| 227 | int amdgpu_amdkfd_get_noretry(struct kgd_dev *kgd); | 227 | int amdgpu_amdkfd_get_noretry(struct kgd_dev *kgd); |
| 228 | uint8_t amdgpu_amdkfd_get_xgmi_hops_count(struct kgd_dev *dst, struct kgd_dev *src); | 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 | /* Read user wptr from a specified user address space with page fault | 232 | /* Read user wptr from a specified user address space with page fault |
| 231 | * disabled. The memory must be pinned and mapped to the hardware when | 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 | struct kgd_dev *kgd, struct kgd_mem *mem, void *drm_priv, | 271 | struct kgd_dev *kgd, struct kgd_mem *mem, void *drm_priv, |
| 270 | uint64_t *size); | 272 | uint64_t *size); |
| 271 | int amdgpu_amdkfd_gpuvm_map_memory_to_gpu( | 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 | int amdgpu_amdkfd_gpuvm_unmap_memory_from_gpu( | 275 | int amdgpu_amdkfd_gpuvm_unmap_memory_from_gpu( |
| 274 | struct kgd_dev *kgd, struct kgd_mem *mem, void *drm_priv); | 276 | struct kgd_dev *kgd, struct kgd_mem *mem, void *drm_priv); |
| 275 | int amdgpu_amdkfd_gpuvm_sync_memory( | 277 | int amdgpu_amdkfd_gpuvm_sync_memory( |
| @@ -330,7 +332,7 @@ int kgd2kfd_pre_reset(struct kfd_dev *kfd); · 54 unmodified lines | |||
| 330 | int kgd2kfd_post_reset(struct kfd_dev *kfd); | 332 | int kgd2kfd_post_reset(struct kfd_dev *kfd); |
| 331 | void kgd2kfd_interrupt(struct kfd_dev *kfd, const void *ih_ring_entry); | 333 | void kgd2kfd_interrupt(struct kfd_dev *kfd, const void *ih_ring_entry); |
| 332 | void kgd2kfd_set_sram_ecc_flag(struct kfd_dev *kfd); | 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 | #else | 336 | #else |
| 335 | static inline int kgd2kfd_init(void) | 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 | static inline | 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 | #endif | 397 | #endif |
| @@ -44,4 +44,5 @@ const struct kfd2kgd_calls aldebaran_kfd2kgd = { · 43 unmodified lines | |||
| 44 | .get_atc_vmid_pasid_mapping_info = | 44 | .get_atc_vmid_pasid_mapping_info = |
| 45 | kgd_gfx_v9_get_atc_vmid_pasid_mapping_info, | 45 | kgd_gfx_v9_get_atc_vmid_pasid_mapping_info, |
| 46 | .set_vm_context_page_table_base = kgd_gfx_v9_set_vm_context_page_table_base, | 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 | kgd_gfx_v9_get_atc_vmid_pasid_mapping_info, | 305 | kgd_gfx_v9_get_atc_vmid_pasid_mapping_info, |
| 306 | .set_vm_context_page_table_base = | 306 | .set_vm_context_page_table_base = |
| 307 | kgd_gfx_v9_set_vm_context_page_table_base, | 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 | case KFD_PREEMPT_TYPE_WAVEFRONT_RESET: | 560 | case KFD_PREEMPT_TYPE_WAVEFRONT_RESET: |
| 561 | type = RESET_WAVES; | 561 | type = RESET_WAVES; |
| 562 | break; | 562 | break; |
| 563 | case KFD_PREEMPT_TYPE_WAVEFRONT_SAVE: | ||
| 564 | type = SAVE_WAVES; | ||
| 565 | break; | ||
| 563 | default: | 566 | default: |
| 564 | type = DRAIN_PIPE; | 567 | type = DRAIN_PIPE; |
| 565 | break; | 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 | adev->gfxhub.funcs->setup_vm_pt_regs(adev, vmid, page_table_base); | 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 | const struct kfd2kgd_calls gfx_v10_kfd2kgd = { | 787 | const struct kfd2kgd_calls gfx_v10_kfd2kgd = { |
| 758 | .program_sh_mem_settings = kgd_program_sh_mem_settings, | 788 | .program_sh_mem_settings = kgd_program_sh_mem_settings, |
| 759 | .set_pasid_vmid_mapping = kgd_set_pasid_vmid_mapping, | 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 | .get_atc_vmid_pasid_mapping_info = | 804 | .get_atc_vmid_pasid_mapping_info = |
| 775 | get_atc_vmid_pasid_mapping_info, | 805 | get_atc_vmid_pasid_mapping_info, |
| 776 | .set_vm_context_page_table_base = set_vm_context_page_table_base, | 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 | case KFD_PREEMPT_TYPE_WAVEFRONT_RESET: | 537 | case KFD_PREEMPT_TYPE_WAVEFRONT_RESET: |
| 538 | type = RESET_WAVES; | 538 | type = RESET_WAVES; |
| 539 | break; | 539 | break; |
| 540 | case KFD_PREEMPT_TYPE_WAVEFRONT_SAVE: | ||
| 541 | type = SAVE_WAVES; | ||
| 542 | break; | ||
| 540 | default: | 543 | default: |
| 541 | type = DRAIN_PIPE; | 544 | type = DRAIN_PIPE; |
| 542 | break; | 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 | adev->gfxhub.funcs->setup_vm_pt_regs(adev, vmid, page_table_base); | 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 | #if 0 | 691 | #if 0 |
| 662 | uint32_t enable_debug_trap_v10_3(struct kgd_dev *kgd, | 692 | uint32_t enable_debug_trap_v10_3(struct kgd_dev *kgd, |
| 663 | uint32_t trap_debug_wave_launch_mode, | 693 | uint32_t trap_debug_wave_launch_mode, |
| @@ -820,6 +850,7 @@ const struct kfd2kgd_calls gfx_v10_3_kfd2kgd = { · 156 unmodified lines | |||
| 820 | .address_watch_get_offset = address_watch_get_offset_v10_3, | 850 | .address_watch_get_offset = address_watch_get_offset_v10_3, |
| 821 | .get_atc_vmid_pasid_mapping_info = NULL, | 851 | .get_atc_vmid_pasid_mapping_info = NULL, |
| 822 | .set_vm_context_page_table_base = set_vm_context_page_table_base_v10_3, | 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 | #if 0 | 854 | #if 0 |
| 824 | .enable_debug_trap = enable_debug_trap_v10_3, | 855 | .enable_debug_trap = enable_debug_trap_v10_3, |
| 825 | .disable_debug_trap = disable_debug_trap_v10_3, | 856 | .disable_debug_trap = disable_debug_trap_v10_3, |
| @@ -42,7 +42,8 @@ · 41 unmodified lines | |||
| 42 | enum hqd_dequeue_request_type { | 42 | enum hqd_dequeue_request_type { |
| 43 | NO_ACTION = 0, | 43 | NO_ACTION = 0, |
| 44 | DRAIN_PIPE, | 44 | DRAIN_PIPE, |
| 45 | RESET_WAVES | 45 | RESET_WAVES, |
| 46 | SAVE_WAVES | ||
| 46 | }; | 47 | }; |
| 47 | 48 | ||
| 48 | static inline struct amdgpu_device *get_amdgpu_device(struct kgd_dev *kgd) | 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 | case KFD_PREEMPT_TYPE_WAVEFRONT_RESET: | 567 | case KFD_PREEMPT_TYPE_WAVEFRONT_RESET: |
| 567 | type = RESET_WAVES; | 568 | type = RESET_WAVES; |
| 568 | break; | 569 | break; |
| 570 | case KFD_PREEMPT_TYPE_WAVEFRONT_SAVE: | ||
| 571 | type = SAVE_WAVES; | ||
| 572 | break; | ||
| 569 | default: | 573 | default: |
| 570 | type = DRAIN_PIPE; | 574 | type = DRAIN_PIPE; |
| 571 | break; | 575 | break; |
| @@ -878,6 +882,32 @@ void kgd_gfx_v9_get_cu_occupancy(struct kgd_dev *kgd, int pasid, · 306 unmodified lines | |||
| 878 | adev->gfx.cu_info.max_waves_per_simd; | 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 | const struct kfd2kgd_calls gfx_v9_kfd2kgd = { | 911 | const struct kfd2kgd_calls gfx_v9_kfd2kgd = { |
| 882 | .program_sh_mem_settings = kgd_gfx_v9_program_sh_mem_settings, | 912 | .program_sh_mem_settings = kgd_gfx_v9_program_sh_mem_settings, |
| 883 | .set_pasid_vmid_mapping = kgd_gfx_v9_set_pasid_vmid_mapping, | 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 | kgd_gfx_v9_get_atc_vmid_pasid_mapping_info, | 929 | kgd_gfx_v9_get_atc_vmid_pasid_mapping_info, |
| 900 | .set_vm_context_page_table_base = kgd_gfx_v9_set_vm_context_page_table_base, | 930 | .set_vm_context_page_table_base = kgd_gfx_v9_set_vm_context_page_table_base, |
| 901 | .get_cu_occupancy = kgd_gfx_v9_get_cu_occupancy, | 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 | uint32_t vmid, uint64_t page_table_base); | 65 | uint32_t vmid, uint64_t page_table_base); |
| 66 | void kgd_gfx_v9_get_cu_occupancy(struct kgd_dev *kgd, int pasid, | 66 | void kgd_gfx_v9_get_cu_occupancy(struct kgd_dev *kgd, int pasid, |
| 67 | int *pasid_wave_cnt, int *max_waves_per_cu); | 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 | static int update_gpuvm_pte(struct kgd_mem *mem, | 1058 | static int update_gpuvm_pte(struct kgd_mem *mem, |
| 1059 | struct kfd_mem_attachment *entry, | 1059 | struct kfd_mem_attachment *entry, |
| 1060 | struct amdgpu_sync *sync) | 1060 | struct amdgpu_sync *sync, |
| 1061 | bool *table_freed) | ||
| 1061 | { | 1062 | { |
| 1062 | struct amdgpu_bo_va *bo_va = entry->bo_va; | 1063 | struct amdgpu_bo_va *bo_va = entry->bo_va; |
| 1063 | struct amdgpu_device *adev = entry->adev; | 1064 | struct amdgpu_device *adev = entry->adev; |
| @@ -1068,7 +1069,7 @@ static int update_gpuvm_pte(struct kgd_mem *mem, · 4 unmodified lines | |||
| 1068 | return ret; | 1069 | return ret; |
| 1069 | 1070 | ||
| 1070 | /* Update the page tables */ | 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 | if (ret) { | 1073 | if (ret) { |
| 1073 | pr_err("amdgpu_vm_bo_update failed\n"); | 1074 | pr_err("amdgpu_vm_bo_update failed\n"); |
| 1074 | return ret; | 1075 | return ret; |
| @@ -1080,7 +1081,8 @@ static int update_gpuvm_pte(struct kgd_mem *mem, · 5 unmodified lines | |||
| 1080 | static int map_bo_to_gpuvm(struct kgd_mem *mem, | 1081 | static int map_bo_to_gpuvm(struct kgd_mem *mem, |
| 1081 | struct kfd_mem_attachment *entry, | 1082 | struct kfd_mem_attachment *entry, |
| 1082 | struct amdgpu_sync *sync, | 1083 | struct amdgpu_sync *sync, |
| 1083 | bool no_update_pte) | 1084 | bool no_update_pte, |
| 1085 | bool *table_freed) | ||
| 1084 | { | 1086 | { |
| 1085 | int ret; | 1087 | int ret; |
| 1086 | 1088 | ||
| @@ -1097,7 +1099,7 @@ static int map_bo_to_gpuvm(struct kgd_mem *mem, · 10 unmodified lines | |||
| 1097 | if (no_update_pte) | 1099 | if (no_update_pte) |
| 1098 | return 0; | 1100 | return 0; |
| 1099 | 1101 | ||
| 1100 | ret = update_gpuvm_pte(mem, entry, sync); | 1102 | ret = update_gpuvm_pte(mem, entry, sync, table_freed); |
| 1101 | if (ret) { | 1103 | if (ret) { |
| 1102 | pr_err("update_gpuvm_pte() failed\n"); | 1104 | pr_err("update_gpuvm_pte() failed\n"); |
| 1103 | goto update_gpuvm_pte_failed; | 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 | if (avm->process_info) | 1287 | if (avm->process_info) |
| 1286 | return -EINVAL; | 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 | /* Convert VM into a compute VM */ | 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 | if (ret) | 1300 | if (ret) |
| 1291 | return ret; | 1301 | return ret; |
| 1292 | 1302 | ||
| 1303 | ret = amdgpu_vm_set_pasid(adev, avm, pasid); | ||
| 1304 | if (ret) | ||
| 1305 | return ret; | ||
| 1293 | /* Initialize KFD part of the VM and process info */ | 1306 | /* Initialize KFD part of the VM and process info */ |
| 1294 | ret = init_kfd_vm(avm, process_info, ef); | 1307 | ret = init_kfd_vm(avm, process_info, ef); |
| 1295 | if (ret) | 1308 | if (ret) |
| @@ -1594,7 +1607,8 @@ int amdgpu_amdkfd_gpuvm_free_memory_of_gpu( · 298 unmodified lines | |||
| 1594 | } | 1607 | } |
| 1595 | 1608 | ||
| 1596 | int amdgpu_amdkfd_gpuvm_map_memory_to_gpu( | 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 | struct amdgpu_device *adev = get_amdgpu_device(kgd); | 1613 | struct amdgpu_device *adev = get_amdgpu_device(kgd); |
| 1600 | struct amdgpu_vm *avm = drm_priv_to_vm(drm_priv); | 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 | entry->va, entry->va + bo_size, entry); | 1696 | entry->va, entry->va + bo_size, entry); |
| 1683 | 1697 | ||
| 1684 | ret = map_bo_to_gpuvm(mem, entry, ctx.sync, | 1698 | ret = map_bo_to_gpuvm(mem, entry, ctx.sync, |
| 1685 | is_invalid_userptr); | 1699 | is_invalid_userptr, table_freed); |
| 1686 | if (ret) { | 1700 | if (ret) { |
| 1687 | pr_err("Failed to map bo to gpuvm\n"); | 1701 | pr_err("Failed to map bo to gpuvm\n"); |
| 1688 | goto out_unreserve; | 1702 | goto out_unreserve; |
| @@ -1706,6 +1720,12 @@ int amdgpu_amdkfd_gpuvm_map_memory_to_gpu( · 17 unmodified lines | |||
| 1706 | true); | 1720 | true); |
| 1707 | ret = unreserve_bo_and_vms(&ctx, false, false); | 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 | goto out; | 1729 | goto out; |
| 1710 | 1730 | ||
| 1711 | out_unreserve: | 1731 | out_unreserve: |
| @@ -2132,7 +2152,7 @@ static int validate_invalid_user_pages(struct amdkfd_process_info *process_info) · 420 unmodified lines | |||
| 2132 | continue; | 2152 | continue; |
| 2133 | 2153 | ||
| 2134 | kfd_mem_dmaunmap_attachment(mem, attachment); | 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 | if (ret) { | 2156 | if (ret) { |
| 2137 | pr_err("%s: update PTE failed\n", __func__); | 2157 | pr_err("%s: update PTE failed\n", __func__); |
| 2138 | /* make sure this gets validated again */ | 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 | continue; | 2358 | continue; |
| 2339 | 2359 | ||
| 2340 | kfd_mem_dmaunmap_attachment(mem, attachment); | 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 | if (ret) { | 2362 | if (ret) { |
| 2343 | pr_debug("Memory eviction: update PTE failed. Try again\n"); | 2363 | pr_debug("Memory eviction: update PTE failed. Try again\n"); |
| 2344 | goto validate_map_fail; | 2364 | goto validate_map_fail; |
| @@ -34,6 +34,7 @@ struct amdgpu_fpriv; · 33 unmodified lines | |||
| 34 | struct amdgpu_bo_list_entry { | 34 | struct amdgpu_bo_list_entry { |
| 35 | struct ttm_validate_buffer tv; | 35 | struct ttm_validate_buffer tv; |
| 36 | struct amdgpu_bo_va *bo_va; | 36 | struct amdgpu_bo_va *bo_va; |
| 37 | struct dma_fence_chain *chain; | ||
| 37 | uint32_t priority; | 38 | uint32_t priority; |
| 38 | struct page **user_pages; | 39 | struct page **user_pages; |
| 39 | bool user_invalidated; | 40 | bool user_invalidated; |
| @@ -572,6 +572,20 @@ static int amdgpu_cs_parser_bos(struct amdgpu_cs_parser *p, · 571 unmodified lines | |||
| 572 | goto out; | 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 | amdgpu_cs_get_threshold_for_moves(p->adev, &p->bytes_moved_threshold, | 589 | amdgpu_cs_get_threshold_for_moves(p->adev, &p->bytes_moved_threshold, |
| 576 | &p->bytes_moved_vis_threshold); | 590 | &p->bytes_moved_vis_threshold); |
| 577 | p->bytes_moved = 0; | 591 | p->bytes_moved = 0; |
| @@ -599,15 +613,6 @@ static int amdgpu_cs_parser_bos(struct amdgpu_cs_parser *p, · 21 unmodified lines | |||
| 599 | gws = p->bo_list->gws_obj; | 613 | gws = p->bo_list->gws_obj; |
| 600 | oa = p->bo_list->oa_obj; | 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 | if (gds) { | 616 | if (gds) { |
| 612 | p->job->gds_base = amdgpu_bo_gpu_offset(gds) >> PAGE_SHIFT; | 617 | p->job->gds_base = amdgpu_bo_gpu_offset(gds) >> PAGE_SHIFT; |
| 613 | p->job->gds_size = amdgpu_bo_size(gds) >> PAGE_SHIFT; | 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 | error_validate: | 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 | ttm_eu_backoff_reservation(&p->ticket, &p->validated); | 642 | ttm_eu_backoff_reservation(&p->ticket, &p->validated); |
| 643 | } | ||
| 634 | out: | 644 | out: |
| 635 | return r; | 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 | unsigned i; | 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 | ttm_eu_backoff_reservation(&parser->ticket, | 691 | ttm_eu_backoff_reservation(&parser->ticket, |
| 675 | &parser->validated); | 692 | &parser->validated); |
| 693 | } | ||
| 676 | 694 | ||
| 677 | for (i = 0; i < parser->num_post_deps; i++) { | 695 | for (i = 0; i < parser->num_post_deps; i++) { |
| 678 | drm_syncobj_put(parser->post_deps[i].syncobj); | 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 | if (r) | 799 | if (r) |
| 782 | return r; | 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 | if (r) | 803 | if (r) |
| 786 | return r; | 804 | return r; |
| 787 | 805 | ||
| @@ -792,7 +810,7 @@ static int amdgpu_cs_vm_handling(struct amdgpu_cs_parser *p) · 4 unmodified lines | |||
| 792 | if (amdgpu_mcbp || amdgpu_sriov_vf(adev)) { | 810 | if (amdgpu_mcbp || amdgpu_sriov_vf(adev)) { |
| 793 | bo_va = fpriv->csa_va; | 811 | bo_va = fpriv->csa_va; |
| 794 | BUG_ON(!bo_va); | 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 | if (r) | 814 | if (r) |
| 797 | return r; | 815 | return r; |
| 798 | 816 | ||
| @@ -811,7 +829,7 @@ static int amdgpu_cs_vm_handling(struct amdgpu_cs_parser *p) · 12 unmodified lines | |||
| 811 | if (bo_va == NULL) | 829 | if (bo_va == NULL) |
| 812 | continue; | 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 | if (r) | 833 | if (r) |
| 816 | return r; | 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 | dep->chain = NULL; | 1128 | dep->chain = NULL; |
| 1111 | if (syncobj_deps[i].point) { | 1129 | if (syncobj_deps[i].point) { |
| 1112 | dep->chain = kmalloc(sizeof(*dep->chain), GFP_KERNEL); | 1130 | dep->chain = dma_fence_chain_alloc(); |
| 1113 | if (!dep->chain) | 1131 | if (!dep->chain) |
| 1114 | return -ENOMEM; | 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 | dep->syncobj = drm_syncobj_find(p->filp, | 1135 | dep->syncobj = drm_syncobj_find(p->filp, |
| 1118 | syncobj_deps[i].handle); | 1136 | syncobj_deps[i].handle); |
| 1119 | if (!dep->syncobj) { | 1137 | if (!dep->syncobj) { |
| 1120 | kfree(dep->chain); | 1138 | dma_fence_chain_free(dep->chain); |
| 1121 | return -EINVAL; | 1139 | return -EINVAL; |
| 1122 | } | 1140 | } |
| 1123 | dep->point = syncobj_deps[i].point; | 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 | amdgpu_vm_move_to_lru_tail(p->adev, &fpriv->vm); | 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 | ttm_eu_fence_buffer_objects(&p->ticket, &p->validated, p->fence); | 1288 | ttm_eu_fence_buffer_objects(&p->ticket, &p->validated, p->fence); |
| 1249 | mutex_unlock(&p->adev->notifier_lock); | 1289 | mutex_unlock(&p->adev->notifier_lock); |
| 1250 | 1290 | ||
| @@ -1414,7 +1414,7 @@ no_preempt: · 1413 unmodified lines | |||
| 1414 | continue; | 1414 | continue; |
| 1415 | } | 1415 | } |
| 1416 | job = to_amdgpu_job(s_job); | 1416 | job = to_amdgpu_job(s_job); |
| 1417 | if (preempted && job->fence == fence) | 1417 | if (preempted && (&job->hw_fence) == fence) |
| 1418 | /* mark the job as preempted */ | 1418 | /* mark the job as preempted */ |
| 1419 | job->preemption_status |= AMDGPU_IB_PREEMPTED; | 1419 | job->preemption_status |= AMDGPU_IB_PREEMPTED; |
| 1420 | } | 1420 | } |
| @@ -116,6 +116,7 @@ const char *amdgpu_asic_name[] = { · 115 unmodified lines | |||
| 116 | "RENOIR", | 116 | "RENOIR", |
| 117 | "ALDEBARAN", | 117 | "ALDEBARAN", |
| 118 | "NAVI10", | 118 | "NAVI10", |
| 119 | "CYAN_SKILLFISH", | ||
| 119 | "NAVI14", | 120 | "NAVI14", |
| 120 | "NAVI12", | 121 | "NAVI12", |
| 121 | "SIENNA_CICHLID", | 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 | * @adev: amdgpu_device pointer | 293 | * @adev: amdgpu_device pointer |
| 293 | * @pos: offset of the buffer in vram | 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 | * @size: read/write size, sizeof(@buf) must > @size | 296 | * @size: read/write size, sizeof(@buf) must > @size |
| 296 | * @write: true - write to vram, otherwise - read from vram | 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 | void amdgpu_device_mm_access(struct amdgpu_device *adev, loff_t pos, |
| 299 | uint32_t *buf, size_t size, bool write) | 300 | void *buf, size_t size, bool write) |
| 300 | { | 301 | { |
| 301 | unsigned long flags; | 302 | unsigned long flags; |
| 302 | uint32_t hi = ~0; | 303 | uint32_t hi = ~0, tmp = 0; |
| 304 | uint32_t *data = buf; | ||
| 303 | uint64_t last; | 305 | uint64_t last; |
| 304 | int idx; | 306 | int idx; |
| 305 | 307 | ||
| 306 | if (!drm_dev_enter(&adev->ddev, &idx)) | 308 | if (!drm_dev_enter(&adev->ddev, &idx)) |
| 307 | return; | 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 | #ifdef CONFIG_64BIT | 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 | last = min(pos + size, adev->gmc.visible_vram_size); | 354 | last = min(pos + size, adev->gmc.visible_vram_size); |
| 311 | if (last > pos) { | 355 | if (last > pos) { |
| 312 | void __iomem *addr = adev->mman.aper_base_kaddr + pos; | 356 | addr = adev->mman.aper_base_kaddr + pos; |
| 313 | size_t count = last - pos; | 357 | count = last - pos; |
| 314 | 358 | ||
| 315 | if (write) { | 359 | if (write) { |
| 316 | memcpy_toio(addr, buf, count); | 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 | memcpy_fromio(buf, addr, count); | 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 | #endif | 374 | #endif |
| 375 | } | ||
| 333 | 376 | ||
| 334 | spin_lock_irqsave(&adev->mmio_idx_lock, flags); | 377 | /** |
| 335 | for (last = pos + size; pos < last; pos += 4) { | 378 | * amdgpu_device_vram_access - read/write a buffer in vram |
| 336 | uint32_t tmp = pos >> 31; | 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); | 391 | /* try to using vram apreature to access vram first */ |
| 339 | if (tmp != hi) { | 392 | count = amdgpu_device_aper_access(adev, pos, buf, size, write); |
| 340 | WREG32_NO_KIQ(mmMM_INDEX_HI, tmp); | 393 | size -= count; |
| 341 | hi = tmp; | 394 | if (size) { |
| 342 | } | 395 | /* using MM to access rest vram */ |
| 343 | if (write) | 396 | pos += count; |
| 344 | WREG32_NO_KIQ(mmMM_DATA, *buf++); | 397 | buf += count; |
| 345 | else | 398 | amdgpu_device_mm_access(adev, pos, buf, size, write); |
| 346 | *buf++ = RREG32_NO_KIQ(mmMM_DATA); | ||
| 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 | adev->gfx.rlc.funcs && | 564 | adev->gfx.rlc.funcs && |
| 519 | adev->gfx.rlc.funcs->is_rlcg_access_range) { | 565 | adev->gfx.rlc.funcs->is_rlcg_access_range) { |
| 520 | if (adev->gfx.rlc.funcs->is_rlcg_access_range(adev, reg)) | 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 | } else { | 568 | } else { |
| 523 | writel(v, ((void __iomem *)adev->rmmio) + (reg * 4)); | 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 | * amdgpu_device_vga_set_decode - enable/disable vga decode | 1313 | * amdgpu_device_vga_set_decode - enable/disable vga decode |
| 1268 | * | 1314 | * |
| 1269 | * @cookie: amdgpu_device pointer | 1315 | * @pdev: PCI device pointer |
| 1270 | * @state: enable/disable vga decode | 1316 | * @state: enable/disable vga decode |
| 1271 | * | 1317 | * |
| 1272 | * Enable/disable vga decode (all asics). | 1318 | * Enable/disable vga decode (all asics). |
| 1273 | * Returns VGA resource flags. | 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 | amdgpu_asic_set_vga_state(adev, state); | 1325 | amdgpu_asic_set_vga_state(adev, state); |
| 1279 | if (state) | 1326 | if (state) |
| 1280 | return VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM | | 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 | break; | 1441 | break; |
| 1395 | case CHIP_YELLOW_CARP: | 1442 | case CHIP_YELLOW_CARP: |
| 1396 | break; | 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 | default: | 1448 | default: |
| 1398 | return -EINVAL; | 1449 | return -EINVAL; |
| 1399 | } | 1450 | } |
| @@ -2100,6 +2151,7 @@ static int amdgpu_device_ip_early_init(struct amdgpu_device *adev) · 700 unmodified lines | |||
| 2100 | case CHIP_BEIGE_GOBY: | 2151 | case CHIP_BEIGE_GOBY: |
| 2101 | case CHIP_VANGOGH: | 2152 | case CHIP_VANGOGH: |
| 2102 | case CHIP_YELLOW_CARP: | 2153 | case CHIP_YELLOW_CARP: |
| 2154 | case CHIP_CYAN_SKILLFISH: | ||
| 2103 | if (adev->asic_type == CHIP_VANGOGH) | 2155 | if (adev->asic_type == CHIP_VANGOGH) |
| 2104 | adev->family = AMDGPU_FAMILY_VGH; | 2156 | adev->family = AMDGPU_FAMILY_VGH; |
| 2105 | else if (adev->asic_type == CHIP_YELLOW_CARP) | 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 | fence_driver_init: | 3647 | fence_driver_init: |
| 3596 | /* Fence driver */ | 3648 | /* Fence driver */ |
| 3597 | r = amdgpu_fence_driver_init(adev); | 3649 | r = amdgpu_fence_driver_sw_init(adev); |
| 3598 | if (r) { | 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 | amdgpu_vf_error_put(adev, AMDGIM_ERROR_VF_FENCE_INIT_FAIL, 0, 0); | 3652 | amdgpu_vf_error_put(adev, AMDGIM_ERROR_VF_FENCE_INIT_FAIL, 0, 0); |
| 3601 | goto failed; | 3653 | goto failed; |
| 3602 | } | 3654 | } |
| @@ -3623,6 +3675,8 @@ fence_driver_init: · 20 unmodified lines | |||
| 3623 | goto release_ras_con; | 3675 | goto release_ras_con; |
| 3624 | } | 3676 | } |
| 3625 | 3677 | ||
| 3678 | amdgpu_fence_driver_hw_init(adev); | ||
| 3679 | |||
| 3626 | dev_info(adev->dev, | 3680 | dev_info(adev->dev, |
| 3627 | "SE %d, SH per SE %d, CU per SH %d, active_cu_number %d\n", | 3681 | "SE %d, SH per SE %d, CU per SH %d, active_cu_number %d\n", |
| 3628 | adev->gfx.config.max_shader_engines, | 3682 | adev->gfx.config.max_shader_engines, |
| @@ -3714,7 +3768,7 @@ fence_driver_init: · 85 unmodified lines | |||
| 3714 | /* this will fail for cards that aren't VGA class devices, just | 3768 | /* this will fail for cards that aren't VGA class devices, just |
| 3715 | * ignore it */ | 3769 | * ignore it */ |
| 3716 | if ((adev->pdev->class >> 8) == PCI_CLASS_DISPLAY_VGA) | 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 | if (amdgpu_device_supports_px(ddev)) { | 3773 | if (amdgpu_device_supports_px(ddev)) { |
| 3720 | px = true; | 3774 | px = true; |
| @@ -3771,7 +3825,10 @@ void amdgpu_device_fini_hw(struct amdgpu_device *adev) · 50 unmodified lines | |||
| 3771 | { | 3825 | { |
| 3772 | dev_info(adev->dev, "amdgpu: finishing device.\n"); | 3826 | dev_info(adev->dev, "amdgpu: finishing device.\n"); |
| 3773 | flush_delayed_work(&adev->delayed_init_work); | 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 | adev->shutdown = true; | 3832 | adev->shutdown = true; |
| 3776 | 3833 | ||
| 3777 | /* make sure IB test finished before entering exclusive mode | 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 | else | 3847 | else |
| 3791 | drm_atomic_helper_shutdown(adev_to_drm(adev)); | 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 | if (adev->pm_sysfs_en) | 3852 | if (adev->pm_sysfs_en) |
| 3796 | amdgpu_pm_sysfs_fini(adev); | 3853 | amdgpu_pm_sysfs_fini(adev); |
| @@ -3812,7 +3869,7 @@ void amdgpu_device_fini_hw(struct amdgpu_device *adev) · 15 unmodified lines | |||
| 3812 | void amdgpu_device_fini_sw(struct amdgpu_device *adev) | 3869 | void amdgpu_device_fini_sw(struct amdgpu_device *adev) |
| 3813 | { | 3870 | { |
| 3814 | amdgpu_device_ip_fini(adev); | 3871 | amdgpu_device_ip_fini(adev); |
| 3815 | amdgpu_fence_driver_fini_sw(adev); | 3872 | amdgpu_fence_driver_sw_fini(adev); |
| 3816 | release_firmware(adev->firmware.gpu_info_fw); | 3873 | release_firmware(adev->firmware.gpu_info_fw); |
| 3817 | adev->firmware.gpu_info_fw = NULL; | 3874 | adev->firmware.gpu_info_fw = NULL; |
| 3818 | adev->accel_working = false; | 3875 | adev->accel_working = false; |
| @@ -3833,7 +3890,7 @@ void amdgpu_device_fini_sw(struct amdgpu_device *adev) · 14 unmodified lines | |||
| 3833 | vga_switcheroo_fini_domain_pm_ops(adev->dev); | 3890 | vga_switcheroo_fini_domain_pm_ops(adev->dev); |
| 3834 | } | 3891 | } |
| 3835 | if ((adev->pdev->class >> 8) == PCI_CLASS_DISPLAY_VGA) | 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 | if (IS_ENABLED(CONFIG_PERF_EVENTS)) | 3895 | if (IS_ENABLED(CONFIG_PERF_EVENTS)) |
| 3839 | amdgpu_pmu_fini(adev); | 3896 | amdgpu_pmu_fini(adev); |
| @@ -3887,7 +3944,7 @@ int amdgpu_device_suspend(struct drm_device *dev, bool fbcon) · 47 unmodified lines | |||
| 3887 | /* evict vram memory */ | 3944 | /* evict vram memory */ |
| 3888 | amdgpu_bo_evict_vram(adev); | 3945 | amdgpu_bo_evict_vram(adev); |
| 3889 | 3946 | ||
| 3890 | amdgpu_fence_driver_suspend(adev); | 3947 | amdgpu_fence_driver_hw_fini(adev); |
| 3891 | 3948 | ||
| 3892 | amdgpu_device_ip_suspend_phase2(adev); | 3949 | amdgpu_device_ip_suspend_phase2(adev); |
| 3893 | /* evict remaining vram memory | 3950 | /* evict remaining vram memory |
| @@ -3932,8 +3989,7 @@ int amdgpu_device_resume(struct drm_device *dev, bool fbcon) · 38 unmodified lines | |||
| 3932 | dev_err(adev->dev, "amdgpu_device_ip_resume failed (%d).\n", r); | 3989 | dev_err(adev->dev, "amdgpu_device_ip_resume failed (%d).\n", r); |
| 3933 | return r; | 3990 | return r; |
| 3934 | } | 3991 | } |
| 3935 | amdgpu_fence_driver_resume(adev); | 3992 | amdgpu_fence_driver_hw_init(adev); |
| 3936 | |||
| 3937 | 3993 | ||
| 3938 | r = amdgpu_device_ip_late_init(adev); | 3994 | r = amdgpu_device_ip_late_init(adev); |
| 3939 | if (r) | 3995 | if (r) |
| @@ -4394,7 +4450,7 @@ int amdgpu_device_mode1_reset(struct amdgpu_device *adev) · 454 unmodified lines | |||
| 4394 | int amdgpu_device_pre_asic_reset(struct amdgpu_device *adev, | 4450 | int amdgpu_device_pre_asic_reset(struct amdgpu_device *adev, |
| 4395 | struct amdgpu_reset_context *reset_context) | 4451 | struct amdgpu_reset_context *reset_context) |
| 4396 | { | 4452 | { |
| 4397 | int i, r = 0; | 4453 | int i, j, r = 0; |
| 4398 | struct amdgpu_job *job = NULL; | 4454 | struct amdgpu_job *job = NULL; |
| 4399 | bool need_full_reset = | 4455 | bool need_full_reset = |
| 4400 | test_bit(AMDGPU_NEED_FULL_RESET, &reset_context->flags); | 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 | if (!ring || !ring->sched.thread) | 4474 | if (!ring || !ring->sched.thread) |
| 4419 | continue; | 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 | /* after all hw jobs are reset, hw fence is meaningless, so force_completion */ | 4488 | /* after all hw jobs are reset, hw fence is meaningless, so force_completion */ |
| 4422 | amdgpu_fence_driver_force_completion(ring); | 4489 | amdgpu_fence_driver_force_completion(ring); |
| 4423 | } | 4490 | } |
| 4424 | 4491 | ||
| 4425 | if(job) | 4492 | if (job && job->vm) |
| 4426 | drm_sched_increase_karma(&job->base); | 4493 | drm_sched_increase_karma(&job->base); |
| 4427 | 4494 | ||
| 4428 | r = amdgpu_reset_prepare_hwcontext(adev, reset_context); | 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 | DRM_INFO("Bailing on TDR for s_job:%llx, hive: %llx as another already in progress", | 4953 | DRM_INFO("Bailing on TDR for s_job:%llx, hive: %llx as another already in progress", |
| 4887 | job ? job->base.id : -1, hive->hive_id); | 4954 | job ? job->base.id : -1, hive->hive_id); |
| 4888 | amdgpu_put_xgmi_hive(hive); | 4955 | amdgpu_put_xgmi_hive(hive); |
| 4889 | if (job) | 4956 | if (job && job->vm) |
| 4890 | drm_sched_increase_karma(&job->base); | 4957 | drm_sched_increase_karma(&job->base); |
| 4891 | return 0; | 4958 | return 0; |
| 4892 | } | 4959 | } |
| @@ -4910,7 +4977,7 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev, · 17 unmodified lines | |||
| 4910 | job ? job->base.id : -1); | 4977 | job ? job->base.id : -1); |
| 4911 | 4978 | ||
| 4912 | /* even we skipped this reset, still need to set the job to guilty */ | 4979 | /* even we skipped this reset, still need to set the job to guilty */ |
| 4913 | if (job) | 4980 | if (job && job->vm) |
| 4914 | drm_sched_increase_karma(&job->base); | 4981 | drm_sched_increase_karma(&job->base); |
| 4915 | goto skip_recovery; | 4982 | goto skip_recovery; |
| 4916 | } | 4983 | } |
| @@ -5277,6 +5344,10 @@ int amdgpu_device_baco_exit(struct drm_device *dev) · 360 unmodified lines | |||
| 5277 | adev->nbio.funcs->enable_doorbell_interrupt) | 5344 | adev->nbio.funcs->enable_doorbell_interrupt) |
| 5278 | adev->nbio.funcs->enable_doorbell_interrupt(adev, true); | 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 | return 0; | 5351 | return 0; |
| 5281 | } | 5352 | } |
| 5282 | 5353 | ||
| @@ -42,48 +42,6 @@ · 41 unmodified lines | |||
| 42 | #include <linux/pci-p2pdma.h> | 42 | #include <linux/pci-p2pdma.h> |
| 43 | #include <linux/pm_runtime.h> | 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 | * amdgpu_dma_buf_attach - &dma_buf_ops.attach implementation | 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 | if (r < 0) | 68 | if (r < 0) |
| 111 | goto out; | 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 | return 0; | 71 | return 0; |
| 132 | 72 | ||
| 133 | out: | 73 | out: |
| @@ -150,9 +90,6 @@ static void amdgpu_dma_buf_detach(struct dma_buf *dmabuf, · 16 unmodified lines | |||
| 150 | struct amdgpu_bo *bo = gem_to_amdgpu_bo(obj); | 90 | struct amdgpu_bo *bo = gem_to_amdgpu_bo(obj); |
| 151 | struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev); | 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 | pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); | 93 | pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); |
| 157 | pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); | 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 | bo = gem_to_amdgpu_bo(gobj); | 355 | bo = gem_to_amdgpu_bo(gobj); |
| 419 | bo->allowed_domains = AMDGPU_GEM_DOMAIN_GTT; | 356 | bo->allowed_domains = AMDGPU_GEM_DOMAIN_GTT; |
| 420 | bo->preferred_domains = AMDGPU_GEM_DOMAIN_GTT; | 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 | dma_resv_unlock(resv); | 359 | dma_resv_unlock(resv); |
| 425 | return gobj; | 360 | return gobj; |
| @@ -870,11 +870,10 @@ MODULE_PARM_DESC(reset_method, "GPU reset method (-1 = auto (default), 0 = legac · 869 unmodified lines | |||
| 870 | module_param_named(reset_method, amdgpu_reset_method, int, 0444); | 870 | module_param_named(reset_method, amdgpu_reset_method, int, 0444); |
| 871 | 871 | ||
| 872 | /** | 872 | /** |
| 873 | * DOC: bad_page_threshold (int) | 873 | * DOC: bad_page_threshold (int) Bad page threshold is specifies the |
| 874 | * Bad page threshold is to specify the threshold value of faulty pages | 874 | * threshold value of faulty pages detected by RAS ECC, which may |
| 875 | * detected by RAS ECC, that may result in GPU entering bad status if total | 875 | * result in the GPU entering bad status when the number of total |
| 876 | * faulty pages by ECC exceed threshold value and leave it for user's further | 876 | * faulty pages by ECC exceeds the threshold value. |
| 877 | * check. | ||
| 878 | */ | 877 | */ |
| 879 | MODULE_PARM_DESC(bad_page_threshold, "Bad page threshold(-1 = auto(default value), 0 = disable bad page retirement)"); | 878 | MODULE_PARM_DESC(bad_page_threshold, "Bad page threshold(-1 = auto(default value), 0 = disable bad page retirement)"); |
| 880 | module_param_named(bad_page_threshold, amdgpu_bad_page_threshold, int, 0444); | 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 | {0x1002, 0x740F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ALDEBARAN|AMD_EXP_HW_SUPPORT}, | 1212 | {0x1002, 0x740F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ALDEBARAN|AMD_EXP_HW_SUPPORT}, |
| 1214 | {0x1002, 0x7410, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ALDEBARAN|AMD_EXP_HW_SUPPORT}, | 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 | /* BEIGE_GOBY */ | 1218 | /* BEIGE_GOBY */ |
| 1217 | {0x1002, 0x7420, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BEIGE_GOBY}, | 1219 | {0x1002, 0x7420, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BEIGE_GOBY}, |
| 1218 | {0x1002, 0x7421, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BEIGE_GOBY}, | 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 | int ret, retry = 0; | 1238 | int ret, retry = 0; |
| 1237 | bool supports_atomic = false; | 1239 | bool supports_atomic = false; |
| 1238 | 1240 | ||
| 1239 | if (!amdgpu_virtual_display && | 1241 | if (amdgpu_virtual_display || |
| 1240 | amdgpu_device_asic_has_dc_support(flags & AMD_ASIC_MASK)) | 1242 | amdgpu_device_asic_has_dc_support(flags & AMD_ASIC_MASK)) |
| 1241 | supports_atomic = true; | 1243 | supports_atomic = true; |
| 1242 | 1244 | ||
| @@ -1292,7 +1294,7 @@ static int amdgpu_pci_probe(struct pci_dev *pdev, · 49 unmodified lines | |||
| 1292 | #endif | 1294 | #endif |
| 1293 | 1295 | ||
| 1294 | /* Get rid of things like offb */ | 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 | if (ret) | 1298 | if (ret) |
| 1297 | return ret; | 1299 | return ret; |
| 1298 | 1300 | ||
| @@ -1474,7 +1476,7 @@ static int amdgpu_pmops_suspend(struct device *dev) · 175 unmodified lines | |||
| 1474 | struct amdgpu_device *adev = drm_to_adev(drm_dev); | 1476 | struct amdgpu_device *adev = drm_to_adev(drm_dev); |
| 1475 | int r; | 1477 | int r; |
| 1476 | 1478 | ||
| 1477 | if (amdgpu_acpi_is_s0ix_supported(adev)) | 1479 | if (amdgpu_acpi_is_s0ix_active(adev)) |
| 1478 | adev->in_s0ix = true; | 1480 | adev->in_s0ix = true; |
| 1479 | adev->in_s3 = true; | 1481 | adev->in_s3 = true; |
| 1480 | r = amdgpu_device_suspend(drm_dev, true); | 1482 | r = amdgpu_device_suspend(drm_dev, true); |
| @@ -1490,7 +1492,7 @@ static int amdgpu_pmops_resume(struct device *dev) · 9 unmodified lines | |||
| 1490 | int r; | 1492 | int r; |
| 1491 | 1493 | ||
| 1492 | r = amdgpu_device_resume(drm_dev, true); | 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 | adev->in_s0ix = false; | 1496 | adev->in_s0ix = false; |
| 1495 | return r; | 1497 | return r; |
| 1496 | } | 1498 | } |
| @@ -1784,7 +1786,6 @@ static const struct drm_driver amdgpu_kms_driver = { · 287 unmodified lines | |||
| 1784 | .open = amdgpu_driver_open_kms, | 1786 | .open = amdgpu_driver_open_kms, |
| 1785 | .postclose = amdgpu_driver_postclose_kms, | 1787 | .postclose = amdgpu_driver_postclose_kms, |
| 1786 | .lastclose = amdgpu_driver_lastclose_kms, | 1788 | .lastclose = amdgpu_driver_lastclose_kms, |
| 1787 | .irq_handler = amdgpu_irq_handler, | ||
| 1788 | .ioctls = amdgpu_ioctls_kms, | 1789 | .ioctls = amdgpu_ioctls_kms, |
| 1789 | .num_ioctls = ARRAY_SIZE(amdgpu_ioctls_kms), | 1790 | .num_ioctls = ARRAY_SIZE(amdgpu_ioctls_kms), |
| 1790 | .dumb_create = amdgpu_mode_dumb_create, | 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 | return 0; | 273 | return 0; |
| 274 | 274 | ||
| 275 | out: | 275 | out: |
| 276 | if (abo) { | ||
| 277 | |||
| 278 | } | ||
| 279 | if (fb && ret) { | 276 | if (fb && ret) { |
| 280 | drm_gem_object_put(gobj); | 277 | drm_gem_object_put(gobj); |
| 281 | drm_framebuffer_unregister_private(fb); | 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 | /* disable all the possible outputs/crtcs before entering KMS mode */ | 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 | drm_helper_disable_unused_functions(adev_to_drm(adev)); | 345 | drm_helper_disable_unused_functions(adev_to_drm(adev)); |
| 349 | 346 | ||
| 350 | drm_fb_helper_initial_config(&rfbdev->helper, bpp_sel); | 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 | * @ring: ring the fence is associated with | 130 | * @ring: ring the fence is associated with |
| 131 | * @f: resulting fence object | 131 | * @f: resulting fence object |
| 132 | * @job: job the fence is embedded in | ||
| 132 | * @flags: flags to pass into the subordinate .emit_fence() call | 133 | * @flags: flags to pass into the subordinate .emit_fence() call |
| 133 | * | 134 | * |
| 134 | * Emits a fence command on the requested ring (all asics). | 135 | * Emits a fence command on the requested ring (all asics). |
| 135 | * Returns 0 on success, -ENOMEM on failure. | 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 | unsigned flags) | 139 | unsigned flags) |
| 139 | { | 140 | { |
| 140 | struct amdgpu_device *adev = ring->adev; | 141 | struct amdgpu_device *adev = ring->adev; |
| 141 | struct amdgpu_fence *fence; | 142 | struct dma_fence *fence; |
| 143 | struct amdgpu_fence *am_fence; | ||
| 142 | struct dma_fence __rcu **ptr; | 144 | struct dma_fence __rcu **ptr; |
| 143 | uint32_t seq; | 145 | uint32_t seq; |
| 144 | int r; | 146 | int r; |
| 145 | 147 | ||
| 146 | fence = kmem_cache_alloc(amdgpu_fence_slab, GFP_KERNEL); | 148 | if (job == NULL) { |
| 147 | if (fence == NULL) | 149 | /* create a sperate hw fence */ |
| 148 | return -ENOMEM; | 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 | seq = ++ring->fence_drv.sync_seq; | 160 | seq = ++ring->fence_drv.sync_seq; |
| 151 | fence->ring = ring; | 161 | if (job != NULL && job->job_run_counter) { |
| 152 | dma_fence_init(&fence->base, &amdgpu_fence_ops, | 162 | /* reinit seq for resubmitted jobs */ |
| 153 | &ring->fence_drv.lock, | 163 | fence->seqno = seq; |
| 154 | adev->fence_context + ring->idx, | 164 | } else { |
| 155 | seq); | 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 | amdgpu_ring_emit_fence(ring, ring->fence_drv.gpu_addr, | 176 | amdgpu_ring_emit_fence(ring, ring->fence_drv.gpu_addr, |
| 157 | seq, flags | AMDGPU_FENCE_FLAG_INT); | 177 | seq, flags | AMDGPU_FENCE_FLAG_INT); |
| 158 | pm_runtime_get_noresume(adev_to_drm(adev)->dev); | 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 | /* This function can't be called concurrently anyway, otherwise | 195 | /* This function can't be called concurrently anyway, otherwise |
| 176 | * emitting the fence would mess up the hardware ring buffer. | 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 | return 0; | 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 | amdgpu_fence_write(ring, atomic_read(&ring->fence_drv.last_seq)); | 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 | ring->fence_drv.irq_src = irq_src; | 440 | ring->fence_drv.irq_src = irq_src; |
| 424 | ring->fence_drv.irq_type = irq_type; | 441 | ring->fence_drv.irq_type = irq_type; |
| 425 | ring->fence_drv.initialized = true; | 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 | r = drm_sched_init(&ring->sched, &amdgpu_sched_ops, | 508 | r = drm_sched_init(&ring->sched, &amdgpu_sched_ops, |
| 492 | num_hw_submission, amdgpu_job_hang_limit, | 509 | num_hw_submission, amdgpu_job_hang_limit, |
| 493 | timeout, sched_score, ring->name); | 510 | timeout, NULL, sched_score, ring->name); |
| 494 | if (r) { | 511 | if (r) { |
| 495 | DRM_ERROR("Failed to create scheduler on ring %s.\n", | 512 | DRM_ERROR("Failed to create scheduler on ring %s.\n", |
| 496 | ring->name); | 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 | * for all possible rings. | 522 | * for all possible rings. |
| 506 | * | 523 | * |
| 507 | * @adev: amdgpu device pointer | 524 | * @adev: amdgpu device pointer |
| @@ -512,20 +529,20 @@ int amdgpu_fence_driver_init_ring(struct amdgpu_ring *ring, · 4 unmodified lines | |||
| 512 | * amdgpu_fence_driver_start_ring(). | 529 | * amdgpu_fence_driver_start_ring(). |
| 513 | * Returns 0 for success. | 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 | return 0; | 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 | * for all possible rings. | 539 | * for all possible rings. |
| 523 | * | 540 | * |
| 524 | * @adev: amdgpu device pointer | 541 | * @adev: amdgpu device pointer |
| 525 | * | 542 | * |
| 526 | * Tear down the fence driver for all possible rings (all asics). | 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 | int i, r; | 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 | if (!ring || !ring->fence_drv.initialized) | 552 | if (!ring || !ring->fence_drv.initialized) |
| 536 | continue; | 553 | continue; |
| 537 | if (!ring->no_scheduler) | 554 | |
| 538 | drm_sched_fini(&ring->sched); | ||
| 539 | /* You can't wait for HW to signal if it's gone */ | 555 | /* You can't wait for HW to signal if it's gone */ |
| 540 | if (!drm_dev_is_unplugged(&adev->ddev)) | 556 | if (!drm_dev_is_unplugged(&adev->ddev)) |
| 541 | r = amdgpu_fence_wait_empty(ring); | 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 | unsigned int i, j; | 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 | if (!ring || !ring->fence_drv.initialized) | 579 | if (!ring || !ring->fence_drv.initialized) |
| 564 | continue; | 580 | continue; |
| 565 | 581 | ||
| 582 | if (!ring->no_scheduler) | ||
| 583 | drm_sched_fini(&ring->sched); | ||
| 584 | |||
| 566 | for (j = 0; j <= ring->fence_drv.num_fences_mask; ++j) | 585 | for (j = 0; j <= ring->fence_drv.num_fences_mask; ++j) |
| 567 | dma_fence_put(ring->fence_drv.fences[j]); | 586 | dma_fence_put(ring->fence_drv.fences[j]); |
| 568 | kfree(ring->fence_drv.fences); | 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 | 594 | * amdgpu_fence_driver_hw_init - enable 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 | ||
| 607 | * for all possible rings. | 595 | * for all possible rings. |
| 608 | * | 596 | * |
| 609 | * @adev: amdgpu device pointer | 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 | * Not all asics have all rings, so each asic will only | 600 | * Not all asics have all rings, so each asic will only |
| 613 | * start the fence driver on the rings it has using | 601 | * start the fence driver on the rings it has using |
| 614 | * amdgpu_fence_driver_start_ring(). | 602 | * amdgpu_fence_driver_start_ring(). |
| 615 | * Returns 0 for success. | 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 | int i; | 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 | static const char *amdgpu_fence_get_timeline_name(struct dma_fence *f) | 642 | static const char *amdgpu_fence_get_timeline_name(struct dma_fence *f) |
| 655 | { | 643 | { |
| 656 | struct amdgpu_fence *fence = to_amdgpu_fence(f); | 644 | struct amdgpu_ring *ring; |
| 657 | return (const char *)fence->ring->name; | 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 | static bool amdgpu_fence_enable_signaling(struct dma_fence *f) | 664 | static bool amdgpu_fence_enable_signaling(struct dma_fence *f) |
| 669 | { | 665 | { |
| 670 | struct amdgpu_fence *fence = to_amdgpu_fence(f); | 666 | struct amdgpu_ring *ring; |
| 671 | struct amdgpu_ring *ring = fence->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 | if (!timer_pending(&ring->fence_drv.fallback_timer)) | 676 | if (!timer_pending(&ring->fence_drv.fallback_timer)) |
| 674 | amdgpu_fence_schedule_fallback(ring); | 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 | return true; | 681 | return true; |
| 679 | } | 682 | } |
| @@ -688,8 +691,20 @@ static bool amdgpu_fence_enable_signaling(struct dma_fence *f) · 8 unmodified lines | |||
| 688 | static void amdgpu_fence_free(struct rcu_head *rcu) | 691 | static void amdgpu_fence_free(struct rcu_head *rcu) |
| 689 | { | 692 | { |
| 690 | struct dma_fence *f = container_of(rcu, struct dma_fence, rcu); | 693 | struct dma_fence *f = container_of(rcu, struct dma_fence, rcu); |
| 691 | struct amdgpu_fence *fence = to_amdgpu_fence(f); | 694 | |
| 692 | kmem_cache_free(amdgpu_fence_slab, fence); | 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 | .release = amdgpu_fence_release, | 727 | .release = amdgpu_fence_release, |
| 713 | }; | 728 | }; |
| 714 | 729 | ||
| 730 | |||
| 715 | /* | 731 | /* |
| 716 | * Fence debugfs | 732 | * Fence debugfs |
| 717 | */ | 733 | */ |
| @@ -27,10 +27,10 @@ · 26 unmodified lines | |||
| 27 | #include "smu_v11_0_i2c.h" | 27 | #include "smu_v11_0_i2c.h" |
| 28 | #include "atom.h" | 28 | #include "atom.h" |
| 29 | #include "amdgpu_fru_eeprom.h" | 29 | #include "amdgpu_fru_eeprom.h" |
| 30 | #include "amdgpu_eeprom.h" | ||
| 30 | 31 | ||
| 31 | #define I2C_PRODUCT_INFO_ADDR 0xAC | 32 | #define FRU_EEPROM_MADDR 0x60000 |
| 32 | #define I2C_PRODUCT_INFO_ADDR_SIZE 0x2 | 33 | #define I2C_PRODUCT_INFO_OFFSET 0xC0 |
| 33 | #define I2C_PRODUCT_INFO_OFFSET 0xC0 | ||
| 34 | 34 | ||
| 35 | static bool is_fru_eeprom_supported(struct amdgpu_device *adev) | 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 | static int amdgpu_fru_read_eeprom(struct amdgpu_device *adev, uint32_t addrptr, | 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 | int ret, size; | 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 | if (ret < 1) { | 70 | if (ret < 1) { |
| 79 | DRM_WARN("FRU: Failed to get size field"); | 71 | DRM_WARN("FRU: Failed to get size field"); |
| 80 | return ret; | 72 | return ret; |
| @@ -83,13 +75,9 @@ static int amdgpu_fru_read_eeprom(struct amdgpu_device *adev, uint32_t addrptr, · 2 unmodified lines | |||
| 83 | /* The size returned by the i2c requires subtraction of 0xC0 since the | 75 | /* The size returned by the i2c requires subtraction of 0xC0 since the |
| 84 | * size apparently always reports as 0xC0+actual size. | 76 | * size apparently always reports as 0xC0+actual size. |
| 85 | */ | 77 | */ |
| 86 | size = buff[2] - I2C_PRODUCT_INFO_OFFSET; | 78 | size = buff[0] - 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); | ||
| 92 | 79 | ||
| 80 | ret = amdgpu_eeprom_read(&adev->pm.smu_i2c, addrptr + 1, buff, size); | ||
| 93 | if (ret < 1) { | 81 | if (ret < 1) { |
| 94 | DRM_WARN("FRU: Failed to get data field"); | 82 | DRM_WARN("FRU: Failed to get data field"); |
| 95 | return ret; | 83 | return ret; |
| @@ -101,8 +89,8 @@ static int amdgpu_fru_read_eeprom(struct amdgpu_device *adev, uint32_t addrptr, · 5 unmodified lines | |||
| 101 | int amdgpu_fru_get_product_info(struct amdgpu_device *adev) | 89 | int amdgpu_fru_get_product_info(struct amdgpu_device *adev) |
| 102 | { | 90 | { |
| 103 | unsigned char buff[34]; | 91 | unsigned char buff[34]; |
| 104 | int addrptr, size; | 92 | u32 addrptr; |
| 105 | int len; | 93 | int size, len; |
| 106 | 94 | ||
| 107 | if (!is_fru_eeprom_supported(adev)) | 95 | if (!is_fru_eeprom_supported(adev)) |
| 108 | return 0; | 96 | return 0; |
| @@ -125,7 +113,7 @@ int amdgpu_fru_get_product_info(struct amdgpu_device *adev) · 16 unmodified lines | |||
| 125 | * Bytes 8-a are all 1-byte and refer to the size of the entire struct, | 113 | * Bytes 8-a are all 1-byte and refer to the size of the entire struct, |
| 126 | * and the language field, so just start from 0xb, manufacturer size | 114 | * and the language field, so just start from 0xb, manufacturer size |
| 127 | */ | 115 | */ |
| 128 | addrptr = 0xb; | 116 | addrptr = FRU_EEPROM_MADDR + 0xb; |
| 129 | size = amdgpu_fru_read_eeprom(adev, addrptr, buff); | 117 | size = amdgpu_fru_read_eeprom(adev, addrptr, buff); |
| 130 | if (size < 1) { | 118 | if (size < 1) { |
| 131 | DRM_ERROR("Failed to read FRU Manufacturer, ret:%d", size); | 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 | if (adev->dummy_page_addr) | 76 | if (adev->dummy_page_addr) |
| 77 | return 0; | 77 | return 0; |
| 78 | adev->dummy_page_addr = dma_map_page(&adev->pdev->dev, dummy_page, 0, | 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 | if (dma_mapping_error(&adev->pdev->dev, adev->dummy_page_addr)) { | 80 | if (dma_mapping_error(&adev->pdev->dev, adev->dummy_page_addr)) { |
| 81 | dev_err(&adev->pdev->dev, "Failed to DMA MAP the dummy page\n"); | 81 | dev_err(&adev->pdev->dev, "Failed to DMA MAP the dummy page\n"); |
| 82 | adev->dummy_page_addr = 0; | 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 | if (!adev->dummy_page_addr) | 97 | if (!adev->dummy_page_addr) |
| 98 | return; | 98 | return; |
| 99 | pci_unmap_page(adev->pdev, adev->dummy_page_addr, | 99 | dma_unmap_page(&adev->pdev->dev, adev->dummy_page_addr, PAGE_SIZE, |
| 100 | PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); | 100 | DMA_BIDIRECTIONAL); |
| 101 | adev->dummy_page_addr = 0; | 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 | if (operation == AMDGPU_VA_OP_MAP || | 622 | if (operation == AMDGPU_VA_OP_MAP || |
| 623 | operation == AMDGPU_VA_OP_REPLACE) { | 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 | if (r) | 625 | if (r) |
| 626 | goto error; | 626 | goto error; |
| 627 | } | 627 | } |
| @@ -838,7 +838,8 @@ int amdgpu_gem_op_ioctl(struct drm_device *dev, void *data, · 210 unmodified lines | |||
| 838 | break; | 838 | break; |
| 839 | } | 839 | } |
| 840 | case AMDGPU_GEM_OP_SET_PLACEMENT: | 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 | r = -EINVAL; | 843 | r = -EINVAL; |
| 843 | amdgpu_bo_unreserve(robj); | 844 | amdgpu_bo_unreserve(robj); |
| 844 | break; | 845 | break; |
| @@ -903,7 +904,7 @@ int amdgpu_mode_dumb_create(struct drm_file *file_priv, · 58 unmodified lines | |||
| 903 | DIV_ROUND_UP(args->bpp, 8), 0); | 904 | DIV_ROUND_UP(args->bpp, 8), 0); |
| 904 | args->size = (u64)args->pitch * args->height; | 905 | args->size = (u64)args->pitch * args->height; |
| 905 | args->size = ALIGN(args->size, PAGE_SIZE); | 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 | amdgpu_display_supported_domains(adev, flags)); | 908 | amdgpu_display_supported_domains(adev, flags)); |
| 908 | r = amdgpu_gem_object_create(adev, args->size, 0, domain, flags, | 909 | r = amdgpu_gem_object_create(adev, args->size, 0, domain, flags, |
| 909 | ttm_bo_type_device, NULL, &gobj); | 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 | adev->gfx.ras_if->block = AMDGPU_RAS_BLOCK__GFX; | 629 | adev->gfx.ras_if->block = AMDGPU_RAS_BLOCK__GFX; |
| 630 | adev->gfx.ras_if->type = AMDGPU_RAS_ERROR__MULTI_UNCORRECTABLE; | 630 | adev->gfx.ras_if->type = AMDGPU_RAS_ERROR__MULTI_UNCORRECTABLE; |
| 631 | adev->gfx.ras_if->sub_block_index = 0; | 631 | adev->gfx.ras_if->sub_block_index = 0; |
| 632 | strcpy(adev->gfx.ras_if->name, "gfx"); | ||
| 633 | } | 632 | } |
| 634 | fs_info.head = ih_info.head = *adev->gfx.ras_if; | 633 | fs_info.head = ih_info.head = *adev->gfx.ras_if; |
| 635 | r = amdgpu_ras_late_init(adev, adev->gfx.ras_if, | 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 | return r; | 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 | return 0; | 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 | struct amdgpu_gtt_node *node; | 132 | struct amdgpu_gtt_node *node; |
| 133 | int r; | 133 | int r; |
| 134 | 134 | ||
| 135 | spin_lock(&mgr->lock); | 135 | if (!(place->flags & TTM_PL_FLAG_TEMPORARY) && |
| 136 | if (tbo->resource && tbo->resource->mem_type != TTM_PL_TT && | 136 | atomic64_add_return(num_pages, &mgr->used) > man->size) { |
| 137 | atomic64_read(&mgr->available) < num_pages) { | 137 | atomic64_sub(num_pages, &mgr->used); |
| 138 | spin_unlock(&mgr->lock); | ||
| 139 | return -ENOSPC; | 138 | return -ENOSPC; |
| 140 | } | 139 | } |
| 141 | atomic64_sub(num_pages, &mgr->available); | ||
| 142 | spin_unlock(&mgr->lock); | ||
| 143 | 140 | ||
| 144 | node = kzalloc(struct_size(node, base.mm_nodes, 1), GFP_KERNEL); | 141 | node = kzalloc(struct_size(node, base.mm_nodes, 1), GFP_KERNEL); |
| 145 | if (!node) { | 142 | if (!node) { |
| @@ -175,7 +172,8 @@ err_free: · 29 unmodified lines | |||
| 175 | kfree(node); | 172 | kfree(node); |
| 176 | 173 | ||
| 177 | err_out: | 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 | return r; | 178 | return r; |
| 181 | } | 179 | } |
| @@ -198,7 +196,9 @@ static void amdgpu_gtt_mgr_del(struct ttm_resource_manager *man, · 16 unmodified lines | |||
| 198 | if (drm_mm_node_allocated(&node->base.mm_nodes[0])) | 196 | if (drm_mm_node_allocated(&node->base.mm_nodes[0])) |
| 199 | drm_mm_remove_node(&node->base.mm_nodes[0]); | 197 | drm_mm_remove_node(&node->base.mm_nodes[0]); |
| 200 | spin_unlock(&mgr->lock); | 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 | kfree(node); | 203 | kfree(node); |
| 204 | } | 204 | } |
| @@ -213,9 +213,8 @@ static void amdgpu_gtt_mgr_del(struct ttm_resource_manager *man, · 8 unmodified lines | |||
| 213 | uint64_t amdgpu_gtt_mgr_usage(struct ttm_resource_manager *man) | 213 | uint64_t amdgpu_gtt_mgr_usage(struct ttm_resource_manager *man) |
| 214 | { | 214 | { |
| 215 | struct amdgpu_gtt_mgr *mgr = to_gtt_mgr(man); | 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 | drm_mm_print(&mgr->mm, printer); | 264 | drm_mm_print(&mgr->mm, printer); |
| 266 | spin_unlock(&mgr->lock); | 265 | spin_unlock(&mgr->lock); |
| 267 | 266 | ||
| 268 | drm_printf(printer, "man size:%llu pages, gtt available:%lld pages, usage:%lluMB\n", | 267 | drm_printf(printer, "man size:%llu pages, gtt used:%llu pages\n", |
| 269 | man->size, (u64)atomic64_read(&mgr->available), | 268 | man->size, atomic64_read(&mgr->used)); |
| 270 | amdgpu_gtt_mgr_usage(man) >> 20); | ||
| 271 | } | 269 | } |
| 272 | 270 | ||
| 273 | static const struct ttm_resource_manager_func amdgpu_gtt_mgr_func = { | 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 | size = (adev->gmc.gart_size >> PAGE_SHIFT) - start; | 297 | size = (adev->gmc.gart_size >> PAGE_SHIFT) - start; |
| 300 | drm_mm_init(&mgr->mm, start, size); | 298 | drm_mm_init(&mgr->mm, start, size); |
| 301 | spin_lock_init(&mgr->lock); | 299 | spin_lock_init(&mgr->lock); |
| 302 | atomic64_set(&mgr->available, gtt_size >> PAGE_SHIFT); | 300 | atomic64_set(&mgr->used, 0); |
| 303 | 301 | ||
| 304 | ttm_set_driver_manager(&adev->mman.bdev, TTM_PL_TT, &mgr->manager); | 302 | ttm_set_driver_manager(&adev->mman.bdev, TTM_PL_TT, &mgr->manager); |
| 305 | ttm_resource_manager_set_used(man, true); | 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 | adev->hdp.ras_if->block = AMDGPU_RAS_BLOCK__HDP; | 41 | adev->hdp.ras_if->block = AMDGPU_RAS_BLOCK__HDP; |
| 42 | adev->hdp.ras_if->type = AMDGPU_RAS_ERROR__MULTI_UNCORRECTABLE; | 42 | adev->hdp.ras_if->type = AMDGPU_RAS_ERROR__MULTI_UNCORRECTABLE; |
| 43 | adev->hdp.ras_if->sub_block_index = 0; | 43 | adev->hdp.ras_if->sub_block_index = 0; |
| 44 | strcpy(adev->hdp.ras_if->name, "hdp"); | ||
| 45 | } | 44 | } |
| 46 | ih_info.head = fs_info.head = *adev->hdp.ras_if; | 45 | ih_info.head = fs_info.head = *adev->hdp.ras_if; |
| 47 | r = amdgpu_ras_late_init(adev, adev->hdp.ras_if, | 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 | void | 339 | void |
| 340 | amdgpu_i2c_router_select_ddc_port(const struct amdgpu_connector *amdgpu_connector) | 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 | if (!amdgpu_connector->router.ddc_valid) | 344 | if (!amdgpu_connector->router.ddc_valid) |
| 345 | return; | 345 | return; |
| @@ -262,7 +262,7 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned num_ibs, · 261 unmodified lines | |||
| 262 | fence_flags | AMDGPU_FENCE_FLAG_64BIT); | 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 | if (r) { | 266 | if (r) { |
| 267 | dev_err(adev->dev, "failed to emit fence (%d)\n", r); | 267 | dev_err(adev->dev, "failed to emit fence (%d)\n", r); |
| 268 | if (job && job->vmid) | 268 | if (job && job->vmid) |
| @@ -46,7 +46,6 @@ · 45 unmodified lines | |||
| 46 | #include <linux/pci.h> | 46 | #include <linux/pci.h> |
| 47 | 47 | ||
| 48 | #include <drm/drm_crtc_helper.h> | 48 | #include <drm/drm_crtc_helper.h> |
| 49 | #include <drm/drm_irq.h> | ||
| 50 | #include <drm/drm_vblank.h> | 49 | #include <drm/drm_vblank.h> |
| 51 | #include <drm/amdgpu_drm.h> | 50 | #include <drm/amdgpu_drm.h> |
| 52 | #include <drm/drm_drv.h> | 51 | #include <drm/drm_drv.h> |
| @@ -184,7 +183,7 @@ void amdgpu_irq_disable_all(struct amdgpu_device *adev) · 131 unmodified lines | |||
| 184 | * Returns: | 183 | * Returns: |
| 185 | * result of handling the IRQ, as defined by &irqreturn_t | 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 | struct drm_device *dev = (struct drm_device *) arg; | 188 | struct drm_device *dev = (struct drm_device *) arg; |
| 190 | struct amdgpu_device *adev = drm_to_adev(dev); | 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 | int amdgpu_irq_init(struct amdgpu_device *adev) | 306 | int amdgpu_irq_init(struct amdgpu_device *adev) |
| 308 | { | 307 | { |
| 309 | int r = 0; | 308 | int r = 0; |
| 309 | unsigned int irq; | ||
| 310 | 310 | ||
| 311 | spin_lock_init(&adev->irq.lock); | 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 | INIT_WORK(&adev->irq.ih2_work, amdgpu_irq_handle_ih2); | 349 | INIT_WORK(&adev->irq.ih2_work, amdgpu_irq_handle_ih2); |
| 350 | INIT_WORK(&adev->irq.ih_soft_work, amdgpu_irq_handle_ih_soft); | 350 | INIT_WORK(&adev->irq.ih_soft_work, amdgpu_irq_handle_ih_soft); |
| 351 | 351 | ||
| 352 | adev->irq.installed = true; | 352 | /* Use vector 0 for MSI-X. */ |
| 353 | /* Use vector 0 for MSI-X */ | 353 | r = pci_irq_vector(adev->pdev, 0); |
| 354 | r = drm_irq_install(adev_to_drm(adev), 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 | if (r) { | 361 | if (r) { |
| 356 | adev->irq.installed = false; | ||
| 357 | if (!amdgpu_device_has_dc_support(adev)) | 362 | if (!amdgpu_device_has_dc_support(adev)) |
| 358 | flush_work(&adev->hotplug_work); | 363 | flush_work(&adev->hotplug_work); |
| 359 | return r; | 364 | return r; |
| 360 | } | 365 | } |
| 366 | adev->irq.installed = true; | ||
| 367 | adev->irq.irq = irq; | ||
| 361 | adev_to_drm(adev)->max_vblank_count = 0x00ffffff; | 368 | adev_to_drm(adev)->max_vblank_count = 0x00ffffff; |
| 362 | 369 | ||
| 363 | DRM_DEBUG("amdgpu: irq initialized.\n"); | 370 | DRM_DEBUG("amdgpu: irq initialized.\n"); |
| @@ -368,7 +375,7 @@ int amdgpu_irq_init(struct amdgpu_device *adev) · 4 unmodified lines | |||
| 368 | void amdgpu_irq_fini_hw(struct amdgpu_device *adev) | 375 | void amdgpu_irq_fini_hw(struct amdgpu_device *adev) |
| 369 | { | 376 | { |
| 370 | if (adev->irq.installed) { | 377 | if (adev->irq.installed) { |
| 371 | drm_irq_uninstall(&adev->ddev); | 378 | free_irq(adev->irq.irq, adev_to_drm(adev)); |
| 372 | adev->irq.installed = false; | 379 | adev->irq.installed = false; |
| 373 | if (adev->irq.msi_enabled) | 380 | if (adev->irq.msi_enabled) |
| 374 | pci_free_irq_vectors(adev->pdev); | 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 | int i, j, k; | 592 | int i, j, k; |
| 586 | 593 | ||
| 587 | if (amdgpu_sriov_vf(adev)) | 594 | if (amdgpu_sriov_vf(adev) || amdgpu_passthrough(adev)) |
| 588 | amdgpu_restore_msix(adev); | 595 | amdgpu_restore_msix(adev); |
| 589 | 596 | ||
| 590 | for (i = 0; i < AMDGPU_IRQ_CLIENTID_MAX; ++i) { | 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 | int amdgpu_irq_get(struct amdgpu_device *adev, struct amdgpu_irq_src *src, | 624 | int amdgpu_irq_get(struct amdgpu_device *adev, struct amdgpu_irq_src *src, |
| 618 | unsigned type) | 625 | unsigned type) |
| 619 | { | 626 | { |
| 620 | if (!adev_to_drm(adev)->irq_enabled) | 627 | if (!adev->irq.installed) |
| 621 | return -ENOENT; | 628 | return -ENOENT; |
| 622 | 629 | ||
| 623 | if (type >= src->num_types) | 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 | int amdgpu_irq_put(struct amdgpu_device *adev, struct amdgpu_irq_src *src, | 654 | int amdgpu_irq_put(struct amdgpu_device *adev, struct amdgpu_irq_src *src, |
| 648 | unsigned type) | 655 | unsigned type) |
| 649 | { | 656 | { |
| 650 | if (!adev_to_drm(adev)->irq_enabled) | 657 | if (!adev->irq.installed) |
| 651 | return -ENOENT; | 658 | return -ENOENT; |
| 652 | 659 | ||
| 653 | if (type >= src->num_types) | 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 | bool amdgpu_irq_enabled(struct amdgpu_device *adev, struct amdgpu_irq_src *src, | 685 | bool amdgpu_irq_enabled(struct amdgpu_device *adev, struct amdgpu_irq_src *src, |
| 679 | unsigned type) | 686 | unsigned type) |
| 680 | { | 687 | { |
| 681 | if (!adev_to_drm(adev)->irq_enabled) | 688 | if (!adev->irq.installed) |
| 682 | return false; | 689 | return false; |
| 683 | 690 | ||
| 684 | if (type >= src->num_types) | 691 | if (type >= src->num_types) |
| @@ -80,6 +80,7 @@ struct amdgpu_irq_src_funcs { · 79 unmodified lines | |||
| 80 | 80 | ||
| 81 | struct amdgpu_irq { | 81 | struct amdgpu_irq { |
| 82 | bool installed; | 82 | bool installed; |
| 83 | unsigned int irq; | ||
| 83 | spinlock_t lock; | 84 | spinlock_t lock; |
| 84 | /* interrupt sources */ | 85 | /* interrupt sources */ |
| 85 | struct amdgpu_irq_client client[AMDGPU_IRQ_CLIENTID_MAX]; | 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 | void amdgpu_irq_disable_all(struct amdgpu_device *adev); | 103 | void amdgpu_irq_disable_all(struct amdgpu_device *adev); |
| 103 | irqreturn_t amdgpu_irq_handler(int irq, void *arg); | ||
| 104 | 104 | ||
| 105 | int amdgpu_irq_init(struct amdgpu_device *adev); | 105 | int amdgpu_irq_init(struct amdgpu_device *adev); |
| 106 | void amdgpu_irq_fini_sw(struct amdgpu_device *adev); | 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 | struct amdgpu_ring *ring = to_amdgpu_ring(job->base.sched); | 128 | struct amdgpu_ring *ring = to_amdgpu_ring(job->base.sched); |
| 129 | struct dma_fence *f; | 129 | struct dma_fence *f; |
| 130 | struct dma_fence *hw_fence; | ||
| 130 | unsigned i; | 131 | unsigned i; |
| 131 | 132 | ||
| 132 | /* use sched fence if available */ | 133 | if (job->hw_fence.ops == NULL) |
| 133 | f = job->base.s_fence ? &job->base.s_fence->finished : job->fence; | 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 | for (i = 0; i < job->num_ibs; ++i) | 140 | for (i = 0; i < job->num_ibs; ++i) |
| 136 | amdgpu_ib_free(ring->adev, &job->ibs[i], f); | 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 | drm_sched_job_cleanup(s_job); | 148 | drm_sched_job_cleanup(s_job); |
| 144 | 149 | ||
| 145 | dma_fence_put(job->fence); | ||
| 146 | amdgpu_sync_free(&job->sync); | 150 | amdgpu_sync_free(&job->sync); |
| 147 | amdgpu_sync_free(&job->sched_sync); | 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 | void amdgpu_job_free(struct amdgpu_job *job) | 160 | void amdgpu_job_free(struct amdgpu_job *job) |
| 152 | { | 161 | { |
| 153 | amdgpu_job_free_resources(job); | 162 | amdgpu_job_free_resources(job); |
| 154 | |||
| 155 | dma_fence_put(job->fence); | ||
| 156 | amdgpu_sync_free(&job->sync); | 163 | amdgpu_sync_free(&job->sync); |
| 157 | amdgpu_sync_free(&job->sched_sync); | 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 | int amdgpu_job_submit(struct amdgpu_job *job, struct drm_sched_entity *entity, | 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 | job->base.sched = &ring->sched; | 197 | job->base.sched = &ring->sched; |
| 186 | r = amdgpu_ib_schedule(ring, job->num_ibs, job->ibs, NULL, fence); | 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 | if (r) | 201 | if (r) |
| 189 | return r; | 202 | return r; |
| 190 | 203 | ||
| 191 | amdgpu_job_free(job); | 204 | amdgpu_job_free(job); |
| 205 | dma_fence_put(*fence); | ||
| 206 | |||
| 192 | return 0; | 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 | if (r) | 261 | if (r) |
| 247 | DRM_ERROR("Error scheduling IBs (%d)\n", r); | 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 | amdgpu_job_free_resources(job); | 270 | amdgpu_job_free_resources(job); |
| 254 | 271 | ||
| 255 | fence = r ? ERR_PTR(r) : fence; | 272 | fence = r ? ERR_PTR(r) : fence; |
| @@ -46,7 +46,8 @@ struct amdgpu_job { · 45 unmodified lines | |||
| 46 | struct amdgpu_sync sync; | 46 | struct amdgpu_sync sync; |
| 47 | struct amdgpu_sync sched_sync; | 47 | struct amdgpu_sync sched_sync; |
| 48 | struct amdgpu_ib *ibs; | 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 | uint32_t preamble_status; | 51 | uint32_t preamble_status; |
| 51 | uint32_t preemption_status; | 52 | uint32_t preemption_status; |
| 52 | uint32_t num_ibs; | 53 | uint32_t num_ibs; |
| @@ -62,6 +63,9 @@ struct amdgpu_job { · 9 unmodified lines | |||
| 62 | /* user fence handling */ | 63 | /* user fence handling */ |
| 63 | uint64_t uf_addr; | 64 | uint64_t uf_addr; |
| 64 | uint64_t uf_sequence; | 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 | int amdgpu_job_alloc(struct amdgpu_device *adev, unsigned num_ibs, | 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 | int i; | 48 | int i; |
| 49 | 49 | ||
| 50 | cancel_delayed_work_sync(&adev->jpeg.idle_work); | ||
| 51 | |||
| 52 | for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) { | 50 | for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) { |
| 53 | if (adev->jpeg.harvest_config & (1 << i)) | 51 | if (adev->jpeg.harvest_config & (1 << i)) |
| 54 | continue; | 52 | continue; |
| @@ -341,27 +341,27 @@ static int amdgpu_firmware_info(struct drm_amdgpu_info_firmware *fw_info, · 340 unmodified lines | |||
| 341 | switch (query_fw->index) { | 341 | switch (query_fw->index) { |
| 342 | case TA_FW_TYPE_PSP_XGMI: | 342 | case TA_FW_TYPE_PSP_XGMI: |
| 343 | fw_info->ver = adev->psp.ta_fw_version; | 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 | break; | 345 | break; |
| 346 | case TA_FW_TYPE_PSP_RAS: | 346 | case TA_FW_TYPE_PSP_RAS: |
| 347 | fw_info->ver = adev->psp.ta_fw_version; | 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 | break; | 349 | break; |
| 350 | case TA_FW_TYPE_PSP_HDCP: | 350 | case TA_FW_TYPE_PSP_HDCP: |
| 351 | fw_info->ver = adev->psp.ta_fw_version; | 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 | break; | 353 | break; |
| 354 | case TA_FW_TYPE_PSP_DTM: | 354 | case TA_FW_TYPE_PSP_DTM: |
| 355 | fw_info->ver = adev->psp.ta_fw_version; | 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 | break; | 357 | break; |
| 358 | case TA_FW_TYPE_PSP_RAP: | 358 | case TA_FW_TYPE_PSP_RAP: |
| 359 | fw_info->ver = adev->psp.ta_fw_version; | 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 | break; | 361 | break; |
| 362 | case TA_FW_TYPE_PSP_SECUREDISPLAY: | 362 | case TA_FW_TYPE_PSP_SECUREDISPLAY: |
| 363 | fw_info->ver = adev->psp.ta_fw_version; | 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 | break; | 365 | break; |
| 366 | default: | 366 | default: |
| 367 | return -EINVAL; | 367 | return -EINVAL; |
| @@ -374,12 +374,12 @@ static int amdgpu_firmware_info(struct drm_amdgpu_info_firmware *fw_info, · 6 unmodified lines | |||
| 374 | fw_info->feature = adev->sdma.instance[query_fw->index].feature_version; | 374 | fw_info->feature = adev->sdma.instance[query_fw->index].feature_version; |
| 375 | break; | 375 | break; |
| 376 | case AMDGPU_INFO_FW_SOS: | 376 | case AMDGPU_INFO_FW_SOS: |
| 377 | fw_info->ver = adev->psp.sos_fw_version; | 377 | fw_info->ver = adev->psp.sos.fw_version; |
| 378 | fw_info->feature = adev->psp.sos_feature_version; | 378 | fw_info->feature = adev->psp.sos.feature_version; |
| 379 | break; | 379 | break; |
| 380 | case AMDGPU_INFO_FW_ASD: | 380 | case AMDGPU_INFO_FW_ASD: |
| 381 | fw_info->ver = adev->psp.asd_fw_version; | 381 | fw_info->ver = adev->psp.asd.fw_version; |
| 382 | fw_info->feature = adev->psp.asd_feature_version; | 382 | fw_info->feature = adev->psp.asd.feature_version; |
| 383 | break; | 383 | break; |
| 384 | case AMDGPU_INFO_FW_DMCU: | 384 | case AMDGPU_INFO_FW_DMCU: |
| 385 | fw_info->ver = adev->dm.dmcu_fw_version; | 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 | fw_info->feature = 0; | 390 | fw_info->feature = 0; |
| 391 | break; | 391 | break; |
| 392 | case AMDGPU_INFO_FW_TOC: | 392 | case AMDGPU_INFO_FW_TOC: |
| 393 | fw_info->ver = adev->psp.toc_fw_version; | 393 | fw_info->ver = adev->psp.toc.fw_version; |
| 394 | fw_info->feature = adev->psp.toc_feature_version; | 394 | fw_info->feature = adev->psp.toc.feature_version; |
| 395 | break; | 395 | break; |
| 396 | default: | 396 | default: |
| 397 | return -EINVAL; | 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 | pasid = 0; | 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 | if (r) | 1183 | if (r) |
| 1184 | goto error_pasid; | 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 | fpriv->prt_va = amdgpu_vm_bo_add(adev, &fpriv->vm, NULL); | 1190 | fpriv->prt_va = amdgpu_vm_bo_add(adev, &fpriv->vm, NULL); |
| 1187 | if (!fpriv->prt_va) { | 1191 | if (!fpriv->prt_va) { |
| 1188 | r = -ENOMEM; | 1192 | r = -ENOMEM; |
| @@ -1210,8 +1214,10 @@ error_vm: · 21 unmodified lines | |||
| 1210 | amdgpu_vm_fini(adev, &fpriv->vm); | 1214 | amdgpu_vm_fini(adev, &fpriv->vm); |
| 1211 | 1215 | ||
| 1212 | error_pasid: | 1216 | error_pasid: |
| 1213 | if (pasid) | 1217 | if (pasid) { |
| 1214 | amdgpu_pasid_free(pasid); | 1218 | amdgpu_pasid_free(pasid); |
| 1219 | amdgpu_vm_set_pasid(adev, &fpriv->vm, 0); | ||
| 1220 | } | ||
| 1215 | 1221 | ||
| 1216 | kfree(fpriv); | 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 | adev->mmhub.ras_if->block = AMDGPU_RAS_BLOCK__MMHUB; | 41 | adev->mmhub.ras_if->block = AMDGPU_RAS_BLOCK__MMHUB; |
| 42 | adev->mmhub.ras_if->type = AMDGPU_RAS_ERROR__MULTI_UNCORRECTABLE; | 42 | adev->mmhub.ras_if->type = AMDGPU_RAS_ERROR__MULTI_UNCORRECTABLE; |
| 43 | adev->mmhub.ras_if->sub_block_index = 0; | 43 | adev->mmhub.ras_if->sub_block_index = 0; |
| 44 | strcpy(adev->mmhub.ras_if->name, "mmhub"); | ||
| 45 | } | 44 | } |
| 46 | ih_info.head = fs_info.head = *adev->mmhub.ras_if; | 45 | ih_info.head = fs_info.head = *adev->mmhub.ras_if; |
| 47 | r = amdgpu_ras_late_init(adev, adev->mmhub.ras_if, | 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 | adev->nbio.ras_if->block = AMDGPU_RAS_BLOCK__PCIE_BIF; | 39 | adev->nbio.ras_if->block = AMDGPU_RAS_BLOCK__PCIE_BIF; |
| 40 | adev->nbio.ras_if->type = AMDGPU_RAS_ERROR__MULTI_UNCORRECTABLE; | 40 | adev->nbio.ras_if->type = AMDGPU_RAS_ERROR__MULTI_UNCORRECTABLE; |
| 41 | adev->nbio.ras_if->sub_block_index = 0; | 41 | adev->nbio.ras_if->sub_block_index = 0; |
| 42 | strcpy(adev->nbio.ras_if->name, "pcie_bif"); | ||
| 43 | } | 42 | } |
| 44 | ih_info.head = fs_info.head = *adev->nbio.ras_if; | 43 | ih_info.head = fs_info.head = *adev->nbio.ras_if; |
| 45 | r = amdgpu_ras_late_init(adev, adev->nbio.ras_if, | 44 | r = amdgpu_ras_late_init(adev, adev->nbio.ras_if, |
| @@ -95,6 +95,7 @@ struct amdgpu_nbio_funcs { · 94 unmodified lines | |||
| 95 | void (*program_aspm)(struct amdgpu_device *adev); | 95 | void (*program_aspm)(struct amdgpu_device *adev); |
| 96 | void (*apply_lc_spc_mode_wa)(struct amdgpu_device *adev); | 96 | void (*apply_lc_spc_mode_wa)(struct amdgpu_device *adev); |
| 97 | void (*apply_l1_link_width_reconfig_wa)(struct amdgpu_device *adev); | 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 | struct amdgpu_nbio { | 101 | struct amdgpu_nbio { |
| @@ -196,7 +196,7 @@ void amdgpu_bo_placement_from_domain(struct amdgpu_bo *abo, u32 domain) · 195 unmodified lines | |||
| 196 | c++; | 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 | placement->num_placement = c; | 201 | placement->num_placement = c; |
| 202 | placement->placement = places; | 202 | placement->placement = places; |
| @@ -731,7 +731,7 @@ retry: · 528 unmodified lines | |||
| 731 | /** | 731 | /** |
| 732 | * amdgpu_bo_add_to_shadow_list - add a BO to the shadow list | 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 | * Insert a BO to the shadow list. | 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 | return -EINVAL; | 913 | return -EINVAL; |
| 914 | 914 | ||
| 915 | /* A shared bo cannot be migrated to VRAM */ | 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 | if (domain & AMDGPU_GEM_DOMAIN_GTT) | 917 | if (domain & AMDGPU_GEM_DOMAIN_GTT) |
| 918 | domain = AMDGPU_GEM_DOMAIN_GTT; | 918 | domain = AMDGPU_GEM_DOMAIN_GTT; |
| 919 | else | 919 | else |
| @@ -947,7 +947,7 @@ int amdgpu_bo_pin_restricted(struct amdgpu_bo *bo, u32 domain, · 27 unmodified lines | |||
| 947 | /* This assumes only APU display buffers are pinned with (VRAM|GTT). | 947 | /* This assumes only APU display buffers are pinned with (VRAM|GTT). |
| 948 | * See function amdgpu_display_supported_domains() | 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 | if (bo->tbo.base.import_attach) | 952 | if (bo->tbo.base.import_attach) |
| 953 | dma_buf_pin(bo->tbo.base.import_attach); | 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 | * @adev: amdgpu device object | 1522 | * @adev: amdgpu device object |
| 1523 | * @domain: allowed :ref:`memory domains <amdgpu_memory_domains>` | 1523 | * @domain: allowed :ref:`memory domains <amdgpu_memory_domains>` |
| 1524 | * | 1524 | * |
| 1525 | * Returns: | 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 | uint32_t domain) | 1529 | uint32_t domain) |
| 1530 | { | 1530 | { |
| 1531 | if (domain == (AMDGPU_GEM_DOMAIN_VRAM | AMDGPU_GEM_DOMAIN_GTT)) { | 1531 | if (domain == (AMDGPU_GEM_DOMAIN_VRAM | AMDGPU_GEM_DOMAIN_GTT)) { |
| @@ -100,7 +100,6 @@ struct amdgpu_bo { · 99 unmodified lines | |||
| 100 | struct ttm_buffer_object tbo; | 100 | struct ttm_buffer_object tbo; |
| 101 | struct ttm_bo_kmap_obj kmap; | 101 | struct ttm_bo_kmap_obj kmap; |
| 102 | u64 flags; | 102 | u64 flags; |
| 103 | unsigned prime_shared_count; | ||
| 104 | /* per VM structure for page tables and with virtual addresses */ | 103 | /* per VM structure for page tables and with virtual addresses */ |
| 105 | struct amdgpu_vm_bo_base *vm_bo; | 104 | struct amdgpu_vm_bo_base *vm_bo; |
| 106 | /* Constant after initialization */ | 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 | void amdgpu_bo_add_to_shadow_list(struct amdgpu_bo_vm *vmbo); | 333 | void amdgpu_bo_add_to_shadow_list(struct amdgpu_bo_vm *vmbo); |
| 335 | int amdgpu_bo_restore_shadow(struct amdgpu_bo *shadow, | 334 | int amdgpu_bo_restore_shadow(struct amdgpu_bo *shadow, |
| 336 | struct dma_fence **fence); | 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 | uint32_t domain); | 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 | * Calculate feedback and reference divider for a given post divider. Makes | 80 | * Calculate feedback and reference divider for a given post divider. Makes |
| 81 | * sure we stay within the limits. | 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, | 83 | static void amdgpu_pll_get_fb_ref_div(struct amdgpu_device *adev, unsigned int nom, |
| 84 | unsigned fb_div_max, unsigned ref_div_max, | 84 | unsigned int den, unsigned int post_div, |
| 85 | unsigned *fb_div, unsigned *ref_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 | /* limit reference * post divider to a maximum */ | 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 | /* get matching reference and feedback divider */ | 95 | /* get matching reference and feedback divider */ |
| 91 | *ref_div = min(max(DIV_ROUND_CLOSEST(den, post_div), 1u), ref_div_max); | 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 | * Try to calculate the PLL parameters to generate the given frequency: | 117 | * Try to calculate the PLL parameters to generate the given frequency: |
| 113 | * dot_clock = (ref_freq * feedback_div) / (ref_div * post_div) | 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 | u32 freq, | 122 | u32 freq, |
| 117 | u32 *dot_clock_p, | 123 | u32 *dot_clock_p, |
| 118 | u32 *fb_div_p, | 124 | u32 *fb_div_p, |
| @@ -199,7 +205,7 @@ void amdgpu_pll_compute(struct amdgpu_pll *pll, · 80 unmodified lines | |||
| 199 | 205 | ||
| 200 | for (post_div = post_div_min; post_div <= post_div_max; ++post_div) { | 206 | for (post_div = post_div_min; post_div <= post_div_max; ++post_div) { |
| 201 | unsigned diff; | 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 | ref_div_max, &fb_div, &ref_div); | 209 | ref_div_max, &fb_div, &ref_div); |
| 204 | diff = abs(target_clock - (pll->reference_freq * fb_div) / | 210 | diff = abs(target_clock - (pll->reference_freq * fb_div) / |
| 205 | (ref_div * post_div)); | 211 | (ref_div * post_div)); |
| @@ -214,7 +220,7 @@ void amdgpu_pll_compute(struct amdgpu_pll *pll, · 8 unmodified lines | |||
| 214 | post_div = post_div_best; | 220 | post_div = post_div_best; |
| 215 | 221 | ||
| 216 | /* get the feedback and reference divider for the optimal value */ | 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 | &fb_div, &ref_div); | 224 | &fb_div, &ref_div); |
| 219 | 225 | ||
| 220 | /* reduce the numbers to a simpler ratio once more */ | 226 | /* reduce the numbers to a simpler ratio once more */ |
| @@ -24,7 +24,8 @@ · 23 unmodified lines | |||
| 24 | #ifndef __AMDGPU_PLL_H__ | 24 | #ifndef __AMDGPU_PLL_H__ |
| 25 | #define __AMDGPU_PLL_H__ | 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 | u32 freq, | 29 | u32 freq, |
| 29 | u32 *dot_clock_p, | 30 | u32 *dot_clock_p, |
| 30 | u32 *fb_div_p, | 31 | u32 *fb_div_p, |
| @@ -24,16 +24,17 @@ · 23 unmodified lines | |||
| 24 | */ | 24 | */ |
| 25 | 25 | ||
| 26 | #include <linux/firmware.h> | 26 | #include <linux/firmware.h> |
| 27 | #include <linux/dma-mapping.h> | ||
| 28 | #include <drm/drm_drv.h> | 27 | #include <drm/drm_drv.h> |
| 29 | 28 | ||
| 30 | #include "amdgpu.h" | 29 | #include "amdgpu.h" |
| 31 | #include "amdgpu_psp.h" | 30 | #include "amdgpu_psp.h" |
| 32 | #include "amdgpu_ucode.h" | 31 | #include "amdgpu_ucode.h" |
| 32 | #include "amdgpu_xgmi.h" | ||
| 33 | #include "soc15_common.h" | 33 | #include "soc15_common.h" |
| 34 | #include "psp_v3_1.h" | 34 | #include "psp_v3_1.h" |
| 35 | #include "psp_v10_0.h" | 35 | #include "psp_v10_0.h" |
| 36 | #include "psp_v11_0.h" | 36 | #include "psp_v11_0.h" |
| 37 | #include "psp_v11_0_8.h" | ||
| 37 | #include "psp_v12_0.h" | 38 | #include "psp_v12_0.h" |
| 38 | #include "psp_v13_0.h" | 39 | #include "psp_v13_0.h" |
| 39 | 40 | ||
| @@ -41,8 +42,6 @@ · 1 unmodified line | |||
| 41 | #include "amdgpu_securedisplay.h" | 42 | #include "amdgpu_securedisplay.h" |
| 42 | #include "amdgpu_atomfirmware.h" | 43 | #include "amdgpu_atomfirmware.h" |
| 43 | 44 | ||
| 44 | #include <drm/drm_drv.h> | ||
| 45 | |||
| 46 | static int psp_sysfs_init(struct amdgpu_device *adev); | 45 | static int psp_sysfs_init(struct amdgpu_device *adev); |
| 47 | static void psp_sysfs_fini(struct amdgpu_device *adev); | 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 | psp_v13_0_set_psp_funcs(psp); | 121 | psp_v13_0_set_psp_funcs(psp); |
| 123 | psp->autoload_supported = true; | 122 | psp->autoload_supported = true; |
| 124 | break; | 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 | default: | 130 | default: |
| 126 | return -EINVAL; | 131 | return -EINVAL; |
| 127 | } | 132 | } |
| @@ -247,6 +252,12 @@ static int psp_sw_init(void *handle) · 119 unmodified lines | |||
| 247 | struct psp_runtime_boot_cfg_entry boot_cfg_entry; | 252 | struct psp_runtime_boot_cfg_entry boot_cfg_entry; |
| 248 | struct psp_memory_training_context *mem_training_ctx = &psp->mem_train_ctx; | 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 | if (!amdgpu_sriov_vf(adev)) { | 261 | if (!amdgpu_sriov_vf(adev)) { |
| 251 | ret = psp_init_microcode(psp); | 262 | ret = psp_init_microcode(psp); |
| 252 | if (ret) { | 263 | if (ret) { |
| @@ -309,25 +320,30 @@ static int psp_sw_init(void *handle) · 56 unmodified lines | |||
| 309 | static int psp_sw_fini(void *handle) | 320 | static int psp_sw_fini(void *handle) |
| 310 | { | 321 | { |
| 311 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; | 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); | 326 | psp_memory_training_fini(psp); |
| 314 | if (adev->psp.sos_fw) { | 327 | if (psp->sos_fw) { |
| 315 | release_firmware(adev->psp.sos_fw); | 328 | release_firmware(psp->sos_fw); |
| 316 | adev->psp.sos_fw = NULL; | 329 | psp->sos_fw = NULL; |
| 317 | } | 330 | } |
| 318 | if (adev->psp.asd_fw) { | 331 | if (psp->asd_fw) { |
| 319 | release_firmware(adev->psp.asd_fw); | 332 | release_firmware(psp->asd_fw); |
| 320 | adev->psp.asd_fw = NULL; | 333 | psp->asd_fw = NULL; |
| 321 | } | 334 | } |
| 322 | if (adev->psp.ta_fw) { | 335 | if (psp->ta_fw) { |
| 323 | release_firmware(adev->psp.ta_fw); | 336 | release_firmware(psp->ta_fw); |
| 324 | adev->psp.ta_fw = NULL; | 337 | psp->ta_fw = NULL; |
| 325 | } | 338 | } |
| 326 | 339 | ||
| 327 | if (adev->asic_type == CHIP_NAVI10 || | 340 | if (adev->asic_type == CHIP_NAVI10 || |
| 328 | adev->asic_type == CHIP_SIENNA_CICHLID) | 341 | adev->asic_type == CHIP_SIENNA_CICHLID) |
| 329 | psp_sysfs_fini(adev); | 342 | psp_sysfs_fini(adev); |
| 330 | 343 | ||
| 344 | kfree(cmd); | ||
| 345 | cmd = NULL; | ||
| 346 | |||
| 331 | return 0; | 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 | return -ETIME; | 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 | static int | 413 | static int |
| 360 | psp_cmd_submit_buf(struct psp_context *psp, | 414 | psp_cmd_submit_buf(struct psp_context *psp, |
| 361 | struct amdgpu_firmware_info *ucode, | 415 | struct amdgpu_firmware_info *ucode, |
| @@ -373,8 +427,6 @@ psp_cmd_submit_buf(struct psp_context *psp, · 11 unmodified lines | |||
| 373 | if (!drm_dev_enter(&psp->adev->ddev, &idx)) | 427 | if (!drm_dev_enter(&psp->adev->ddev, &idx)) |
| 374 | return 0; | 428 | return 0; |
| 375 | 429 | ||
| 376 | mutex_lock(&psp->mutex); | ||
| 377 | |||
| 378 | memset(psp->cmd_buf_mem, 0, PSP_CMD_BUFFER_SIZE); | 430 | memset(psp->cmd_buf_mem, 0, PSP_CMD_BUFFER_SIZE); |
| 379 | 431 | ||
| 380 | memcpy(psp->cmd_buf_mem, cmd, sizeof(struct psp_gfx_cmd_resp)); | 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 | if (!skip_unsupport && (psp->cmd_buf_mem->resp.status || !timeout) && !ras_intr) { | 470 | if (!skip_unsupport && (psp->cmd_buf_mem->resp.status || !timeout) && !ras_intr) { |
| 419 | if (ucode) | 471 | if (ucode) |
| 420 | DRM_WARN("failed to load ucode id (%d) ", | 472 | DRM_WARN("failed to load ucode (%s) ", |
| 421 | ucode->ucode_id); | 473 | amdgpu_ucode_name(ucode->ucode_id)); |
| 422 | DRM_WARN("psp command (0x%X) failed and response status is (0x%X)\n", | 474 | DRM_WARN("psp gfx command (%s) failed and response status is (0x%X)\n", |
| 423 | psp->cmd_buf_mem->cmd_id, | 475 | psp_gfx_cmd_name(psp->cmd_buf_mem->cmd_id), |
| 424 | psp->cmd_buf_mem->resp.status); | 476 | psp->cmd_buf_mem->resp.status); |
| 425 | if (!timeout) { | 477 | if (!timeout) { |
| 426 | ret = -EINVAL; | 478 | ret = -EINVAL; |
| @@ -434,11 +486,26 @@ psp_cmd_submit_buf(struct psp_context *psp, · 7 unmodified lines | |||
| 434 | } | 486 | } |
| 435 | 487 | ||
| 436 | exit: | 488 | exit: |
| 437 | mutex_unlock(&psp->mutex); | ||
| 438 | drm_dev_exit(idx); | 489 | drm_dev_exit(idx); |
| 439 | return ret; | 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 | static void psp_prep_tmr_cmd_buf(struct psp_context *psp, | 509 | static void psp_prep_tmr_cmd_buf(struct psp_context *psp, |
| 443 | struct psp_gfx_cmd_resp *cmd, | 510 | struct psp_gfx_cmd_resp *cmd, |
| 444 | uint64_t tmr_mc, struct amdgpu_bo *tmr_bo) | 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 | uint32_t *tmr_size) | 540 | uint32_t *tmr_size) |
| 474 | { | 541 | { |
| 475 | int ret; | 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 | /* Copy toc to psp firmware private buffer */ | 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 | ret = psp_cmd_submit_buf(psp, NULL, cmd, | 550 | ret = psp_cmd_submit_buf(psp, NULL, cmd, |
| 487 | psp->fence_buf_mc_addr); | 551 | psp->fence_buf_mc_addr); |
| 488 | if (!ret) | 552 | if (!ret) |
| 489 | *tmr_size = psp->cmd_buf_mem->resp.tmr_size; | 553 | *tmr_size = psp->cmd_buf_mem->resp.tmr_size; |
| 490 | kfree(cmd); | 554 | |
| 555 | release_psp_cmd_buf(psp); | ||
| 556 | |||
| 491 | return ret; | 557 | return ret; |
| 492 | } | 558 | } |
| 493 | 559 | ||
| @@ -511,8 +577,8 @@ static int psp_tmr_init(struct psp_context *psp) · 17 unmodified lines | |||
| 511 | /* For ASICs support RLC autoload, psp will parse the toc | 577 | /* For ASICs support RLC autoload, psp will parse the toc |
| 512 | * and calculate the total size of TMR needed */ | 578 | * and calculate the total size of TMR needed */ |
| 513 | if (!amdgpu_sriov_vf(psp->adev) && | 579 | if (!amdgpu_sriov_vf(psp->adev) && |
| 514 | psp->toc_start_addr && | 580 | psp->toc.start_addr && |
| 515 | psp->toc_bin_size && | 581 | psp->toc.size_bytes && |
| 516 | psp->fw_pri_buf) { | 582 | psp->fw_pri_buf) { |
| 517 | ret = psp_load_toc(psp, &tmr_size); | 583 | ret = psp_load_toc(psp, &tmr_size); |
| 518 | if (ret) { | 584 | if (ret) { |
| @@ -552,9 +618,7 @@ static int psp_tmr_load(struct psp_context *psp) · 33 unmodified lines | |||
| 552 | if (amdgpu_sriov_vf(psp->adev) && psp_skip_tmr(psp)) | 618 | if (amdgpu_sriov_vf(psp->adev) && psp_skip_tmr(psp)) |
| 553 | return 0; | 619 | return 0; |
| 554 | 620 | ||
| 555 | cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL); | 621 | cmd = acquire_psp_cmd_buf(psp); |
| 556 | if (!cmd) | ||
| 557 | return -ENOMEM; | ||
| 558 | 622 | ||
| 559 | psp_prep_tmr_cmd_buf(psp, cmd, psp->tmr_mc_addr, psp->tmr_bo); | 623 | psp_prep_tmr_cmd_buf(psp, cmd, psp->tmr_mc_addr, psp->tmr_bo); |
| 560 | DRM_INFO("reserve 0x%lx from 0x%llx for PSP TMR\n", | 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 | ret = psp_cmd_submit_buf(psp, NULL, cmd, | 627 | ret = psp_cmd_submit_buf(psp, NULL, cmd, |
| 564 | psp->fence_buf_mc_addr); | 628 | psp->fence_buf_mc_addr); |
| 565 | 629 | ||
| 566 | kfree(cmd); | 630 | release_psp_cmd_buf(psp); |
| 567 | 631 | ||
| 568 | return ret; | 632 | return ret; |
| 569 | } | 633 | } |
| 570 | 634 | ||
| 571 | static void psp_prep_tmr_unload_cmd_buf(struct psp_context *psp, | 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 | if (amdgpu_sriov_vf(psp->adev)) | 638 | if (amdgpu_sriov_vf(psp->adev)) |
| 575 | cmd->cmd_id = GFX_CMD_ID_DESTROY_VMR; | 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 | static int psp_tmr_unload(struct psp_context *psp) | 644 | static int psp_tmr_unload(struct psp_context *psp) |
| 581 | { | 645 | { |
| 582 | int ret; | 646 | int ret; |
| 583 | struct psp_gfx_cmd_resp *cmd; | 647 | struct psp_gfx_cmd_resp *cmd = acquire_psp_cmd_buf(psp); |
| 584 | |||
| 585 | cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL); | ||
| 586 | if (!cmd) | ||
| 587 | return -ENOMEM; | ||
| 588 | 648 | ||
| 589 | psp_prep_tmr_unload_cmd_buf(psp, cmd); | 649 | psp_prep_tmr_unload_cmd_buf(psp, cmd); |
| 590 | DRM_INFO("free PSP TMR buffer\n"); | 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 | ret = psp_cmd_submit_buf(psp, NULL, cmd, | 652 | ret = psp_cmd_submit_buf(psp, NULL, cmd, |
| 593 | psp->fence_buf_mc_addr); | 653 | psp->fence_buf_mc_addr); |
| 594 | 654 | ||
| 595 | kfree(cmd); | 655 | release_psp_cmd_buf(psp); |
| 596 | 656 | ||
| 597 | return ret; | 657 | return ret; |
| 598 | } | 658 | } |
| @@ -626,9 +686,7 @@ int psp_get_fw_attestation_records_addr(struct psp_context *psp, · 27 unmodified lines | |||
| 626 | if (amdgpu_sriov_vf(psp->adev)) | 686 | if (amdgpu_sriov_vf(psp->adev)) |
| 627 | return 0; | 687 | return 0; |
| 628 | 688 | ||
| 629 | cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL); | 689 | cmd = acquire_psp_cmd_buf(psp); |
| 630 | if (!cmd) | ||
| 631 | return -ENOMEM; | ||
| 632 | 690 | ||
| 633 | cmd->cmd_id = GFX_CMD_ID_GET_FW_ATTESTATION; | 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 | ((uint64_t)cmd->resp.uresp.fwar_db_info.fwar_db_addr_hi << 32); | 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 | return ret; | 703 | return ret; |
| 646 | } | 704 | } |
| @@ -648,13 +706,13 @@ int psp_get_fw_attestation_records_addr(struct psp_context *psp, · 1 unmodified line | |||
| 648 | static int psp_boot_config_get(struct amdgpu_device *adev, uint32_t *boot_cfg) | 706 | static int psp_boot_config_get(struct amdgpu_device *adev, uint32_t *boot_cfg) |
| 649 | { | 707 | { |
| 650 | struct psp_context *psp = &adev->psp; | 708 | struct psp_context *psp = &adev->psp; |
| 651 | struct psp_gfx_cmd_resp *cmd = psp->cmd; | 709 | struct psp_gfx_cmd_resp *cmd; |
| 652 | int ret; | 710 | int ret; |
| 653 | 711 | ||
| 654 | if (amdgpu_sriov_vf(adev)) | 712 | if (amdgpu_sriov_vf(adev)) |
| 655 | return 0; | 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 | cmd->cmd_id = GFX_CMD_ID_BOOT_CFG; | 717 | cmd->cmd_id = GFX_CMD_ID_BOOT_CFG; |
| 660 | cmd->cmd.boot_cfg.sub_cmd = BOOTCFG_CMD_GET; | 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 | (cmd->resp.uresp.boot_cfg.boot_cfg & BOOT_CONFIG_GECC) ? 1 : 0; | 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 | return ret; | 728 | return ret; |
| 669 | } | 729 | } |
| 670 | 730 | ||
| 671 | static int psp_boot_config_set(struct amdgpu_device *adev, uint32_t boot_cfg) | 731 | static int psp_boot_config_set(struct amdgpu_device *adev, uint32_t boot_cfg) |
| 672 | { | 732 | { |
| 733 | int ret; | ||
| 673 | struct psp_context *psp = &adev->psp; | 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 | if (amdgpu_sriov_vf(adev)) | 737 | if (amdgpu_sriov_vf(adev)) |
| 677 | return 0; | 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 | cmd->cmd_id = GFX_CMD_ID_BOOT_CFG; | 742 | cmd->cmd_id = GFX_CMD_ID_BOOT_CFG; |
| 682 | cmd->cmd.boot_cfg.sub_cmd = BOOTCFG_CMD_SET; | 743 | cmd->cmd.boot_cfg.sub_cmd = BOOTCFG_CMD_SET; |
| 683 | cmd->cmd.boot_cfg.boot_config = boot_cfg; | 744 | cmd->cmd.boot_cfg.boot_config = boot_cfg; |
| 684 | cmd->cmd.boot_cfg.boot_config_valid = boot_cfg; | 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 | static int psp_rl_load(struct amdgpu_device *adev) | 754 | static int psp_rl_load(struct amdgpu_device *adev) |
| 690 | { | 755 | { |
| 756 | int ret; | ||
| 691 | struct psp_context *psp = &adev->psp; | 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 | return 0; | 761 | return 0; |
| 696 | 762 | ||
| 697 | memset(psp->fw_pri_buf, 0, PSP_1_MEG); | 763 | cmd = acquire_psp_cmd_buf(psp); |
| 698 | memcpy(psp->fw_pri_buf, psp->rl_start_addr, psp->rl_bin_size); | ||
| 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 | cmd->cmd_id = GFX_CMD_ID_LOAD_IP_FW; | 768 | cmd->cmd_id = GFX_CMD_ID_LOAD_IP_FW; |
| 703 | cmd->cmd.cmd_load_ip_fw.fw_phy_addr_lo = lower_32_bits(psp->fw_pri_mc_addr); | 769 | cmd->cmd.cmd_load_ip_fw.fw_phy_addr_lo = lower_32_bits(psp->fw_pri_mc_addr); |
| 704 | cmd->cmd.cmd_load_ip_fw.fw_phy_addr_hi = upper_32_bits(psp->fw_pri_mc_addr); | 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 | cmd->cmd.cmd_load_ip_fw.fw_type = GFX_FW_TYPE_REG_LIST; | 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 | static void psp_prep_asd_load_cmd_buf(struct psp_gfx_cmd_resp *cmd, | 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 | * add workaround to bypass it for sriov now. | 800 | * add workaround to bypass it for sriov now. |
| 731 | * TODO: add version check to make it common | 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 | return 0; | 804 | return 0; |
| 735 | 805 | ||
| 736 | cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL); | 806 | cmd = acquire_psp_cmd_buf(psp); |
| 737 | if (!cmd) | ||
| 738 | return -ENOMEM; | ||
| 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 | psp_prep_asd_load_cmd_buf(cmd, psp->fw_pri_mc_addr, | 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 | ret = psp_cmd_submit_buf(psp, NULL, cmd, | 813 | ret = psp_cmd_submit_buf(psp, NULL, cmd, |
| 746 | psp->fence_buf_mc_addr); | 814 | psp->fence_buf_mc_addr); |
| @@ -749,7 +817,7 @@ static int psp_asd_load(struct psp_context *psp) · 2 unmodified lines | |||
| 749 | psp->asd_context.session_id = cmd->resp.session_id; | 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 | return ret; | 822 | return ret; |
| 755 | } | 823 | } |
| @@ -772,9 +840,7 @@ static int psp_asd_unload(struct psp_context *psp) · 16 unmodified lines | |||
| 772 | if (!psp->asd_context.asd_initialized) | 840 | if (!psp->asd_context.asd_initialized) |
| 773 | return 0; | 841 | return 0; |
| 774 | 842 | ||
| 775 | cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL); | 843 | cmd = acquire_psp_cmd_buf(psp); |
| 776 | if (!cmd) | ||
| 777 | return -ENOMEM; | ||
| 778 | 844 | ||
| 779 | psp_prep_ta_unload_cmd_buf(cmd, psp->asd_context.session_id); | 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 | if (!ret) | 849 | if (!ret) |
| 784 | psp->asd_context.asd_initialized = false; | 850 | psp->asd_context.asd_initialized = false; |
| 785 | 851 | ||
| 786 | kfree(cmd); | 852 | release_psp_cmd_buf(psp); |
| 787 | 853 | ||
| 788 | return ret; | 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 | int psp_reg_program(struct psp_context *psp, enum psp_reg_prog_id reg, | 865 | int psp_reg_program(struct psp_context *psp, enum psp_reg_prog_id reg, |
| 800 | uint32_t value) | 866 | uint32_t value) |
| 801 | { | 867 | { |
| 802 | struct psp_gfx_cmd_resp *cmd = NULL; | 868 | struct psp_gfx_cmd_resp *cmd; |
| 803 | int ret = 0; | 869 | int ret = 0; |
| 804 | 870 | ||
| 805 | if (reg >= PSP_REG_LAST) | 871 | if (reg >= PSP_REG_LAST) |
| 806 | return -EINVAL; | 872 | return -EINVAL; |
| 807 | 873 | ||
| 808 | cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL); | 874 | cmd = acquire_psp_cmd_buf(psp); |
| 809 | if (!cmd) | ||
| 810 | return -ENOMEM; | ||
| 811 | 875 | ||
| 812 | psp_prep_reg_prog_cmd_buf(cmd, reg, value); | 876 | psp_prep_reg_prog_cmd_buf(cmd, reg, value); |
| 813 | ret = psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr); | 877 | ret = psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr); |
| 814 | if (ret) | 878 | if (ret) |
| 815 | DRM_ERROR("PSP failed to program reg id %d", reg); | 879 | DRM_ERROR("PSP failed to program reg id %d", reg); |
| 816 | 880 | ||
| 817 | kfree(cmd); | 881 | release_psp_cmd_buf(psp); |
| 882 | |||
| 818 | return ret; | 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 | cmd->cmd.cmd_load_ta.cmd_buf_len = ta_shared_size; | 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 | int ret; | 906 | int ret; |
| 840 | 907 | ||
| 841 | /* | 908 | /* |
| 842 | * Allocate 16k memory aligned to 4k from Frame Buffer (local | 909 | * Allocate 16k memory aligned to 4k from Frame Buffer (local |
| 843 | * physical) for xgmi ta <-> Driver | 910 | * physical) for ta to host memory |
| 844 | */ | 911 | */ |
| 845 | ret = amdgpu_bo_create_kernel(psp->adev, PSP_XGMI_SHARED_MEM_SIZE, | 912 | ret = amdgpu_bo_create_kernel(psp->adev, shared_mem_size, PAGE_SIZE, |
| 846 | PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM, | 913 | AMDGPU_GEM_DOMAIN_VRAM, |
| 847 | &psp->xgmi_context.xgmi_shared_bo, | 914 | &mem_ctx->shared_bo, |
| 848 | &psp->xgmi_context.xgmi_shared_mc_addr, | 915 | &mem_ctx->shared_mc_addr, |
| 849 | &psp->xgmi_context.xgmi_shared_buf); | 916 | &mem_ctx->shared_buf); |
| 850 | 917 | ||
| 851 | return ret; | 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 | static void psp_prep_ta_invoke_cmd_buf(struct psp_gfx_cmd_resp *cmd, | 933 | static void psp_prep_ta_invoke_cmd_buf(struct psp_gfx_cmd_resp *cmd, |
| 855 | uint32_t ta_cmd_id, | 934 | uint32_t ta_cmd_id, |
| 856 | uint32_t session_id) | 935 | uint32_t session_id) |
| @@ -865,18 +944,14 @@ static int psp_ta_invoke(struct psp_context *psp, · 8 unmodified lines | |||
| 865 | uint32_t session_id) | 944 | uint32_t session_id) |
| 866 | { | 945 | { |
| 867 | int ret; | 946 | int ret; |
| 868 | struct psp_gfx_cmd_resp *cmd; | 947 | struct psp_gfx_cmd_resp *cmd = acquire_psp_cmd_buf(psp); |
| 869 | |||
| 870 | cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL); | ||
| 871 | if (!cmd) | ||
| 872 | return -ENOMEM; | ||
| 873 | 948 | ||
| 874 | psp_prep_ta_invoke_cmd_buf(cmd, ta_cmd_id, session_id); | 949 | psp_prep_ta_invoke_cmd_buf(cmd, ta_cmd_id, session_id); |
| 875 | 950 | ||
| 876 | ret = psp_cmd_submit_buf(psp, NULL, cmd, | 951 | ret = psp_cmd_submit_buf(psp, NULL, cmd, |
| 877 | psp->fence_buf_mc_addr); | 952 | psp->fence_buf_mc_addr); |
| 878 | 953 | ||
| 879 | kfree(cmd); | 954 | release_psp_cmd_buf(psp); |
| 880 | 955 | ||
| 881 | return ret; | 956 | return ret; |
| 882 | } | 957 | } |
| @@ -890,27 +965,25 @@ static int psp_xgmi_load(struct psp_context *psp) · 7 unmodified lines | |||
| 890 | * TODO: bypass the loading in sriov for now | 965 | * TODO: bypass the loading in sriov for now |
| 891 | */ | 966 | */ |
| 892 | 967 | ||
| 893 | cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL); | 968 | cmd = acquire_psp_cmd_buf(psp); |
| 894 | if (!cmd) | ||
| 895 | return -ENOMEM; | ||
| 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 | psp_prep_ta_load_cmd_buf(cmd, | 972 | psp_prep_ta_load_cmd_buf(cmd, |
| 900 | psp->fw_pri_mc_addr, | 973 | psp->fw_pri_mc_addr, |
| 901 | psp->ta_xgmi_ucode_size, | 974 | psp->xgmi.size_bytes, |
| 902 | psp->xgmi_context.xgmi_shared_mc_addr, | 975 | psp->xgmi_context.context.mem_context.shared_mc_addr, |
| 903 | PSP_XGMI_SHARED_MEM_SIZE); | 976 | PSP_XGMI_SHARED_MEM_SIZE); |
| 904 | 977 | ||
| 905 | ret = psp_cmd_submit_buf(psp, NULL, cmd, | 978 | ret = psp_cmd_submit_buf(psp, NULL, cmd, |
| 906 | psp->fence_buf_mc_addr); | 979 | psp->fence_buf_mc_addr); |
| 907 | 980 | ||
| 908 | if (!ret) { | 981 | if (!ret) { |
| 909 | psp->xgmi_context.initialized = 1; | 982 | psp->xgmi_context.context.initialized = true; |
| 910 | psp->xgmi_context.session_id = cmd->resp.session_id; | 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 | return ret; | 988 | return ret; |
| 916 | } | 989 | } |
| @@ -930,57 +1003,56 @@ static int psp_xgmi_unload(struct psp_context *psp) · 13 unmodified lines | |||
| 930 | * TODO: bypass the unloading in sriov for now | 1003 | * TODO: bypass the unloading in sriov for now |
| 931 | */ | 1004 | */ |
| 932 | 1005 | ||
| 933 | cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL); | 1006 | cmd = acquire_psp_cmd_buf(psp); |
| 934 | if (!cmd) | ||
| 935 | return -ENOMEM; | ||
| 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 | ret = psp_cmd_submit_buf(psp, NULL, cmd, | 1010 | ret = psp_cmd_submit_buf(psp, NULL, cmd, |
| 940 | psp->fence_buf_mc_addr); | 1011 | psp->fence_buf_mc_addr); |
| 941 | 1012 | ||
| 942 | kfree(cmd); | 1013 | release_psp_cmd_buf(psp); |
| 943 | 1014 | ||
| 944 | return ret; | 1015 | return ret; |
| 945 | } | 1016 | } |
| 946 | 1017 | ||
| 947 | int psp_xgmi_invoke(struct psp_context *psp, uint32_t ta_cmd_id) | 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 | int psp_xgmi_terminate(struct psp_context *psp) | 1023 | int psp_xgmi_terminate(struct psp_context *psp) |
| 953 | { | 1024 | { |
| 954 | int ret; | 1025 | int ret; |
| 955 | 1026 | ||
| 956 | if (!psp->xgmi_context.initialized) | 1027 | if (!psp->xgmi_context.context.initialized) |
| 957 | return 0; | 1028 | return 0; |
| 958 | 1029 | ||
| 959 | ret = psp_xgmi_unload(psp); | 1030 | ret = psp_xgmi_unload(psp); |
| 960 | if (ret) | 1031 | if (ret) |
| 961 | return ret; | 1032 | return ret; |
| 962 | 1033 | ||
| 963 | psp->xgmi_context.initialized = 0; | 1034 | psp->xgmi_context.context.initialized = false; |
| 964 | 1035 | ||
| 965 | /* free xgmi shared memory */ | 1036 | /* free xgmi shared memory */ |
| 966 | amdgpu_bo_free_kernel(&psp->xgmi_context.xgmi_shared_bo, | 1037 | psp_ta_free_shared_buf(&psp->xgmi_context.context.mem_context); |
| 967 | &psp->xgmi_context.xgmi_shared_mc_addr, | ||
| 968 | &psp->xgmi_context.xgmi_shared_buf); | ||
| 969 | 1038 | ||
| 970 | return 0; | 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 | struct ta_xgmi_shared_memory *xgmi_cmd; | 1044 | struct ta_xgmi_shared_memory *xgmi_cmd; |
| 976 | int ret; | 1045 | int ret; |
| 977 | 1046 | ||
| 978 | if (!psp->adev->psp.ta_fw || | 1047 | if (!psp->ta_fw || |
| 979 | !psp->adev->psp.ta_xgmi_ucode_size || | 1048 | !psp->xgmi.size_bytes || |
| 980 | !psp->adev->psp.ta_xgmi_start_addr) | 1049 | !psp->xgmi.start_addr) |
| 981 | return -ENOENT; | 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 | ret = psp_xgmi_init_shared_buf(psp); | 1056 | ret = psp_xgmi_init_shared_buf(psp); |
| 985 | if (ret) | 1057 | if (ret) |
| 986 | return ret; | 1058 | return ret; |
| @@ -991,9 +1063,11 @@ int psp_xgmi_initialize(struct psp_context *psp) · 4 unmodified lines | |||
| 991 | if (ret) | 1063 | if (ret) |
| 992 | return ret; | 1064 | return ret; |
| 993 | 1065 | ||
| 1066 | invoke: | ||
| 994 | /* Initialize XGMI session */ | 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 | memset(xgmi_cmd, 0, sizeof(struct ta_xgmi_shared_memory)); | 1069 | memset(xgmi_cmd, 0, sizeof(struct ta_xgmi_shared_memory)); |
| 1070 | xgmi_cmd->flag_extend_link_record = set_extended_data; | ||
| 997 | xgmi_cmd->cmd_id = TA_COMMAND_XGMI__INITIALIZE; | 1071 | xgmi_cmd->cmd_id = TA_COMMAND_XGMI__INITIALIZE; |
| 998 | 1072 | ||
| 999 | ret = psp_xgmi_invoke(psp, xgmi_cmd->cmd_id); | 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 | struct ta_xgmi_shared_memory *xgmi_cmd; | 1080 | struct ta_xgmi_shared_memory *xgmi_cmd; |
| 1007 | int ret; | 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 | memset(xgmi_cmd, 0, sizeof(struct ta_xgmi_shared_memory)); | 1084 | memset(xgmi_cmd, 0, sizeof(struct ta_xgmi_shared_memory)); |
| 1011 | 1085 | ||
| 1012 | xgmi_cmd->cmd_id = TA_COMMAND_XGMI__GET_HIVE_ID; | 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 | struct ta_xgmi_shared_memory *xgmi_cmd; | 1100 | struct ta_xgmi_shared_memory *xgmi_cmd; |
| 1027 | int ret; | 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 | memset(xgmi_cmd, 0, sizeof(struct ta_xgmi_shared_memory)); | 1104 | memset(xgmi_cmd, 0, sizeof(struct ta_xgmi_shared_memory)); |
| 1031 | 1105 | ||
| 1032 | xgmi_cmd->cmd_id = TA_COMMAND_XGMI__GET_NODE_ID; | 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 | return 0; | 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 | int psp_xgmi_get_topology_info(struct psp_context *psp, | 1170 | int psp_xgmi_get_topology_info(struct psp_context *psp, |
| 1045 | int number_devices, | 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 | struct ta_xgmi_shared_memory *xgmi_cmd; | 1175 | struct ta_xgmi_shared_memory *xgmi_cmd; |
| 1049 | struct ta_xgmi_cmd_get_topology_info_input *topology_info_input; | 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 | if (!topology || topology->num_nodes > TA_XGMI__MAX_CONNECTED_NODES) | 1181 | if (!topology || topology->num_nodes > TA_XGMI__MAX_CONNECTED_NODES) |
| 1055 | return -EINVAL; | 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 | memset(xgmi_cmd, 0, sizeof(struct ta_xgmi_shared_memory)); | 1185 | memset(xgmi_cmd, 0, sizeof(struct ta_xgmi_shared_memory)); |
| 1186 | xgmi_cmd->flag_extend_link_record = get_extended_data; | ||
| 1059 | 1187 | ||
| 1060 | /* Fill in the shared memory with topology information as input */ | 1188 | /* Fill in the shared memory with topology information as input */ |
| 1061 | topology_info_input = &xgmi_cmd->xgmi_in_message.get_topology_info; | 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 | topology_info_output = &xgmi_cmd->xgmi_out_message.get_topology_info; | 1206 | topology_info_output = &xgmi_cmd->xgmi_out_message.get_topology_info; |
| 1079 | topology->num_nodes = xgmi_cmd->xgmi_out_message.get_topology_info.num_nodes; | 1207 | topology->num_nodes = xgmi_cmd->xgmi_out_message.get_topology_info.num_nodes; |
| 1080 | for (i = 0; i < topology->num_nodes; i++) { | 1208 | for (i = 0; i < topology->num_nodes; i++) { |
| 1081 | topology->nodes[i].node_id = topology_info_output->nodes[i].node_id; | 1209 | /* extended data will either be 0 or equal to non-extended data */ |
| 1082 | topology->nodes[i].num_hops = topology_info_output->nodes[i].num_hops; | 1210 | if (topology_info_output->nodes[i].num_hops) |
| 1083 | topology->nodes[i].is_sharing_enabled = topology_info_output->nodes[i].is_sharing_enabled; | 1211 | topology->nodes[i].num_hops = topology_info_output->nodes[i].num_hops; |
| 1084 | topology->nodes[i].sdma_engine = topology_info_output->nodes[i].sdma_engine; | 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 | return 0; | 1250 | return 0; |
| @@ -1098,7 +1261,7 @@ int psp_xgmi_set_topology_info(struct psp_context *psp, · 10 unmodified lines | |||
| 1098 | if (!topology || topology->num_nodes > TA_XGMI__MAX_CONNECTED_NODES) | 1261 | if (!topology || topology->num_nodes > TA_XGMI__MAX_CONNECTED_NODES) |
| 1099 | return -EINVAL; | 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 | memset(xgmi_cmd, 0, sizeof(struct ta_xgmi_shared_memory)); | 1265 | memset(xgmi_cmd, 0, sizeof(struct ta_xgmi_shared_memory)); |
| 1103 | 1266 | ||
| 1104 | topology_info_input = &xgmi_cmd->xgmi_in_message.get_topology_info; | 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 | // ras begin | 1282 | // ras begin |
| 1120 | static int psp_ras_init_shared_buf(struct psp_context *psp) | 1283 | static int psp_ras_init_shared_buf(struct psp_context *psp) |
| 1121 | { | 1284 | { |
| 1122 | int ret; | 1285 | return psp_ta_init_shared_buf(psp, &psp->ras_context.context.mem_context, |
| 1123 | 1286 | PSP_RAS_SHARED_MEM_SIZE); | |
| 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; | ||
| 1135 | } | 1287 | } |
| 1136 | 1288 | ||
| 1137 | static int psp_ras_load(struct psp_context *psp) | 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 | if (amdgpu_sriov_vf(psp->adev)) | 1298 | if (amdgpu_sriov_vf(psp->adev)) |
| 1147 | return 0; | 1299 | return 0; |
| 1148 | 1300 | ||
| 1149 | cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL); | 1301 | psp_copy_fw(psp, psp->ras.start_addr, psp->ras.size_bytes); |
| 1150 | if (!cmd) | ||
| 1151 | return -ENOMEM; | ||
| 1152 | |||
| 1153 | psp_copy_fw(psp, psp->ta_ras_start_addr, psp->ta_ras_ucode_size); | ||
| 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 | if (psp->adev->gmc.xgmi.connected_to_cpu) | 1305 | if (psp->adev->gmc.xgmi.connected_to_cpu) |
| 1158 | ras_cmd->ras_in_message.init_flags.poison_mode_en = 1; | 1306 | ras_cmd->ras_in_message.init_flags.poison_mode_en = 1; |
| 1159 | else | 1307 | else |
| 1160 | ras_cmd->ras_in_message.init_flags.dgpu_mode = 1; | 1308 | ras_cmd->ras_in_message.init_flags.dgpu_mode = 1; |
| 1161 | 1309 | ||
| 1310 | cmd = acquire_psp_cmd_buf(psp); | ||
| 1311 | |||
| 1162 | psp_prep_ta_load_cmd_buf(cmd, | 1312 | psp_prep_ta_load_cmd_buf(cmd, |
| 1163 | psp->fw_pri_mc_addr, | 1313 | psp->fw_pri_mc_addr, |
| 1164 | psp->ta_ras_ucode_size, | 1314 | psp->ras.size_bytes, |
| 1165 | psp->ras.ras_shared_mc_addr, | 1315 | psp->ras_context.context.mem_context.shared_mc_addr, |
| 1166 | PSP_RAS_SHARED_MEM_SIZE); | 1316 | PSP_RAS_SHARED_MEM_SIZE); |
| 1167 | 1317 | ||
| 1168 | ret = psp_cmd_submit_buf(psp, NULL, cmd, | 1318 | ret = psp_cmd_submit_buf(psp, NULL, cmd, |
| 1169 | psp->fence_buf_mc_addr); | 1319 | psp->fence_buf_mc_addr); |
| 1170 | 1320 | ||
| 1171 | if (!ret) { | 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 | if (!ras_cmd->ras_status) | 1324 | if (!ras_cmd->ras_status) |
| 1175 | psp->ras.ras_initialized = true; | 1325 | psp->ras_context.context.initialized = true; |
| 1176 | else | 1326 | else |
| 1177 | dev_warn(psp->adev->dev, "RAS Init Status: 0x%X\n", ras_cmd->ras_status); | 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 | if (ret || ras_cmd->ras_status) | 1332 | if (ret || ras_cmd->ras_status) |
| 1181 | amdgpu_ras_fini(psp->adev); | 1333 | amdgpu_ras_fini(psp->adev); |
| 1182 | 1334 | ||
| 1183 | kfree(cmd); | ||
| 1184 | |||
| 1185 | return ret; | 1335 | return ret; |
| 1186 | } | 1336 | } |
| 1187 | 1337 | ||
| @@ -1196,16 +1346,14 @@ static int psp_ras_unload(struct psp_context *psp) · 8 unmodified lines | |||
| 1196 | if (amdgpu_sriov_vf(psp->adev)) | 1346 | if (amdgpu_sriov_vf(psp->adev)) |
| 1197 | return 0; | 1347 | return 0; |
| 1198 | 1348 | ||
| 1199 | cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL); | 1349 | cmd = acquire_psp_cmd_buf(psp); |
| 1200 | if (!cmd) | ||
| 1201 | return -ENOMEM; | ||
| 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 | ret = psp_cmd_submit_buf(psp, NULL, cmd, | 1353 | ret = psp_cmd_submit_buf(psp, NULL, cmd, |
| 1206 | psp->fence_buf_mc_addr); | 1354 | psp->fence_buf_mc_addr); |
| 1207 | 1355 | ||
| 1208 | kfree(cmd); | 1356 | release_psp_cmd_buf(psp); |
| 1209 | 1357 | ||
| 1210 | return ret; | 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 | struct ta_ras_shared_memory *ras_cmd; | 1363 | struct ta_ras_shared_memory *ras_cmd; |
| 1216 | int ret; | 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 | * TODO: bypass the loading in sriov for now | 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 | if (amdgpu_sriov_vf(psp->adev)) | 1371 | if (amdgpu_sriov_vf(psp->adev)) |
| 1224 | return 0; | 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 | if (amdgpu_ras_intr_triggered()) | 1376 | if (amdgpu_ras_intr_triggered()) |
| 1229 | return ret; | 1377 | return ret; |
| @@ -1279,10 +1427,10 @@ int psp_ras_enable_features(struct psp_context *psp, · 49 unmodified lines | |||
| 1279 | struct ta_ras_shared_memory *ras_cmd; | 1427 | struct ta_ras_shared_memory *ras_cmd; |
| 1280 | int ret; | 1428 | int ret; |
| 1281 | 1429 | ||
| 1282 | if (!psp->ras.ras_initialized) | 1430 | if (!psp->ras_context.context.initialized) |
| 1283 | return -EINVAL; | 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 | memset(ras_cmd, 0, sizeof(struct ta_ras_shared_memory)); | 1434 | memset(ras_cmd, 0, sizeof(struct ta_ras_shared_memory)); |
| 1287 | 1435 | ||
| 1288 | if (enable) | 1436 | if (enable) |
| @@ -1309,19 +1457,17 @@ static int psp_ras_terminate(struct psp_context *psp) · 20 unmodified lines | |||
| 1309 | if (amdgpu_sriov_vf(psp->adev)) | 1457 | if (amdgpu_sriov_vf(psp->adev)) |
| 1310 | return 0; | 1458 | return 0; |
| 1311 | 1459 | ||
| 1312 | if (!psp->ras.ras_initialized) | 1460 | if (!psp->ras_context.context.initialized) |
| 1313 | return 0; | 1461 | return 0; |
| 1314 | 1462 | ||
| 1315 | ret = psp_ras_unload(psp); | 1463 | ret = psp_ras_unload(psp); |
| 1316 | if (ret) | 1464 | if (ret) |
| 1317 | return ret; | 1465 | return ret; |
| 1318 | 1466 | ||
| 1319 | psp->ras.ras_initialized = false; | 1467 | psp->ras_context.context.initialized = false; |
| 1320 | 1468 | ||
| 1321 | /* free ras shared memory */ | 1469 | /* free ras shared memory */ |
| 1322 | amdgpu_bo_free_kernel(&psp->ras.ras_shared_bo, | 1470 | psp_ta_free_shared_buf(&psp->ras_context.context.mem_context); |
| 1323 | &psp->ras.ras_shared_mc_addr, | ||
| 1324 | &psp->ras.ras_shared_buf); | ||
| 1325 | 1471 | ||
| 1326 | return 0; | 1472 | return 0; |
| 1327 | } | 1473 | } |
| @@ -1338,8 +1484,8 @@ static int psp_ras_initialize(struct psp_context *psp) · 10 unmodified lines | |||
| 1338 | if (amdgpu_sriov_vf(adev)) | 1484 | if (amdgpu_sriov_vf(adev)) |
| 1339 | return 0; | 1485 | return 0; |
| 1340 | 1486 | ||
| 1341 | if (!adev->psp.ta_ras_ucode_size || | 1487 | if (!adev->psp.ras.size_bytes || |
| 1342 | !adev->psp.ta_ras_start_addr) { | 1488 | !adev->psp.ras.start_addr) { |
| 1343 | dev_info(adev->dev, "RAS: optional ras ta ucode is not available\n"); | 1489 | dev_info(adev->dev, "RAS: optional ras ta ucode is not available\n"); |
| 1344 | return 0; | 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 | ret = psp_ras_init_shared_buf(psp); | 1535 | ret = psp_ras_init_shared_buf(psp); |
| 1390 | if (ret) | 1536 | if (ret) |
| 1391 | return ret; | 1537 | return ret; |
| @@ -1404,10 +1550,10 @@ int psp_ras_trigger_error(struct psp_context *psp, · 12 unmodified lines | |||
| 1404 | struct ta_ras_shared_memory *ras_cmd; | 1550 | struct ta_ras_shared_memory *ras_cmd; |
| 1405 | int ret; | 1551 | int ret; |
| 1406 | 1552 | ||
| 1407 | if (!psp->ras.ras_initialized) | 1553 | if (!psp->ras_context.context.initialized) |
| 1408 | return -EINVAL; | 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 | memset(ras_cmd, 0, sizeof(struct ta_ras_shared_memory)); | 1557 | memset(ras_cmd, 0, sizeof(struct ta_ras_shared_memory)); |
| 1412 | 1558 | ||
| 1413 | ras_cmd->cmd_id = TA_RAS_COMMAND__TRIGGER_ERROR; | 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 | // HDCP start | 1575 | // HDCP start |
| 1430 | static int psp_hdcp_init_shared_buf(struct psp_context *psp) | 1576 | static int psp_hdcp_init_shared_buf(struct psp_context *psp) |
| 1431 | { | 1577 | { |
| 1432 | int ret; | 1578 | return psp_ta_init_shared_buf(psp, &psp->hdcp_context.context.mem_context, |
| 1433 | 1579 | PSP_HDCP_SHARED_MEM_SIZE); | |
| 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; | ||
| 1445 | } | 1580 | } |
| 1446 | 1581 | ||
| 1447 | static int psp_hdcp_load(struct psp_context *psp) | 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 | if (amdgpu_sriov_vf(psp->adev)) | 1590 | if (amdgpu_sriov_vf(psp->adev)) |
| 1456 | return 0; | 1591 | return 0; |
| 1457 | 1592 | ||
| 1458 | cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL); | 1593 | psp_copy_fw(psp, psp->hdcp.start_addr, |
| 1459 | if (!cmd) | 1594 | psp->hdcp.size_bytes); |
| 1460 | return -ENOMEM; | ||
| 1461 | 1595 | ||
| 1462 | psp_copy_fw(psp, psp->ta_hdcp_start_addr, | 1596 | cmd = acquire_psp_cmd_buf(psp); |
| 1463 | psp->ta_hdcp_ucode_size); | ||
| 1464 | 1597 | ||
| 1465 | psp_prep_ta_load_cmd_buf(cmd, | 1598 | psp_prep_ta_load_cmd_buf(cmd, |
| 1466 | psp->fw_pri_mc_addr, | 1599 | psp->fw_pri_mc_addr, |
| 1467 | psp->ta_hdcp_ucode_size, | 1600 | psp->hdcp.size_bytes, |
| 1468 | psp->hdcp_context.hdcp_shared_mc_addr, | 1601 | psp->hdcp_context.context.mem_context.shared_mc_addr, |
| 1469 | PSP_HDCP_SHARED_MEM_SIZE); | 1602 | PSP_HDCP_SHARED_MEM_SIZE); |
| 1470 | 1603 | ||
| 1471 | ret = psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr); | 1604 | ret = psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr); |
| 1472 | 1605 | ||
| 1473 | if (!ret) { | 1606 | if (!ret) { |
| 1474 | psp->hdcp_context.hdcp_initialized = true; | 1607 | psp->hdcp_context.context.initialized = true; |
| 1475 | psp->hdcp_context.session_id = cmd->resp.session_id; | 1608 | psp->hdcp_context.context.session_id = cmd->resp.session_id; |
| 1476 | mutex_init(&psp->hdcp_context.mutex); | 1609 | mutex_init(&psp->hdcp_context.mutex); |
| 1477 | } | 1610 | } |
| 1478 | 1611 | ||
| 1479 | kfree(cmd); | 1612 | release_psp_cmd_buf(psp); |
| 1480 | 1613 | ||
| 1481 | return ret; | 1614 | return ret; |
| 1482 | } | 1615 | } |
| @@ -1490,13 +1623,13 @@ static int psp_hdcp_initialize(struct psp_context *psp) · 7 unmodified lines | |||
| 1490 | if (amdgpu_sriov_vf(psp->adev)) | 1623 | if (amdgpu_sriov_vf(psp->adev)) |
| 1491 | return 0; | 1624 | return 0; |
| 1492 | 1625 | ||
| 1493 | if (!psp->adev->psp.ta_hdcp_ucode_size || | 1626 | if (!psp->hdcp.size_bytes || |
| 1494 | !psp->adev->psp.ta_hdcp_start_addr) { | 1627 | !psp->hdcp.start_addr) { |
| 1495 | dev_info(psp->adev->dev, "HDCP: optional hdcp ta ucode is not available\n"); | 1628 | dev_info(psp->adev->dev, "HDCP: optional hdcp ta ucode is not available\n"); |
| 1496 | return 0; | 1629 | return 0; |
| 1497 | } | 1630 | } |
| 1498 | 1631 | ||
| 1499 | if (!psp->hdcp_context.hdcp_initialized) { | 1632 | if (!psp->hdcp_context.context.initialized) { |
| 1500 | ret = psp_hdcp_init_shared_buf(psp); | 1633 | ret = psp_hdcp_init_shared_buf(psp); |
| 1501 | if (ret) | 1634 | if (ret) |
| 1502 | return ret; | 1635 | return ret; |
| @@ -1520,15 +1653,13 @@ static int psp_hdcp_unload(struct psp_context *psp) · 17 unmodified lines | |||
| 1520 | if (amdgpu_sriov_vf(psp->adev)) | 1653 | if (amdgpu_sriov_vf(psp->adev)) |
| 1521 | return 0; | 1654 | return 0; |
| 1522 | 1655 | ||
| 1523 | cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL); | 1656 | cmd = acquire_psp_cmd_buf(psp); |
| 1524 | if (!cmd) | ||
| 1525 | return -ENOMEM; | ||
| 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 | ret = psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr); | 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 | return ret; | 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 | if (amdgpu_sriov_vf(psp->adev)) | 1672 | if (amdgpu_sriov_vf(psp->adev)) |
| 1542 | return 0; | 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 | static int psp_hdcp_terminate(struct psp_context *psp) | 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 | if (amdgpu_sriov_vf(psp->adev)) | 1685 | if (amdgpu_sriov_vf(psp->adev)) |
| 1555 | return 0; | 1686 | return 0; |
| 1556 | 1687 | ||
| 1557 | if (!psp->hdcp_context.hdcp_initialized) { | 1688 | if (!psp->hdcp_context.context.initialized) { |
| 1558 | if (psp->hdcp_context.hdcp_shared_buf) | 1689 | if (psp->hdcp_context.context.mem_context.shared_buf) |
| 1559 | goto out; | 1690 | goto out; |
| 1560 | else | 1691 | else |
| 1561 | return 0; | 1692 | return 0; |
| @@ -1565,13 +1696,11 @@ static int psp_hdcp_terminate(struct psp_context *psp) · 3 unmodified lines | |||
| 1565 | if (ret) | 1696 | if (ret) |
| 1566 | return ret; | 1697 | return ret; |
| 1567 | 1698 | ||
| 1568 | psp->hdcp_context.hdcp_initialized = false; | 1699 | psp->hdcp_context.context.initialized = false; |
| 1569 | 1700 | ||
| 1570 | out: | 1701 | out: |
| 1571 | /* free hdcp shared memory */ | 1702 | /* free hdcp shared memory */ |
| 1572 | amdgpu_bo_free_kernel(&psp->hdcp_context.hdcp_shared_bo, | 1703 | psp_ta_free_shared_buf(&psp->hdcp_context.context.mem_context); |
| 1573 | &psp->hdcp_context.hdcp_shared_mc_addr, | ||
| 1574 | &psp->hdcp_context.hdcp_shared_buf); | ||
| 1575 | 1704 | ||
| 1576 | return 0; | 1705 | return 0; |
| 1577 | } | 1706 | } |
| @@ -1580,19 +1709,8 @@ out: · 2 unmodified lines | |||
| 1580 | // DTM start | 1709 | // DTM start |
| 1581 | static int psp_dtm_init_shared_buf(struct psp_context *psp) | 1710 | static int psp_dtm_init_shared_buf(struct psp_context *psp) |
| 1582 | { | 1711 | { |
| 1583 | int ret; | 1712 | return psp_ta_init_shared_buf(psp, &psp->dtm_context.context.mem_context, |
| 1584 | 1713 | PSP_DTM_SHARED_MEM_SIZE); | |
| 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; | ||
| 1596 | } | 1714 | } |
| 1597 | 1715 | ||
| 1598 | static int psp_dtm_load(struct psp_context *psp) | 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 | if (amdgpu_sriov_vf(psp->adev)) | 1724 | if (amdgpu_sriov_vf(psp->adev)) |
| 1607 | return 0; | 1725 | return 0; |
| 1608 | 1726 | ||
| 1609 | cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL); | 1727 | psp_copy_fw(psp, psp->dtm.start_addr, psp->dtm.size_bytes); |
| 1610 | if (!cmd) | ||
| 1611 | return -ENOMEM; | ||
| 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 | psp_prep_ta_load_cmd_buf(cmd, | 1731 | psp_prep_ta_load_cmd_buf(cmd, |
| 1616 | psp->fw_pri_mc_addr, | 1732 | psp->fw_pri_mc_addr, |
| 1617 | psp->ta_dtm_ucode_size, | 1733 | psp->dtm.size_bytes, |
| 1618 | psp->dtm_context.dtm_shared_mc_addr, | 1734 | psp->dtm_context.context.mem_context.shared_mc_addr, |
| 1619 | PSP_DTM_SHARED_MEM_SIZE); | 1735 | PSP_DTM_SHARED_MEM_SIZE); |
| 1620 | 1736 | ||
| 1621 | ret = psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr); | 1737 | ret = psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr); |
| 1622 | 1738 | ||
| 1623 | if (!ret) { | 1739 | if (!ret) { |
| 1624 | psp->dtm_context.dtm_initialized = true; | 1740 | psp->dtm_context.context.initialized = true; |
| 1625 | psp->dtm_context.session_id = cmd->resp.session_id; | 1741 | psp->dtm_context.context.session_id = cmd->resp.session_id; |
| 1626 | mutex_init(&psp->dtm_context.mutex); | 1742 | mutex_init(&psp->dtm_context.mutex); |
| 1627 | } | 1743 | } |
| 1628 | 1744 | ||
| 1629 | kfree(cmd); | 1745 | release_psp_cmd_buf(psp); |
| 1630 | 1746 | ||
| 1631 | return ret; | 1747 | return ret; |
| 1632 | } | 1748 | } |
| @@ -1641,13 +1757,13 @@ static int psp_dtm_initialize(struct psp_context *psp) · 8 unmodified lines | |||
| 1641 | if (amdgpu_sriov_vf(psp->adev)) | 1757 | if (amdgpu_sriov_vf(psp->adev)) |
| 1642 | return 0; | 1758 | return 0; |
| 1643 | 1759 | ||
| 1644 | if (!psp->adev->psp.ta_dtm_ucode_size || | 1760 | if (!psp->dtm.size_bytes || |
| 1645 | !psp->adev->psp.ta_dtm_start_addr) { | 1761 | !psp->dtm.start_addr) { |
| 1646 | dev_info(psp->adev->dev, "DTM: optional dtm ta ucode is not available\n"); | 1762 | dev_info(psp->adev->dev, "DTM: optional dtm ta ucode is not available\n"); |
| 1647 | return 0; | 1763 | return 0; |
| 1648 | } | 1764 | } |
| 1649 | 1765 | ||
| 1650 | if (!psp->dtm_context.dtm_initialized) { | 1766 | if (!psp->dtm_context.context.initialized) { |
| 1651 | ret = psp_dtm_init_shared_buf(psp); | 1767 | ret = psp_dtm_init_shared_buf(psp); |
| 1652 | if (ret) | 1768 | if (ret) |
| 1653 | return ret; | 1769 | return ret; |
| @@ -1671,15 +1787,13 @@ static int psp_dtm_unload(struct psp_context *psp) · 17 unmodified lines | |||
| 1671 | if (amdgpu_sriov_vf(psp->adev)) | 1787 | if (amdgpu_sriov_vf(psp->adev)) |
| 1672 | return 0; | 1788 | return 0; |
| 1673 | 1789 | ||
| 1674 | cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL); | 1790 | cmd = acquire_psp_cmd_buf(psp); |
| 1675 | if (!cmd) | ||
| 1676 | return -ENOMEM; | ||
| 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 | ret = psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr); | 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 | return ret; | 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 | if (amdgpu_sriov_vf(psp->adev)) | 1806 | if (amdgpu_sriov_vf(psp->adev)) |
| 1693 | return 0; | 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 | static int psp_dtm_terminate(struct psp_context *psp) | 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 | if (amdgpu_sriov_vf(psp->adev)) | 1819 | if (amdgpu_sriov_vf(psp->adev)) |
| 1706 | return 0; | 1820 | return 0; |
| 1707 | 1821 | ||
| 1708 | if (!psp->dtm_context.dtm_initialized) { | 1822 | if (!psp->dtm_context.context.initialized) { |
| 1709 | if (psp->dtm_context.dtm_shared_buf) | 1823 | if (psp->dtm_context.context.mem_context.shared_buf) |
| 1710 | goto out; | 1824 | goto out; |
| 1711 | else | 1825 | else |
| 1712 | return 0; | 1826 | return 0; |
| @@ -1716,13 +1830,11 @@ static int psp_dtm_terminate(struct psp_context *psp) · 3 unmodified lines | |||
| 1716 | if (ret) | 1830 | if (ret) |
| 1717 | return ret; | 1831 | return ret; |
| 1718 | 1832 | ||
| 1719 | psp->dtm_context.dtm_initialized = false; | 1833 | psp->dtm_context.context.initialized = false; |
| 1720 | 1834 | ||
| 1721 | out: | 1835 | out: |
| 1722 | /* free hdcp shared memory */ | 1836 | /* free dtm shared memory */ |
| 1723 | amdgpu_bo_free_kernel(&psp->dtm_context.dtm_shared_bo, | 1837 | psp_ta_free_shared_buf(&psp->dtm_context.context.mem_context); |
| 1724 | &psp->dtm_context.dtm_shared_mc_addr, | ||
| 1725 | &psp->dtm_context.dtm_shared_buf); | ||
| 1726 | 1838 | ||
| 1727 | return 0; | 1839 | return 0; |
| 1728 | } | 1840 | } |
| @@ -1731,19 +1843,8 @@ out: · 2 unmodified lines | |||
| 1731 | // RAP start | 1843 | // RAP start |
| 1732 | static int psp_rap_init_shared_buf(struct psp_context *psp) | 1844 | static int psp_rap_init_shared_buf(struct psp_context *psp) |
| 1733 | { | 1845 | { |
| 1734 | int ret; | 1846 | return psp_ta_init_shared_buf(psp, &psp->rap_context.context.mem_context, |
| 1735 | 1847 | PSP_RAP_SHARED_MEM_SIZE); | |
| 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; | ||
| 1747 | } | 1848 | } |
| 1748 | 1849 | ||
| 1749 | static int psp_rap_load(struct psp_context *psp) | 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 | int ret; | 1852 | int ret; |
| 1752 | struct psp_gfx_cmd_resp *cmd; | 1853 | struct psp_gfx_cmd_resp *cmd; |
| 1753 | 1854 | ||
| 1754 | cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL); | 1855 | psp_copy_fw(psp, psp->rap.start_addr, psp->rap.size_bytes); |
| 1755 | if (!cmd) | ||
| 1756 | return -ENOMEM; | ||
| 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 | psp_prep_ta_load_cmd_buf(cmd, | 1859 | psp_prep_ta_load_cmd_buf(cmd, |
| 1761 | psp->fw_pri_mc_addr, | 1860 | psp->fw_pri_mc_addr, |
| 1762 | psp->ta_rap_ucode_size, | 1861 | psp->rap.size_bytes, |
| 1763 | psp->rap_context.rap_shared_mc_addr, | 1862 | psp->rap_context.context.mem_context.shared_mc_addr, |
| 1764 | PSP_RAP_SHARED_MEM_SIZE); | 1863 | PSP_RAP_SHARED_MEM_SIZE); |
| 1765 | 1864 | ||
| 1766 | ret = psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr); | 1865 | ret = psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr); |
| 1767 | 1866 | ||
| 1768 | if (!ret) { | 1867 | if (!ret) { |
| 1769 | psp->rap_context.rap_initialized = true; | 1868 | psp->rap_context.context.initialized = true; |
| 1770 | psp->rap_context.session_id = cmd->resp.session_id; | 1869 | psp->rap_context.context.session_id = cmd->resp.session_id; |
| 1771 | mutex_init(&psp->rap_context.mutex); | 1870 | mutex_init(&psp->rap_context.mutex); |
| 1772 | } | 1871 | } |
| 1773 | 1872 | ||
| 1774 | kfree(cmd); | 1873 | release_psp_cmd_buf(psp); |
| 1775 | 1874 | ||
| 1776 | return ret; | 1875 | return ret; |
| 1777 | } | 1876 | } |
| @@ -1779,17 +1878,13 @@ static int psp_rap_load(struct psp_context *psp) · 1 unmodified line | |||
| 1779 | static int psp_rap_unload(struct psp_context *psp) | 1878 | static int psp_rap_unload(struct psp_context *psp) |
| 1780 | { | 1879 | { |
| 1781 | int ret; | 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); | 1883 | psp_prep_ta_unload_cmd_buf(cmd, psp->rap_context.context.session_id); |
| 1785 | if (!cmd) | ||
| 1786 | return -ENOMEM; | ||
| 1787 | |||
| 1788 | psp_prep_ta_unload_cmd_buf(cmd, psp->rap_context.session_id); | ||
| 1789 | 1884 | ||
| 1790 | ret = psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr); | 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 | return ret; | 1889 | return ret; |
| 1795 | } | 1890 | } |
| @@ -1805,13 +1900,13 @@ static int psp_rap_initialize(struct psp_context *psp) · 9 unmodified lines | |||
| 1805 | if (amdgpu_sriov_vf(psp->adev)) | 1900 | if (amdgpu_sriov_vf(psp->adev)) |
| 1806 | return 0; | 1901 | return 0; |
| 1807 | 1902 | ||
| 1808 | if (!psp->adev->psp.ta_rap_ucode_size || | 1903 | if (!psp->rap.size_bytes || |
| 1809 | !psp->adev->psp.ta_rap_start_addr) { | 1904 | !psp->rap.start_addr) { |
| 1810 | dev_info(psp->adev->dev, "RAP: optional rap ta ucode is not available\n"); | 1905 | dev_info(psp->adev->dev, "RAP: optional rap ta ucode is not available\n"); |
| 1811 | return 0; | 1906 | return 0; |
| 1812 | } | 1907 | } |
| 1813 | 1908 | ||
| 1814 | if (!psp->rap_context.rap_initialized) { | 1909 | if (!psp->rap_context.context.initialized) { |
| 1815 | ret = psp_rap_init_shared_buf(psp); | 1910 | ret = psp_rap_init_shared_buf(psp); |
| 1816 | if (ret) | 1911 | if (ret) |
| 1817 | return ret; | 1912 | return ret; |
| @@ -1825,11 +1920,9 @@ static int psp_rap_initialize(struct psp_context *psp) · 7 unmodified lines | |||
| 1825 | if (ret || status != TA_RAP_STATUS__SUCCESS) { | 1920 | if (ret || status != TA_RAP_STATUS__SUCCESS) { |
| 1826 | psp_rap_unload(psp); | 1921 | psp_rap_unload(psp); |
| 1827 | 1922 | ||
| 1828 | amdgpu_bo_free_kernel(&psp->rap_context.rap_shared_bo, | 1923 | psp_ta_free_shared_buf(&psp->rap_context.context.mem_context); |
| 1829 | &psp->rap_context.rap_shared_mc_addr, | ||
| 1830 | &psp->rap_context.rap_shared_buf); | ||
| 1831 | 1924 | ||
| 1832 | psp->rap_context.rap_initialized = false; | 1925 | psp->rap_context.context.initialized = false; |
| 1833 | 1926 | ||
| 1834 | dev_warn(psp->adev->dev, "RAP TA initialize fail (%d) status %d.\n", | 1927 | dev_warn(psp->adev->dev, "RAP TA initialize fail (%d) status %d.\n", |
| 1835 | ret, status); | 1928 | ret, status); |
| @@ -1844,17 +1937,15 @@ static int psp_rap_terminate(struct psp_context *psp) · 8 unmodified lines | |||
| 1844 | { | 1937 | { |
| 1845 | int ret; | 1938 | int ret; |
| 1846 | 1939 | ||
| 1847 | if (!psp->rap_context.rap_initialized) | 1940 | if (!psp->rap_context.context.initialized) |
| 1848 | return 0; | 1941 | return 0; |
| 1849 | 1942 | ||
| 1850 | ret = psp_rap_unload(psp); | 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 | /* free rap shared memory */ | 1947 | /* free rap shared memory */ |
| 1855 | amdgpu_bo_free_kernel(&psp->rap_context.rap_shared_bo, | 1948 | psp_ta_free_shared_buf(&psp->rap_context.context.mem_context); |
| 1856 | &psp->rap_context.rap_shared_mc_addr, | ||
| 1857 | &psp->rap_context.rap_shared_buf); | ||
| 1858 | 1949 | ||
| 1859 | return ret; | 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 | struct ta_rap_shared_memory *rap_cmd; | 1955 | struct ta_rap_shared_memory *rap_cmd; |
| 1865 | int ret = 0; | 1956 | int ret = 0; |
| 1866 | 1957 | ||
| 1867 | if (!psp->rap_context.rap_initialized) | 1958 | if (!psp->rap_context.context.initialized) |
| 1868 | return 0; | 1959 | return 0; |
| 1869 | 1960 | ||
| 1870 | if (ta_cmd_id != TA_CMD_RAP__INITIALIZE && | 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 | mutex_lock(&psp->rap_context.mutex); | 1965 | mutex_lock(&psp->rap_context.mutex); |
| 1875 | 1966 | ||
| 1876 | rap_cmd = (struct ta_rap_shared_memory *) | 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 | memset(rap_cmd, 0, sizeof(struct ta_rap_shared_memory)); | 1969 | memset(rap_cmd, 0, sizeof(struct ta_rap_shared_memory)); |
| 1879 | 1970 | ||
| 1880 | rap_cmd->cmd_id = ta_cmd_id; | 1971 | rap_cmd->cmd_id = ta_cmd_id; |
| 1881 | rap_cmd->validation_method_id = METHOD_A; | 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 | if (ret) | 1975 | if (ret) |
| 1885 | goto out_unlock; | 1976 | goto out_unlock; |
| 1886 | 1977 | ||
| @@ -1897,67 +1988,48 @@ out_unlock: · 10 unmodified lines | |||
| 1897 | /* securedisplay start */ | 1988 | /* securedisplay start */ |
| 1898 | static int psp_securedisplay_init_shared_buf(struct psp_context *psp) | 1989 | static int psp_securedisplay_init_shared_buf(struct psp_context *psp) |
| 1899 | { | 1990 | { |
| 1900 | int ret; | 1991 | return psp_ta_init_shared_buf( |
| 1901 | 1992 | psp, &psp->securedisplay_context.context.mem_context, | |
| 1902 | /* | 1993 | PSP_SECUREDISPLAY_SHARED_MEM_SIZE); |
| 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; | ||
| 1913 | } | 1994 | } |
| 1914 | 1995 | ||
| 1915 | static int psp_securedisplay_load(struct psp_context *psp) | 1996 | static int psp_securedisplay_load(struct psp_context *psp) |
| 1916 | { | 1997 | { |
| 1917 | int ret; | 1998 | int ret; |
| 1918 | struct psp_gfx_cmd_resp *cmd; | 1999 | struct psp_gfx_cmd_resp *cmd = acquire_psp_cmd_buf(psp); |
| 1919 | |||
| 1920 | cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL); | ||
| 1921 | if (!cmd) | ||
| 1922 | return -ENOMEM; | ||
| 1923 | 2000 | ||
| 1924 | memset(psp->fw_pri_buf, 0, PSP_1_MEG); | 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 | psp_prep_ta_load_cmd_buf(cmd, | 2004 | psp_prep_ta_load_cmd_buf(cmd, |
| 1928 | psp->fw_pri_mc_addr, | 2005 | psp->fw_pri_mc_addr, |
| 1929 | psp->ta_securedisplay_ucode_size, | 2006 | psp->securedisplay.size_bytes, |
| 1930 | psp->securedisplay_context.securedisplay_shared_mc_addr, | 2007 | psp->securedisplay_context.context.mem_context.shared_mc_addr, |
| 1931 | PSP_SECUREDISPLAY_SHARED_MEM_SIZE); | 2008 | PSP_SECUREDISPLAY_SHARED_MEM_SIZE); |
| 1932 | 2009 | ||
| 1933 | ret = psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr); | 2010 | ret = psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr); |
| 1934 | 2011 | ||
| 1935 | if (ret) | 2012 | if (!ret) { |
| 1936 | goto failed; | 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; | 2018 | release_psp_cmd_buf(psp); |
| 1939 | psp->securedisplay_context.session_id = cmd->resp.session_id; | ||
| 1940 | mutex_init(&psp->securedisplay_context.mutex); | ||
| 1941 | 2019 | ||
| 1942 | failed: | ||
| 1943 | kfree(cmd); | ||
| 1944 | return ret; | 2020 | return ret; |
| 1945 | } | 2021 | } |
| 1946 | 2022 | ||
| 1947 | static int psp_securedisplay_unload(struct psp_context *psp) | 2023 | static int psp_securedisplay_unload(struct psp_context *psp) |
| 1948 | { | 2024 | { |
| 1949 | int ret; | 2025 | int ret; |
| 1950 | struct psp_gfx_cmd_resp *cmd; | 2026 | struct psp_gfx_cmd_resp *cmd = acquire_psp_cmd_buf(psp); |
| 1951 | |||
| 1952 | cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL); | ||
| 1953 | if (!cmd) | ||
| 1954 | return -ENOMEM; | ||
| 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 | ret = psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr); | 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 | return ret; | 2034 | return ret; |
| 1963 | } | 2035 | } |
| @@ -1973,13 +2045,13 @@ static int psp_securedisplay_initialize(struct psp_context *psp) · 9 unmodified lines | |||
| 1973 | if (amdgpu_sriov_vf(psp->adev)) | 2045 | if (amdgpu_sriov_vf(psp->adev)) |
| 1974 | return 0; | 2046 | return 0; |
| 1975 | 2047 | ||
| 1976 | if (!psp->adev->psp.ta_securedisplay_ucode_size || | 2048 | if (!psp->securedisplay.size_bytes || |
| 1977 | !psp->adev->psp.ta_securedisplay_start_addr) { | 2049 | !psp->securedisplay.start_addr) { |
| 1978 | dev_info(psp->adev->dev, "SECUREDISPLAY: securedisplay ta ucode is not available\n"); | 2050 | dev_info(psp->adev->dev, "SECUREDISPLAY: securedisplay ta ucode is not available\n"); |
| 1979 | return 0; | 2051 | return 0; |
| 1980 | } | 2052 | } |
| 1981 | 2053 | ||
| 1982 | if (!psp->securedisplay_context.securedisplay_initialized) { | 2054 | if (!psp->securedisplay_context.context.initialized) { |
| 1983 | ret = psp_securedisplay_init_shared_buf(psp); | 2055 | ret = psp_securedisplay_init_shared_buf(psp); |
| 1984 | if (ret) | 2056 | if (ret) |
| 1985 | return ret; | 2057 | return ret; |
| @@ -1996,11 +2068,9 @@ static int psp_securedisplay_initialize(struct psp_context *psp) · 10 unmodified lines | |||
| 1996 | if (ret) { | 2068 | if (ret) { |
| 1997 | psp_securedisplay_unload(psp); | 2069 | psp_securedisplay_unload(psp); |
| 1998 | 2070 | ||
| 1999 | amdgpu_bo_free_kernel(&psp->securedisplay_context.securedisplay_shared_bo, | 2071 | psp_ta_free_shared_buf(&psp->securedisplay_context.context.mem_context); |
| 2000 | &psp->securedisplay_context.securedisplay_shared_mc_addr, | ||
| 2001 | &psp->securedisplay_context.securedisplay_shared_buf); | ||
| 2002 | 2072 | ||
| 2003 | psp->securedisplay_context.securedisplay_initialized = false; | 2073 | psp->securedisplay_context.context.initialized = false; |
| 2004 | 2074 | ||
| 2005 | dev_err(psp->adev->dev, "SECUREDISPLAY TA initialize fail.\n"); | 2075 | dev_err(psp->adev->dev, "SECUREDISPLAY TA initialize fail.\n"); |
| 2006 | return -EINVAL; | 2076 | return -EINVAL; |
| @@ -2025,19 +2095,17 @@ static int psp_securedisplay_terminate(struct psp_context *psp) · 18 unmodified lines | |||
| 2025 | if (amdgpu_sriov_vf(psp->adev)) | 2095 | if (amdgpu_sriov_vf(psp->adev)) |
| 2026 | return 0; | 2096 | return 0; |
| 2027 | 2097 | ||
| 2028 | if (!psp->securedisplay_context.securedisplay_initialized) | 2098 | if (!psp->securedisplay_context.context.initialized) |
| 2029 | return 0; | 2099 | return 0; |
| 2030 | 2100 | ||
| 2031 | ret = psp_securedisplay_unload(psp); | 2101 | ret = psp_securedisplay_unload(psp); |
| 2032 | if (ret) | 2102 | if (ret) |
| 2033 | return ret; | 2103 | return ret; |
| 2034 | 2104 | ||
| 2035 | psp->securedisplay_context.securedisplay_initialized = false; | 2105 | psp->securedisplay_context.context.initialized = false; |
| 2036 | 2106 | ||
| 2037 | /* free securedisplay shared memory */ | 2107 | /* free securedisplay shared memory */ |
| 2038 | amdgpu_bo_free_kernel(&psp->securedisplay_context.securedisplay_shared_bo, | 2108 | psp_ta_free_shared_buf(&psp->securedisplay_context.context.mem_context); |
| 2039 | &psp->securedisplay_context.securedisplay_shared_mc_addr, | ||
| 2040 | &psp->securedisplay_context.securedisplay_shared_buf); | ||
| 2041 | 2109 | ||
| 2042 | return ret; | 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 | int ret; | 2115 | int ret; |
| 2048 | 2116 | ||
| 2049 | if (!psp->securedisplay_context.securedisplay_initialized) | 2117 | if (!psp->securedisplay_context.context.initialized) |
| 2050 | return -EINVAL; | 2118 | return -EINVAL; |
| 2051 | 2119 | ||
| 2052 | if (ta_cmd_id != TA_SECUREDISPLAY_COMMAND__QUERY_TA && | 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 | mutex_lock(&psp->securedisplay_context.mutex); | 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 | mutex_unlock(&psp->securedisplay_context.mutex); | 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 | int ret; | 2137 | int ret; |
| 2070 | 2138 | ||
| 2071 | if (!amdgpu_sriov_vf(adev)) { | 2139 | if (!amdgpu_sriov_vf(adev)) { |
| 2072 | if (psp->kdb_bin_size && | 2140 | if ((is_psp_fw_valid(psp->kdb)) && |
| 2073 | (psp->funcs->bootloader_load_kdb != NULL)) { | 2141 | (psp->funcs->bootloader_load_kdb != NULL)) { |
| 2074 | ret = psp_bootloader_load_kdb(psp); | 2142 | ret = psp_bootloader_load_kdb(psp); |
| 2075 | if (ret) { | 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 | ret = psp_bootloader_load_spl(psp); | 2151 | ret = psp_bootloader_load_spl(psp); |
| 2083 | if (ret) { | 2152 | if (ret) { |
| 2084 | DRM_ERROR("PSP load spl failed!\n"); | 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); | 2158 | if ((is_psp_fw_valid(psp->sys)) && |
| 2090 | if (ret) { | 2159 | (psp->funcs->bootloader_load_sysdrv != NULL)) { |
| 2091 | DRM_ERROR("PSP load sysdrv failed!\n"); | 2160 | ret = psp_bootloader_load_sysdrv(psp); |
| 2092 | return ret; | 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); | 2167 | if ((is_psp_fw_valid(psp->soc_drv)) && |
| 2096 | if (ret) { | 2168 | (psp->funcs->bootloader_load_soc_drv != NULL)) { |
| 2097 | DRM_ERROR("PSP load sos failed!\n"); | 2169 | ret = psp_bootloader_load_soc_drv(psp); |
| 2098 | return ret; | 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 | int ret; | 2401 | int ret; |
| 2300 | uint64_t fw_mem_mc_addr = ucode->mc_addr; | 2402 | uint64_t fw_mem_mc_addr = ucode->mc_addr; |
| 2301 | 2403 | ||
| 2302 | memset(cmd, 0, sizeof(struct psp_gfx_cmd_resp)); | ||
| 2303 | |||
| 2304 | cmd->cmd_id = GFX_CMD_ID_LOAD_IP_FW; | 2404 | cmd->cmd_id = GFX_CMD_ID_LOAD_IP_FW; |
| 2305 | cmd->cmd.cmd_load_ip_fw.fw_phy_addr_lo = lower_32_bits(fw_mem_mc_addr); | 2405 | cmd->cmd.cmd_load_ip_fw.fw_phy_addr_lo = lower_32_bits(fw_mem_mc_addr); |
| 2306 | cmd->cmd.cmd_load_ip_fw.fw_phy_addr_hi = upper_32_bits(fw_mem_mc_addr); | 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 | return ret; | 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 | struct amdgpu_firmware_info *ucode) | 2417 | struct amdgpu_firmware_info *ucode) |
| 2318 | { | 2418 | { |
| 2319 | int ret = 0; | 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); | 2422 | ret = psp_prep_load_ip_fw_cmd_buf(ucode, cmd); |
| 2322 | if (ret) | 2423 | if (!ret) { |
| 2323 | return 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, | 2428 | release_psp_cmd_buf(psp); |
| 2326 | psp->fence_buf_mc_addr); | ||
| 2327 | 2429 | ||
| 2328 | return ret; | 2430 | return ret; |
| 2329 | } | 2431 | } |
| @@ -2334,7 +2436,7 @@ static int psp_load_smu_fw(struct psp_context *psp) · 4 unmodified lines | |||
| 2334 | struct amdgpu_device *adev = psp->adev; | 2436 | struct amdgpu_device *adev = psp->adev; |
| 2335 | struct amdgpu_firmware_info *ucode = | 2437 | struct amdgpu_firmware_info *ucode = |
| 2336 | &adev->firmware.ucode[AMDGPU_UCODE_ID_SMC]; | 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 | if (!ucode->fw || amdgpu_sriov_vf(psp->adev)) | 2441 | if (!ucode->fw || amdgpu_sriov_vf(psp->adev)) |
| 2340 | return 0; | 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 | if (ret) | 2456 | if (ret) |
| 2355 | DRM_ERROR("PSP load smu failed!\n"); | 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 | for (i = 0; i < ucode_count; ++i) { | 2506 | for (i = 0; i < ucode_count; ++i) { |
| 2405 | ucode = ucode_list[i]; | 2507 | ucode = ucode_list[i]; |
| 2406 | psp_print_fw_hdr(psp, ucode); | 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 | if (ret) | 2510 | if (ret) |
| 2409 | return ret; | 2511 | return ret; |
| 2410 | } | 2512 | } |
| 2411 | return ret; | 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 | int i, ret; | 2518 | int i, ret; |
| 2417 | struct amdgpu_firmware_info *ucode; | 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 | psp_print_fw_hdr(psp, ucode); | 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 | if (ret) | 2556 | if (ret) |
| 2455 | return ret; | 2557 | return ret; |
| 2456 | 2558 | ||
| @@ -2478,10 +2580,6 @@ static int psp_load_fw(struct amdgpu_device *adev) · 21 unmodified lines | |||
| 2478 | goto skip_memalloc; | 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 | if (amdgpu_sriov_vf(adev)) { | 2583 | if (amdgpu_sriov_vf(adev)) { |
| 2486 | ret = amdgpu_bo_create_kernel(adev, PSP_1_MEG, PSP_1_MEG, | 2584 | ret = amdgpu_bo_create_kernel(adev, PSP_1_MEG, PSP_1_MEG, |
| 2487 | AMDGPU_GEM_DOMAIN_VRAM, | 2585 | AMDGPU_GEM_DOMAIN_VRAM, |
| @@ -2527,7 +2625,7 @@ skip_memalloc: · 39 unmodified lines | |||
| 2527 | if (ret) | 2625 | if (ret) |
| 2528 | goto failed; | 2626 | goto failed; |
| 2529 | 2627 | ||
| 2530 | ret = psp_np_fw_load(psp); | 2628 | ret = psp_load_non_psp_fw(psp); |
| 2531 | if (ret) | 2629 | if (ret) |
| 2532 | goto failed; | 2630 | goto failed; |
| 2533 | 2631 | ||
| @@ -2543,7 +2641,7 @@ skip_memalloc: · 9 unmodified lines | |||
| 2543 | return ret; | 2641 | return ret; |
| 2544 | } | 2642 | } |
| 2545 | 2643 | ||
| 2546 | if (psp->adev->psp.ta_fw) { | 2644 | if (psp->ta_fw) { |
| 2547 | ret = psp_ras_initialize(psp); | 2645 | ret = psp_ras_initialize(psp); |
| 2548 | if (ret) | 2646 | if (ret) |
| 2549 | dev_err(psp->adev->dev, | 2647 | dev_err(psp->adev->dev, |
| @@ -2615,7 +2713,7 @@ static int psp_hw_fini(void *handle) · 65 unmodified lines | |||
| 2615 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; | 2713 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; |
| 2616 | struct psp_context *psp = &adev->psp; | 2714 | struct psp_context *psp = &adev->psp; |
| 2617 | 2715 | ||
| 2618 | if (psp->adev->psp.ta_fw) { | 2716 | if (psp->ta_fw) { |
| 2619 | psp_ras_terminate(psp); | 2717 | psp_ras_terminate(psp); |
| 2620 | psp_securedisplay_terminate(psp); | 2718 | psp_securedisplay_terminate(psp); |
| 2621 | psp_rap_terminate(psp); | 2719 | psp_rap_terminate(psp); |
| @@ -2635,9 +2733,6 @@ static int psp_hw_fini(void *handle) · 13 unmodified lines | |||
| 2635 | amdgpu_bo_free_kernel(&psp->cmd_buf_bo, &psp->cmd_buf_mc_addr, | 2733 | amdgpu_bo_free_kernel(&psp->cmd_buf_bo, &psp->cmd_buf_mc_addr, |
| 2636 | (void **)&psp->cmd_buf_mem); | 2734 | (void **)&psp->cmd_buf_mem); |
| 2637 | 2735 | ||
| 2638 | kfree(psp->cmd); | ||
| 2639 | psp->cmd = NULL; | ||
| 2640 | |||
| 2641 | return 0; | 2736 | return 0; |
| 2642 | } | 2737 | } |
| 2643 | 2738 | ||
| @@ -2648,7 +2743,7 @@ static int psp_suspend(void *handle) · 4 unmodified lines | |||
| 2648 | struct psp_context *psp = &adev->psp; | 2743 | struct psp_context *psp = &adev->psp; |
| 2649 | 2744 | ||
| 2650 | if (adev->gmc.xgmi.num_physical_nodes > 1 && | 2745 | if (adev->gmc.xgmi.num_physical_nodes > 1 && |
| 2651 | psp->xgmi_context.initialized == 1) { | 2746 | psp->xgmi_context.context.initialized) { |
| 2652 | ret = psp_xgmi_terminate(psp); | 2747 | ret = psp_xgmi_terminate(psp); |
| 2653 | if (ret) { | 2748 | if (ret) { |
| 2654 | DRM_ERROR("Failed to terminate xgmi ta\n"); | 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 | ret = psp_ras_terminate(psp); | 2755 | ret = psp_ras_terminate(psp); |
| 2661 | if (ret) { | 2756 | if (ret) { |
| 2662 | DRM_ERROR("Failed to terminate ras ta\n"); | 2757 | DRM_ERROR("Failed to terminate ras ta\n"); |
| @@ -2727,7 +2822,7 @@ static int psp_resume(void *handle) · 64 unmodified lines | |||
| 2727 | if (ret) | 2822 | if (ret) |
| 2728 | goto failed; | 2823 | goto failed; |
| 2729 | 2824 | ||
| 2730 | ret = psp_np_fw_load(psp); | 2825 | ret = psp_load_non_psp_fw(psp); |
| 2731 | if (ret) | 2826 | if (ret) |
| 2732 | goto failed; | 2827 | goto failed; |
| 2733 | 2828 | ||
| @@ -2738,7 +2833,7 @@ static int psp_resume(void *handle) · 4 unmodified lines | |||
| 2738 | } | 2833 | } |
| 2739 | 2834 | ||
| 2740 | if (adev->gmc.xgmi.num_physical_nodes > 1) { | 2835 | if (adev->gmc.xgmi.num_physical_nodes > 1) { |
| 2741 | ret = psp_xgmi_initialize(psp); | 2836 | ret = psp_xgmi_initialize(psp, false, true); |
| 2742 | /* Warning the XGMI seesion initialize failure | 2837 | /* Warning the XGMI seesion initialize failure |
| 2743 | * Instead of stop driver initialization | 2838 | * Instead of stop driver initialization |
| 2744 | */ | 2839 | */ |
| @@ -2747,7 +2842,7 @@ static int psp_resume(void *handle) · 2 unmodified lines | |||
| 2747 | "XGMI: Failed to initialize XGMI session\n"); | 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 | ret = psp_ras_initialize(psp); | 2846 | ret = psp_ras_initialize(psp); |
| 2752 | if (ret) | 2847 | if (ret) |
| 2753 | dev_err(psp->adev->dev, | 2848 | dev_err(psp->adev->dev, |
| @@ -2801,17 +2896,15 @@ int psp_gpu_reset(struct amdgpu_device *adev) · 47 unmodified lines | |||
| 2801 | int psp_rlc_autoload_start(struct psp_context *psp) | 2896 | int psp_rlc_autoload_start(struct psp_context *psp) |
| 2802 | { | 2897 | { |
| 2803 | int ret; | 2898 | int ret; |
| 2804 | struct psp_gfx_cmd_resp *cmd; | 2899 | struct psp_gfx_cmd_resp *cmd = acquire_psp_cmd_buf(psp); |
| 2805 | |||
| 2806 | cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL); | ||
| 2807 | if (!cmd) | ||
| 2808 | return -ENOMEM; | ||
| 2809 | 2900 | ||
| 2810 | cmd->cmd_id = GFX_CMD_ID_AUTOLOAD_RLC; | 2901 | cmd->cmd_id = GFX_CMD_ID_AUTOLOAD_RLC; |
| 2811 | 2902 | ||
| 2812 | ret = psp_cmd_submit_buf(psp, NULL, cmd, | 2903 | ret = psp_cmd_submit_buf(psp, NULL, cmd, |
| 2813 | psp->fence_buf_mc_addr); | 2904 | psp->fence_buf_mc_addr); |
| 2814 | kfree(cmd); | 2905 | |
| 2906 | release_psp_cmd_buf(psp); | ||
| 2907 | |||
| 2815 | return ret; | 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 | ucode.mc_addr = cmd_gpu_addr; | 2918 | ucode.mc_addr = cmd_gpu_addr; |
| 2826 | ucode.ucode_size = cmd_size; | 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 | int psp_ring_cmd_submit(struct psp_context *psp, | 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 | goto out; | 2994 | goto out; |
| 2902 | 2995 | ||
| 2903 | asd_hdr = (const struct psp_firmware_header_v1_0 *)adev->psp.asd_fw->data; | 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); | 2997 | 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); | 2998 | 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); | 2999 | adev->psp.asd.size_bytes = le32_to_cpu(asd_hdr->header.ucode_size_bytes); |
| 2907 | adev->psp.asd_start_addr = (uint8_t *)asd_hdr + | 3000 | adev->psp.asd.start_addr = (uint8_t *)asd_hdr + |
| 2908 | le32_to_cpu(asd_hdr->header.ucode_array_offset_bytes); | 3001 | le32_to_cpu(asd_hdr->header.ucode_array_offset_bytes); |
| 2909 | return 0; | 3002 | return 0; |
| 2910 | out: | 3003 | out: |
| @@ -2918,7 +3011,7 @@ int psp_init_toc_microcode(struct psp_context *psp, · 7 unmodified lines | |||
| 2918 | const char *chip_name) | 3011 | const char *chip_name) |
| 2919 | { | 3012 | { |
| 2920 | struct amdgpu_device *adev = psp->adev; | 3013 | struct amdgpu_device *adev = psp->adev; |
| 2921 | char fw_name[30]; | 3014 | char fw_name[PSP_FW_NAME_LEN]; |
| 2922 | const struct psp_firmware_header_v1_0 *toc_hdr; | 3015 | const struct psp_firmware_header_v1_0 *toc_hdr; |
| 2923 | int err = 0; | 3016 | int err = 0; |
| 2924 | 3017 | ||
| @@ -2937,10 +3030,10 @@ int psp_init_toc_microcode(struct psp_context *psp, · 12 unmodified lines | |||
| 2937 | goto out; | 3030 | goto out; |
| 2938 | 3031 | ||
| 2939 | toc_hdr = (const struct psp_firmware_header_v1_0 *)adev->psp.toc_fw->data; | 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); | 3033 | 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); | 3034 | 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); | 3035 | adev->psp.toc.size_bytes = le32_to_cpu(toc_hdr->header.ucode_size_bytes); |
| 2943 | adev->psp.toc_start_addr = (uint8_t *)toc_hdr + | 3036 | adev->psp.toc.start_addr = (uint8_t *)toc_hdr + |
| 2944 | le32_to_cpu(toc_hdr->header.ucode_array_offset_bytes); | 3037 | le32_to_cpu(toc_hdr->header.ucode_array_offset_bytes); |
| 2945 | return 0; | 3038 | return 0; |
| 2946 | out: | 3039 | out: |
| @@ -2950,6 +3043,82 @@ out: · 3 unmodified lines | |||
| 2950 | return err; | 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 | static int psp_init_sos_base_fw(struct amdgpu_device *adev) | 3122 | static int psp_init_sos_base_fw(struct amdgpu_device *adev) |
| 2954 | { | 3123 | { |
| 2955 | const struct psp_firmware_header_v1_0 *sos_hdr; | 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 | le32_to_cpu(sos_hdr->header.ucode_array_offset_bytes); | 3130 | le32_to_cpu(sos_hdr->header.ucode_array_offset_bytes); |
| 2962 | 3131 | ||
| 2963 | if (adev->gmc.xgmi.connected_to_cpu || (adev->asic_type != CHIP_ALDEBARAN)) { | 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); | 3133 | 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); | 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); | 3136 | adev->psp.sys.size_bytes = le32_to_cpu(sos_hdr->sos.offset_bytes); |
| 2968 | adev->psp.sys_start_addr = ucode_array_start_addr; | 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); | 3139 | adev->psp.sos.size_bytes = le32_to_cpu(sos_hdr->sos.size_bytes); |
| 2971 | adev->psp.sos_start_addr = ucode_array_start_addr + | 3140 | adev->psp.sos.start_addr = ucode_array_start_addr + |
| 2972 | le32_to_cpu(sos_hdr->sos.offset_bytes); | 3141 | le32_to_cpu(sos_hdr->sos.offset_bytes); |
| 3142 | adev->psp.xgmi_context.supports_extended_data = false; | ||
| 2973 | } else { | 3143 | } else { |
| 2974 | /* Load alternate PSP SOS FW */ | 3144 | /* Load alternate PSP SOS FW */ |
| 2975 | sos_hdr_v1_3 = (const struct psp_firmware_header_v1_3 *)adev->psp.sos_fw->data; | 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); | 3147 | 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); | 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); | 3150 | adev->psp.sys.size_bytes = le32_to_cpu(sos_hdr_v1_3->sys_drv_aux.size_bytes); |
| 2981 | adev->psp.sys_start_addr = ucode_array_start_addr + | 3151 | adev->psp.sys.start_addr = ucode_array_start_addr + |
| 2982 | le32_to_cpu(sos_hdr_v1_3->sys_drv_aux.offset_bytes); | 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); | 3154 | adev->psp.sos.size_bytes = le32_to_cpu(sos_hdr_v1_3->sos_aux.size_bytes); |
| 2985 | adev->psp.sos_start_addr = ucode_array_start_addr + | 3155 | adev->psp.sos.start_addr = ucode_array_start_addr + |
| 2986 | le32_to_cpu(sos_hdr_v1_3->sos_aux.offset_bytes); | 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 | dev_warn(adev->dev, "PSP SOS FW not available"); | 3161 | dev_warn(adev->dev, "PSP SOS FW not available"); |
| 2991 | return -EINVAL; | 3162 | return -EINVAL; |
| 2992 | } | 3163 | } |
| @@ -3003,8 +3174,10 @@ int psp_init_sos_microcode(struct psp_context *psp, · 10 unmodified lines | |||
| 3003 | const struct psp_firmware_header_v1_1 *sos_hdr_v1_1; | 3174 | const struct psp_firmware_header_v1_1 *sos_hdr_v1_1; |
| 3004 | const struct psp_firmware_header_v1_2 *sos_hdr_v1_2; | 3175 | const struct psp_firmware_header_v1_2 *sos_hdr_v1_2; |
| 3005 | const struct psp_firmware_header_v1_3 *sos_hdr_v1_3; | 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 | int err = 0; | 3178 | int err = 0; |
| 3007 | uint8_t *ucode_array_start_addr; | 3179 | uint8_t *ucode_array_start_addr; |
| 3180 | int fw_index = 0; | ||
| 3008 | 3181 | ||
| 3009 | if (!chip_name) { | 3182 | if (!chip_name) { |
| 3010 | dev_err(adev->dev, "invalid chip name for sos microcode\n"); | 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 | if (sos_hdr->header.header_version_minor == 1) { | 3207 | if (sos_hdr->header.header_version_minor == 1) { |
| 3035 | sos_hdr_v1_1 = (const struct psp_firmware_header_v1_1 *)adev->psp.sos_fw->data; | 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); | 3209 | adev->psp.toc.size_bytes = le32_to_cpu(sos_hdr_v1_1->toc.size_bytes); |
| 3037 | adev->psp.toc_start_addr = (uint8_t *)adev->psp.sys_start_addr + | 3210 | adev->psp.toc.start_addr = (uint8_t *)adev->psp.sys.start_addr + |
| 3038 | le32_to_cpu(sos_hdr_v1_1->toc.offset_bytes); | 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); | 3212 | adev->psp.kdb.size_bytes = le32_to_cpu(sos_hdr_v1_1->kdb.size_bytes); |
| 3040 | adev->psp.kdb_start_addr = (uint8_t *)adev->psp.sys_start_addr + | 3213 | adev->psp.kdb.start_addr = (uint8_t *)adev->psp.sys.start_addr + |
| 3041 | le32_to_cpu(sos_hdr_v1_1->kdb.offset_bytes); | 3214 | le32_to_cpu(sos_hdr_v1_1->kdb.offset_bytes); |
| 3042 | } | 3215 | } |
| 3043 | if (sos_hdr->header.header_version_minor == 2) { | 3216 | if (sos_hdr->header.header_version_minor == 2) { |
| 3044 | sos_hdr_v1_2 = (const struct psp_firmware_header_v1_2 *)adev->psp.sos_fw->data; | 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); | 3218 | adev->psp.kdb.size_bytes = le32_to_cpu(sos_hdr_v1_2->kdb.size_bytes); |
| 3046 | adev->psp.kdb_start_addr = (uint8_t *)adev->psp.sys_start_addr + | 3219 | adev->psp.kdb.start_addr = (uint8_t *)adev->psp.sys.start_addr + |
| 3047 | le32_to_cpu(sos_hdr_v1_2->kdb.offset_bytes); | 3220 | le32_to_cpu(sos_hdr_v1_2->kdb.offset_bytes); |
| 3048 | } | 3221 | } |
| 3049 | if (sos_hdr->header.header_version_minor == 3) { | 3222 | if (sos_hdr->header.header_version_minor == 3) { |
| 3050 | sos_hdr_v1_3 = (const struct psp_firmware_header_v1_3 *)adev->psp.sos_fw->data; | 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); | 3224 | adev->psp.toc.size_bytes = le32_to_cpu(sos_hdr_v1_3->v1_1.toc.size_bytes); |
| 3052 | adev->psp.toc_start_addr = ucode_array_start_addr + | 3225 | adev->psp.toc.start_addr = ucode_array_start_addr + |
| 3053 | le32_to_cpu(sos_hdr_v1_3->v1_1.toc.offset_bytes); | 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); | 3227 | adev->psp.kdb.size_bytes = le32_to_cpu(sos_hdr_v1_3->v1_1.kdb.size_bytes); |
| 3055 | adev->psp.kdb_start_addr = ucode_array_start_addr + | 3228 | adev->psp.kdb.start_addr = ucode_array_start_addr + |
| 3056 | le32_to_cpu(sos_hdr_v1_3->v1_1.kdb.offset_bytes); | 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); | 3230 | adev->psp.spl.size_bytes = le32_to_cpu(sos_hdr_v1_3->spl.size_bytes); |
| 3058 | adev->psp.spl_start_addr = ucode_array_start_addr + | 3231 | adev->psp.spl.start_addr = ucode_array_start_addr + |
| 3059 | le32_to_cpu(sos_hdr_v1_3->spl.offset_bytes); | 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); | 3233 | adev->psp.rl.size_bytes = le32_to_cpu(sos_hdr_v1_3->rl.size_bytes); |
| 3061 | adev->psp.rl_start_addr = ucode_array_start_addr + | 3234 | adev->psp.rl.start_addr = ucode_array_start_addr + |
| 3062 | le32_to_cpu(sos_hdr_v1_3->rl.offset_bytes); | 3235 | le32_to_cpu(sos_hdr_v1_3->rl.offset_bytes); |
| 3063 | } | 3236 | } |
| 3064 | break; | 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 | default: | 3255 | default: |
| 3066 | dev_err(adev->dev, | 3256 | dev_err(adev->dev, |
| 3067 | "unsupported psp sos firmware\n"); | 3257 | "unsupported psp sos firmware\n"); |
| @@ -3080,7 +3270,7 @@ out: · 12 unmodified lines | |||
| 3080 | } | 3270 | } |
| 3081 | 3271 | ||
| 3082 | static int parse_ta_bin_descriptor(struct psp_context *psp, | 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 | const struct ta_firmware_header_v2_0 *ta_hdr) | 3274 | const struct ta_firmware_header_v2_0 *ta_hdr) |
| 3085 | { | 3275 | { |
| 3086 | uint8_t *ucode_start_addr = NULL; | 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 | switch (desc->fw_type) { | 3285 | switch (desc->fw_type) { |
| 3096 | case TA_FW_TYPE_PSP_ASD: | 3286 | case TA_FW_TYPE_PSP_ASD: |
| 3097 | psp->asd_fw_version = le32_to_cpu(desc->fw_version); | 3287 | psp->asd.fw_version = le32_to_cpu(desc->fw_version); |
| 3098 | psp->asd_feature_version = le32_to_cpu(desc->fw_version); | 3288 | psp->asd.feature_version = le32_to_cpu(desc->fw_version); |
| 3099 | psp->asd_ucode_size = le32_to_cpu(desc->size_bytes); | 3289 | psp->asd.size_bytes = le32_to_cpu(desc->size_bytes); |
| 3100 | psp->asd_start_addr = ucode_start_addr; | 3290 | psp->asd.start_addr = ucode_start_addr; |
| 3101 | break; | 3291 | break; |
| 3102 | case TA_FW_TYPE_PSP_XGMI: | 3292 | case TA_FW_TYPE_PSP_XGMI: |
| 3103 | psp->ta_xgmi_ucode_version = le32_to_cpu(desc->fw_version); | 3293 | psp->xgmi.feature_version = le32_to_cpu(desc->fw_version); |
| 3104 | psp->ta_xgmi_ucode_size = le32_to_cpu(desc->size_bytes); | 3294 | psp->xgmi.size_bytes = le32_to_cpu(desc->size_bytes); |
| 3105 | psp->ta_xgmi_start_addr = ucode_start_addr; | 3295 | psp->xgmi.start_addr = ucode_start_addr; |
| 3106 | break; | 3296 | break; |
| 3107 | case TA_FW_TYPE_PSP_RAS: | 3297 | case TA_FW_TYPE_PSP_RAS: |
| 3108 | psp->ta_ras_ucode_version = le32_to_cpu(desc->fw_version); | 3298 | psp->ras.feature_version = le32_to_cpu(desc->fw_version); |
| 3109 | psp->ta_ras_ucode_size = le32_to_cpu(desc->size_bytes); | 3299 | psp->ras.size_bytes = le32_to_cpu(desc->size_bytes); |
| 3110 | psp->ta_ras_start_addr = ucode_start_addr; | 3300 | psp->ras.start_addr = ucode_start_addr; |
| 3111 | break; | 3301 | break; |
| 3112 | case TA_FW_TYPE_PSP_HDCP: | 3302 | case TA_FW_TYPE_PSP_HDCP: |
| 3113 | psp->ta_hdcp_ucode_version = le32_to_cpu(desc->fw_version); | 3303 | psp->hdcp.feature_version = le32_to_cpu(desc->fw_version); |
| 3114 | psp->ta_hdcp_ucode_size = le32_to_cpu(desc->size_bytes); | 3304 | psp->hdcp.size_bytes = le32_to_cpu(desc->size_bytes); |
| 3115 | psp->ta_hdcp_start_addr = ucode_start_addr; | 3305 | psp->hdcp.start_addr = ucode_start_addr; |
| 3116 | break; | 3306 | break; |
| 3117 | case TA_FW_TYPE_PSP_DTM: | 3307 | case TA_FW_TYPE_PSP_DTM: |
| 3118 | psp->ta_dtm_ucode_version = le32_to_cpu(desc->fw_version); | 3308 | psp->dtm.feature_version = le32_to_cpu(desc->fw_version); |
| 3119 | psp->ta_dtm_ucode_size = le32_to_cpu(desc->size_bytes); | 3309 | psp->dtm.size_bytes = le32_to_cpu(desc->size_bytes); |
| 3120 | psp->ta_dtm_start_addr = ucode_start_addr; | 3310 | psp->dtm.start_addr = ucode_start_addr; |
| 3121 | break; | 3311 | break; |
| 3122 | case TA_FW_TYPE_PSP_RAP: | 3312 | case TA_FW_TYPE_PSP_RAP: |
| 3123 | psp->ta_rap_ucode_version = le32_to_cpu(desc->fw_version); | 3313 | psp->rap.feature_version = le32_to_cpu(desc->fw_version); |
| 3124 | psp->ta_rap_ucode_size = le32_to_cpu(desc->size_bytes); | 3314 | psp->rap.size_bytes = le32_to_cpu(desc->size_bytes); |
| 3125 | psp->ta_rap_start_addr = ucode_start_addr; | 3315 | psp->rap.start_addr = ucode_start_addr; |
| 3126 | break; | 3316 | break; |
| 3127 | case TA_FW_TYPE_PSP_SECUREDISPLAY: | 3317 | case TA_FW_TYPE_PSP_SECUREDISPLAY: |
| 3128 | psp->ta_securedisplay_ucode_version = le32_to_cpu(desc->fw_version); | 3318 | psp->securedisplay.feature_version = le32_to_cpu(desc->fw_version); |
| 3129 | psp->ta_securedisplay_ucode_size = le32_to_cpu(desc->size_bytes); | 3319 | psp->securedisplay.size_bytes = le32_to_cpu(desc->size_bytes); |
| 3130 | psp->ta_securedisplay_start_addr = ucode_start_addr; | 3320 | psp->securedisplay.start_addr = ucode_start_addr; |
| 3131 | break; | 3321 | break; |
| 3132 | default: | 3322 | default: |
| 3133 | dev_warn(psp->adev->dev, "Unsupported TA type: %d\n", desc->fw_type); | 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 | goto out; | 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 | dev_err(adev->dev, "packed TA count exceeds maximum limit\n"); | 3362 | dev_err(adev->dev, "packed TA count exceeds maximum limit\n"); |
| 3173 | err = -EINVAL; | 3363 | err = -EINVAL; |
| 3174 | goto out; | 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 | struct drm_device *ddev = dev_get_drvdata(dev); | 3426 | struct drm_device *ddev = dev_get_drvdata(dev); |
| 3237 | struct amdgpu_device *adev = drm_to_adev(ddev); | 3427 | struct amdgpu_device *adev = drm_to_adev(ddev); |
| 3238 | void *cpu_addr; | ||
| 3239 | dma_addr_t dma_addr; | ||
| 3240 | int ret, idx; | 3428 | int ret, idx; |
| 3241 | char fw_name[100]; | 3429 | char fw_name[100]; |
| 3242 | const struct firmware *usbc_pd_fw; | 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 | if (!adev->ip_blocks[AMD_IP_BLOCK_TYPE_PSP].status.late_initialized) { | 3435 | if (!adev->ip_blocks[AMD_IP_BLOCK_TYPE_PSP].status.late_initialized) { |
| 3245 | DRM_INFO("PSP block is not ready yet."); | 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 | if (ret) | 3445 | if (ret) |
| 3255 | goto fail; | 3446 | goto fail; |
| 3256 | 3447 | ||
| 3257 | /* We need contiguous physical mem to place the FW for psp to access */ | 3448 | /* LFB address which is aligned to 1MB boundary per PSP request */ |
| 3258 | cpu_addr = dma_alloc_coherent(adev->dev, usbc_pd_fw->size, &dma_addr, GFP_KERNEL); | 3449 | ret = amdgpu_bo_create_kernel(adev, usbc_pd_fw->size, 0x100000, |
| 3259 | 3450 | AMDGPU_GEM_DOMAIN_VRAM, | |
| 3260 | ret = dma_mapping_error(adev->dev, dma_addr); | 3451 | &fw_buf_bo, |
| 3452 | &fw_pri_mc_addr, | ||
| 3453 | &fw_pri_cpu_addr); | ||
| 3261 | if (ret) | 3454 | if (ret) |
| 3262 | goto rel_buf; | 3455 | goto rel_buf; |
| 3263 | 3456 | ||
| 3264 | memcpy_toio(cpu_addr, usbc_pd_fw->data, usbc_pd_fw->size); | 3457 | memcpy_toio(fw_pri_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 | ||
| 3275 | 3458 | ||
| 3276 | mutex_lock(&adev->psp.mutex); | 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 | mutex_unlock(&adev->psp.mutex); | 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 | rel_buf: | 3465 | rel_buf: |
| 3281 | dma_free_coherent(adev->dev, usbc_pd_fw->size, cpu_addr, dma_addr); | ||
| 3282 | release_firmware(usbc_pd_fw); | 3466 | release_firmware(usbc_pd_fw); |
| 3283 | fail: | 3467 | fail: |
| 3284 | if (ret) { | 3468 | if (ret) { |
| @@ -3307,7 +3491,10 @@ static DEVICE_ATTR(usbc_pd_fw, S_IRUGO | S_IWUSR, · 22 unmodified lines | |||
| 3307 | psp_usbc_pd_fw_sysfs_read, | 3491 | psp_usbc_pd_fw_sysfs_read, |
| 3308 | psp_usbc_pd_fw_sysfs_write); | 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 | const struct amd_ip_funcs psp_ip_funcs = { | 3499 | const struct amd_ip_funcs psp_ip_funcs = { |
| 3313 | .name = "psp", | 3500 | .name = "psp", |
| @@ -3369,6 +3556,14 @@ const struct amdgpu_ip_block_version psp_v11_0_ip_block = · 55 unmodified lines | |||
| 3369 | .funcs = &psp_ip_funcs, | 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 | const struct amdgpu_ip_block_version psp_v12_0_ip_block = | 3567 | const struct amdgpu_ip_block_version psp_v12_0_ip_block = |
| 3373 | { | 3568 | { |
| 3374 | .type = AMD_IP_BLOCK_TYPE_PSP, | 3569 | .type = AMD_IP_BLOCK_TYPE_PSP, |
| @@ -48,11 +48,15 @@ · 47 unmodified lines | |||
| 48 | struct psp_context; | 48 | struct psp_context; |
| 49 | struct psp_xgmi_node_info; | 49 | struct psp_xgmi_node_info; |
| 50 | struct psp_xgmi_topology_info; | 50 | struct psp_xgmi_topology_info; |
| 51 | struct psp_bin_desc; | ||
| 51 | 52 | ||
| 52 | enum psp_bootloader_cmd { | 53 | enum psp_bootloader_cmd { |
| 53 | PSP_BL__LOAD_SYSDRV = 0x10000, | 54 | PSP_BL__LOAD_SYSDRV = 0x10000, |
| 54 | PSP_BL__LOAD_SOSDRV = 0x20000, | 55 | PSP_BL__LOAD_SOSDRV = 0x20000, |
| 55 | PSP_BL__LOAD_KEY_DATABASE = 0x80000, | 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 | PSP_BL__DRAM_LONG_TRAIN = 0x100000, | 60 | PSP_BL__DRAM_LONG_TRAIN = 0x100000, |
| 57 | PSP_BL__DRAM_SHORT_TRAIN = 0x200000, | 61 | PSP_BL__DRAM_SHORT_TRAIN = 0x200000, |
| 58 | PSP_BL__LOAD_TOS_SPL_TABLE = 0x10000000, | 62 | PSP_BL__LOAD_TOS_SPL_TABLE = 0x10000000, |
| @@ -93,6 +97,9 @@ struct psp_funcs · 34 unmodified lines | |||
| 93 | int (*bootloader_load_kdb)(struct psp_context *psp); | 97 | int (*bootloader_load_kdb)(struct psp_context *psp); |
| 94 | int (*bootloader_load_spl)(struct psp_context *psp); | 98 | int (*bootloader_load_spl)(struct psp_context *psp); |
| 95 | int (*bootloader_load_sysdrv)(struct psp_context *psp); | 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 | int (*bootloader_load_sos)(struct psp_context *psp); | 103 | int (*bootloader_load_sos)(struct psp_context *psp); |
| 97 | int (*ring_init)(struct psp_context *psp, enum psp_ring_type ring_type); | 104 | int (*ring_init)(struct psp_context *psp, enum psp_ring_type ring_type); |
| 98 | int (*ring_create)(struct psp_context *psp, | 105 | int (*ring_create)(struct psp_context *psp, |
| @@ -106,7 +113,7 @@ struct psp_funcs · 7 unmodified lines | |||
| 106 | int (*mem_training)(struct psp_context *psp, uint32_t ops); | 113 | int (*mem_training)(struct psp_context *psp, uint32_t ops); |
| 107 | uint32_t (*ring_get_wptr)(struct psp_context *psp); | 114 | uint32_t (*ring_get_wptr)(struct psp_context *psp); |
| 108 | void (*ring_set_wptr)(struct psp_context *psp, uint32_t value); | 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 | int (*read_usbc_pd_fw)(struct psp_context *psp, uint32_t *fw_ver); | 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 | uint8_t num_hops; | 123 | uint8_t num_hops; |
| 117 | uint8_t is_sharing_enabled; | 124 | uint8_t is_sharing_enabled; |
| 118 | enum ta_xgmi_assigned_sdma_engine sdma_engine; | 125 | enum ta_xgmi_assigned_sdma_engine sdma_engine; |
| 126 | uint8_t num_links; | ||
| 119 | }; | 127 | }; |
| 120 | 128 | ||
| 121 | struct psp_xgmi_topology_info { | 129 | struct psp_xgmi_topology_info { |
| @@ -128,59 +136,32 @@ struct psp_asd_context { · 6 unmodified lines | |||
| 128 | uint32_t session_id; | 136 | uint32_t session_id; |
| 129 | }; | 137 | }; |
| 130 | 138 | ||
| 131 | struct psp_xgmi_context { | 139 | struct ta_mem_context { |
| 132 | uint8_t initialized; | 140 | struct amdgpu_bo *shared_bo; |
| 133 | uint32_t session_id; | 141 | uint64_t shared_mc_addr; |
| 134 | struct amdgpu_bo *xgmi_shared_bo; | 142 | void *shared_buf; |
| 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; | ||
| 148 | }; | 143 | }; |
| 149 | 144 | ||
| 150 | struct psp_hdcp_context { | 145 | struct ta_context { |
| 151 | bool hdcp_initialized; | 146 | bool initialized; |
| 152 | uint32_t session_id; | 147 | uint32_t session_id; |
| 153 | struct amdgpu_bo *hdcp_shared_bo; | 148 | struct ta_mem_context mem_context; |
| 154 | uint64_t hdcp_shared_mc_addr; | ||
| 155 | void *hdcp_shared_buf; | ||
| 156 | struct mutex mutex; | ||
| 157 | }; | 149 | }; |
| 158 | 150 | ||
| 159 | struct psp_dtm_context { | 151 | struct ta_cp_context { |
| 160 | bool dtm_initialized; | 152 | struct ta_context context; |
| 161 | uint32_t session_id; | 153 | struct mutex mutex; |
| 162 | struct amdgpu_bo *dtm_shared_bo; | ||
| 163 | uint64_t dtm_shared_mc_addr; | ||
| 164 | void *dtm_shared_buf; | ||
| 165 | struct mutex mutex; | ||
| 166 | }; | 154 | }; |
| 167 | 155 | ||
| 168 | struct psp_rap_context { | 156 | struct psp_xgmi_context { |
| 169 | bool rap_initialized; | 157 | struct ta_context context; |
| 170 | uint32_t session_id; | 158 | struct psp_xgmi_topology_info top_info; |
| 171 | struct amdgpu_bo *rap_shared_bo; | 159 | bool supports_extended_data; |
| 172 | uint64_t rap_shared_mc_addr; | ||
| 173 | void *rap_shared_buf; | ||
| 174 | struct mutex mutex; | ||
| 175 | }; | 160 | }; |
| 176 | 161 | ||
| 177 | struct psp_securedisplay_context { | 162 | struct psp_ras_context { |
| 178 | bool securedisplay_initialized; | 163 | struct ta_context context; |
| 179 | uint32_t session_id; | 164 | struct amdgpu_ras *ras; |
| 180 | struct amdgpu_bo *securedisplay_shared_bo; | ||
| 181 | uint64_t securedisplay_shared_mc_addr; | ||
| 182 | void *securedisplay_shared_buf; | ||
| 183 | struct mutex mutex; | ||
| 184 | }; | 165 | }; |
| 185 | 166 | ||
| 186 | #define MEM_TRAIN_SYSTEM_SIGNATURE 0x54534942 | 167 | #define MEM_TRAIN_SYSTEM_SIGNATURE 0x54534942 |
| @@ -282,6 +263,13 @@ struct psp_runtime_boot_cfg_entry { · 95 unmodified lines | |||
| 282 | uint32_t reserved; | 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 | struct psp_context | 273 | struct psp_context |
| 286 | { | 274 | { |
| 287 | struct amdgpu_device *adev; | 275 | struct amdgpu_device *adev; |
| @@ -297,36 +285,26 @@ struct psp_context · 9 unmodified lines | |||
| 297 | 285 | ||
| 298 | /* sos firmware */ | 286 | /* sos firmware */ |
| 299 | const struct firmware *sos_fw; | 287 | const struct firmware *sos_fw; |
| 300 | uint32_t sos_fw_version; | 288 | struct psp_bin_desc sys; |
| 301 | uint32_t sos_feature_version; | 289 | struct psp_bin_desc sos; |
| 302 | uint32_t sys_bin_size; | 290 | struct psp_bin_desc toc; |
| 303 | uint32_t sos_bin_size; | 291 | struct psp_bin_desc kdb; |
| 304 | uint32_t toc_bin_size; | 292 | struct psp_bin_desc spl; |
| 305 | uint32_t kdb_bin_size; | 293 | struct psp_bin_desc rl; |
| 306 | uint32_t spl_bin_size; | 294 | struct psp_bin_desc soc_drv; |
| 307 | uint32_t rl_bin_size; | 295 | struct psp_bin_desc intf_drv; |
| 308 | uint8_t *sys_start_addr; | 296 | struct psp_bin_desc dbg_drv; |
| 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; | ||
| 314 | 297 | ||
| 315 | /* tmr buffer */ | 298 | /* tmr buffer */ |
| 316 | struct amdgpu_bo *tmr_bo; | 299 | struct amdgpu_bo *tmr_bo; |
| 317 | uint64_t tmr_mc_addr; | 300 | uint64_t tmr_mc_addr; |
| 318 | 301 | ||
| 319 | /* asd firmware */ | 302 | /* asd firmware */ |
| 320 | const struct firmware *asd_fw; | 303 | const struct firmware *asd_fw; |
| 321 | uint32_t asd_fw_version; | 304 | struct psp_bin_desc asd; |
| 322 | uint32_t asd_feature_version; | ||
| 323 | uint32_t asd_ucode_size; | ||
| 324 | uint8_t *asd_start_addr; | ||
| 325 | 305 | ||
| 326 | /* toc firmware */ | 306 | /* toc firmware */ |
| 327 | const struct firmware *toc_fw; | 307 | const struct firmware *toc_fw; |
| 328 | uint32_t toc_fw_version; | ||
| 329 | uint32_t toc_feature_version; | ||
| 330 | 308 | ||
| 331 | /* fence buffer */ | 309 | /* fence buffer */ |
| 332 | struct amdgpu_bo *fence_buf_bo; | 310 | struct amdgpu_bo *fence_buf_bo; |
| @@ -348,36 +326,20 @@ struct psp_context · 15 unmodified lines | |||
| 348 | /* xgmi ta firmware and buffer */ | 326 | /* xgmi ta firmware and buffer */ |
| 349 | const struct firmware *ta_fw; | 327 | const struct firmware *ta_fw; |
| 350 | uint32_t ta_fw_version; | 328 | uint32_t ta_fw_version; |
| 351 | uint32_t ta_xgmi_ucode_version; | 329 | struct psp_bin_desc xgmi; |
| 352 | uint32_t ta_xgmi_ucode_size; | 330 | struct psp_bin_desc ras; |
| 353 | uint8_t *ta_xgmi_start_addr; | 331 | struct psp_bin_desc hdcp; |
| 354 | uint32_t ta_ras_ucode_version; | 332 | struct psp_bin_desc dtm; |
| 355 | uint32_t ta_ras_ucode_size; | 333 | struct psp_bin_desc rap; |
| 356 | uint8_t *ta_ras_start_addr; | 334 | struct psp_bin_desc securedisplay; |
| 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; | ||
| 373 | 335 | ||
| 374 | struct psp_asd_context asd_context; | 336 | struct psp_asd_context asd_context; |
| 375 | struct psp_xgmi_context xgmi_context; | 337 | struct psp_xgmi_context xgmi_context; |
| 376 | struct psp_ras_context ras; | 338 | struct psp_ras_context ras_context; |
| 377 | struct psp_hdcp_context hdcp_context; | 339 | struct ta_cp_context hdcp_context; |
| 378 | struct psp_dtm_context dtm_context; | 340 | struct ta_cp_context dtm_context; |
| 379 | struct psp_rap_context rap_context; | 341 | struct ta_cp_context rap_context; |
| 380 | struct psp_securedisplay_context securedisplay_context; | 342 | struct ta_cp_context securedisplay_context; |
| 381 | struct mutex mutex; | 343 | struct mutex mutex; |
| 382 | struct psp_memory_training_context mem_train_ctx; | 344 | struct psp_memory_training_context mem_train_ctx; |
| 383 | 345 | ||
| @@ -402,6 +364,12 @@ struct amdgpu_psp_funcs { · 18 unmodified lines | |||
| 402 | ((psp)->funcs->bootloader_load_spl ? (psp)->funcs->bootloader_load_spl((psp)) : 0) | 364 | ((psp)->funcs->bootloader_load_spl ? (psp)->funcs->bootloader_load_spl((psp)) : 0) |
| 403 | #define psp_bootloader_load_sysdrv(psp) \ | 365 | #define psp_bootloader_load_sysdrv(psp) \ |
| 404 | ((psp)->funcs->bootloader_load_sysdrv ? (psp)->funcs->bootloader_load_sysdrv((psp)) : 0) | 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 | #define psp_bootloader_load_sos(psp) \ | 373 | #define psp_bootloader_load_sos(psp) \ |
| 406 | ((psp)->funcs->bootloader_load_sos ? (psp)->funcs->bootloader_load_sos((psp)) : 0) | 374 | ((psp)->funcs->bootloader_load_sos ? (psp)->funcs->bootloader_load_sos((psp)) : 0) |
| 407 | #define psp_smu_reload_quirk(psp) \ | 375 | #define psp_smu_reload_quirk(psp) \ |
| @@ -414,9 +382,9 @@ struct amdgpu_psp_funcs { · 6 unmodified lines | |||
| 414 | #define psp_ring_get_wptr(psp) (psp)->funcs->ring_get_wptr((psp)) | 382 | #define psp_ring_get_wptr(psp) (psp)->funcs->ring_get_wptr((psp)) |
| 415 | #define psp_ring_set_wptr(psp, value) (psp)->funcs->ring_set_wptr((psp), (value)) | 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 | ((psp)->funcs->load_usbc_pd_fw ? \ | 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 | #define psp_read_usbc_pd_fw(psp, fw_ver) \ | 389 | #define psp_read_usbc_pd_fw(psp, fw_ver) \ |
| 422 | ((psp)->funcs->read_usbc_pd_fw ? \ | 390 | ((psp)->funcs->read_usbc_pd_fw ? \ |
| @@ -427,6 +395,7 @@ extern const struct amd_ip_funcs psp_ip_funcs; · 4 unmodified lines | |||
| 427 | extern const struct amdgpu_ip_block_version psp_v3_1_ip_block; | 395 | extern const struct amdgpu_ip_block_version psp_v3_1_ip_block; |
| 428 | extern const struct amdgpu_ip_block_version psp_v10_0_ip_block; | 396 | extern const struct amdgpu_ip_block_version psp_v10_0_ip_block; |
| 429 | extern const struct amdgpu_ip_block_version psp_v11_0_ip_block; | 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 | extern const struct amdgpu_ip_block_version psp_v12_0_ip_block; | 399 | extern const struct amdgpu_ip_block_version psp_v12_0_ip_block; |
| 431 | extern const struct amdgpu_ip_block_version psp_v13_0_ip_block; | 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 | int psp_update_vcn_sram(struct amdgpu_device *adev, int inst_idx, | 406 | int psp_update_vcn_sram(struct amdgpu_device *adev, int inst_idx, |
| 438 | uint64_t cmd_gpu_addr, int cmd_size); | 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 | int psp_xgmi_terminate(struct psp_context *psp); | 410 | int psp_xgmi_terminate(struct psp_context *psp); |
| 442 | int psp_xgmi_invoke(struct psp_context *psp, uint32_t ta_cmd_id); | 411 | int psp_xgmi_invoke(struct psp_context *psp, uint32_t ta_cmd_id); |
| 443 | int psp_xgmi_get_hive_id(struct psp_context *psp, uint64_t *hive_id); | 412 | int psp_xgmi_get_hive_id(struct psp_context *psp, uint64_t *hive_id); |
| 444 | int psp_xgmi_get_node_id(struct psp_context *psp, uint64_t *node_id); | 413 | int psp_xgmi_get_node_id(struct psp_context *psp, uint64_t *node_id); |
| 445 | int psp_xgmi_get_topology_info(struct psp_context *psp, | 414 | int psp_xgmi_get_topology_info(struct psp_context *psp, |
| 446 | int number_devices, | 415 | int number_devices, |
| 447 | struct psp_xgmi_topology_info *topology); | 416 | struct psp_xgmi_topology_info *topology, |
| 417 | bool get_extended_data); | ||
| 448 | int psp_xgmi_set_topology_info(struct psp_context *psp, | 418 | int psp_xgmi_set_topology_info(struct psp_context *psp, |
| 449 | int number_devices, | 419 | int number_devices, |
| 450 | struct psp_xgmi_topology_info *topology); | 420 | struct psp_xgmi_topology_info *topology); |
| @@ -483,4 +453,5 @@ int psp_load_fw_list(struct psp_context *psp, · 32 unmodified lines | |||
| 483 | struct amdgpu_firmware_info **ucode_list, int ucode_count); | 453 | struct amdgpu_firmware_info **ucode_list, int ucode_count); |
| 484 | void psp_copy_fw(struct psp_context *psp, uint8_t *start_addr, uint32_t bin_size); | 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 | #endif | 457 | #endif |
| @@ -76,7 +76,7 @@ static ssize_t amdgpu_rap_debugfs_write(struct file *f, const char __user *buf, · 75 unmodified lines | |||
| 76 | dev_info(adev->dev, "RAP L0 validate test success.\n"); | 76 | dev_info(adev->dev, "RAP L0 validate test success.\n"); |
| 77 | } else { | 77 | } else { |
| 78 | rap_shared_mem = (struct ta_rap_shared_memory *) | 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 | rap_cmd_output = &(rap_shared_mem->rap_out_message.output); | 80 | rap_cmd_output = &(rap_shared_mem->rap_out_message.output); |
| 81 | 81 | ||
| 82 | dev_info(adev->dev, "RAP test failed, the output is:\n"); | 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 | #if defined(CONFIG_DEBUG_FS) | 119 | #if defined(CONFIG_DEBUG_FS) |
| 120 | struct drm_minor *minor = adev_to_drm(adev)->primary; | 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 | return; | 123 | return; |
| 124 | 124 | ||
| 125 | debugfs_create_file("rap_test", S_IWUSR, minor->debugfs_root, | 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 | #define ras_err_str(i) (ras_error_string[ffs(i)]) | 66 | #define ras_err_str(i) (ras_error_string[ffs(i)]) |
| 67 | #define ras_block_str(i) (ras_block_string[i]) | ||
| 68 | 67 | ||
| 69 | #define RAS_DEFAULT_FLAGS (AMDGPU_RAS_FLAG_INIT_BY_VBIOS) | 68 | #define RAS_DEFAULT_FLAGS (AMDGPU_RAS_FLAG_INIT_BY_VBIOS) |
| 70 | 69 | ||
| 71 | /* inject address is 52 bits */ | 70 | /* inject address is 52 bits */ |
| 72 | #define RAS_UMC_INJECT_ADDR_LIMIT (0x1ULL << 52) | 71 | #define RAS_UMC_INJECT_ADDR_LIMIT (0x1ULL << 52) |
| 73 | 72 | ||
| 74 | /* typical ECC bad page rate(1 bad page per 100MB VRAM) */ | 73 | /* typical ECC bad page rate is 1 bad page per 100MB VRAM */ |
| 75 | #define RAS_BAD_PAGE_RATE (100 * 1024 * 1024ULL) | 74 | #define RAS_BAD_PAGE_COVER (100 * 1024 * 1024ULL) |
| 76 | 75 | ||
| 77 | enum amdgpu_ras_retire_page_reservation { | 76 | enum amdgpu_ras_retire_page_reservation { |
| 78 | AMDGPU_RAS_RETIRE_PAGE_RESERVED, | 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 | * to see which blocks support RAS on a particular asic. | 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, | 357 | static ssize_t amdgpu_ras_debugfs_ctrl_write(struct file *f, |
| 359 | size_t size, loff_t *pos) | 358 | const char __user *buf, |
| 359 | size_t size, loff_t *pos) | ||
| 360 | { | 360 | { |
| 361 | struct amdgpu_device *adev = (struct amdgpu_device *)file_inode(f)->i_private; | 361 | struct amdgpu_device *adev = (struct amdgpu_device *)file_inode(f)->i_private; |
| 362 | struct ras_debug_if data; | 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 | ret = amdgpu_ras_debugfs_ctrl_parse_data(f, buf, size, pos, &data); | 371 | ret = amdgpu_ras_debugfs_ctrl_parse_data(f, buf, size, pos, &data); |
| 372 | if (ret) | 372 | if (ret) |
| 373 | return -EINVAL; | 373 | return ret; |
| 374 | 374 | ||
| 375 | if (data.op == 3) { | 375 | if (data.op == 3) { |
| 376 | ret = amdgpu_reserve_page_direct(adev, data.inject.address); | 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 | /* umc ce/ue error injection for a bad page is not allowed */ | 403 | /* umc ce/ue error injection for a bad page is not allowed */ |
| 404 | if ((data.head.block == AMDGPU_RAS_BLOCK__UMC) && | 404 | if ((data.head.block == AMDGPU_RAS_BLOCK__UMC) && |
| 405 | amdgpu_ras_check_bad_page(adev, data.inject.address)) { | 405 | amdgpu_ras_check_bad_page(adev, data.inject.address)) { |
| 406 | dev_warn(adev->dev, "RAS WARN: 0x%llx has been marked " | 406 | dev_warn(adev->dev, "RAS WARN: inject: 0x%llx has " |
| 407 | "as bad before error injection!\n", | 407 | "already been marked as bad!\n", |
| 408 | data.inject.address); | 408 | data.inject.address); |
| 409 | break; | 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 | * will reset EEPROM table to 0 entries. | 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, | 442 | static ssize_t amdgpu_ras_debugfs_eeprom_write(struct file *f, |
| 443 | size_t size, loff_t *pos) | 443 | const char __user *buf, |
| 444 | size_t size, loff_t *pos) | ||
| 444 | { | 445 | { |
| 445 | struct amdgpu_device *adev = | 446 | struct amdgpu_device *adev = |
| 446 | (struct amdgpu_device *)file_inode(f)->i_private; | 447 | (struct amdgpu_device *)file_inode(f)->i_private; |
| 447 | int ret; | 448 | int ret; |
| 448 | 449 | ||
| 449 | ret = amdgpu_ras_eeprom_reset_table( | 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 | amdgpu_ras_get_context(adev)->flags = RAS_DEFAULT_FLAGS; | 456 | amdgpu_ras_get_context(adev)->flags = RAS_DEFAULT_FLAGS; |
| 454 | return size; | 457 | return size; |
| 455 | } else { | 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 | if (obj && (--obj->use == 0)) | 529 | if (obj && (--obj->use == 0)) |
| 527 | list_del(&obj->node); | 530 | list_del(&obj->node); |
| 528 | if (obj && (obj->use < 0)) | 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 | /* make one obj and return it. */ | 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 | .type = default_ras_type, | 792 | .type = default_ras_type, |
| 790 | .sub_block_index = 0, | 793 | .sub_block_index = 0, |
| 791 | }; | 794 | }; |
| 792 | strcpy(head.name, ras_block_str(i)); | ||
| 793 | if (bypass) { | 795 | if (bypass) { |
| 794 | /* | 796 | /* |
| 795 | * bypass psp. vbios enable ras for us. | 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 | &con->bad_page_cnt_threshold); | 1318 | &con->bad_page_cnt_threshold); |
| 1317 | debugfs_create_x32("ras_hw_enabled", 0444, dir, &adev->ras_hw_enabled); | 1319 | debugfs_create_x32("ras_hw_enabled", 0444, dir, &adev->ras_hw_enabled); |
| 1318 | debugfs_create_x32("ras_enabled", 0444, dir, &adev->ras_enabled); | 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 | * After one uncorrectable error happens, usually GPU recovery will | 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 | control = &con->eeprom_control; | 1842 | control = &con->eeprom_control; |
| 1835 | data = con->eh_data; | 1843 | data = con->eh_data; |
| 1836 | save_count = data->count - control->num_recs; | 1844 | save_count = data->count - control->ras_num_recs; |
| 1837 | /* only new entries are saved */ | 1845 | /* only new entries are saved */ |
| 1838 | if (save_count > 0) { | 1846 | if (save_count > 0) { |
| 1839 | if (amdgpu_ras_eeprom_process_recods(control, | 1847 | if (amdgpu_ras_eeprom_append(control, |
| 1840 | &data->bps[control->num_recs], | 1848 | &data->bps[control->ras_num_recs], |
| 1841 | true, | 1849 | save_count)) { |
| 1842 | save_count)) { | ||
| 1843 | dev_err(adev->dev, "Failed to save EEPROM table data!"); | 1850 | dev_err(adev->dev, "Failed to save EEPROM table data!"); |
| 1844 | return -EIO; | 1851 | return -EIO; |
| 1845 | } | 1852 | } |
| @@ -1857,28 +1864,24 @@ int amdgpu_ras_save_bad_pages(struct amdgpu_device *adev) · 11 unmodified lines | |||
| 1857 | static int amdgpu_ras_load_bad_pages(struct amdgpu_device *adev) | 1864 | static int amdgpu_ras_load_bad_pages(struct amdgpu_device *adev) |
| 1858 | { | 1865 | { |
| 1859 | struct amdgpu_ras_eeprom_control *control = | 1866 | struct amdgpu_ras_eeprom_control *control = |
| 1860 | &adev->psp.ras.ras->eeprom_control; | 1867 | &adev->psp.ras_context.ras->eeprom_control; |
| 1861 | struct eeprom_table_record *bps = NULL; | 1868 | struct eeprom_table_record *bps; |
| 1862 | int ret = 0; | 1869 | int ret; |
| 1863 | 1870 | ||
| 1864 | /* no bad page record, skip eeprom access */ | 1871 | /* no bad page record, skip eeprom access */ |
| 1865 | if (!control->num_recs || (amdgpu_bad_page_threshold == 0)) | 1872 | if (control->ras_num_recs == 0 || amdgpu_bad_page_threshold == 0) |
| 1866 | return ret; | 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 | if (!bps) | 1876 | if (!bps) |
| 1870 | return -ENOMEM; | 1877 | return -ENOMEM; |
| 1871 | 1878 | ||
| 1872 | if (amdgpu_ras_eeprom_process_recods(control, bps, false, | 1879 | ret = amdgpu_ras_eeprom_read(control, bps, control->ras_num_recs); |
| 1873 | control->num_recs)) { | 1880 | if (ret) |
| 1874 | dev_err(adev->dev, "Failed to load EEPROM table records!"); | 1881 | dev_err(adev->dev, "Failed to load EEPROM table records!"); |
| 1875 | ret = -EIO; | 1882 | else |
| 1876 | goto out; | 1883 | ret = amdgpu_ras_add_bad_pages(adev, bps, control->ras_num_recs); |
| 1877 | } | ||
| 1878 | |||
| 1879 | ret = amdgpu_ras_add_bad_pages(adev, bps, control->num_recs); | ||
| 1880 | 1884 | ||
| 1881 | out: | ||
| 1882 | kfree(bps); | 1885 | kfree(bps); |
| 1883 | return ret; | 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 | static void amdgpu_ras_validate_threshold(struct amdgpu_device *adev, | 1923 | static void amdgpu_ras_validate_threshold(struct amdgpu_device *adev, |
| 1921 | uint32_t max_length) | 1924 | uint32_t max_count) |
| 1922 | { | 1925 | { |
| 1923 | struct amdgpu_ras *con = amdgpu_ras_get_context(adev); | 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 | * Justification of value bad_page_cnt_threshold in ras structure | 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 | * take no effect. | 1944 | * take no effect. |
| 1944 | */ | 1945 | */ |
| 1945 | 1946 | ||
| 1946 | if (tmp_threshold < -1) | 1947 | if (amdgpu_bad_page_threshold < 0) { |
| 1947 | tmp_threshold = -1; | 1948 | u64 val = adev->gmc.mc_vram_size; |
| 1948 | else if (tmp_threshold > max_length) | ||
| 1949 | tmp_threshold = max_length; | ||
| 1950 | 1949 | ||
| 1951 | if (tmp_threshold == -1) { | 1950 | do_div(val, RAS_BAD_PAGE_COVER); |
| 1952 | val = adev->gmc.mc_vram_size; | ||
| 1953 | do_div(val, RAS_BAD_PAGE_RATE); | ||
| 1954 | con->bad_page_cnt_threshold = min(lower_32_bits(val), | 1951 | con->bad_page_cnt_threshold = min(lower_32_bits(val), |
| 1955 | max_length); | 1952 | max_count); |
| 1956 | } else { | 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 | struct amdgpu_ras *con = amdgpu_ras_get_context(adev); | 1961 | struct amdgpu_ras *con = amdgpu_ras_get_context(adev); |
| 1964 | struct ras_err_handler_data **data; | 1962 | struct ras_err_handler_data **data; |
| 1965 | uint32_t max_eeprom_records_len = 0; | 1963 | u32 max_eeprom_records_count = 0; |
| 1966 | bool exc_err_limit = false; | 1964 | bool exc_err_limit = false; |
| 1967 | int ret; | 1965 | int ret; |
| 1968 | 1966 | ||
| 1969 | if (adev->ras_enabled && con) | 1967 | if (!con) |
| 1970 | data = &con->eh_data; | ||
| 1971 | else | ||
| 1972 | return 0; | 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 | *data = kmalloc(sizeof(**data), GFP_KERNEL | __GFP_ZERO); | 1981 | *data = kmalloc(sizeof(**data), GFP_KERNEL | __GFP_ZERO); |
| 1975 | if (!*data) { | 1982 | if (!*data) { |
| 1976 | ret = -ENOMEM; | 1983 | ret = -ENOMEM; |
| @@ -1980,10 +1987,9 @@ int amdgpu_ras_recovery_init(struct amdgpu_device *adev) · 3 unmodified lines | |||
| 1980 | mutex_init(&con->recovery_lock); | 1987 | mutex_init(&con->recovery_lock); |
| 1981 | INIT_WORK(&con->recovery_work, amdgpu_ras_do_recovery); | 1988 | INIT_WORK(&con->recovery_work, amdgpu_ras_do_recovery); |
| 1982 | atomic_set(&con->in_recovery, 0); | 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(); | 1991 | max_eeprom_records_count = amdgpu_ras_eeprom_max_record_count(); |
| 1986 | amdgpu_ras_validate_threshold(adev, max_eeprom_records_len); | 1992 | amdgpu_ras_validate_threshold(adev, max_eeprom_records_count); |
| 1987 | 1993 | ||
| 1988 | /* Todo: During test the SMU might fail to read the eeprom through I2C | 1994 | /* Todo: During test the SMU might fail to read the eeprom through I2C |
| 1989 | * when the GPU is pending on XGMI reset during probe time | 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 | if (exc_err_limit || ret) | 2005 | if (exc_err_limit || ret) |
| 2000 | goto free; | 2006 | goto free; |
| 2001 | 2007 | ||
| 2002 | if (con->eeprom_control.num_recs) { | 2008 | if (con->eeprom_control.ras_num_recs) { |
| 2003 | ret = amdgpu_ras_load_bad_pages(adev); | 2009 | ret = amdgpu_ras_load_bad_pages(adev); |
| 2004 | if (ret) | 2010 | if (ret) |
| 2005 | goto free; | 2011 | goto free; |
| 2006 | 2012 | ||
| 2007 | if (adev->smu.ppt_funcs && adev->smu.ppt_funcs->send_hbm_bad_pages_num) | 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 | return 0; | 2017 | return 0; |
| @@ -2015,7 +2021,7 @@ free: · 3 unmodified lines | |||
| 2015 | kfree(*data); | 2021 | kfree(*data); |
| 2016 | con->eh_data = NULL; | 2022 | con->eh_data = NULL; |
| 2017 | out: | 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 | * Except error threshold exceeding case, other failure cases in this | 2027 | * Except error threshold exceeding case, other failure cases in this |
| @@ -49,10 +49,14 @@ enum amdgpu_ras_block { · 48 unmodified lines | |||
| 49 | AMDGPU_RAS_BLOCK__MP0, | 49 | AMDGPU_RAS_BLOCK__MP0, |
| 50 | AMDGPU_RAS_BLOCK__MP1, | 50 | AMDGPU_RAS_BLOCK__MP1, |
| 51 | AMDGPU_RAS_BLOCK__FUSE, | 51 | AMDGPU_RAS_BLOCK__FUSE, |
| 52 | AMDGPU_RAS_BLOCK__MPIO, | ||
| 52 | 53 | ||
| 53 | AMDGPU_RAS_BLOCK__LAST | 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 | #define AMDGPU_RAS_BLOCK_COUNT AMDGPU_RAS_BLOCK__LAST | 60 | #define AMDGPU_RAS_BLOCK_COUNT AMDGPU_RAS_BLOCK__LAST |
| 57 | #define AMDGPU_RAS_BLOCK_MASK ((1ULL << AMDGPU_RAS_BLOCK_COUNT) - 1) | 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 | enum amdgpu_ras_block block; | 310 | enum amdgpu_ras_block block; |
| 307 | enum amdgpu_ras_error_type type; | 311 | enum amdgpu_ras_error_type type; |
| 308 | uint32_t sub_block_index; | 312 | uint32_t sub_block_index; |
| 309 | /* block name */ | ||
| 310 | char name[32]; | 313 | char name[32]; |
| 311 | }; | 314 | }; |
| 312 | 315 | ||
| @@ -318,6 +321,7 @@ struct amdgpu_ras { · 5 unmodified lines | |||
| 318 | /* sysfs */ | 321 | /* sysfs */ |
| 319 | struct device_attribute features_attr; | 322 | struct device_attribute features_attr; |
| 320 | struct bin_attribute badpages_attr; | 323 | struct bin_attribute badpages_attr; |
| 324 | struct dentry *de_ras_eeprom_table; | ||
| 321 | /* block array */ | 325 | /* block array */ |
| 322 | struct ras_manager *objs; | 326 | struct ras_manager *objs; |
| 323 | 327 | ||
| @@ -417,7 +421,7 @@ struct ras_badpage { · 93 unmodified lines | |||
| 417 | /* interfaces for IP */ | 421 | /* interfaces for IP */ |
| 418 | struct ras_fs_if { | 422 | struct ras_fs_if { |
| 419 | struct ras_common_if head; | 423 | struct ras_common_if head; |
| 420 | char sysfs_name[32]; | 424 | const char* sysfs_name; |
| 421 | char debugfs_name[32]; | 425 | char debugfs_name[32]; |
| 422 | }; | 426 | }; |
| 423 | 427 | ||
| @@ -469,8 +473,8 @@ struct ras_debug_if { · 45 unmodified lines | |||
| 469 | * 8: feature disable | 473 | * 8: feature disable |
| 470 | */ | 474 | */ |
| 471 | 475 | ||
| 472 | #define amdgpu_ras_get_context(adev) ((adev)->psp.ras.ras) | 476 | #define amdgpu_ras_get_context(adev) ((adev)->psp.ras_context.ras) |
| 473 | #define amdgpu_ras_set_context(adev, ras_con) ((adev)->psp.ras.ras = (ras_con)) | 477 | #define amdgpu_ras_set_context(adev, ras_con) ((adev)->psp.ras_context.ras = (ras_con)) |
| 474 | 478 | ||
| 475 | /* check if ras is supported on block, say, sdma, gfx */ | 479 | /* check if ras is supported on block, say, sdma, gfx */ |
| 476 | static inline int amdgpu_ras_is_supported(struct amdgpu_device *adev, | 480 | static inline int amdgpu_ras_is_supported(struct amdgpu_device *adev, |
| @@ -26,94 +26,131 @@ · 25 unmodified lines | |||
| 26 | #include "amdgpu_ras.h" | 26 | #include "amdgpu_ras.h" |
| 27 | #include <linux/bits.h> | 27 | #include <linux/bits.h> |
| 28 | #include "atom.h" | 28 | #include "atom.h" |
| 29 | #include "amdgpu_eeprom.h" | ||
| 29 | #include "amdgpu_atomfirmware.h" | 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 | 34 | #define EEPROM_I2C_MADDR_VEGA20 0x0 |
| 32 | #define EEPROM_I2C_TARGET_ADDR_ARCTURUS 0xA8 | 35 | #define EEPROM_I2C_MADDR_ARCTURUS 0x40000 |
| 33 | #define EEPROM_I2C_TARGET_ADDR_ARCTURUS_D342 0xA0 | 36 | #define EEPROM_I2C_MADDR_ARCTURUS_D342 0x0 |
| 34 | #define EEPROM_I2C_TARGET_ADDR_SIENNA_CICHLID 0xA0 | 37 | #define EEPROM_I2C_MADDR_SIENNA_CICHLID 0x0 |
| 35 | #define EEPROM_I2C_TARGET_ADDR_ALDEBARAN 0xA0 | 38 | #define EEPROM_I2C_MADDR_ALDEBARAN 0x0 |
| 36 | 39 | ||
| 37 | /* | 40 | /* |
| 38 | * The 2 macros bellow represent the actual size in bytes that | 41 | * The 2 macros bellow represent the actual size in bytes that |
| 39 | * those entities occupy in the EEPROM memory. | 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 | * uses uint64 to store 6b fields such as retired_page. | 44 | * uses uint64 to store 6b fields such as retired_page. |
| 42 | */ | 45 | */ |
| 43 | #define EEPROM_TABLE_HEADER_SIZE 20 | 46 | #define RAS_TABLE_HEADER_SIZE 20 |
| 44 | #define EEPROM_TABLE_RECORD_SIZE 24 | 47 | #define RAS_TABLE_RECORD_SIZE 24 |
| 45 | |||
| 46 | #define EEPROM_ADDRESS_SIZE 0x2 | ||
| 47 | 48 | ||
| 48 | /* Table hdr is 'AMDR' */ | 49 | /* Table hdr is 'AMDR' */ |
| 49 | #define EEPROM_TABLE_HDR_VAL 0x414d4452 | 50 | #define RAS_TABLE_HDR_VAL 0x414d4452 |
| 50 | #define EEPROM_TABLE_VER 0x00010000 | 51 | #define RAS_TABLE_VER 0x00010000 |
| 51 | 52 | ||
| 52 | /* Bad GPU tag ‘BADG’ */ | 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 */ | 83 | #define RAS_NUM_RECS(_tbl_hdr) (((_tbl_hdr)->tbl_size - \ |
| 56 | #define EEPROM_SIZE_BYTES 256000 | 84 | RAS_TABLE_HEADER_SIZE) / RAS_TABLE_RECORD_SIZE) |
| 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) | ||
| 62 | 85 | ||
| 63 | #define to_amdgpu_device(x) (container_of(x, struct amdgpu_ras, eeprom_control))->adev | 86 | #define to_amdgpu_device(x) (container_of(x, struct amdgpu_ras, eeprom_control))->adev |
| 64 | 87 | ||
| 65 | static bool __is_ras_eeprom_supported(struct amdgpu_device *adev) | 88 | static bool __is_ras_eeprom_supported(struct amdgpu_device *adev) |
| 66 | { | 89 | { |
| 67 | if ((adev->asic_type == CHIP_VEGA20) || | 90 | return adev->asic_type == CHIP_VEGA20 || |
| 68 | (adev->asic_type == CHIP_ARCTURUS) || | 91 | adev->asic_type == CHIP_ARCTURUS || |
| 69 | (adev->asic_type == CHIP_SIENNA_CICHLID) || | 92 | adev->asic_type == CHIP_SIENNA_CICHLID || |
| 70 | (adev->asic_type == CHIP_ALDEBARAN)) | 93 | adev->asic_type == CHIP_ALDEBARAN; |
| 71 | return true; | ||
| 72 | |||
| 73 | return false; | ||
| 74 | } | 94 | } |
| 75 | 95 | ||
| 76 | static bool __get_eeprom_i2c_addr_arct(struct amdgpu_device *adev, | 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 | struct atom_context *atom_ctx = adev->mode_info.atom_context; | 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 | return false; | 102 | return false; |
| 83 | 103 | ||
| 84 | if (strnstr(atom_ctx->vbios_version, | 104 | if (strnstr(atom_ctx->vbios_version, |
| 85 | "D342", | 105 | "D342", |
| 86 | sizeof(atom_ctx->vbios_version))) | 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 | else | 108 | else |
| 89 | *i2c_addr = EEPROM_I2C_TARGET_ADDR_ARCTURUS; | 109 | control->i2c_address = EEPROM_I2C_MADDR_ARCTURUS; |
| 90 | 110 | ||
| 91 | return true; | 111 | return true; |
| 92 | } | 112 | } |
| 93 | 113 | ||
| 94 | static bool __get_eeprom_i2c_addr(struct amdgpu_device *adev, | 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 | return false; | 120 | return false; |
| 99 | 121 | ||
| 100 | if (amdgpu_atomfirmware_ras_rom_addr(adev, (uint8_t*)i2c_addr)) | 122 | control->i2c_address = 0; |
| 101 | return true; | 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 | switch (adev->asic_type) { | 140 | switch (adev->asic_type) { |
| 104 | case CHIP_VEGA20: | 141 | case CHIP_VEGA20: |
| 105 | *i2c_addr = EEPROM_I2C_TARGET_ADDR_VEGA20; | 142 | control->i2c_address = EEPROM_I2C_MADDR_VEGA20; |
| 106 | break; | 143 | break; |
| 107 | 144 | ||
| 108 | case CHIP_ARCTURUS: | 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 | case CHIP_SIENNA_CICHLID: | 148 | case CHIP_SIENNA_CICHLID: |
| 112 | *i2c_addr = EEPROM_I2C_TARGET_ADDR_SIENNA_CICHLID; | 149 | control->i2c_address = EEPROM_I2C_MADDR_SIENNA_CICHLID; |
| 113 | break; | 150 | break; |
| 114 | 151 | ||
| 115 | case CHIP_ALDEBARAN: | 152 | case CHIP_ALDEBARAN: |
| 116 | *i2c_addr = EEPROM_I2C_TARGET_ADDR_ALDEBARAN; | 153 | control->i2c_address = EEPROM_I2C_MADDR_ALDEBARAN; |
| 117 | break; | 154 | break; |
| 118 | 155 | ||
| 119 | default: | 156 | default: |
| @@ -123,10 +160,11 @@ static bool __get_eeprom_i2c_addr(struct amdgpu_device *adev, · 3 unmodified lines | |||
| 123 | return true; | 160 | return true; |
| 124 | } | 161 | } |
| 125 | 162 | ||
| 126 | static void __encode_table_header_to_buff(struct amdgpu_ras_eeprom_table_header *hdr, | 163 | static void |
| 127 | unsigned char *buff) | 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 | pp[0] = cpu_to_le32(hdr->header); | 169 | pp[0] = cpu_to_le32(hdr->header); |
| 132 | pp[1] = cpu_to_le32(hdr->version); | 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 | pp[4] = cpu_to_le32(hdr->checksum); | 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, | 176 | static void |
| 139 | unsigned char *buff) | 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 | hdr->header = le32_to_cpu(pp[0]); | 182 | hdr->header = le32_to_cpu(pp[0]); |
| 144 | hdr->version = le32_to_cpu(pp[1]); | 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 | hdr->checksum = le32_to_cpu(pp[4]); | 186 | hdr->checksum = le32_to_cpu(pp[4]); |
| 148 | } | 187 | } |
| 149 | 188 | ||
| 150 | static int __update_table_header(struct amdgpu_ras_eeprom_control *control, | 189 | static int __write_table_header(struct amdgpu_ras_eeprom_control *control) |
| 151 | unsigned char *buff) | ||
| 152 | { | 190 | { |
| 153 | int ret = 0; | 191 | u8 buf[RAS_TABLE_HEADER_SIZE]; |
| 154 | struct amdgpu_device *adev = to_amdgpu_device(control); | 192 | struct amdgpu_device *adev = to_amdgpu_device(control); |
| 155 | struct i2c_msg msg = { | 193 | int res; |
| 156 | .addr = 0, | ||
| 157 | .flags = 0, | ||
| 158 | .len = EEPROM_ADDRESS_SIZE + EEPROM_TABLE_HEADER_SIZE, | ||
| 159 | .buf = buff, | ||
| 160 | }; | ||
| 161 | |||
| 162 | 194 | ||
| 163 | *(uint16_t *)buff = EEPROM_HDR_START; | 195 | memset(buf, 0, sizeof(buf)); |
| 164 | __encode_table_header_to_buff(&control->tbl_hdr, buff + EEPROM_ADDRESS_SIZE); | 196 | __encode_table_header_to_buf(&control->tbl_hdr, buf); |
| 165 | |||
| 166 | msg.addr = control->i2c_address; | ||
| 167 | 197 | ||
| 168 | /* i2c may be unstable in gpu reset */ | 198 | /* i2c may be unstable in gpu reset */ |
| 169 | down_read(&adev->reset_sem); | 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 | up_read(&adev->reset_sem); | 204 | up_read(&adev->reset_sem); |
| 172 | 205 | ||
| 173 | if (ret < 1) | 206 | if (res < 0) { |
| 174 | DRM_ERROR("Failed to write EEPROM table header, ret:%d", ret); | 207 | DRM_ERROR("Failed to write EEPROM table header:%d", res); |
| 175 | 208 | } else if (res < RAS_TABLE_HEADER_SIZE) { | |
| 176 | return ret; | 209 | DRM_ERROR("Short write:%d out of %d\n", |
| 177 | } | 210 | res, RAS_TABLE_HEADER_SIZE); |
| 178 | 211 | res = -EIO; | |
| 179 | static uint32_t __calc_hdr_byte_sum(struct amdgpu_ras_eeprom_control *control) | 212 | } else { |
| 180 | { | 213 | res = 0; |
| 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 | } | ||
| 204 | } | 214 | } |
| 205 | 215 | ||
| 206 | return tbl_sum; | 216 | return res; |
| 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); | ||
| 232 | } | 217 | } |
| 233 | 218 | ||
| 234 | /* table sum mod 256 + checksum must equals 256 */ | 219 | static u8 __calc_hdr_byte_sum(const struct amdgpu_ras_eeprom_control *control) |
| 235 | static bool __validate_tbl_checksum(struct amdgpu_ras_eeprom_control *control, | ||
| 236 | struct eeprom_table_record *records, int num) | ||
| 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) { | 225 | /* Header checksum, skip checksum field in the calculation */ |
| 241 | DRM_WARN("Checksum mismatch, checksum: %u ", control->tbl_hdr.checksum); | 226 | sz = sizeof(control->tbl_hdr) - sizeof(control->tbl_hdr.checksum); |
| 242 | return false; | 227 | pp = (u8 *) &control->tbl_hdr; |
| 243 | } | 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 | static int amdgpu_ras_eeprom_correct_header_tag( | 235 | static int amdgpu_ras_eeprom_correct_header_tag( |
| 249 | struct amdgpu_ras_eeprom_control *control, | 236 | struct amdgpu_ras_eeprom_control *control, |
| 250 | uint32_t header) | 237 | uint32_t header) |
| 251 | { | 238 | { |
| 252 | unsigned char buff[EEPROM_ADDRESS_SIZE + EEPROM_TABLE_HEADER_SIZE]; | ||
| 253 | struct amdgpu_ras_eeprom_table_header *hdr = &control->tbl_hdr; | 239 | struct amdgpu_ras_eeprom_table_header *hdr = &control->tbl_hdr; |
| 254 | int ret = 0; | 240 | u8 *hh; |
| 255 | 241 | int res; | |
| 256 | memset(buff, 0, EEPROM_ADDRESS_SIZE + EEPROM_TABLE_HEADER_SIZE); | 242 | u8 csum; |
| 257 | 243 | ||
| 258 | mutex_lock(&control->tbl_mutex); | 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 | hdr->header = header; | 252 | hdr->header = header; |
| 260 | ret = __update_table_header(control, buff); | 253 | hdr->checksum = csum; |
| 261 | mutex_unlock(&control->tbl_mutex); | 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 | int amdgpu_ras_eeprom_reset_table(struct amdgpu_ras_eeprom_control *control) | 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 | struct amdgpu_ras_eeprom_table_header *hdr = &control->tbl_hdr; | 269 | struct amdgpu_ras_eeprom_table_header *hdr = &control->tbl_hdr; |
| 270 | int ret = 0; | 270 | u8 csum; |
| 271 | 271 | int res; | |
| 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; | ||
| 314 | 272 | ||
| 315 | if (!__get_eeprom_i2c_addr(adev, &control->i2c_address)) | 273 | mutex_lock(&control->ras_tbl_mutex); |
| 316 | return -EINVAL; | ||
| 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; | 280 | csum = __calc_hdr_byte_sum(control); |
| 321 | /* Read/Create table header from EEPROM address 0 */ | 281 | csum = -csum; |
| 322 | ret = i2c_transfer(&adev->pm.smu_i2c, &msg, 1); | 282 | hdr->checksum = csum; |
| 323 | if (ret < 1) { | 283 | res = __write_table_header(control); |
| 324 | DRM_ERROR("Failed to read EEPROM table header, ret:%d", ret); | ||
| 325 | return ret; | ||
| 326 | } | ||
| 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) { | 288 | amdgpu_ras_debugfs_set_ret_size(control); |
| 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; | ||
| 335 | 289 | ||
| 336 | DRM_DEBUG_DRIVER("Found existing EEPROM table with %d records", | 290 | mutex_unlock(&control->ras_tbl_mutex); |
| 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"); | ||
| 353 | 291 | ||
| 354 | ret = amdgpu_ras_eeprom_reset_table(control); | 292 | return res; |
| 355 | } | ||
| 356 | |||
| 357 | return ret == 1 ? 0 : -EIO; | ||
| 358 | } | 293 | } |
| 359 | 294 | ||
| 360 | static void __encode_table_record_to_buff(struct amdgpu_ras_eeprom_control *control, | 295 | static void |
| 361 | struct eeprom_table_record *record, | 296 | __encode_table_record_to_buf(struct amdgpu_ras_eeprom_control *control, |
| 362 | unsigned char *buff) | 297 | struct eeprom_table_record *record, |
| 298 | unsigned char *buf) | ||
| 363 | { | 299 | { |
| 364 | __le64 tmp = 0; | 300 | __le64 tmp = 0; |
| 365 | int i = 0; | 301 | int i = 0; |
| 366 | 302 | ||
| 367 | /* Next are all record fields according to EEPROM page spec in LE foramt */ | 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 | tmp = cpu_to_le64(record->ts); | 308 | tmp = cpu_to_le64(record->ts); |
| 373 | memcpy(buff + i, &tmp, 8); | 309 | memcpy(buf + i, &tmp, 8); |
| 374 | i += 8; | 310 | i += 8; |
| 375 | 311 | ||
| 376 | tmp = cpu_to_le64((record->offset & 0xffffffffffff)); | 312 | tmp = cpu_to_le64((record->offset & 0xffffffffffff)); |
| 377 | memcpy(buff + i, &tmp, 6); | 313 | memcpy(buf + i, &tmp, 6); |
| 378 | i += 6; | 314 | i += 6; |
| 379 | 315 | ||
| 380 | buff[i++] = record->mem_channel; | 316 | buf[i++] = record->mem_channel; |
| 381 | buff[i++] = record->mcumc_id; | 317 | buf[i++] = record->mcumc_id; |
| 382 | 318 | ||
| 383 | tmp = cpu_to_le64((record->retired_page & 0xffffffffffff)); | 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, | 323 | static void |
| 388 | struct eeprom_table_record *record, | 324 | __decode_table_record_from_buf(struct amdgpu_ras_eeprom_control *control, |
| 389 | unsigned char *buff) | 325 | struct eeprom_table_record *record, |
| 326 | unsigned char *buf) | ||
| 390 | { | 327 | { |
| 391 | __le64 tmp = 0; | 328 | __le64 tmp = 0; |
| 392 | int i = 0; | 329 | int i = 0; |
| 393 | 330 | ||
| 394 | /* Next are all record fields according to EEPROM page spec in LE foramt */ | 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 | record->ts = le64_to_cpu(tmp); | 337 | record->ts = le64_to_cpu(tmp); |
| 401 | i += 8; | 338 | i += 8; |
| 402 | 339 | ||
| 403 | memcpy(&tmp, buff + i, 6); | 340 | memcpy(&tmp, buf + i, 6); |
| 404 | record->offset = (le64_to_cpu(tmp) & 0xffffffffffff); | 341 | record->offset = (le64_to_cpu(tmp) & 0xffffffffffff); |
| 405 | i += 6; | 342 | i += 6; |
| 406 | 343 | ||
| 407 | record->mem_channel = buff[i++]; | 344 | record->mem_channel = buf[i++]; |
| 408 | record->mcumc_id = buff[i++]; | 345 | record->mcumc_id = buf[i++]; |
| 409 | 346 | ||
| 410 | memcpy(&tmp, buff + i, 6); | 347 | memcpy(&tmp, buf + i, 6); |
| 411 | record->retired_page = (le64_to_cpu(tmp) & 0xffffffffffff); | 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 | bool amdgpu_ras_eeprom_check_err_threshold(struct amdgpu_device *adev) | 351 | bool amdgpu_ras_eeprom_check_err_threshold(struct amdgpu_device *adev) |
| 448 | { | 352 | { |
| 449 | struct amdgpu_ras *con = amdgpu_ras_get_context(adev); | 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 | if (!(con->features & BIT(AMDGPU_RAS_BLOCK__UMC))) | 362 | if (!(con->features & BIT(AMDGPU_RAS_BLOCK__UMC))) |
| 459 | return false; | 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 | dev_warn(adev->dev, "This GPU is in BAD status."); | 366 | dev_warn(adev->dev, "This GPU is in BAD status."); |
| 463 | dev_warn(adev->dev, "Please retire it or setting one bigger " | 367 | dev_warn(adev->dev, "Please retire it or set a larger " |
| 464 | "threshold value when reloading driver.\n"); | 368 | "threshold value when reloading driver.\n"); |
| 465 | return true; | 369 | return true; |
| 466 | } | 370 | } |
| 467 | 371 | ||
| 468 | return false; | 372 | return false; |
| 469 | } | 373 | } |
| 470 | 374 | ||
| 471 | int amdgpu_ras_eeprom_process_recods(struct amdgpu_ras_eeprom_control *control, | 375 | /** |
| 472 | struct eeprom_table_record *records, | 376 | * __amdgpu_ras_eeprom_write -- write indexed from buffer to EEPROM |
| 473 | bool write, | 377 | * @control: pointer to control structure |
| 474 | int num) | 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 | struct amdgpu_device *adev = to_amdgpu_device(control); | 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)) | 392 | /* i2c may be unstable in gpu reset */ |
| 484 | return 0; | 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, | 413 | return res; |
| 487 | GFP_KERNEL); | 414 | } |
| 488 | if (!buffs) | ||
| 489 | return -ENOMEM; | ||
| 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); | 429 | /* Encode all of them in one go. |
| 494 | if (!msgs) { | 430 | */ |
| 495 | ret = -ENOMEM; | 431 | pp = buf; |
| 496 | goto free_buff; | 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 | /* | 520 | static int |
| 500 | * If saved bad pages number exceeds the bad page threshold for | 521 | amdgpu_ras_eeprom_update_header(struct amdgpu_ras_eeprom_control *control) |
| 501 | * the whole VRAM, update table header to mark the BAD GPU tag | 522 | { |
| 502 | * and schedule one ras recovery after eeprom write is done, | 523 | struct amdgpu_device *adev = to_amdgpu_device(control); |
| 503 | * this can avoid the missing for latest records. | 524 | struct amdgpu_ras *ras = amdgpu_ras_get_context(adev); |
| 504 | * | 525 | u8 *buf, *pp, csum; |
| 505 | * This new header will be picked up and checked in the bootup | 526 | u32 buf_size; |
| 506 | * by ras recovery, which may break bootup process to notify | 527 | int res; |
| 507 | * user this GPU is in bad state and to retire such GPU for | 528 | |
| 508 | * further check. | 529 | /* Modify the header if it exceeds. |
| 509 | */ | 530 | */ |
| 510 | if (write && (amdgpu_bad_page_threshold != 0) && | 531 | if (amdgpu_bad_page_threshold != 0 && |
| 511 | ((control->num_recs + num) >= ras->bad_page_cnt_threshold)) { | 532 | control->ras_num_recs >= ras->bad_page_cnt_threshold) { |
| 512 | dev_warn(adev->dev, | 533 | dev_warn(adev->dev, |
| 513 | "Saved bad pages(%d) reaches threshold value(%d).\n", | 534 | "Saved bad pages %d reaches threshold value %d\n", |
| 514 | control->num_recs + num, ras->bad_page_cnt_threshold); | 535 | control->ras_num_recs, ras->bad_page_cnt_threshold); |
| 515 | control->tbl_hdr.header = EEPROM_TABLE_HDR_BAD; | 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 */ | 553 | down_read(&adev->reset_sem); |
| 519 | if (write && (control->next_addr + EEPROM_TABLE_RECORD_SIZE * num > EEPROM_SIZE_BYTES)) | 554 | res = amdgpu_eeprom_read(&adev->pm.smu_i2c, |
| 520 | control->next_addr = EEPROM_RECORD_START; | 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 | /* | 570 | /* Recalc the checksum. |
| 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 | ||
| 526 | */ | 571 | */ |
| 527 | for (i = 0; i < num; i++) { | 572 | csum = 0; |
| 528 | buff = &buffs[i * (EEPROM_ADDRESS_SIZE + EEPROM_TABLE_RECORD_SIZE)]; | 573 | for (pp = buf; pp < buf + buf_size; pp++) |
| 529 | record = &records[i]; | 574 | csum += *pp; |
| 530 | msg = &msgs[i]; | 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 | /* | 606 | if (!__is_ras_eeprom_supported(adev)) |
| 535 | * Update bits 16,17 of EEPROM address in I2C address by setting them | 607 | return 0; |
| 536 | * to bits 1,2 of Device address byte | 608 | |
| 537 | */ | 609 | if (num == 0) { |
| 538 | msg->addr = control->i2c_address | | 610 | DRM_ERROR("will not append 0 records\n"); |
| 539 | ((control->next_addr & EEPROM_ADDR_MSB_MASK) >> 15); | 611 | return -EINVAL; |
| 540 | msg->flags = write ? 0 : I2C_M_RD; | 612 | } else if (num > control->ras_max_record_count) { |
| 541 | msg->len = EEPROM_ADDRESS_SIZE + EEPROM_TABLE_RECORD_SIZE; | 613 | DRM_ERROR("cannot append %d records than the size of table %d\n", |
| 542 | msg->buf = buff; | 614 | num, control->ras_max_record_count); |
| 543 | 615 | return -EINVAL; | |
| 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; | ||
| 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 | /* i2c may be unstable in gpu reset */ | 647 | /* i2c may be unstable in gpu reset */ |
| 560 | down_read(&adev->reset_sem); | 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 | up_read(&adev->reset_sem); | 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) { | 691 | if (!__is_ras_eeprom_supported(adev)) |
| 565 | DRM_ERROR("Failed to process EEPROM table records, ret:%d", ret); | 692 | return 0; |
| 566 | 693 | ||
| 567 | /* TODO Restore prev next EEPROM address ? */ | 694 | if (num == 0) { |
| 568 | goto free_msgs; | 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) { | 707 | /* Determine how many records to read, from the first record |
| 573 | for (i = 0; i < num; i++) { | 708 | * index, fri, to the end of the table, and from the beginning |
| 574 | buff = &buffs[i*(EEPROM_ADDRESS_SIZE + EEPROM_TABLE_RECORD_SIZE)]; | 709 | * of the table, such that the total number of records is |
| 575 | record = &records[i]; | 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); | 737 | mutex_lock(&control->ras_tbl_mutex); |
| 578 | } | 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) { | 749 | res = 0; |
| 582 | uint32_t old_hdr_byte_sum = __calc_hdr_byte_sum(control); | 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 | /* | 799 | return res; |
| 585 | * Update table header with size and CRC and account for table | 800 | } |
| 586 | * wrap around where the assumption is that we treat it as empty | 801 | |
| 587 | * table | 802 | const struct file_operations amdgpu_ras_debugfs_eeprom_size_ops = { |
| 588 | * | 803 | .owner = THIS_MODULE, |
| 589 | * TODO - Check the assumption is correct | 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; | 909 | s = *pos - strlen(tbl_hdr_str) - tbl_hdr_fmt_size - |
| 592 | control->num_recs %= EEPROM_MAX_RECORD_NUM; | 910 | strlen(rec_hdr_str); |
| 593 | control->tbl_hdr.tbl_size += EEPROM_TABLE_RECORD_SIZE * num; | 911 | s = s / rec_hdr_fmt_size; |
| 594 | if (control->tbl_hdr.tbl_size > EEPROM_SIZE_BYTES) | 912 | r = *pos - strlen(tbl_hdr_str) - tbl_hdr_fmt_size - |
| 595 | control->tbl_hdr.tbl_size = EEPROM_TABLE_HEADER_SIZE + | 913 | strlen(rec_hdr_str); |
| 596 | control->num_recs * EEPROM_TABLE_RECORD_SIZE; | 914 | r = r % rec_hdr_fmt_size; |
| 597 | 915 | ||
| 598 | __update_tbl_checksum(control, records, num, old_hdr_byte_sum); | 916 | for ( ; size > 0 && s < control->ras_num_recs; s++) { |
| 599 | 917 | u32 ai = RAS_RI_TO_AI(control, s); | |
| 600 | __update_table_header(control, buffs); | 918 | /* Read a single record |
| 601 | } else if (!__validate_tbl_checksum(control, records, num)) { | 919 | */ |
| 602 | DRM_WARN("EEPROM Table checksum mismatch!"); | 920 | res = __amdgpu_ras_eeprom_read(control, dare, ai, 1); |
| 603 | /* TODO Uncomment when EEPROM read/write is relliable */ | 921 | if (res) |
| 604 | /* ret = -EIO; */ | 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: | 952 | static ssize_t |
| 608 | kfree(msgs); | 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: | 973 | if (copy_to_user(buf, &data[*pos], res)) |
| 611 | kfree(buffs); | 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 */ | 1036 | int amdgpu_ras_eeprom_init(struct amdgpu_ras_eeprom_control *control, |
| 624 | #if 0 | 1037 | bool *exceed_err_limit) |
| 625 | void amdgpu_ras_eeprom_test(struct amdgpu_ras_eeprom_control *control) | ||
| 626 | { | 1038 | { |
| 627 | int i; | 1039 | struct amdgpu_device *adev = to_amdgpu_device(control); |
| 628 | struct eeprom_table_record *recs = kcalloc(1, sizeof(*recs), GFP_KERNEL); | 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) | 1050 | /* Verify i2c adapter is initialized */ |
| 631 | return; | 1051 | if (!adev->pm.smu_i2c.algo) |
| 1052 | return -ENOENT; | ||
| 632 | 1053 | ||
| 633 | for (i = 0; i < 1 ; i++) { | 1054 | if (!__get_eeprom_i2c_addr(adev, control)) |
| 634 | recs[i].address = 0xdeadbeef; | 1055 | return -EINVAL; |
| 635 | recs[i].retired_page = i; | 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)) { | 1113 | res = amdgpu_ras_eeprom_reset_table(control); |
| 645 | for (i = 0; i < 1; i++) | 1114 | } |
| 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"); | ||
| 650 | 1115 | ||
| 651 | } else | 1116 | return res < 0 ? res : 0; |
| 652 | DRM_ERROR("Failed in writing to table"); | ||
| 653 | } | 1117 | } |
| 654 | #endif | ||
| @@ -28,10 +28,11 @@ · 27 unmodified lines | |||
| 28 | 28 | ||
| 29 | struct amdgpu_device; | 29 | struct amdgpu_device; |
| 30 | 30 | ||
| 31 | enum amdgpu_ras_eeprom_err_type{ | 31 | enum amdgpu_ras_eeprom_err_type { |
| 32 | AMDGPU_RAS_EEPROM_ERR_PLACE_HOLDER, | 32 | AMDGPU_RAS_EEPROM_ERR_NA, |
| 33 | AMDGPU_RAS_EEPROM_ERR_RECOVERABLE, | 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 | struct amdgpu_ras_eeprom_table_header { | 38 | struct amdgpu_ras_eeprom_table_header { |
| @@ -40,15 +41,45 @@ struct amdgpu_ras_eeprom_table_header { · 2 unmodified lines | |||
| 40 | uint32_t first_rec_offset; | 41 | uint32_t first_rec_offset; |
| 41 | uint32_t tbl_size; | 42 | uint32_t tbl_size; |
| 42 | uint32_t checksum; | 43 | uint32_t checksum; |
| 43 | }__attribute__((__packed__)); | 44 | } __packed; |
| 44 | 45 | ||
| 45 | struct amdgpu_ras_eeprom_control { | 46 | struct amdgpu_ras_eeprom_control { |
| 46 | struct amdgpu_ras_eeprom_table_header tbl_hdr; | 47 | struct amdgpu_ras_eeprom_table_header tbl_hdr; |
| 47 | uint32_t next_addr; | 48 | |
| 48 | unsigned int num_recs; | 49 | /* Base I2C EEPPROM 19-bit memory address, |
| 49 | struct mutex tbl_mutex; | 50 | * where the table is located. For more information, |
| 50 | uint32_t tbl_byte_sum; | 51 | * see top of amdgpu_eeprom.c. |
| 51 | uint16_t i2c_address; // 8-bit represented address | 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 | unsigned char mem_channel; | 106 | unsigned char mem_channel; |
| 76 | unsigned char mcumc_id; | 107 | unsigned char mcumc_id; |
| 77 | }__attribute__((__packed__)); | 108 | } __packed; |
| 78 | 109 | ||
| 79 | int amdgpu_ras_eeprom_init(struct amdgpu_ras_eeprom_control *control, | 110 | int amdgpu_ras_eeprom_init(struct amdgpu_ras_eeprom_control *control, |
| 80 | bool *exceed_err_limit); | 111 | bool *exceed_err_limit); |
| 112 | |||
| 81 | int amdgpu_ras_eeprom_reset_table(struct amdgpu_ras_eeprom_control *control); | 113 | int amdgpu_ras_eeprom_reset_table(struct amdgpu_ras_eeprom_control *control); |
| 82 | 114 | ||
| 83 | bool amdgpu_ras_eeprom_check_err_threshold(struct amdgpu_device *adev); | 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, | 117 | int amdgpu_ras_eeprom_read(struct amdgpu_ras_eeprom_control *control, |
| 86 | struct eeprom_table_record *records, | 118 | struct eeprom_table_record *records, const u32 num); |
| 87 | bool write, | 119 | |
| 88 | int num); | 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 | #endif // _AMDGPU_RAS_EEPROM_H | 130 | #endif // _AMDGPU_RAS_EEPROM_H |
| @@ -48,6 +48,9 @@ · 47 unmodified lines | |||
| 48 | #define AMDGPU_FENCE_FLAG_INT (1 << 1) | 48 | #define AMDGPU_FENCE_FLAG_INT (1 << 1) |
| 49 | #define AMDGPU_FENCE_FLAG_TC_WB_ONLY (1 << 2) | 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 | #define to_amdgpu_ring(s) container_of((s), struct amdgpu_ring, sched) | 54 | #define to_amdgpu_ring(s) container_of((s), struct amdgpu_ring, sched) |
| 52 | 55 | ||
| 53 | #define AMDGPU_IB_POOL_SIZE (1024 * 1024) | 56 | #define AMDGPU_IB_POOL_SIZE (1024 * 1024) |
| @@ -106,9 +109,6 @@ struct amdgpu_fence_driver { · 52 unmodified lines | |||
| 106 | struct dma_fence **fences; | 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 | void amdgpu_fence_driver_force_completion(struct amdgpu_ring *ring); | 112 | void amdgpu_fence_driver_force_completion(struct amdgpu_ring *ring); |
| 113 | 113 | ||
| 114 | int amdgpu_fence_driver_init_ring(struct amdgpu_ring *ring, | 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 | int amdgpu_fence_driver_start_ring(struct amdgpu_ring *ring, | 117 | int amdgpu_fence_driver_start_ring(struct amdgpu_ring *ring, |
| 118 | struct amdgpu_irq_src *irq_src, | 118 | struct amdgpu_irq_src *irq_src, |
| 119 | unsigned irq_type); | 119 | unsigned irq_type); |
| 120 | void amdgpu_fence_driver_suspend(struct amdgpu_device *adev); | 120 | void amdgpu_fence_driver_hw_init(struct amdgpu_device *adev); |
| 121 | void amdgpu_fence_driver_resume(struct amdgpu_device *adev); | 121 | void amdgpu_fence_driver_hw_fini(struct amdgpu_device *adev); |
| 122 | int amdgpu_fence_emit(struct amdgpu_ring *ring, struct dma_fence **fence, | 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 | unsigned flags); | 125 | unsigned flags); |
| 124 | int amdgpu_fence_emit_polling(struct amdgpu_ring *ring, uint32_t *s, | 126 | int amdgpu_fence_emit_polling(struct amdgpu_ring *ring, uint32_t *s, |
| 125 | uint32_t timeout); | 127 | uint32_t timeout); |
| @@ -127,8 +127,8 @@ struct amdgpu_rlc_funcs { · 126 unmodified lines | |||
| 127 | void (*reset)(struct amdgpu_device *adev); | 127 | void (*reset)(struct amdgpu_device *adev); |
| 128 | void (*start)(struct amdgpu_device *adev); | 128 | void (*start)(struct amdgpu_device *adev); |
| 129 | void (*update_spm_vmid)(struct amdgpu_device *adev, unsigned vmid); | 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); | 130 | void (*sriov_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); | 131 | u32 (*sriov_rreg)(struct amdgpu_device *adev, u32 offset, u32 acc_flags, u32 hwip); |
| 132 | bool (*is_rlcg_access_range)(struct amdgpu_device *adev, uint32_t reg); | 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 | adev->sdma.ras_if->block = AMDGPU_RAS_BLOCK__SDMA; | 105 | adev->sdma.ras_if->block = AMDGPU_RAS_BLOCK__SDMA; |
| 106 | adev->sdma.ras_if->type = AMDGPU_RAS_ERROR__MULTI_UNCORRECTABLE; | 106 | adev->sdma.ras_if->type = AMDGPU_RAS_ERROR__MULTI_UNCORRECTABLE; |
| 107 | adev->sdma.ras_if->sub_block_index = 0; | 107 | adev->sdma.ras_if->sub_block_index = 0; |
| 108 | strcpy(adev->sdma.ras_if->name, "sdma"); | ||
| 109 | } | 108 | } |
| 110 | fs_info.head = ih_info->head = *adev->sdma.ras_if; | 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 | void psp_prep_securedisplay_cmd_buf(struct psp_context *psp, struct securedisplay_cmd **cmd, | 80 | void psp_prep_securedisplay_cmd_buf(struct psp_context *psp, struct securedisplay_cmd **cmd, |
| 81 | enum ta_securedisplay_command command_id) | 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 | memset(*cmd, 0, sizeof(struct securedisplay_cmd)); | 84 | memset(*cmd, 0, sizeof(struct securedisplay_cmd)); |
| 85 | (*cmd)->status = TA_SECUREDISPLAY_STATUS__GENERIC_FAILURE; | 85 | (*cmd)->status = TA_SECUREDISPLAY_STATUS__GENERIC_FAILURE; |
| 86 | (*cmd)->cmd_id = command_id; | 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 | #if defined(CONFIG_DEBUG_FS) | 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 | return; | 174 | return; |
| 175 | 175 | ||
| 176 | debugfs_create_file("securedisplay_test", S_IWUSR, adev_to_drm(adev)->primary->debugfs_root, | 176 | debugfs_create_file("securedisplay_test", S_IWUSR, adev_to_drm(adev)->primary->debugfs_root, |
| @@ -28,6 +28,8 @@ · 27 unmodified lines | |||
| 28 | * Christian König <christian.koenig@amd.com> | 28 | * Christian König <christian.koenig@amd.com> |
| 29 | */ | 29 | */ |
| 30 | 30 | ||
| 31 | #include <linux/dma-fence-chain.h> | ||
| 32 | |||
| 31 | #include "amdgpu.h" | 33 | #include "amdgpu.h" |
| 32 | #include "amdgpu_trace.h" | 34 | #include "amdgpu_trace.h" |
| 33 | #include "amdgpu_amdkfd.h" | 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 | return amdgpu_sync_fence(sync, fence); | 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 | * amdgpu_sync_resv - sync to a reservation object | 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 | /* always sync to the exclusive fence */ | 263 | /* always sync to the exclusive fence */ |
| 213 | f = dma_resv_excl_fence(resv); | 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 | flist = dma_resv_shared_list(resv); | 278 | flist = dma_resv_shared_list(resv); |
| 217 | if (!flist || r) | 279 | if (!flist) |
| 218 | return r; | 280 | return 0; |
| 219 | 281 | ||
| 220 | for (i = 0; i < flist->shared_count; ++i) { | 282 | for (i = 0; i < flist->shared_count; ++i) { |
| 221 | void *fence_owner; | ||
| 222 | |||
| 223 | f = rcu_dereference_protected(flist->shared[i], | 283 | f = rcu_dereference_protected(flist->shared[i], |
| 224 | dma_resv_held(resv)); | 284 | dma_resv_held(resv)); |
| 225 | 285 | ||
| 226 | fence_owner = amdgpu_sync_get_owner(f); | 286 | if (amdgpu_sync_test_fence(adev, mode, owner, f)) { |
| 227 | |||
| 228 | /* Always sync to moves, no matter what */ | ||
| 229 | if (fence_owner == AMDGPU_FENCE_OWNER_UNDEFINED) { | ||
| 230 | r = amdgpu_sync_fence(sync, f); | 287 | r = amdgpu_sync_fence(sync, f); |
| 231 | if (r) | 288 | if (r) |
| 232 | break; | 289 | return r; |
| 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; | ||
| 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 | * BOs to be evicted from VRAM | 149 | * BOs to be evicted from VRAM |
| 150 | */ | 150 | */ |
| 151 | amdgpu_bo_placement_from_domain(abo, AMDGPU_GEM_DOMAIN_VRAM | | 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 | abo->placements[0].fpfn = adev->gmc.visible_vram_size >> PAGE_SHIFT; | 154 | abo->placements[0].fpfn = adev->gmc.visible_vram_size >> PAGE_SHIFT; |
| 154 | abo->placements[0].lpfn = 0; | 155 | abo->placements[0].lpfn = 0; |
| 155 | abo->placement.busy_placement = &abo->placements[1]; | 156 | abo->placement.busy_placement = &abo->placements[1]; |
| 156 | abo->placement.num_busy_placement = 1; | 157 | abo->placement.num_busy_placement = 1; |
| 157 | } else { | 158 | } else { |
| 158 | /* Move to GTT memory */ | 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 | break; | 163 | break; |
| 162 | case TTM_PL_TT: | 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 | hop->fpfn = 0; | 523 | hop->fpfn = 0; |
| 522 | hop->lpfn = 0; | 524 | hop->lpfn = 0; |
| 523 | hop->mem_type = TTM_PL_TT; | 525 | hop->mem_type = TTM_PL_TT; |
| 524 | hop->flags = 0; | 526 | hop->flags = TTM_PL_FLAG_TEMPORARY; |
| 525 | return -EMULTIHOP; | 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 | struct amdgpu_ttm_tt *gtt = (void *)ttm; | 1123 | struct amdgpu_ttm_tt *gtt = (void *)ttm; |
| 1122 | 1124 | ||
| 1123 | /* user pages are bound by amdgpu_ttm_tt_pin_userptr() */ | 1125 | /* user pages are bound by amdgpu_ttm_tt_pin_userptr() */ |
| 1124 | if (gtt && gtt->userptr) { | 1126 | if (gtt->userptr) { |
| 1125 | ttm->sg = kzalloc(sizeof(struct sg_table), GFP_KERNEL); | 1127 | ttm->sg = kzalloc(sizeof(struct sg_table), GFP_KERNEL); |
| 1126 | if (!ttm->sg) | 1128 | if (!ttm->sg) |
| 1127 | return -ENOMEM; | 1129 | return -ENOMEM; |
| @@ -1146,7 +1148,7 @@ static void amdgpu_ttm_tt_unpopulate(struct ttm_device *bdev, · 18 unmodified lines | |||
| 1146 | struct amdgpu_ttm_tt *gtt = (void *)ttm; | 1148 | struct amdgpu_ttm_tt *gtt = (void *)ttm; |
| 1147 | struct amdgpu_device *adev; | 1149 | struct amdgpu_device *adev; |
| 1148 | 1150 | ||
| 1149 | if (gtt && gtt->userptr) { | 1151 | if (gtt->userptr) { |
| 1150 | amdgpu_ttm_tt_set_user_pages(ttm, NULL); | 1152 | amdgpu_ttm_tt_set_user_pages(ttm, NULL); |
| 1151 | kfree(ttm->sg); | 1153 | kfree(ttm->sg); |
| 1152 | ttm->sg = NULL; | 1154 | ttm->sg = NULL; |
| @@ -1394,6 +1396,41 @@ static bool amdgpu_ttm_bo_eviction_valuable(struct ttm_buffer_object *bo, · 241 unmodified lines | |||
| 1394 | return ttm_bo_eviction_valuable(bo, place); | 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 | * amdgpu_ttm_access_memory - Read or Write memory that backs a buffer object. | 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 | struct amdgpu_bo *abo = ttm_to_amdgpu_bo(bo); | 1450 | struct amdgpu_bo *abo = ttm_to_amdgpu_bo(bo); |
| 1414 | struct amdgpu_device *adev = amdgpu_ttm_adev(abo->tbo.bdev); | 1451 | struct amdgpu_device *adev = amdgpu_ttm_adev(abo->tbo.bdev); |
| 1415 | struct amdgpu_res_cursor cursor; | 1452 | struct amdgpu_res_cursor cursor; |
| 1416 | unsigned long flags; | ||
| 1417 | uint32_t value = 0; | ||
| 1418 | int ret = 0; | 1453 | int ret = 0; |
| 1419 | 1454 | ||
| 1420 | if (bo->resource->mem_type != TTM_PL_VRAM) | 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 | amdgpu_res_first(bo->resource, offset, len, &cursor); | 1458 | amdgpu_res_first(bo->resource, offset, len, &cursor); |
| 1424 | while (cursor.remaining) { | 1459 | while (cursor.remaining) { |
| 1425 | uint64_t aligned_pos = cursor.start & ~(uint64_t)3; | 1460 | size_t count, size = cursor.size; |
| 1426 | uint64_t bytes = 4 - (cursor.start & 3); | 1461 | loff_t pos = cursor.start; |
| 1427 | uint32_t shift = (cursor.start & 3) * 8; | 1462 | |
| 1428 | uint32_t mask = 0xffffffff << shift; | 1463 | count = amdgpu_device_aper_access(adev, pos, buf, size, write); |
| 1429 | 1464 | size -= count; | |
| 1430 | if (cursor.size < bytes) { | 1465 | if (size) { |
| 1431 | mask &= 0xffffffff >> (bytes - cursor.size) * 8; | 1466 | /* using MM to access rest vram and handle un-aligned address */ |
| 1432 | bytes = cursor.size; | 1467 | pos += count; |
| 1433 | } | 1468 | buf += count; |
| 1434 | 1469 | amdgpu_ttm_vram_mm_access(adev, pos, buf, size, write); | |
| 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); | ||
| 1455 | } | 1470 | } |
| 1456 | 1471 | ||
| 1457 | ret += bytes; | 1472 | ret += cursor.size; |
| 1458 | buf = (uint8_t *)buf + bytes; | 1473 | buf += cursor.size; |
| 1459 | amdgpu_res_next(&cursor, bytes); | 1474 | amdgpu_res_next(&cursor, cursor.size); |
| 1460 | } | 1475 | } |
| 1461 | 1476 | ||
| 1462 | return ret; | 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 | return -ENXIO; | 2161 | return -ENXIO; |
| 2147 | 2162 | ||
| 2148 | while (size) { | 2163 | while (size) { |
| 2149 | unsigned long flags; | ||
| 2150 | uint32_t value; | 2164 | uint32_t value; |
| 2151 | 2165 | ||
| 2152 | if (*pos >= adev->gmc.mc_vram_size) | 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 | if (r) | 2170 | if (r) |
| 2157 | return r; | 2171 | return r; |
| 2158 | 2172 | ||
| 2159 | spin_lock_irqsave(&adev->mmio_idx_lock, flags); | 2173 | amdgpu_device_mm_access(adev, *pos, &value, 4, true); |
| 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); | ||
| 2164 | 2174 | ||
| 2165 | result += 4; | 2175 | result += 4; |
| 2166 | buf += 4; | 2176 | buf += 4; |
| @@ -52,7 +52,7 @@ struct amdgpu_gtt_mgr { · 51 unmodified lines | |||
| 52 | struct ttm_resource_manager manager; | 52 | struct ttm_resource_manager manager; |
| 53 | struct drm_mm mm; | 53 | struct drm_mm mm; |
| 54 | spinlock_t lock; | 54 | spinlock_t lock; |
| 55 | atomic64_t available; | 55 | atomic64_t used; |
| 56 | }; | 56 | }; |
| 57 | 57 | ||
| 58 | struct amdgpu_preempt_mgr { | 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 | return AMDGPU_FW_LOAD_DIRECT; | 409 | return AMDGPU_FW_LOAD_DIRECT; |
| 410 | else | 410 | else |
| 411 | return AMDGPU_FW_LOAD_PSP; | 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 | default: | 418 | default: |
| 413 | DRM_ERROR("Unknown firmware load type\n"); | 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 | return AMDGPU_FW_LOAD_DIRECT; | 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 | #define FW_VERSION_ATTR(name, mode, field) \ | 503 | #define FW_VERSION_ATTR(name, mode, field) \ |
| 420 | static ssize_t show_##name(struct device *dev, \ | 504 | static ssize_t show_##name(struct device *dev, \ |
| 421 | struct device_attribute *attr, \ | 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 | FW_VERSION_ATTR(rlc_srls_fw_version, 0444, gfx.rlc_srls_fw_version); | 524 | FW_VERSION_ATTR(rlc_srls_fw_version, 0444, gfx.rlc_srls_fw_version); |
| 441 | FW_VERSION_ATTR(mec_fw_version, 0444, gfx.mec_fw_version); | 525 | FW_VERSION_ATTR(mec_fw_version, 0444, gfx.mec_fw_version); |
| 442 | FW_VERSION_ATTR(mec2_fw_version, 0444, gfx.mec2_fw_version); | 526 | FW_VERSION_ATTR(mec2_fw_version, 0444, gfx.mec2_fw_version); |
| 443 | FW_VERSION_ATTR(sos_fw_version, 0444, psp.sos_fw_version); | 527 | FW_VERSION_ATTR(sos_fw_version, 0444, psp.sos.fw_version); |
| 444 | FW_VERSION_ATTR(asd_fw_version, 0444, psp.asd_fw_version); | 528 | 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); | 529 | FW_VERSION_ATTR(ta_ras_fw_version, 0444, psp.ras.feature_version); |
| 446 | FW_VERSION_ATTR(ta_xgmi_fw_version, 0444, psp.ta_xgmi_ucode_version); | 530 | FW_VERSION_ATTR(ta_xgmi_fw_version, 0444, psp.xgmi.feature_version); |
| 447 | FW_VERSION_ATTR(smc_fw_version, 0444, pm.fw_version); | 531 | FW_VERSION_ATTR(smc_fw_version, 0444, pm.fw_version); |
| 448 | FW_VERSION_ATTR(sdma_fw_version, 0444, sdma.instance[0].fw_version); | 532 | FW_VERSION_ATTR(sdma_fw_version, 0444, sdma.instance[0].fw_version); |
| 449 | FW_VERSION_ATTR(sdma2_fw_version, 0444, sdma.instance[1].fw_version); | 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 | uint32_t pptable_entry_offset; | 71 | uint32_t pptable_entry_offset; |
| 72 | }; | 72 | }; |
| 73 | 73 | ||
| 74 | struct psp_fw_bin_desc { | 74 | struct psp_fw_legacy_bin_desc { |
| 75 | uint32_t fw_version; | 75 | uint32_t fw_version; |
| 76 | uint32_t offset_bytes; | 76 | uint32_t offset_bytes; |
| 77 | uint32_t size_bytes; | 77 | uint32_t size_bytes; |
| @@ -80,50 +80,67 @@ struct psp_fw_bin_desc { · 2 unmodified lines | |||
| 80 | /* version_major=1, version_minor=0 */ | 80 | /* version_major=1, version_minor=0 */ |
| 81 | struct psp_firmware_header_v1_0 { | 81 | struct psp_firmware_header_v1_0 { |
| 82 | struct common_firmware_header header; | 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 | /* version_major=1, version_minor=1 */ | 86 | /* version_major=1, version_minor=1 */ |
| 87 | struct psp_firmware_header_v1_1 { | 87 | struct psp_firmware_header_v1_1 { |
| 88 | struct psp_firmware_header_v1_0 v1_0; | 88 | struct psp_firmware_header_v1_0 v1_0; |
| 89 | struct psp_fw_bin_desc toc; | 89 | struct psp_fw_legacy_bin_desc toc; |
| 90 | struct psp_fw_bin_desc kdb; | 90 | struct psp_fw_legacy_bin_desc kdb; |
| 91 | }; | 91 | }; |
| 92 | 92 | ||
| 93 | /* version_major=1, version_minor=2 */ | 93 | /* version_major=1, version_minor=2 */ |
| 94 | struct psp_firmware_header_v1_2 { | 94 | struct psp_firmware_header_v1_2 { |
| 95 | struct psp_firmware_header_v1_0 v1_0; | 95 | struct psp_firmware_header_v1_0 v1_0; |
| 96 | struct psp_fw_bin_desc res; | 96 | struct psp_fw_legacy_bin_desc res; |
| 97 | struct psp_fw_bin_desc kdb; | 97 | struct psp_fw_legacy_bin_desc kdb; |
| 98 | }; | 98 | }; |
| 99 | 99 | ||
| 100 | /* version_major=1, version_minor=3 */ | 100 | /* version_major=1, version_minor=3 */ |
| 101 | struct psp_firmware_header_v1_3 { | 101 | struct psp_firmware_header_v1_3 { |
| 102 | struct psp_firmware_header_v1_1 v1_1; | 102 | struct psp_firmware_header_v1_1 v1_1; |
| 103 | struct psp_fw_bin_desc spl; | 103 | struct psp_fw_legacy_bin_desc spl; |
| 104 | struct psp_fw_bin_desc rl; | 104 | struct psp_fw_legacy_bin_desc rl; |
| 105 | struct psp_fw_bin_desc sys_drv_aux; | 105 | struct psp_fw_legacy_bin_desc sys_drv_aux; |
| 106 | struct psp_fw_bin_desc sos_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 | /* version_major=1, version_minor=0 */ | 136 | /* version_major=1, version_minor=0 */ |
| 110 | struct ta_firmware_header_v1_0 { | 137 | struct ta_firmware_header_v1_0 { |
| 111 | struct common_firmware_header header; | 138 | struct common_firmware_header header; |
| 112 | uint32_t ta_xgmi_ucode_version; | 139 | struct psp_fw_legacy_bin_desc xgmi; |
| 113 | uint32_t ta_xgmi_offset_bytes; | 140 | struct psp_fw_legacy_bin_desc ras; |
| 114 | uint32_t ta_xgmi_size_bytes; | 141 | struct psp_fw_legacy_bin_desc hdcp; |
| 115 | uint32_t ta_ras_ucode_version; | 142 | struct psp_fw_legacy_bin_desc dtm; |
| 116 | uint32_t ta_ras_offset_bytes; | 143 | struct psp_fw_legacy_bin_desc securedisplay; |
| 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; | ||
| 127 | }; | 144 | }; |
| 128 | 145 | ||
| 129 | enum ta_fw_type { | 146 | enum ta_fw_type { |
| @@ -138,18 +155,11 @@ enum ta_fw_type { · 8 unmodified lines | |||
| 138 | TA_FW_TYPE_MAX_INDEX, | 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 | /* version_major=2, version_minor=0 */ | 158 | /* version_major=2, version_minor=0 */ |
| 149 | struct ta_firmware_header_v2_0 { | 159 | struct ta_firmware_header_v2_0 { |
| 150 | struct common_firmware_header header; | 160 | struct common_firmware_header header; |
| 151 | uint32_t ta_fw_bin_count; | 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 | /* version_major=1, version_minor=0 */ | 165 | /* version_major=1, version_minor=0 */ |
| @@ -312,6 +322,7 @@ union amdgpu_firmware_header { · 156 unmodified lines | |||
| 312 | struct psp_firmware_header_v1_0 psp; | 322 | struct psp_firmware_header_v1_0 psp; |
| 313 | struct psp_firmware_header_v1_1 psp_v1_1; | 323 | struct psp_firmware_header_v1_1 psp_v1_1; |
| 314 | struct psp_firmware_header_v1_3 psp_v1_3; | 324 | struct psp_firmware_header_v1_3 psp_v1_3; |
| 325 | struct psp_firmware_header_v2_0 psp_v2_0; | ||
| 315 | struct ta_firmware_header_v1_0 ta; | 326 | struct ta_firmware_header_v1_0 ta; |
| 316 | struct ta_firmware_header_v2_0 ta_v2_0; | 327 | struct ta_firmware_header_v2_0 ta_v2_0; |
| 317 | struct gfx_firmware_header_v1_0 gfx; | 328 | struct gfx_firmware_header_v1_0 gfx; |
| @@ -326,7 +337,7 @@ union amdgpu_firmware_header { · 8 unmodified lines | |||
| 326 | uint8_t raw[0x100]; | 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 | * fw loading support | 343 | * fw loading support |
| @@ -449,4 +460,6 @@ void amdgpu_ucode_sysfs_fini(struct amdgpu_device *adev); · 116 unmodified lines | |||
| 449 | enum amdgpu_firmware_load_type | 460 | enum amdgpu_firmware_load_type |
| 450 | amdgpu_ucode_get_load_type(struct amdgpu_device *adev, int load_type); | 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 | #endif | 465 | #endif |
| @@ -41,7 +41,6 @@ int amdgpu_umc_ras_late_init(struct amdgpu_device *adev) · 40 unmodified lines | |||
| 41 | adev->umc.ras_if->block = AMDGPU_RAS_BLOCK__UMC; | 41 | adev->umc.ras_if->block = AMDGPU_RAS_BLOCK__UMC; |
| 42 | adev->umc.ras_if->type = AMDGPU_RAS_ERROR__MULTI_UNCORRECTABLE; | 42 | adev->umc.ras_if->type = AMDGPU_RAS_ERROR__MULTI_UNCORRECTABLE; |
| 43 | adev->umc.ras_if->sub_block_index = 0; | 43 | adev->umc.ras_if->sub_block_index = 0; |
| 44 | strcpy(adev->umc.ras_if->name, "umc"); | ||
| 45 | } | 44 | } |
| 46 | ih_info.head = fs_info.head = *adev->umc.ras_if; | 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 | amdgpu_ras_save_bad_pages(adev); | 133 | amdgpu_ras_save_bad_pages(adev); |
| 135 | 134 | ||
| 136 | if (adev->smu.ppt_funcs && adev->smu.ppt_funcs->send_hbm_bad_pages_num) | 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 | amdgpu_ras_reset_gpu(adev); | 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 | int i, j; | 327 | int i, j; |
| 328 | 328 | ||
| 329 | cancel_delayed_work_sync(&adev->uvd.idle_work); | ||
| 330 | drm_sched_entity_destroy(&adev->uvd.entity); | 329 | drm_sched_entity_destroy(&adev->uvd.entity); |
| 331 | 330 | ||
| 332 | for (j = 0; j < adev->uvd.num_uvd_inst; ++j) { | 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 | if (adev->vce.vcpu_bo == NULL) | 218 | if (adev->vce.vcpu_bo == NULL) |
| 219 | return 0; | 219 | return 0; |
| 220 | 220 | ||
| 221 | cancel_delayed_work_sync(&adev->vce.idle_work); | ||
| 222 | drm_sched_entity_destroy(&adev->vce.entity); | 221 | drm_sched_entity_destroy(&adev->vce.entity); |
| 223 | 222 | ||
| 224 | amdgpu_bo_free_kernel(&adev->vce.vcpu_bo, &adev->vce.gpu_addr, | 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 | int i, j; | 259 | int i, j; |
| 260 | 260 | ||
| 261 | cancel_delayed_work_sync(&adev->vcn.idle_work); | ||
| 262 | |||
| 263 | for (j = 0; j < adev->vcn.num_vcn_inst; ++j) { | 261 | for (j = 0; j < adev->vcn.num_vcn_inst; ++j) { |
| 264 | if (adev->vcn.harvest_config & (1 << j)) | 262 | if (adev->vcn.harvest_config & (1 << j)) |
| 265 | continue; | 263 | continue; |
| @@ -531,10 +531,10 @@ static void amdgpu_virt_populate_vf2pf_ucode_info(struct amdgpu_device *adev) · 530 unmodified lines | |||
| 531 | POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_RLC_SRLS, adev->gfx.rlc_srls_fw_version); | 531 | POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_RLC_SRLS, adev->gfx.rlc_srls_fw_version); |
| 532 | POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_MEC, adev->gfx.mec_fw_version); | 532 | POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_MEC, adev->gfx.mec_fw_version); |
| 533 | POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_MEC2, adev->gfx.mec2_fw_version); | 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); | 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); | 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); | 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.ta_xgmi_ucode_version); | 537 | POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_TA_XGMI, adev->psp.xgmi.feature_version); |
| 538 | POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_SMC, adev->pm.fw_version); | 538 | POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_SMC, adev->pm.fw_version); |
| 539 | POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_SDMA, adev->sdma.instance[0].fw_version); | 539 | POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_SDMA, adev->sdma.instance[0].fw_version); |
| 540 | POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_SDMA2, adev->sdma.instance[1].fw_version); | 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 | struct dma_fence_cb cb; | 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 | * vm eviction_lock can be taken in MMU notifiers. Make sure no reclaim-FS | 132 | * vm eviction_lock can be taken in MMU notifiers. Make sure no reclaim-FS |
| 93 | * happens while holding this lock anywhere to prevent deadlocks when | 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 | bp.size = amdgpu_vm_bo_size(adev, level); | 926 | bp.size = amdgpu_vm_bo_size(adev, level); |
| 887 | bp.byte_align = AMDGPU_GPU_PAGE_SIZE; | 927 | bp.byte_align = AMDGPU_GPU_PAGE_SIZE; |
| 888 | bp.domain = AMDGPU_GEM_DOMAIN_VRAM; | 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 | bp.flags = AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS | | 930 | bp.flags = AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS | |
| 891 | AMDGPU_GEM_CREATE_CPU_GTT_USWC; | 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 | amdgpu_gmc_emit_pasid_mapping(ring, job->vmid, job->pasid); | 1218 | amdgpu_gmc_emit_pasid_mapping(ring, job->vmid, job->pasid); |
| 1179 | 1219 | ||
| 1180 | if (vm_flush_needed || pasid_mapping_needed) { | 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 | if (r) | 1222 | if (r) |
| 1183 | return r; | 1223 | return r; |
| 1184 | } | 1224 | } |
| @@ -1758,7 +1798,7 @@ int amdgpu_vm_bo_update_mapping(struct amdgpu_device *adev, · 573 unmodified lines | |||
| 1758 | r = vm->update_funcs->commit(¶ms, fence); | 1798 | r = vm->update_funcs->commit(¶ms, fence); |
| 1759 | 1799 | ||
| 1760 | if (table_freed) | 1800 | if (table_freed) |
| 1761 | *table_freed = params.table_freed; | 1801 | *table_freed = *table_freed || params.table_freed; |
| 1762 | 1802 | ||
| 1763 | error_unlock: | 1803 | error_unlock: |
| 1764 | amdgpu_vm_eviction_unlock(vm); | 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 | * @adev: amdgpu_device pointer | 1856 | * @adev: amdgpu_device pointer |
| 1817 | * @bo_va: requested BO and VM object | 1857 | * @bo_va: requested BO and VM object |
| 1818 | * @clear: if true clear the entries | 1858 | * @clear: if true clear the entries |
| 1859 | * @table_freed: return true if page table is freed | ||
| 1819 | * | 1860 | * |
| 1820 | * Fill in the page table entries for @bo_va. | 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 | * 0 for success, -EINVAL for failure. | 1864 | * 0 for success, -EINVAL for failure. |
| 1824 | */ | 1865 | */ |
| 1825 | int amdgpu_vm_bo_update(struct amdgpu_device *adev, struct amdgpu_bo_va *bo_va, | 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 | struct amdgpu_bo *bo = bo_va->base.bo; | 1869 | struct amdgpu_bo *bo = bo_va->base.bo; |
| 1829 | struct amdgpu_vm *vm = bo_va->base.vm; | 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 | resv, mapping->start, | 1943 | resv, mapping->start, |
| 1903 | mapping->last, update_flags, | 1944 | mapping->last, update_flags, |
| 1904 | mapping->offset, mem, | 1945 | mapping->offset, mem, |
| 1905 | pages_addr, last_update, NULL); | 1946 | pages_addr, last_update, table_freed); |
| 1906 | if (r) | 1947 | if (r) |
| 1907 | return r; | 1948 | return r; |
| 1908 | } | 1949 | } |
| @@ -2154,7 +2195,7 @@ int amdgpu_vm_handle_moved(struct amdgpu_device *adev, · 245 unmodified lines | |||
| 2154 | 2195 | ||
| 2155 | list_for_each_entry_safe(bo_va, tmp, &vm->moved, base.vm_status) { | 2196 | list_for_each_entry_safe(bo_va, tmp, &vm->moved, base.vm_status) { |
| 2156 | /* Per VM BOs never need to bo cleared in the page tables */ | 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 | if (r) | 2199 | if (r) |
| 2159 | return r; | 2200 | return r; |
| 2160 | } | 2201 | } |
| @@ -2173,7 +2214,7 @@ int amdgpu_vm_handle_moved(struct amdgpu_device *adev, · 12 unmodified lines | |||
| 2173 | else | 2214 | else |
| 2174 | clear = true; | 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 | if (r) | 2218 | if (r) |
| 2178 | return r; | 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 | * @adev: amdgpu_device pointer | 2905 | * @adev: amdgpu_device pointer |
| 2865 | * @vm: requested vm | 2906 | * @vm: requested vm |
| 2866 | * @pasid: Process address space identifier | ||
| 2867 | * | 2907 | * |
| 2868 | * Init @vm fields. | 2908 | * Init @vm fields. |
| 2869 | * | 2909 | * |
| 2870 | * Returns: | 2910 | * Returns: |
| 2871 | * 0 for success, error for failure. | 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 | struct amdgpu_bo *root_bo; | 2915 | struct amdgpu_bo *root_bo; |
| 2876 | struct amdgpu_bo_vm *root; | 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 | amdgpu_bo_unreserve(vm->root.bo); | 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 | INIT_KFIFO(vm->faults); | 2987 | INIT_KFIFO(vm->faults); |
| 2961 | 2988 | ||
| 2962 | return 0; | 2989 | return 0; |
| @@ -3012,7 +3039,6 @@ static int amdgpu_vm_check_clean_reserved(struct amdgpu_device *adev, · 49 unmodified lines | |||
| 3012 | * | 3039 | * |
| 3013 | * @adev: amdgpu_device pointer | 3040 | * @adev: amdgpu_device pointer |
| 3014 | * @vm: requested vm | 3041 | * @vm: requested vm |
| 3015 | * @pasid: pasid to use | ||
| 3016 | * | 3042 | * |
| 3017 | * This only works on GFX VMs that don't have any BOs added and no | 3043 | * This only works on GFX VMs that don't have any BOs added and no |
| 3018 | * page tables allocated yet. | 3044 | * page tables allocated yet. |
| @@ -3020,7 +3046,6 @@ static int amdgpu_vm_check_clean_reserved(struct amdgpu_device *adev, · 1 unmodified line | |||
| 3020 | * Changes the following VM parameters: | 3046 | * Changes the following VM parameters: |
| 3021 | * - use_cpu_for_update | 3047 | * - use_cpu_for_update |
| 3022 | * - pte_supports_ats | 3048 | * - pte_supports_ats |
| 3023 | * - pasid (old PASID is released, because compute manages its own PASIDs) | ||
| 3024 | * | 3049 | * |
| 3025 | * Reinitializes the page directory to reflect the changed ATS | 3050 | * Reinitializes the page directory to reflect the changed ATS |
| 3026 | * setting. | 3051 | * setting. |
| @@ -3028,8 +3053,7 @@ static int amdgpu_vm_check_clean_reserved(struct amdgpu_device *adev, · 1 unmodified line | |||
| 3028 | * Returns: | 3053 | * Returns: |
| 3029 | * 0 for success, -errno for errors. | 3054 | * 0 for success, -errno for errors. |
| 3030 | */ | 3055 | */ |
| 3031 | int amdgpu_vm_make_compute(struct amdgpu_device *adev, struct amdgpu_vm *vm, | 3056 | int amdgpu_vm_make_compute(struct amdgpu_device *adev, struct amdgpu_vm *vm) |
| 3032 | u32 pasid) | ||
| 3033 | { | 3057 | { |
| 3034 | bool pte_support_ats = (adev->asic_type == CHIP_RAVEN); | 3058 | bool pte_support_ats = (adev->asic_type == CHIP_RAVEN); |
| 3035 | int r; | 3059 | int r; |
| @@ -3043,19 +3067,6 @@ int amdgpu_vm_make_compute(struct amdgpu_device *adev, struct amdgpu_vm *vm, · 7 unmodified lines | |||
| 3043 | if (r) | 3067 | if (r) |
| 3044 | goto unreserve_bo; | 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 | /* Check if PD needs to be reinitialized and do it before | 3070 | /* Check if PD needs to be reinitialized and do it before |
| 3060 | * changing any other state, in case it fails. | 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 | to_amdgpu_bo_vm(vm->root.bo), | 3076 | to_amdgpu_bo_vm(vm->root.bo), |
| 3066 | false); | 3077 | false); |
| 3067 | if (r) | 3078 | if (r) |
| 3068 | goto free_idr; | 3079 | goto unreserve_bo; |
| 3069 | } | 3080 | } |
| 3070 | 3081 | ||
| 3071 | /* Update VM state */ | 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 | r = amdgpu_bo_sync_wait(vm->root.bo, | 3093 | r = amdgpu_bo_sync_wait(vm->root.bo, |
| 3083 | AMDGPU_FENCE_OWNER_UNDEFINED, true); | 3094 | AMDGPU_FENCE_OWNER_UNDEFINED, true); |
| 3084 | if (r) | 3095 | if (r) |
| 3085 | goto free_idr; | 3096 | goto unreserve_bo; |
| 3086 | 3097 | ||
| 3087 | vm->update_funcs = &amdgpu_vm_cpu_funcs; | 3098 | vm->update_funcs = &amdgpu_vm_cpu_funcs; |
| 3088 | } else { | 3099 | } else { |
| @@ -3092,36 +3103,11 @@ int amdgpu_vm_make_compute(struct amdgpu_device *adev, struct amdgpu_vm *vm, · 3 unmodified lines | |||
| 3092 | vm->last_update = NULL; | 3103 | vm->last_update = NULL; |
| 3093 | vm->is_compute_context = true; | 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 | /* Free the shadow bo for compute VM */ | 3106 | /* Free the shadow bo for compute VM */ |
| 3110 | amdgpu_bo_unref(&to_amdgpu_bo_vm(vm->root.bo)->shadow); | 3107 | amdgpu_bo_unref(&to_amdgpu_bo_vm(vm->root.bo)->shadow); |
| 3111 | 3108 | ||
| 3112 | if (pasid) | ||
| 3113 | vm->pasid = pasid; | ||
| 3114 | |||
| 3115 | goto unreserve_bo; | 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 | unreserve_bo: | 3111 | unreserve_bo: |
| 3126 | amdgpu_bo_unreserve(vm->root.bo); | 3112 | amdgpu_bo_unreserve(vm->root.bo); |
| 3127 | return r; | 3113 | return r; |
| @@ -3137,14 +3123,7 @@ unreserve_bo: · 9 unmodified lines | |||
| 3137 | */ | 3123 | */ |
| 3138 | void amdgpu_vm_release_compute(struct amdgpu_device *adev, struct amdgpu_vm *vm) | 3124 | void amdgpu_vm_release_compute(struct amdgpu_device *adev, struct amdgpu_vm *vm) |
| 3139 | { | 3125 | { |
| 3140 | if (vm->pasid) { | 3126 | amdgpu_vm_set_pasid(adev, vm, 0); |
| 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; | ||
| 3148 | vm->is_compute_context = false; | 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 | root = amdgpu_bo_ref(vm->root.bo); | 3148 | root = amdgpu_bo_ref(vm->root.bo); |
| 3170 | amdgpu_bo_reserve(root, true); | 3149 | amdgpu_bo_reserve(root, true); |
| 3171 | if (vm->pasid) { | 3150 | amdgpu_vm_set_pasid(adev, vm, 0); |
| 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 | |||
| 3180 | dma_fence_wait(vm->last_unlocked, false); | 3151 | dma_fence_wait(vm->last_unlocked, false); |
| 3181 | dma_fence_put(vm->last_unlocked); | 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 | adev->vm_manager.vm_update_mode = 0; | 3229 | adev->vm_manager.vm_update_mode = 0; |
| 3259 | #endif | 3230 | #endif |
| 3260 | 3231 | ||
| 3261 | idr_init(&adev->vm_manager.pasid_idr); | 3232 | xa_init_flags(&adev->vm_manager.pasids, XA_FLAGS_LOCK_IRQ); |
| 3262 | spin_lock_init(&adev->vm_manager.pasid_lock); | ||
| 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 | void amdgpu_vm_manager_fini(struct amdgpu_device *adev) | 3242 | void amdgpu_vm_manager_fini(struct amdgpu_device *adev) |
| 3273 | { | 3243 | { |
| 3274 | WARN_ON(!idr_is_empty(&adev->vm_manager.pasid_idr)); | 3244 | WARN_ON(!xa_empty(&adev->vm_manager.pasids)); |
| 3275 | idr_destroy(&adev->vm_manager.pasid_idr); | 3245 | xa_destroy(&adev->vm_manager.pasids); |
| 3276 | 3246 | ||
| 3277 | amdgpu_vmid_mgr_fini(adev); | 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 | struct amdgpu_vm *vm; | 3311 | struct amdgpu_vm *vm; |
| 3342 | unsigned long flags; | 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 | if (vm) | 3317 | if (vm) |
| 3348 | *task_info = vm->task_info; | 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 | * @adev: amdgpu device pointer | 3345 | * @adev: amdgpu device pointer |
| 3376 | * @pasid: PASID of the VM | 3346 | * @pasid: PASID of the VM |
| 3377 | * @addr: Address of the fault | 3347 | * @addr: Address of the fault |
| 3348 | * @write_fault: true is write fault, false is read fault | ||
| 3378 | * | 3349 | * |
| 3379 | * Try to gracefully handle a VM fault. Return true if the fault was handled and | 3350 | * Try to gracefully handle a VM fault. Return true if the fault was handled and |
| 3380 | * shouldn't be reported any more. | 3351 | * shouldn't be reported any more. |
| 3381 | */ | 3352 | */ |
| 3382 | bool amdgpu_vm_handle_fault(struct amdgpu_device *adev, u32 pasid, | 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 | bool is_compute_context = false; | 3356 | bool is_compute_context = false; |
| 3386 | struct amdgpu_bo *root; | 3357 | struct amdgpu_bo *root; |
| @@ -3389,15 +3360,15 @@ bool amdgpu_vm_handle_fault(struct amdgpu_device *adev, u32 pasid, · 2 unmodified lines | |||
| 3389 | struct amdgpu_vm *vm; | 3360 | struct amdgpu_vm *vm; |
| 3390 | int r; | 3361 | int r; |
| 3391 | 3362 | ||
| 3392 | spin_lock_irqsave(&adev->vm_manager.pasid_lock, irqflags); | 3363 | xa_lock_irqsave(&adev->vm_manager.pasids, irqflags); |
| 3393 | vm = idr_find(&adev->vm_manager.pasid_idr, pasid); | 3364 | vm = xa_load(&adev->vm_manager.pasids, pasid); |
| 3394 | if (vm) { | 3365 | if (vm) { |
| 3395 | root = amdgpu_bo_ref(vm->root.bo); | 3366 | root = amdgpu_bo_ref(vm->root.bo); |
| 3396 | is_compute_context = vm->is_compute_context; | 3367 | is_compute_context = vm->is_compute_context; |
| 3397 | } else { | 3368 | } else { |
| 3398 | root = NULL; | 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 | if (!root) | 3373 | if (!root) |
| 3403 | return false; | 3374 | return false; |
| @@ -3405,7 +3376,7 @@ bool amdgpu_vm_handle_fault(struct amdgpu_device *adev, u32 pasid, · 1 unmodified line | |||
| 3405 | addr /= AMDGPU_GPU_PAGE_SIZE; | 3376 | addr /= AMDGPU_GPU_PAGE_SIZE; |
| 3406 | 3377 | ||
| 3407 | if (is_compute_context && | 3378 | if (is_compute_context && |
| 3408 | !svm_range_restore_pages(adev, pasid, addr)) { | 3379 | !svm_range_restore_pages(adev, pasid, addr, write_fault)) { |
| 3409 | amdgpu_bo_unref(&root); | 3380 | amdgpu_bo_unref(&root); |
| 3410 | return true; | 3381 | return true; |
| 3411 | } | 3382 | } |
| @@ -3415,11 +3386,11 @@ bool amdgpu_vm_handle_fault(struct amdgpu_device *adev, u32 pasid, · 3 unmodified lines | |||
| 3415 | goto error_unref; | 3386 | goto error_unref; |
| 3416 | 3387 | ||
| 3417 | /* Double check that the VM still exists */ | 3388 | /* Double check that the VM still exists */ |
| 3418 | spin_lock_irqsave(&adev->vm_manager.pasid_lock, irqflags); | 3389 | xa_lock_irqsave(&adev->vm_manager.pasids, irqflags); |
| 3419 | vm = idr_find(&adev->vm_manager.pasid_idr, pasid); | 3390 | vm = xa_load(&adev->vm_manager.pasids, pasid); |
| 3420 | if (vm && vm->root.bo != root) | 3391 | if (vm && vm->root.bo != root) |
| 3421 | vm = NULL; | 3392 | vm = NULL; |
| 3422 | spin_unlock_irqrestore(&adev->vm_manager.pasid_lock, irqflags); | 3393 | xa_unlock_irqrestore(&adev->vm_manager.pasids, irqflags); |
| 3423 | if (!vm) | 3394 | if (!vm) |
| 3424 | goto error_unlock; | 3395 | goto error_unlock; |
| 3425 | 3396 | ||
| @@ -359,8 +359,7 @@ struct amdgpu_vm_manager { · 358 unmodified lines | |||
| 359 | /* PASID to VM mapping, will be used in interrupt context to | 359 | /* PASID to VM mapping, will be used in interrupt context to |
| 360 | * look up VM of a page fault | 360 | * look up VM of a page fault |
| 361 | */ | 361 | */ |
| 362 | struct idr pasid_idr; | 362 | struct xarray pasids; |
| 363 | spinlock_t pasid_lock; | ||
| 364 | }; | 363 | }; |
| 365 | 364 | ||
| 366 | struct amdgpu_bo_va_mapping; | 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 | void amdgpu_vm_manager_init(struct amdgpu_device *adev); | 374 | void amdgpu_vm_manager_init(struct amdgpu_device *adev); |
| 376 | void amdgpu_vm_manager_fini(struct amdgpu_device *adev); | 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 | long amdgpu_vm_wait_idle(struct amdgpu_vm *vm, long timeout); | 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); | 381 | int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm); |
| 380 | int amdgpu_vm_make_compute(struct amdgpu_device *adev, struct amdgpu_vm *vm, u32 pasid); | 382 | int amdgpu_vm_make_compute(struct amdgpu_device *adev, struct amdgpu_vm *vm); |
| 381 | void amdgpu_vm_release_compute(struct amdgpu_device *adev, struct amdgpu_vm *vm); | 383 | void amdgpu_vm_release_compute(struct amdgpu_device *adev, struct amdgpu_vm *vm); |
| 382 | void amdgpu_vm_fini(struct amdgpu_device *adev, struct amdgpu_vm *vm); | 384 | void amdgpu_vm_fini(struct amdgpu_device *adev, struct amdgpu_vm *vm); |
| 383 | void amdgpu_vm_get_pd_bo(struct amdgpu_vm *vm, | 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 | struct dma_fence **fence, bool *free_table); | 408 | struct dma_fence **fence, bool *free_table); |
| 407 | int amdgpu_vm_bo_update(struct amdgpu_device *adev, | 409 | int amdgpu_vm_bo_update(struct amdgpu_device *adev, |
| 408 | struct amdgpu_bo_va *bo_va, | 410 | struct amdgpu_bo_va *bo_va, |
| 409 | bool clear); | 411 | bool clear, bool *table_freed); |
| 410 | bool amdgpu_vm_evictable(struct amdgpu_bo *bo); | 412 | bool amdgpu_vm_evictable(struct amdgpu_bo *bo); |
| 411 | void amdgpu_vm_bo_invalidate(struct amdgpu_device *adev, | 413 | void amdgpu_vm_bo_invalidate(struct amdgpu_device *adev, |
| 412 | struct amdgpu_bo *bo, bool evicted); | 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 | void amdgpu_vm_get_task_info(struct amdgpu_device *adev, u32 pasid, | 448 | void amdgpu_vm_get_task_info(struct amdgpu_device *adev, u32 pasid, |
| 447 | struct amdgpu_task_info *task_info); | 449 | struct amdgpu_task_info *task_info); |
| 448 | bool amdgpu_vm_handle_fault(struct amdgpu_device *adev, u32 pasid, | 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 | void amdgpu_vm_set_task_info(struct amdgpu_vm *vm); | 453 | void amdgpu_vm_set_task_info(struct amdgpu_vm *vm); |
| 452 | 454 | ||
| @@ -32,6 +32,10 @@ · 31 unmodified lines | |||
| 32 | #include "wafl/wafl2_4_0_0_smn.h" | 32 | #include "wafl/wafl2_4_0_0_smn.h" |
| 33 | #include "wafl/wafl2_4_0_0_sh_mask.h" | 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 | static DEFINE_MUTEX(xgmi_mutex); | 39 | static DEFINE_MUTEX(xgmi_mutex); |
| 36 | 40 | ||
| 37 | #define AMDGPU_MAX_XGMI_DEVICE_PER_HIVE 4 | 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 | smnPCS_GOPX1_0_PCS_GOPX1_PCS_ERROR_STATUS + 0x100000, | 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 | static const struct amdgpu_pcs_ras_field xgmi_pcs_ras_fields[] = { | 97 | static const struct amdgpu_pcs_ras_field xgmi_pcs_ras_fields[] = { |
| 67 | {"XGMI PCS DataLossErr", | 98 | {"XGMI PCS DataLossErr", |
| 68 | SOC15_REG_FIELD(XGMI0_PCS_GOPX16_PCS_ERROR_STATUS, DataLossErr)}, | 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 | return -EINVAL; | 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 | int amdgpu_xgmi_add_device(struct amdgpu_device *adev) | 558 | int amdgpu_xgmi_add_device(struct amdgpu_device *adev) |
| 490 | { | 559 | { |
| 491 | struct psp_xgmi_topology_info *top_info; | 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 | if (!adev->gmc.xgmi.pending_reset && | 570 | if (!adev->gmc.xgmi.pending_reset && |
| 502 | amdgpu_device_ip_get_ip_block(adev, AMD_IP_BLOCK_TYPE_PSP)) { | 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 | if (ret) { | 573 | if (ret) { |
| 505 | dev_err(adev->dev, | 574 | dev_err(adev->dev, |
| 506 | "XGMI: Failed to initialize xgmi session\n"); | 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 | /* get latest topology info for each device from psp */ | 632 | /* get latest topology info for each device from psp */ |
| 564 | list_for_each_entry(tmp_adev, &hive->device_list, gmc.xgmi.head) { | 633 | list_for_each_entry(tmp_adev, &hive->device_list, gmc.xgmi.head) { |
| 565 | ret = psp_xgmi_get_topology_info(&tmp_adev->psp, count, | 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 | if (ret) { | 636 | if (ret) { |
| 568 | dev_err(tmp_adev->dev, | 637 | dev_err(tmp_adev->dev, |
| 569 | "XGMI: Get topology failure on device %llx, hive %llx, ret %d", | 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 | goto exit_unlock; | 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 | if (!ret && !adev->gmc.xgmi.pending_reset) | 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 | adev->gmc.xgmi.ras_if->block = AMDGPU_RAS_BLOCK__XGMI_WAFL; | 748 | adev->gmc.xgmi.ras_if->block = AMDGPU_RAS_BLOCK__XGMI_WAFL; |
| 652 | adev->gmc.xgmi.ras_if->type = AMDGPU_RAS_ERROR__MULTI_UNCORRECTABLE; | 749 | adev->gmc.xgmi.ras_if->type = AMDGPU_RAS_ERROR__MULTI_UNCORRECTABLE; |
| 653 | adev->gmc.xgmi.ras_if->sub_block_index = 0; | 750 | adev->gmc.xgmi.ras_if->sub_block_index = 0; |
| 654 | strcpy(adev->gmc.xgmi.ras_if->name, "xgmi_wafl"); | ||
| 655 | } | 751 | } |
| 656 | ih_info.head = fs_info.head = *adev->gmc.xgmi.ras_if; | 752 | ih_info.head = fs_info.head = *adev->gmc.xgmi.ras_if; |
| 657 | r = amdgpu_ras_late_init(adev, adev->gmc.xgmi.ras_if, | 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 | pcs_clear_status(adev, | 802 | pcs_clear_status(adev, |
| 707 | xgmi_pcs_err_status_reg_vg20[i]); | 803 | xgmi_pcs_err_status_reg_vg20[i]); |
| 708 | break; | 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 | default: | 816 | default: |
| 710 | break; | 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 | break; | 891 | break; |
| 785 | case CHIP_VEGA20: | 892 | case CHIP_VEGA20: |
| 786 | default: | ||
| 787 | /* check xgmi pcs error */ | 893 | /* check xgmi pcs error */ |
| 788 | for (i = 0; i < ARRAY_SIZE(xgmi_pcs_err_status_reg_vg20); i++) { | 894 | for (i = 0; i < ARRAY_SIZE(xgmi_pcs_err_status_reg_vg20); i++) { |
| 789 | data = RREG32_PCIE(xgmi_pcs_err_status_reg_vg20[i]); | 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 | data, &ue_cnt, &ce_cnt, false); | 905 | data, &ue_cnt, &ce_cnt, false); |
| 800 | } | 906 | } |
| 801 | break; | 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 | adev->gmc.xgmi.ras_funcs->reset_ras_error_count(adev); | 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 | int amdgpu_xgmi_set_pstate(struct amdgpu_device *adev, int pstate); | 59 | int amdgpu_xgmi_set_pstate(struct amdgpu_device *adev, int pstate); |
| 60 | int amdgpu_xgmi_get_hops_count(struct amdgpu_device *adev, | 60 | int amdgpu_xgmi_get_hops_count(struct amdgpu_device *adev, |
| 61 | struct amdgpu_device *peer_adev); | 61 | struct amdgpu_device *peer_adev); |
| 62 | int amdgpu_xgmi_get_num_links(struct amdgpu_device *adev, | ||
| 63 | struct amdgpu_device *peer_adev); | ||
| 62 | uint64_t amdgpu_xgmi_get_relative_phy_addr(struct amdgpu_device *adev, | 64 | uint64_t amdgpu_xgmi_get_relative_phy_addr(struct amdgpu_device *adev, |
| 63 | uint64_t addr); | 65 | uint64_t addr); |
| 64 | static inline bool amdgpu_xgmi_same_hive(struct amdgpu_device *adev, | 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 | pll->reference_div = amdgpu_crtc->pll_reference_div; | 851 | pll->reference_div = amdgpu_crtc->pll_reference_div; |
| 852 | pll->post_div = amdgpu_crtc->pll_post_div; | 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 | &fb_div, &frac_fb_div, &ref_div, &post_div); | 855 | &fb_div, &frac_fb_div, &ref_div, &post_div); |
| 856 | 856 | ||
| 857 | amdgpu_atombios_crtc_program_ss(adev, ATOM_DISABLE, amdgpu_crtc->pll_id, | 857 | amdgpu_atombios_crtc_program_ss(adev, ATOM_DISABLE, amdgpu_crtc->pll_id, |
| @@ -70,7 +70,7 @@ · 69 unmodified lines | |||
| 70 | 70 | ||
| 71 | #include "amdgpu_dm.h" | 71 | #include "amdgpu_dm.h" |
| 72 | #include "amdgpu_amdkfd.h" | 72 | #include "amdgpu_amdkfd.h" |
| 73 | #include "dce_virtual.h" | 73 | #include "amdgpu_vkms.h" |
| 74 | 74 | ||
| 75 | static const struct amdgpu_video_codec_info cik_video_codecs_encode_array[] = | 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 | amdgpu_device_ip_block_add(adev, &cik_sdma_ip_block); | 2259 | amdgpu_device_ip_block_add(adev, &cik_sdma_ip_block); |
| 2260 | amdgpu_device_ip_block_add(adev, &pp_smu_ip_block); | 2260 | amdgpu_device_ip_block_add(adev, &pp_smu_ip_block); |
| 2261 | if (adev->enable_virtual_display) | 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 | #if defined(CONFIG_DRM_AMD_DC) | 2263 | #if defined(CONFIG_DRM_AMD_DC) |
| 2264 | else if (amdgpu_device_has_dc_support(adev)) | 2264 | else if (amdgpu_device_has_dc_support(adev)) |
| 2265 | amdgpu_device_ip_block_add(adev, &dm_ip_block); | 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 | amdgpu_device_ip_block_add(adev, &cik_sdma_ip_block); | 2277 | amdgpu_device_ip_block_add(adev, &cik_sdma_ip_block); |
| 2278 | amdgpu_device_ip_block_add(adev, &pp_smu_ip_block); | 2278 | amdgpu_device_ip_block_add(adev, &pp_smu_ip_block); |
| 2279 | if (adev->enable_virtual_display) | 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 | #if defined(CONFIG_DRM_AMD_DC) | 2281 | #if defined(CONFIG_DRM_AMD_DC) |
| 2282 | else if (amdgpu_device_has_dc_support(adev)) | 2282 | else if (amdgpu_device_has_dc_support(adev)) |
| 2283 | amdgpu_device_ip_block_add(adev, &dm_ip_block); | 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 | amdgpu_device_ip_block_add(adev, &cik_sdma_ip_block); | 2295 | amdgpu_device_ip_block_add(adev, &cik_sdma_ip_block); |
| 2296 | amdgpu_device_ip_block_add(adev, &kv_smu_ip_block); | 2296 | amdgpu_device_ip_block_add(adev, &kv_smu_ip_block); |
| 2297 | if (adev->enable_virtual_display) | 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 | #if defined(CONFIG_DRM_AMD_DC) | 2299 | #if defined(CONFIG_DRM_AMD_DC) |
| 2300 | else if (amdgpu_device_has_dc_support(adev)) | 2300 | else if (amdgpu_device_has_dc_support(adev)) |
| 2301 | amdgpu_device_ip_block_add(adev, &dm_ip_block); | 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 | amdgpu_device_ip_block_add(adev, &cik_sdma_ip_block); | 2315 | amdgpu_device_ip_block_add(adev, &cik_sdma_ip_block); |
| 2316 | amdgpu_device_ip_block_add(adev, &kv_smu_ip_block); | 2316 | amdgpu_device_ip_block_add(adev, &kv_smu_ip_block); |
| 2317 | if (adev->enable_virtual_display) | 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 | #if defined(CONFIG_DRM_AMD_DC) | 2319 | #if defined(CONFIG_DRM_AMD_DC) |
| 2320 | else if (amdgpu_device_has_dc_support(adev)) | 2320 | else if (amdgpu_device_has_dc_support(adev)) |
| 2321 | amdgpu_device_ip_block_add(adev, &dm_ip_block); | 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 | #define GFX10_NUM_GFX_RINGS_Sienna_Cichlid 1 | 56 | #define GFX10_NUM_GFX_RINGS_Sienna_Cichlid 1 |
| 57 | #define GFX10_MEC_HPD_SIZE 2048 | 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 | #define F32_CE_PROGRAM_RAM_SIZE 65536 | 63 | #define F32_CE_PROGRAM_RAM_SIZE 65536 |
| 60 | #define RLCG_UCODE_LOADING_START_ADDRESS 0x00002000L | 64 | #define RLCG_UCODE_LOADING_START_ADDRESS 0x00002000L |
| 61 | 65 | ||
| @@ -181,6 +185,9 @@ · 119 unmodified lines | |||
| 181 | #define GFX_RLCG_GC_READ (0x1 << 28) | 185 | #define GFX_RLCG_GC_READ (0x1 << 28) |
| 182 | #define GFX_RLCG_MMHUB_WRITE (0x2 << 28) | 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 | MODULE_FIRMWARE("amdgpu/navi10_ce.bin"); | 191 | MODULE_FIRMWARE("amdgpu/navi10_ce.bin"); |
| 185 | MODULE_FIRMWARE("amdgpu/navi10_pfp.bin"); | 192 | MODULE_FIRMWARE("amdgpu/navi10_pfp.bin"); |
| 186 | MODULE_FIRMWARE("amdgpu/navi10_me.bin"); | 193 | MODULE_FIRMWARE("amdgpu/navi10_me.bin"); |
| @@ -249,6 +256,39 @@ MODULE_FIRMWARE("amdgpu/yellow_carp_mec.bin"); · 62 unmodified lines | |||
| 249 | MODULE_FIRMWARE("amdgpu/yellow_carp_mec2.bin"); | 256 | MODULE_FIRMWARE("amdgpu/yellow_carp_mec2.bin"); |
| 250 | MODULE_FIRMWARE("amdgpu/yellow_carp_rlc.bin"); | 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 | static const struct soc15_reg_golden golden_settings_gc_10_1[] = | 292 | static const struct soc15_reg_golden golden_settings_gc_10_1[] = |
| 253 | { | 293 | { |
| 254 | SOC15_REG_GOLDEN_VALUE(GC, 0, mmCB_HW_CONTROL_4, 0xffffffff, 0x00400014), | 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 | uint32_t i = 0; | 1526 | uint32_t i = 0; |
| 1487 | uint32_t retries = 50000; | 1527 | uint32_t retries = 50000; |
| 1488 | u32 ret = 0; | 1528 | u32 ret = 0; |
| 1529 | u32 tmp; | ||
| 1489 | 1530 | ||
| 1490 | scratch_reg0 = adev->rmmio + | 1531 | scratch_reg0 = adev->rmmio + |
| 1491 | (adev->reg_offset[GC_HWIP][0][mmSCRATCH_REG0_BASE_IDX] + mmSCRATCH_REG0) * 4; | 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 | writel(v, scratch_reg0); | 1560 | writel(v, scratch_reg0); |
| 1520 | writel(offset | flag, scratch_reg1); | 1561 | writel(offset | flag, scratch_reg1); |
| 1521 | writel(1, spare_int); | 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 | tmp = readl(scratch_reg1); | 1565 | tmp = readl(scratch_reg1); |
| 1526 | if (!(tmp & flag)) | 1566 | if (!(tmp & flag)) |
| 1527 | break; | 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 | udelay(10); | 1569 | udelay(10); |
| 1530 | } | 1570 | } |
| 1531 | 1571 | ||
| 1532 | if (i >= retries) | 1572 | if (i >= retries) { |
| 1533 | pr_err("timeout: rlcg program reg:0x%05x failed !\n", offset); | 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 | ret = readl(scratch_reg0); | 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 | return ret; | 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 | u32 rlcg_flag; | 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 | WREG32(offset, value); | 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 | u32 rlcg_flag; | 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 | SOC15_REG_GOLDEN_VALUE(GC, 0, mmUTCL1_CTRL, 0xffbfffff, 0x00a00000) | 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 | #define DEFAULT_SH_MEM_CONFIG \ | 3579 | #define DEFAULT_SH_MEM_CONFIG \ |
| 3492 | ((SH_MEM_ADDRESS_MODE_64 << SH_MEM_CONFIG__ADDRESS_MODE__SHIFT) | \ | 3580 | ((SH_MEM_ADDRESS_MODE_64 << SH_MEM_CONFIG__ADDRESS_MODE__SHIFT) | \ |
| 3493 | (SH_MEM_ALIGNMENT_MODE_UNALIGNED << SH_MEM_CONFIG__ALIGNMENT_MODE__SHIFT) | \ | 3581 | (SH_MEM_ALIGNMENT_MODE_UNALIGNED << SH_MEM_CONFIG__ALIGNMENT_MODE__SHIFT) | \ |
| 3494 | (SH_MEM_RETRY_MODE_ALL << SH_MEM_CONFIG__RETRY_MODE__SHIFT) | \ | 3582 | (SH_MEM_RETRY_MODE_ALL << SH_MEM_CONFIG__RETRY_MODE__SHIFT) | \ |
| 3495 | (3 << SH_MEM_CONFIG__INITIAL_INST_PREFETCH__SHIFT)) | 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 | static void gfx_v10_0_set_ring_funcs(struct amdgpu_device *adev); | 3588 | static void gfx_v10_0_set_ring_funcs(struct amdgpu_device *adev); |
| 3499 | static void gfx_v10_0_set_irq_funcs(struct amdgpu_device *adev); | 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 | golden_settings_gc_10_3_5, | 3808 | golden_settings_gc_10_3_5, |
| 3719 | (const u32)ARRAY_SIZE(golden_settings_gc_10_3_5)); | 3809 | (const u32)ARRAY_SIZE(golden_settings_gc_10_3_5)); |
| 3720 | break; | 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 | default: | 3819 | default: |
| 3722 | break; | 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 | case CHIP_NAVI10: | 3989 | case CHIP_NAVI10: |
| 3892 | case CHIP_NAVI12: | 3990 | case CHIP_NAVI12: |
| 3893 | case CHIP_NAVI14: | 3991 | case CHIP_NAVI14: |
| 3992 | case CHIP_CYAN_SKILLFISH: | ||
| 3894 | if ((adev->gfx.me_fw_version >= 0x00000046) && | 3993 | if ((adev->gfx.me_fw_version >= 0x00000046) && |
| 3895 | (adev->gfx.me_feature_version >= 27) && | 3994 | (adev->gfx.me_feature_version >= 27) && |
| 3896 | (adev->gfx.pfp_fw_version >= 0x00000068) && | 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 | case CHIP_YELLOW_CARP: | 4124 | case CHIP_YELLOW_CARP: |
| 4026 | chip_name = "yellow_carp"; | 4125 | chip_name = "yellow_carp"; |
| 4027 | break; | 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 | default: | 4133 | default: |
| 4029 | BUG(); | 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 | dst[(*no_fields)++] = wave_read_ind(adev, wave, ixSQ_WAVE_IB_STS2); | 4621 | dst[(*no_fields)++] = wave_read_ind(adev, wave, ixSQ_WAVE_IB_STS2); |
| 4517 | dst[(*no_fields)++] = wave_read_ind(adev, wave, ixSQ_WAVE_IB_DBG1); | 4622 | dst[(*no_fields)++] = wave_read_ind(adev, wave, ixSQ_WAVE_IB_DBG1); |
| 4518 | dst[(*no_fields)++] = wave_read_ind(adev, wave, ixSQ_WAVE_M0); | 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 | static void gfx_v10_0_read_wave_sgprs(struct amdgpu_device *adev, uint32_t simd, | 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 | adev->gfx.config.gb_addr_config_fields.num_pkrs = | 4710 | adev->gfx.config.gb_addr_config_fields.num_pkrs = |
| 4605 | 1 << REG_GET_FIELD(gb_addr_config, GB_ADDR_CONFIG, NUM_PKRS); | 4711 | 1 << REG_GET_FIELD(gb_addr_config, GB_ADDR_CONFIG, NUM_PKRS); |
| 4606 | break; | 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 | default: | 4721 | default: |
| 4608 | BUG(); | 4722 | BUG(); |
| 4609 | break; | 4723 | break; |
| @@ -4708,6 +4822,7 @@ static int gfx_v10_0_sw_init(void *handle) · 98 unmodified lines | |||
| 4708 | case CHIP_NAVI10: | 4822 | case CHIP_NAVI10: |
| 4709 | case CHIP_NAVI14: | 4823 | case CHIP_NAVI14: |
| 4710 | case CHIP_NAVI12: | 4824 | case CHIP_NAVI12: |
| 4825 | case CHIP_CYAN_SKILLFISH: | ||
| 4711 | adev->gfx.me.num_me = 1; | 4826 | adev->gfx.me.num_me = 1; |
| 4712 | adev->gfx.me.num_pipe_per_me = 1; | 4827 | adev->gfx.me.num_pipe_per_me = 1; |
| 4713 | adev->gfx.me.num_queue_per_pipe = 1; | 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 | int r; | 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 | r = gfx_v10_0_wait_for_rlc_autoload_complete(adev); | 5440 | r = gfx_v10_0_wait_for_rlc_autoload_complete(adev); |
| 5325 | if (r) | 5441 | if (r) |
| @@ -5379,7 +5495,7 @@ static int gfx_v10_0_parse_rlc_toc(struct amdgpu_device *adev) · 53 unmodified lines | |||
| 5379 | int ret; | 5495 | int ret; |
| 5380 | RLC_TABLE_OF_CONTENT *rlc_toc; | 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 | AMDGPU_GEM_DOMAIN_GTT, | 5499 | AMDGPU_GEM_DOMAIN_GTT, |
| 5384 | &adev->gfx.rlc.rlc_toc_bo, | 5500 | &adev->gfx.rlc.rlc_toc_bo, |
| 5385 | &adev->gfx.rlc.rlc_toc_gpu_addr, | 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 | /* Copy toc from psp sos fw to rlc toc buffer */ | 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 | rlc_toc = (RLC_TABLE_OF_CONTENT *)adev->gfx.rlc.rlc_toc_buf; | 5511 | rlc_toc = (RLC_TABLE_OF_CONTENT *)adev->gfx.rlc.rlc_toc_buf; |
| 5396 | while (rlc_toc && (rlc_toc->id > FIRMWARE_ID_INVALID) && | 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 | static uint64_t gfx_v10_0_get_gpu_clock_counter(struct amdgpu_device *adev) | 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 | switch (adev->asic_type) { | 7729 | switch (adev->asic_type) { |
| 7616 | case CHIP_VANGOGH: | 7730 | case CHIP_VANGOGH: |
| 7617 | case CHIP_YELLOW_CARP: | 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 | ((uint64_t)RREG32_SOC15(SMUIO, 0, mmGOLDEN_TSC_COUNT_UPPER_Vangogh) << 32ULL); | 7733 | ((uint64_t)RREG32_SOC15(SMUIO, 0, mmGOLDEN_TSC_COUNT_UPPER_Vangogh) << 32ULL); |
| 7620 | break; | 7734 | break; |
| 7621 | default: | 7735 | default: |
| 7622 | clock = (uint64_t)RREG32_SOC15(SMUIO, 0, mmGOLDEN_TSC_COUNT_LOWER) | | 7736 | preempt_disable(); |
| 7623 | ((uint64_t)RREG32_SOC15(SMUIO, 0, mmGOLDEN_TSC_COUNT_UPPER) << 32ULL); | 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 | break; | 7749 | break; |
| 7625 | } | 7750 | } |
| 7626 | mutex_unlock(&adev->gfx.gpu_clock_mutex); | ||
| 7627 | amdgpu_gfx_off_ctrl(adev, true); | ||
| 7628 | return clock; | 7751 | return clock; |
| 7629 | } | 7752 | } |
| 7630 | 7753 | ||
| @@ -7665,6 +7788,7 @@ static int gfx_v10_0_early_init(void *handle) · 34 unmodified lines | |||
| 7665 | case CHIP_NAVI10: | 7788 | case CHIP_NAVI10: |
| 7666 | case CHIP_NAVI14: | 7789 | case CHIP_NAVI14: |
| 7667 | case CHIP_NAVI12: | 7790 | case CHIP_NAVI12: |
| 7791 | case CHIP_CYAN_SKILLFISH: | ||
| 7668 | adev->gfx.num_gfx_rings = GFX10_NUM_GFX_RINGS_NV1X; | 7792 | adev->gfx.num_gfx_rings = GFX10_NUM_GFX_RINGS_NV1X; |
| 7669 | break; | 7793 | break; |
| 7670 | case CHIP_SIENNA_CICHLID: | 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 | .reset = gfx_v10_0_rlc_reset, | 8385 | .reset = gfx_v10_0_rlc_reset, |
| 8262 | .start = gfx_v10_0_rlc_start, | 8386 | .start = gfx_v10_0_rlc_start, |
| 8263 | .update_spm_vmid = gfx_v10_0_update_spm_vmid, | 8387 | .update_spm_vmid = gfx_v10_0_update_spm_vmid, |
| 8264 | .rlcg_wreg = gfx_v10_rlcg_wreg, | 8388 | .sriov_wreg = gfx_v10_sriov_wreg, |
| 8265 | .rlcg_rreg = gfx_v10_rlcg_rreg, | 8389 | .sriov_rreg = gfx_v10_sriov_rreg, |
| 8266 | .is_rlcg_access_range = gfx_v10_0_is_rlcg_access_range, | 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 | case CHIP_DIMGREY_CAVEFISH: | 9549 | case CHIP_DIMGREY_CAVEFISH: |
| 9426 | case CHIP_BEIGE_GOBY: | 9550 | case CHIP_BEIGE_GOBY: |
| 9427 | case CHIP_YELLOW_CARP: | 9551 | case CHIP_YELLOW_CARP: |
| 9552 | case CHIP_CYAN_SKILLFISH: | ||
| 9428 | adev->gfx.rlc.funcs = &gfx_v10_0_rlc_funcs; | 9553 | adev->gfx.rlc.funcs = &gfx_v10_0_rlc_funcs; |
| 9429 | break; | 9554 | break; |
| 9430 | case CHIP_NAVI12: | 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 | dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_TMA_HI); | 3027 | dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_TMA_HI); |
| 3028 | dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_IB_DBG0); | 3028 | dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_IB_DBG0); |
| 3029 | dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_M0); | 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 | static void gfx_v6_0_read_wave_sgprs(struct amdgpu_device *adev, uint32_t simd, | 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 | dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_TMA_HI); | 4198 | dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_TMA_HI); |
| 4199 | dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_IB_DBG0); | 4199 | dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_IB_DBG0); |
| 4200 | dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_M0); | 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 | static void gfx_v7_0_read_wave_sgprs(struct amdgpu_device *adev, uint32_t simd, | 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 | dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_TMA_HI); | 5279 | dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_TMA_HI); |
| 5280 | dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_IB_DBG0); | 5280 | dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_IB_DBG0); |
| 5281 | dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_M0); | 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 | static void gfx_v8_0_read_wave_sgprs(struct amdgpu_device *adev, uint32_t simd, | 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 | u32 v, u32 acc_flags, u32 hwip) | 791 | u32 v, u32 acc_flags, u32 hwip) |
| 792 | { | 792 | { |
| 793 | if ((acc_flags & AMDGPU_REGS_RLC) && | 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 | dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_IB_STS); | 2090 | dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_IB_STS); |
| 2091 | dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_IB_DBG0); | 2091 | dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_IB_DBG0); |
| 2092 | dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_M0); | 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 | static void gfx_v9_0_read_wave_sgprs(struct amdgpu_device *adev, uint32_t simd, | 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 | .reset = gfx_v9_0_rlc_reset, | 5151 | .reset = gfx_v9_0_rlc_reset, |
| 5151 | .start = gfx_v9_0_rlc_start, | 5152 | .start = gfx_v9_0_rlc_start, |
| 5152 | .update_spm_vmid = gfx_v9_0_update_spm_vmid, | 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 | .is_rlcg_access_range = gfx_v9_0_is_rlcg_access_range, | 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 | SOC15_REG_GOLDEN_VALUE(GC, 0, regTCI_CNTL_3, 0xff, 0x20), | 85 | SOC15_REG_GOLDEN_VALUE(GC, 0, regTCI_CNTL_3, 0xff, 0x20), |
| 86 | }; | 86 | }; |
| 87 | 87 | ||
| 88 | /** | 88 | /* |
| 89 | * This shader is used to clear VGPRS and LDS, and also write the input | 89 | * This shader is used to clear VGPRS and LDS, and also write the input |
| 90 | * pattern into the write back buffer, which will be used by driver to | 90 | * pattern into the write back buffer, which will be used by driver to |
| 91 | * check whether all SIMDs have been covered. | 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 | { SOC15_REG_ENTRY(GC, 0, regCOMPUTE_STATIC_THREAD_MGMT_SE7), 0xffffffff }, | 206 | { SOC15_REG_ENTRY(GC, 0, regCOMPUTE_STATIC_THREAD_MGMT_SE7), 0xffffffff }, |
| 207 | }; | 207 | }; |
| 208 | 208 | ||
| 209 | /** | 209 | /* |
| 210 | * The below shaders are used to clear SGPRS, and also write the input | 210 | * The below shaders are used to clear SGPRS, and also write the input |
| 211 | * pattern into the write back buffer. The first two dispatch should be | 211 | * pattern into the write back buffer. The first two dispatch should be |
| 212 | * scheduled simultaneously which make sure that all SGPRS could be | 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 | { SOC15_REG_ENTRY(GC, 0, regCOMPUTE_STATIC_THREAD_MGMT_SE7), 0xffffffff }, | 302 | { SOC15_REG_ENTRY(GC, 0, regCOMPUTE_STATIC_THREAD_MGMT_SE7), 0xffffffff }, |
| 303 | }; | 303 | }; |
| 304 | 304 | ||
| 305 | /** | 305 | /* |
| 306 | * This shader is used to clear the uninitiated sgprs after the above | 306 | * This shader is used to clear the uninitiated sgprs after the above |
| 307 | * two dispatches, because of hardware feature, dispath 0 couldn't clear | 307 | * two dispatches, because of hardware feature, dispath 0 couldn't clear |
| 308 | * top hole sgprs. Therefore need 4 waves per SIMD to cover these sgprs | 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 | max_physical_node_id = 7; | 75 | max_physical_node_id = 7; |
| 76 | break; | 76 | break; |
| 77 | case CHIP_ALDEBARAN: | 77 | case CHIP_ALDEBARAN: |
| 78 | /* just using duplicates for Aldebaran support, revisit later */ | 78 | max_num_physical_nodes = 16; |
| 79 | max_num_physical_nodes = 8; | 79 | max_physical_node_id = 15; |
| 80 | max_physical_node_id = 7; | ||
| 81 | break; | 80 | break; |
| 82 | default: | 81 | default: |
| 83 | return -EINVAL; | 82 | return -EINVAL; |
| @@ -93,6 +93,7 @@ static int gmc_v10_0_process_interrupt(struct amdgpu_device *adev, · 92 unmodified lines | |||
| 93 | struct amdgpu_iv_entry *entry) | 93 | struct amdgpu_iv_entry *entry) |
| 94 | { | 94 | { |
| 95 | bool retry_fault = !!(entry->src_data[1] & 0x80); | 95 | bool retry_fault = !!(entry->src_data[1] & 0x80); |
| 96 | bool write_fault = !!(entry->src_data[1] & 0x20); | ||
| 96 | struct amdgpu_vmhub *hub = &adev->vmhub[entry->vmid_src]; | 97 | struct amdgpu_vmhub *hub = &adev->vmhub[entry->vmid_src]; |
| 97 | struct amdgpu_task_info task_info; | 98 | struct amdgpu_task_info task_info; |
| 98 | uint32_t status = 0; | 99 | uint32_t status = 0; |
| @@ -121,7 +122,7 @@ static int gmc_v10_0_process_interrupt(struct amdgpu_device *adev, · 22 unmodified lines | |||
| 121 | /* Try to handle the recoverable page faults by filling page | 122 | /* Try to handle the recoverable page faults by filling page |
| 122 | * tables | 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 | return 1; | 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 | case CHIP_DIMGREY_CAVEFISH: | 811 | case CHIP_DIMGREY_CAVEFISH: |
| 811 | case CHIP_BEIGE_GOBY: | 812 | case CHIP_BEIGE_GOBY: |
| 812 | case CHIP_YELLOW_CARP: | 813 | case CHIP_YELLOW_CARP: |
| 814 | case CHIP_CYAN_SKILLFISH: | ||
| 813 | default: | 815 | default: |
| 814 | adev->gmc.gart_size = 512ULL << 20; | 816 | adev->gmc.gart_size = 512ULL << 20; |
| 815 | break; | 817 | break; |
| @@ -879,6 +881,7 @@ static int gmc_v10_0_sw_init(void *handle) · 63 unmodified lines | |||
| 879 | case CHIP_DIMGREY_CAVEFISH: | 881 | case CHIP_DIMGREY_CAVEFISH: |
| 880 | case CHIP_BEIGE_GOBY: | 882 | case CHIP_BEIGE_GOBY: |
| 881 | case CHIP_YELLOW_CARP: | 883 | case CHIP_YELLOW_CARP: |
| 884 | case CHIP_CYAN_SKILLFISH: | ||
| 882 | adev->num_vmhubs = 2; | 885 | adev->num_vmhubs = 2; |
| 883 | /* | 886 | /* |
| 884 | * To fulfill 4-level page support, | 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 | case CHIP_DIMGREY_CAVEFISH: | 999 | case CHIP_DIMGREY_CAVEFISH: |
| 997 | case CHIP_BEIGE_GOBY: | 1000 | case CHIP_BEIGE_GOBY: |
| 998 | case CHIP_YELLOW_CARP: | 1001 | case CHIP_YELLOW_CARP: |
| 1002 | case CHIP_CYAN_SKILLFISH: | ||
| 999 | break; | 1003 | break; |
| 1000 | default: | 1004 | default: |
| 1001 | break; | 1005 | break; |
| @@ -53,7 +53,9 @@ · 52 unmodified lines | |||
| 53 | #include "mmhub_v1_7.h" | 53 | #include "mmhub_v1_7.h" |
| 54 | #include "umc_v6_1.h" | 54 | #include "umc_v6_1.h" |
| 55 | #include "umc_v6_0.h" | 55 | #include "umc_v6_0.h" |
| 56 | #include "umc_v6_7.h" | ||
| 56 | #include "hdp_v4_0.h" | 57 | #include "hdp_v4_0.h" |
| 58 | #include "mca_v3_0.h" | ||
| 57 | 59 | ||
| 58 | #include "ivsrcid/vmc/irqsrcs_vmc_1_0.h" | 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 | struct amdgpu_iv_entry *entry) | 507 | struct amdgpu_iv_entry *entry) |
| 506 | { | 508 | { |
| 507 | bool retry_fault = !!(entry->src_data[1] & 0x80); | 509 | bool retry_fault = !!(entry->src_data[1] & 0x80); |
| 510 | bool write_fault = !!(entry->src_data[1] & 0x20); | ||
| 508 | uint32_t status = 0, cid = 0, rw = 0; | 511 | uint32_t status = 0, cid = 0, rw = 0; |
| 509 | struct amdgpu_task_info task_info; | 512 | struct amdgpu_task_info task_info; |
| 510 | struct amdgpu_vmhub *hub; | 513 | struct amdgpu_vmhub *hub; |
| @@ -535,7 +538,7 @@ static int gmc_v9_0_process_interrupt(struct amdgpu_device *adev, · 24 unmodified lines | |||
| 535 | /* Try to handle the recoverable page faults by filling page | 538 | /* Try to handle the recoverable page faults by filling page |
| 536 | * tables | 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 | return 1; | 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 | adev->umc.channel_idx_tbl = &umc_v6_1_channel_idx_tbl[0][0]; | 1171 | adev->umc.channel_idx_tbl = &umc_v6_1_channel_idx_tbl[0][0]; |
| 1169 | adev->umc.ras_funcs = &umc_v6_1_ras_funcs; | 1172 | adev->umc.ras_funcs = &umc_v6_1_ras_funcs; |
| 1170 | break; | 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 | default: | 1186 | default: |
| 1172 | break; | 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 | adev->hdp.ras_funcs = &hdp_v4_0_ras_funcs; | 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 | static int gmc_v9_0_early_init(void *handle) | 1246 | static int gmc_v9_0_early_init(void *handle) |
| 1220 | { | 1247 | { |
| 1221 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; | 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 | gmc_v9_0_set_mmhub_ras_funcs(adev); | 1264 | gmc_v9_0_set_mmhub_ras_funcs(adev); |
| 1238 | gmc_v9_0_set_gfxhub_funcs(adev); | 1265 | gmc_v9_0_set_gfxhub_funcs(adev); |
| 1239 | gmc_v9_0_set_hdp_ras_funcs(adev); | 1266 | gmc_v9_0_set_hdp_ras_funcs(adev); |
| 1267 | gmc_v9_0_set_mca_funcs(adev); | ||
| 1240 | 1268 | ||
| 1241 | adev->gmc.shared_aperture_start = 0x2000000000000000ULL; | 1269 | adev->gmc.shared_aperture_start = 0x2000000000000000ULL; |
| 1242 | adev->gmc.shared_aperture_end = | 1270 | adev->gmc.shared_aperture_end = |
| @@ -1448,6 +1476,8 @@ static int gmc_v9_0_sw_init(void *handle) · 205 unmodified lines | |||
| 1448 | adev->gfxhub.funcs->init(adev); | 1476 | adev->gfxhub.funcs->init(adev); |
| 1449 | 1477 | ||
| 1450 | adev->mmhub.funcs->init(adev); | 1478 | adev->mmhub.funcs->init(adev); |
| 1479 | if (adev->mca.funcs) | ||
| 1480 | adev->mca.funcs->init(adev); | ||
| 1451 | 1481 | ||
| 1452 | spin_lock_init(&adev->gmc.invalidate_lock); | 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 | #ifndef __MMSCH_V1_0_H__ | 24 | #ifndef __MMSCH_V1_0_H__ |
| 25 | #define __MMSCH_V1_0_H__ | 25 | #define __MMSCH_V1_0_H__ |
| 26 | 26 | ||
| 27 | #define MMSCH_VERSION_MAJOR 1 | 27 | #define MMSCH_VERSION 0x1 |
| 28 | #define MMSCH_VERSION_MINOR 0 | ||
| 29 | #define MMSCH_VERSION (MMSCH_VERSION_MAJOR << 16 | MMSCH_VERSION_MINOR) | ||
| 30 | 28 | ||
| 31 | enum mmsch_v1_0_command_type { | 29 | enum mmsch_v1_0_command_type { |
| 32 | MMSCH_COMMAND__DIRECT_REG_WRITE = 0, | 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 | static int xgpu_nv_poll_msg(struct amdgpu_device *adev, enum idh_event event) | 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 | do { | 105 | do { |
| 102 | r = xgpu_nv_mailbox_rcv_msg(adev, event); | 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 | return 0; | 108 | return 0; |
| 105 | 109 | ||
| 106 | msleep(10); | 110 | msleep(10); |
| 107 | timeout -= 10; | 111 | now = (uint64_t)ktime_to_ms(ktime_get()); |
| 108 | } while (timeout > 1); | 112 | } while (timeout > now); |
| 109 | 113 | ||
| 110 | 114 | ||
| 111 | return -ETIME; | 115 | return -ETIME; |
| @@ -149,9 +153,10 @@ static void xgpu_nv_mailbox_trans_msg (struct amdgpu_device *adev, · 37 unmodified lines | |||
| 149 | static int xgpu_nv_send_access_requests(struct amdgpu_device *adev, | 153 | static int xgpu_nv_send_access_requests(struct amdgpu_device *adev, |
| 150 | enum idh_request req) | 154 | enum idh_request req) |
| 151 | { | 155 | { |
| 152 | int r; | 156 | int r, retry = 1; |
| 153 | enum idh_event event = -1; | 157 | enum idh_event event = -1; |
| 154 | 158 | ||
| 159 | send_request: | ||
| 155 | xgpu_nv_mailbox_trans_msg(adev, req, 0, 0, 0); | 160 | xgpu_nv_mailbox_trans_msg(adev, req, 0, 0, 0); |
| 156 | 161 | ||
| 157 | switch (req) { | 162 | switch (req) { |
| @@ -170,6 +175,9 @@ static int xgpu_nv_send_access_requests(struct amdgpu_device *adev, · 12 unmodified lines | |||
| 170 | if (event != -1) { | 175 | if (event != -1) { |
| 171 | r = xgpu_nv_poll_msg(adev, event); | 176 | r = xgpu_nv_poll_msg(adev, event); |
| 172 | if (r) { | 177 | if (r) { |
| 178 | if (retry++ < 2) | ||
| 179 | goto send_request; | ||
| 180 | |||
| 173 | if (req != IDH_REQ_GPU_INIT_DATA) { | 181 | if (req != IDH_REQ_GPU_INIT_DATA) { |
| 174 | pr_err("Doesn't get msg:%d from pf, error=%d\n", event, r); | 182 | pr_err("Doesn't get msg:%d from pf, error=%d\n", event, r); |
| 175 | return r; | 183 | return r; |
| @@ -279,6 +287,8 @@ static void xgpu_nv_mailbox_flr_work(struct work_struct *work) · 103 unmodified lines | |||
| 279 | amdgpu_virt_fini_data_exchange(adev); | 287 | amdgpu_virt_fini_data_exchange(adev); |
| 280 | atomic_set(&adev->in_gpu_reset, 1); | 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 | do { | 292 | do { |
| 283 | if (xgpu_nv_mailbox_peek_msg(adev) == IDH_FLR_NOTIFICATION_CMPL) | 293 | if (xgpu_nv_mailbox_peek_msg(adev) == IDH_FLR_NOTIFICATION_CMPL) |
| 284 | goto flr_done; | 294 | goto flr_done; |
| @@ -37,7 +37,8 @@ enum idh_request { · 36 unmodified lines | |||
| 37 | IDH_REQ_GPU_RESET_ACCESS, | 37 | IDH_REQ_GPU_RESET_ACCESS, |
| 38 | IDH_REQ_GPU_INIT_DATA, | 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 | enum idh_event { | 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 | WREG32_PCIE(smnPCIE_LC_LINK_WIDTH_CNTL, reg_data); | 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 | const struct amdgpu_nbio_funcs nbio_v2_3_funcs = { | 531 | const struct amdgpu_nbio_funcs nbio_v2_3_funcs = { |
| 512 | .get_hdp_flush_req_offset = nbio_v2_3_get_hdp_flush_req_offset, | 532 | .get_hdp_flush_req_offset = nbio_v2_3_get_hdp_flush_req_offset, |
| 513 | .get_hdp_flush_done_offset = nbio_v2_3_get_hdp_flush_done_offset, | 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 | .program_aspm = nbio_v2_3_program_aspm, | 551 | .program_aspm = nbio_v2_3_program_aspm, |
| 532 | .apply_lc_spc_mode_wa = nbio_v2_3_apply_lc_spc_mode_wa, | 552 | .apply_lc_spc_mode_wa = nbio_v2_3_apply_lc_spc_mode_wa, |
| 533 | .apply_l1_link_width_reconfig_wa = nbio_v2_3_apply_l1_link_width_reconfig_wa, | 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 | #define mmRCC_DEV0_EPF0_STRAP0_ALDE 0x0015 | 85 | #define mmRCC_DEV0_EPF0_STRAP0_ALDE 0x0015 |
| 86 | #define mmRCC_DEV0_EPF0_STRAP0_ALDE_BASE_IDX 2 | 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 | static void nbio_v7_4_query_ras_error_count(struct amdgpu_device *adev, | 93 | static void nbio_v7_4_query_ras_error_count(struct amdgpu_device *adev, |
| 89 | void *ras_error_status); | 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 | struct ras_err_data err_data = {0, 0, 0, NULL}; | 351 | struct ras_err_data err_data = {0, 0, 0, NULL}; |
| 347 | struct amdgpu_ras *ras = amdgpu_ras_get_context(adev); | 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 | if (REG_GET_FIELD(bif_doorbell_intr_cntl, | 359 | if (REG_GET_FIELD(bif_doorbell_intr_cntl, |
| 351 | BIF_DOORBELL_INT_CNTL, RAS_CNTLR_INTERRUPT_STATUS)) { | 360 | BIF_DOORBELL_INT_CNTL, RAS_CNTLR_INTERRUPT_STATUS)) { |
| 352 | /* driver has to clear the interrupt status when bif ring is disabled */ | 361 | /* driver has to clear the interrupt status when bif ring is disabled */ |
| 353 | bif_doorbell_intr_cntl = REG_SET_FIELD(bif_doorbell_intr_cntl, | 362 | bif_doorbell_intr_cntl = REG_SET_FIELD(bif_doorbell_intr_cntl, |
| 354 | BIF_DOORBELL_INT_CNTL, | 363 | BIF_DOORBELL_INT_CNTL, |
| 355 | RAS_CNTLR_INTERRUPT_CLEAR, 1); | 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 | if (!ras->disable_ras_err_cnt_harvest) { | 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 | "errors detected in %s block, " | 384 | "errors detected in %s block, " |
| 373 | "no user action is needed.\n", | 385 | "no user action is needed.\n", |
| 374 | obj->err_data.ce_count, | 386 | obj->err_data.ce_count, |
| 375 | adev->nbio.ras_if->name); | 387 | ras_block_str(adev->nbio.ras_if->block)); |
| 376 | 388 | ||
| 377 | if (err_data.ue_count) | 389 | if (err_data.ue_count) |
| 378 | dev_info(adev->dev, "%ld uncorrectable hardware " | 390 | dev_info(adev->dev, "%ld uncorrectable hardware " |
| 379 | "errors detected in %s block\n", | 391 | "errors detected in %s block\n", |
| 380 | obj->err_data.ue_count, | 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 | dev_info(adev->dev, "RAS controller interrupt triggered " | 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 | uint32_t bif_doorbell_intr_cntl; | 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 | if (REG_GET_FIELD(bif_doorbell_intr_cntl, | 415 | if (REG_GET_FIELD(bif_doorbell_intr_cntl, |
| 400 | BIF_DOORBELL_INT_CNTL, RAS_ATHUB_ERR_EVENT_INTERRUPT_STATUS)) { | 416 | BIF_DOORBELL_INT_CNTL, RAS_ATHUB_ERR_EVENT_INTERRUPT_STATUS)) { |
| 401 | /* driver has to clear the interrupt status when bif ring is disabled */ | 417 | /* driver has to clear the interrupt status when bif ring is disabled */ |
| 402 | bif_doorbell_intr_cntl = REG_SET_FIELD(bif_doorbell_intr_cntl, | 418 | bif_doorbell_intr_cntl = REG_SET_FIELD(bif_doorbell_intr_cntl, |
| 403 | BIF_DOORBELL_INT_CNTL, | 419 | BIF_DOORBELL_INT_CNTL, |
| 404 | RAS_ATHUB_ERR_EVENT_INTERRUPT_CLEAR, 1); | 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 | amdgpu_ras_global_ras_isr(adev); | 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 | static void nbio_v7_4_enable_doorbell_interrupt(struct amdgpu_device *adev, | 592 | static void nbio_v7_4_enable_doorbell_interrupt(struct amdgpu_device *adev, |
| 573 | bool enable) | 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 | DOORBELL_INTERRUPT_DISABLE, enable ? 0 : 1); | 600 | DOORBELL_INTERRUPT_DISABLE, enable ? 0 : 1); |
| 577 | } | 601 | } |
| 578 | 602 | ||
| @@ -58,7 +58,7 @@ · 57 unmodified lines | |||
| 58 | #include "jpeg_v2_0.h" | 58 | #include "jpeg_v2_0.h" |
| 59 | #include "vcn_v3_0.h" | 59 | #include "vcn_v3_0.h" |
| 60 | #include "jpeg_v3_0.h" | 60 | #include "jpeg_v3_0.h" |
| 61 | #include "dce_virtual.h" | 61 | #include "amdgpu_vkms.h" |
| 62 | #include "mes_v10_1.h" | 62 | #include "mes_v10_1.h" |
| 63 | #include "mxgpu_nv.h" | 63 | #include "mxgpu_nv.h" |
| 64 | #include "smuio_v11_0.h" | 64 | #include "smuio_v11_0.h" |
| @@ -666,6 +666,9 @@ legacy_init: · 601 unmodified lines | |||
| 666 | case CHIP_YELLOW_CARP: | 666 | case CHIP_YELLOW_CARP: |
| 667 | yellow_carp_reg_base_init(adev); | 667 | yellow_carp_reg_base_init(adev); |
| 668 | break; | 668 | break; |
| 669 | case CHIP_CYAN_SKILLFISH: | ||
| 670 | cyan_skillfish_reg_base_init(adev); | ||
| 671 | break; | ||
| 669 | default: | 672 | default: |
| 670 | return -EINVAL; | 673 | return -EINVAL; |
| 671 | } | 674 | } |
| @@ -682,7 +685,10 @@ int nv_set_ip_blocks(struct amdgpu_device *adev) · 10 unmodified lines | |||
| 682 | { | 685 | { |
| 683 | int r; | 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 | adev->nbio.funcs = &nbio_v7_2_funcs; | 692 | adev->nbio.funcs = &nbio_v7_2_funcs; |
| 687 | adev->nbio.hdp_flush_reg = &nbio_v7_2_hdp_flush_reg; | 693 | adev->nbio.hdp_flush_reg = &nbio_v7_2_hdp_flush_reg; |
| 688 | } else { | 694 | } else { |
| @@ -715,7 +721,7 @@ int nv_set_ip_blocks(struct amdgpu_device *adev) · 26 unmodified lines | |||
| 715 | !amdgpu_sriov_vf(adev)) | 721 | !amdgpu_sriov_vf(adev)) |
| 716 | amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block); | 722 | amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block); |
| 717 | if (adev->enable_virtual_display || amdgpu_sriov_vf(adev)) | 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 | #if defined(CONFIG_DRM_AMD_DC) | 725 | #if defined(CONFIG_DRM_AMD_DC) |
| 720 | else if (amdgpu_device_has_dc_support(adev)) | 726 | else if (amdgpu_device_has_dc_support(adev)) |
| 721 | amdgpu_device_ip_block_add(adev, &dm_ip_block); | 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 | if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) | 749 | if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) |
| 744 | amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block); | 750 | amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block); |
| 745 | if (adev->enable_virtual_display || amdgpu_sriov_vf(adev)) | 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 | #if defined(CONFIG_DRM_AMD_DC) | 753 | #if defined(CONFIG_DRM_AMD_DC) |
| 748 | else if (amdgpu_device_has_dc_support(adev)) | 754 | else if (amdgpu_device_has_dc_support(adev)) |
| 749 | amdgpu_device_ip_block_add(adev, &dm_ip_block); | 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 | is_support_sw_smu(adev)) | 779 | is_support_sw_smu(adev)) |
| 774 | amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block); | 780 | amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block); |
| 775 | if (adev->enable_virtual_display || amdgpu_sriov_vf(adev)) | 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 | #if defined(CONFIG_DRM_AMD_DC) | 783 | #if defined(CONFIG_DRM_AMD_DC) |
| 778 | else if (amdgpu_device_has_dc_support(adev)) | 784 | else if (amdgpu_device_has_dc_support(adev)) |
| 779 | amdgpu_device_ip_block_add(adev, &dm_ip_block); | 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 | is_support_sw_smu(adev)) | 802 | is_support_sw_smu(adev)) |
| 797 | amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block); | 803 | amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block); |
| 798 | if (adev->enable_virtual_display || amdgpu_sriov_vf(adev)) | 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 | #if defined(CONFIG_DRM_AMD_DC) | 806 | #if defined(CONFIG_DRM_AMD_DC) |
| 801 | else if (amdgpu_device_has_dc_support(adev)) | 807 | else if (amdgpu_device_has_dc_support(adev)) |
| 802 | amdgpu_device_ip_block_add(adev, &dm_ip_block); | 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 | amdgpu_device_ip_block_add(adev, &psp_v11_0_ip_block); | 823 | amdgpu_device_ip_block_add(adev, &psp_v11_0_ip_block); |
| 818 | amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block); | 824 | amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block); |
| 819 | if (adev->enable_virtual_display || amdgpu_sriov_vf(adev)) | 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 | #if defined(CONFIG_DRM_AMD_DC) | 827 | #if defined(CONFIG_DRM_AMD_DC) |
| 822 | else if (amdgpu_device_has_dc_support(adev)) | 828 | else if (amdgpu_device_has_dc_support(adev)) |
| 823 | amdgpu_device_ip_block_add(adev, &dm_ip_block); | 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 | is_support_sw_smu(adev)) | 843 | is_support_sw_smu(adev)) |
| 838 | amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block); | 844 | amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block); |
| 839 | if (adev->enable_virtual_display || amdgpu_sriov_vf(adev)) | 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 | #if defined(CONFIG_DRM_AMD_DC) | 847 | #if defined(CONFIG_DRM_AMD_DC) |
| 842 | else if (amdgpu_device_has_dc_support(adev)) | 848 | else if (amdgpu_device_has_dc_support(adev)) |
| 843 | amdgpu_device_ip_block_add(adev, &dm_ip_block); | 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 | amdgpu_device_ip_block_add(adev, &gfx_v10_0_ip_block); | 865 | amdgpu_device_ip_block_add(adev, &gfx_v10_0_ip_block); |
| 860 | amdgpu_device_ip_block_add(adev, &sdma_v5_2_ip_block); | 866 | amdgpu_device_ip_block_add(adev, &sdma_v5_2_ip_block); |
| 861 | if (adev->enable_virtual_display || amdgpu_sriov_vf(adev)) | 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 | #if defined(CONFIG_DRM_AMD_DC) | 869 | #if defined(CONFIG_DRM_AMD_DC) |
| 864 | else if (amdgpu_device_has_dc_support(adev)) | 870 | else if (amdgpu_device_has_dc_support(adev)) |
| 865 | amdgpu_device_ip_block_add(adev, &dm_ip_block); | 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 | amdgpu_device_ip_block_add(adev, &psp_v13_0_ip_block); | 883 | amdgpu_device_ip_block_add(adev, &psp_v13_0_ip_block); |
| 878 | amdgpu_device_ip_block_add(adev, &smu_v13_0_ip_block); | 884 | amdgpu_device_ip_block_add(adev, &smu_v13_0_ip_block); |
| 879 | if (adev->enable_virtual_display || amdgpu_sriov_vf(adev)) | 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 | amdgpu_device_ip_block_add(adev, &gfx_v10_0_ip_block); | 887 | amdgpu_device_ip_block_add(adev, &gfx_v10_0_ip_block); |
| 882 | amdgpu_device_ip_block_add(adev, &sdma_v5_2_ip_block); | 888 | amdgpu_device_ip_block_add(adev, &sdma_v5_2_ip_block); |
| 883 | if (adev->enable_virtual_display || amdgpu_sriov_vf(adev)) | 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 | #if defined(CONFIG_DRM_AMD_DC) | 891 | #if defined(CONFIG_DRM_AMD_DC) |
| 886 | else if (amdgpu_device_has_dc_support(adev)) | 892 | else if (amdgpu_device_has_dc_support(adev)) |
| 887 | amdgpu_device_ip_block_add(adev, &dm_ip_block); | 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 | amdgpu_device_ip_block_add(adev, &vcn_v3_0_ip_block); | 895 | amdgpu_device_ip_block_add(adev, &vcn_v3_0_ip_block); |
| 890 | amdgpu_device_ip_block_add(adev, &jpeg_v3_0_ip_block); | 896 | amdgpu_device_ip_block_add(adev, &jpeg_v3_0_ip_block); |
| 891 | break; | 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 | default: | 912 | default: |
| 893 | return -EINVAL; | 913 | return -EINVAL; |
| 894 | } | 914 | } |
| @@ -1241,6 +1261,11 @@ static int nv_common_early_init(void *handle) · 346 unmodified lines | |||
| 1241 | else | 1261 | else |
| 1242 | adev->external_rev_id = adev->rev_id + 0x01; | 1262 | adev->external_rev_id = adev->rev_id + 0x01; |
| 1243 | break; | 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 | default: | 1269 | default: |
| 1245 | /* FIXME: not supported yet */ | 1270 | /* FIXME: not supported yet */ |
| 1246 | return -EINVAL; | 1271 | return -EINVAL; |
| @@ -38,5 +38,6 @@ void vangogh_reg_base_init(struct amdgpu_device *adev); · 37 unmodified lines | |||
| 38 | int dimgrey_cavefish_reg_base_init(struct amdgpu_device *adev); | 38 | int dimgrey_cavefish_reg_base_init(struct amdgpu_device *adev); |
| 39 | int beige_goby_reg_base_init(struct amdgpu_device *adev); | 39 | int beige_goby_reg_base_init(struct amdgpu_device *adev); |
| 40 | int yellow_carp_reg_base_init(struct amdgpu_device *adev); | 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 | #endif | 43 | #endif |
| @@ -84,29 +84,29 @@ static int psp_v10_0_init_microcode(struct psp_context *psp) · 83 unmodified lines | |||
| 84 | 84 | ||
| 85 | ta_hdr = (const struct ta_firmware_header_v1_0 *) | 85 | ta_hdr = (const struct ta_firmware_header_v1_0 *) |
| 86 | adev->psp.ta_fw->data; | 86 | adev->psp.ta_fw->data; |
| 87 | adev->psp.ta_hdcp_ucode_version = | 87 | adev->psp.hdcp.feature_version = |
| 88 | le32_to_cpu(ta_hdr->ta_hdcp_ucode_version); | 88 | le32_to_cpu(ta_hdr->hdcp.fw_version); |
| 89 | adev->psp.ta_hdcp_ucode_size = | 89 | adev->psp.hdcp.size_bytes = |
| 90 | le32_to_cpu(ta_hdr->ta_hdcp_size_bytes); | 90 | le32_to_cpu(ta_hdr->hdcp.size_bytes); |
| 91 | adev->psp.ta_hdcp_start_addr = | 91 | adev->psp.hdcp.start_addr = |
| 92 | (uint8_t *)ta_hdr + | 92 | (uint8_t *)ta_hdr + |
| 93 | le32_to_cpu(ta_hdr->header.ucode_array_offset_bytes); | 93 | le32_to_cpu(ta_hdr->header.ucode_array_offset_bytes); |
| 94 | 94 | ||
| 95 | adev->psp.ta_dtm_ucode_version = | 95 | adev->psp.dtm.feature_version = |
| 96 | le32_to_cpu(ta_hdr->ta_dtm_ucode_version); | 96 | le32_to_cpu(ta_hdr->dtm.fw_version); |
| 97 | adev->psp.ta_dtm_ucode_size = | 97 | adev->psp.dtm.size_bytes = |
| 98 | le32_to_cpu(ta_hdr->ta_dtm_size_bytes); | 98 | le32_to_cpu(ta_hdr->dtm.size_bytes); |
| 99 | adev->psp.ta_dtm_start_addr = | 99 | adev->psp.dtm.start_addr = |
| 100 | (uint8_t *)adev->psp.ta_hdcp_start_addr + | 100 | (uint8_t *)adev->psp.hdcp.start_addr + |
| 101 | le32_to_cpu(ta_hdr->ta_dtm_offset_bytes); | 101 | le32_to_cpu(ta_hdr->dtm.offset_bytes); |
| 102 | 102 | ||
| 103 | adev->psp.ta_securedisplay_ucode_version = | 103 | adev->psp.securedisplay.feature_version = |
| 104 | le32_to_cpu(ta_hdr->ta_securedisplay_ucode_version); | 104 | le32_to_cpu(ta_hdr->securedisplay.fw_version); |
| 105 | adev->psp.ta_securedisplay_ucode_size = | 105 | adev->psp.securedisplay.size_bytes = |
| 106 | le32_to_cpu(ta_hdr->ta_securedisplay_size_bytes); | 106 | le32_to_cpu(ta_hdr->securedisplay.size_bytes); |
| 107 | adev->psp.ta_securedisplay_start_addr = | 107 | adev->psp.securedisplay.start_addr = |
| 108 | (uint8_t *)adev->psp.ta_hdcp_start_addr + | 108 | (uint8_t *)adev->psp.hdcp.start_addr + |
| 109 | le32_to_cpu(ta_hdr->ta_securedisplay_offset_bytes); | 109 | le32_to_cpu(ta_hdr->securedisplay.offset_bytes); |
| 110 | 110 | ||
| 111 | adev->psp.ta_fw_version = le32_to_cpu(ta_hdr->header.ucode_version); | 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 | /* For large FW files the time to complete can be very long */ | 80 | /* For large FW files the time to complete can be very long */ |
| 81 | #define USBC_PD_POLLING_LIMIT_S 240 | 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 | static int psp_v11_0_init_microcode(struct psp_context *psp) | 86 | static int psp_v11_0_init_microcode(struct psp_context *psp) |
| 84 | { | 87 | { |
| 85 | struct amdgpu_device *adev = psp->adev; | 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 | goto out2; | 151 | goto out2; |
| 149 | 152 | ||
| 150 | ta_hdr = (const struct ta_firmware_header_v1_0 *)adev->psp.ta_fw->data; | 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); | 154 | adev->psp.xgmi.feature_version = le32_to_cpu(ta_hdr->xgmi.fw_version); |
| 152 | adev->psp.ta_xgmi_ucode_size = le32_to_cpu(ta_hdr->ta_xgmi_size_bytes); | 155 | adev->psp.xgmi.size_bytes = le32_to_cpu(ta_hdr->xgmi.size_bytes); |
| 153 | adev->psp.ta_xgmi_start_addr = (uint8_t *)ta_hdr + | 156 | adev->psp.xgmi.start_addr = (uint8_t *)ta_hdr + |
| 154 | le32_to_cpu(ta_hdr->header.ucode_array_offset_bytes); | 157 | le32_to_cpu(ta_hdr->header.ucode_array_offset_bytes); |
| 155 | adev->psp.ta_fw_version = le32_to_cpu(ta_hdr->header.ucode_version); | 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); | 159 | adev->psp.ras.feature_version = le32_to_cpu(ta_hdr->ras.fw_version); |
| 157 | adev->psp.ta_ras_ucode_size = le32_to_cpu(ta_hdr->ta_ras_size_bytes); | 160 | adev->psp.ras.size_bytes = le32_to_cpu(ta_hdr->ras.size_bytes); |
| 158 | adev->psp.ta_ras_start_addr = (uint8_t *)adev->psp.ta_xgmi_start_addr + | 161 | adev->psp.ras.start_addr = (uint8_t *)adev->psp.xgmi.start_addr + |
| 159 | le32_to_cpu(ta_hdr->ta_ras_offset_bytes); | 162 | le32_to_cpu(ta_hdr->ras.offset_bytes); |
| 160 | } | 163 | } |
| 161 | break; | 164 | break; |
| 162 | case CHIP_NAVI10: | 165 | case CHIP_NAVI10: |
| @@ -183,17 +186,17 @@ static int psp_v11_0_init_microcode(struct psp_context *psp) · 20 unmodified lines | |||
| 183 | goto out2; | 186 | goto out2; |
| 184 | 187 | ||
| 185 | ta_hdr = (const struct ta_firmware_header_v1_0 *)adev->psp.ta_fw->data; | 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); | 189 | adev->psp.hdcp.feature_version = le32_to_cpu(ta_hdr->hdcp.fw_version); |
| 187 | adev->psp.ta_hdcp_ucode_size = le32_to_cpu(ta_hdr->ta_hdcp_size_bytes); | 190 | adev->psp.hdcp.size_bytes = le32_to_cpu(ta_hdr->hdcp.size_bytes); |
| 188 | adev->psp.ta_hdcp_start_addr = (uint8_t *)ta_hdr + | 191 | adev->psp.hdcp.start_addr = (uint8_t *)ta_hdr + |
| 189 | le32_to_cpu(ta_hdr->header.ucode_array_offset_bytes); | 192 | le32_to_cpu(ta_hdr->header.ucode_array_offset_bytes); |
| 190 | 193 | ||
| 191 | adev->psp.ta_fw_version = le32_to_cpu(ta_hdr->header.ucode_version); | 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); | 196 | adev->psp.dtm.feature_version = le32_to_cpu(ta_hdr->dtm.fw_version); |
| 194 | adev->psp.ta_dtm_ucode_size = le32_to_cpu(ta_hdr->ta_dtm_size_bytes); | 197 | adev->psp.dtm.size_bytes = le32_to_cpu(ta_hdr->dtm.size_bytes); |
| 195 | adev->psp.ta_dtm_start_addr = (uint8_t *)adev->psp.ta_hdcp_start_addr + | 198 | adev->psp.dtm.start_addr = (uint8_t *)adev->psp.hdcp.start_addr + |
| 196 | le32_to_cpu(ta_hdr->ta_dtm_offset_bytes); | 199 | le32_to_cpu(ta_hdr->dtm.offset_bytes); |
| 197 | } | 200 | } |
| 198 | break; | 201 | break; |
| 199 | case CHIP_SIENNA_CICHLID: | 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 | return ret; | 287 | return ret; |
| 285 | 288 | ||
| 286 | /* Copy PSP KDB binary to memory */ | 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 | /* Provide the PSP KDB to bootloader */ | 292 | /* Provide the PSP KDB to bootloader */ |
| 290 | WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_36, | 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 | return ret; | 318 | return ret; |
| 316 | 319 | ||
| 317 | /* Copy PSP SPL binary to memory */ | 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 | /* Provide the PSP SPL to bootloader */ | 323 | /* Provide the PSP SPL to bootloader */ |
| 321 | WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_36, | 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 | return ret; | 349 | return ret; |
| 347 | 350 | ||
| 348 | /* Copy PSP System Driver binary to memory */ | 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 | /* Provide the sys driver to bootloader */ | 354 | /* Provide the sys driver to bootloader */ |
| 352 | WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_36, | 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 | return ret; | 383 | return ret; |
| 381 | 384 | ||
| 382 | /* Copy Secure OS binary to PSP memory */ | 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 | /* Provide the PSP secure OS to bootloader */ | 388 | /* Provide the PSP secure OS to bootloader */ |
| 386 | WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_36, | 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 | WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_67, value); | 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 | struct amdgpu_device *adev = psp->adev; | 761 | struct amdgpu_device *adev = psp->adev; |
| 759 | uint32_t reg_status; | 762 | uint32_t reg_status; |
| 760 | int ret, i = 0; | 763 | int ret, i = 0; |
| 761 | 764 | ||
| 762 | /* Write lower 32-bit address of the PD Controller FW */ | 765 | /* |
| 763 | WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_36, lower_32_bits(dma_addr)); | 766 | * LFB address which is aligned to 1MB address and has to be |
| 764 | ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_35), | 767 | * right-shifted by 20 so that LFB address can be passed on a 32-bit C2P |
| 765 | 0x80000000, 0x80000000, false); | 768 | * register |
| 766 | if (ret) | 769 | */ |
| 767 | return ret; | 770 | WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_36, (fw_pri_mc_addr >> 20)); |
| 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)); | ||
| 786 | 771 | ||
| 787 | ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_35), | 772 | ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_35), |
| 788 | 0x80000000, 0x80000000, false); | 773 | 0x80000000, 0x80000000, false); |
| 789 | if (ret) | 774 | if (ret) |
| 790 | return ret; | 775 | return ret; |
| 791 | 776 | ||
| 792 | /* Fireup interrupt so PSP can pick up the upper address */ | 777 | /* Fireup interrupt so PSP can pick up the address */ |
| 793 | WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_35, 0x4000000); | 778 | WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_35, (GFX_CMD_USB_PD_USE_LFB << 16)); |
| 794 | 779 | ||
| 795 | /* FW load takes very long time */ | 780 | /* FW load takes very long time */ |
| 796 | do { | 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 | done: | 791 | done: |
| 807 | 792 | ||
| 808 | if ((reg_status & 0xFFFF) != 0) { | 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 | reg_status & 0xFFFF); | 795 | reg_status & 0xFFFF); |
| 811 | return -EIO; | 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 | * Permission is hereby granted, free of charge, to any person obtaining a | 4 | * Permission is hereby granted, free of charge, to any person obtaining a |
| 5 | * copy of this software and associated documentation files (the "Software"), | 5 | * copy of this software and associated documentation files (the "Software"), |
| @@ -20,11 +20,11 @@ · 14 unmodified lines | |||
| 20 | * OTHER DEALINGS IN THE SOFTWARE. | 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__ | 26 | #include "amdgpu_psp.h" |
| 25 | #define __DCE_VIRTUAL_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 | #endif | 30 | #endif |
| 30 | |||
| @@ -84,23 +84,23 @@ static int psp_v12_0_init_microcode(struct psp_context *psp) · 83 unmodified lines | |||
| 84 | 84 | ||
| 85 | ta_hdr = (const struct ta_firmware_header_v1_0 *) | 85 | ta_hdr = (const struct ta_firmware_header_v1_0 *) |
| 86 | adev->psp.ta_fw->data; | 86 | adev->psp.ta_fw->data; |
| 87 | adev->psp.ta_hdcp_ucode_version = | 87 | adev->psp.hdcp.feature_version = |
| 88 | le32_to_cpu(ta_hdr->ta_hdcp_ucode_version); | 88 | le32_to_cpu(ta_hdr->hdcp.fw_version); |
| 89 | adev->psp.ta_hdcp_ucode_size = | 89 | adev->psp.hdcp.size_bytes = |
| 90 | le32_to_cpu(ta_hdr->ta_hdcp_size_bytes); | 90 | le32_to_cpu(ta_hdr->hdcp.size_bytes); |
| 91 | adev->psp.ta_hdcp_start_addr = | 91 | adev->psp.hdcp.start_addr = |
| 92 | (uint8_t *)ta_hdr + | 92 | (uint8_t *)ta_hdr + |
| 93 | le32_to_cpu(ta_hdr->header.ucode_array_offset_bytes); | 93 | le32_to_cpu(ta_hdr->header.ucode_array_offset_bytes); |
| 94 | 94 | ||
| 95 | adev->psp.ta_fw_version = le32_to_cpu(ta_hdr->header.ucode_version); | 95 | adev->psp.ta_fw_version = le32_to_cpu(ta_hdr->header.ucode_version); |
| 96 | 96 | ||
| 97 | adev->psp.ta_dtm_ucode_version = | 97 | adev->psp.dtm.feature_version = |
| 98 | le32_to_cpu(ta_hdr->ta_dtm_ucode_version); | 98 | le32_to_cpu(ta_hdr->dtm.fw_version); |
| 99 | adev->psp.ta_dtm_ucode_size = | 99 | adev->psp.dtm.size_bytes = |
| 100 | le32_to_cpu(ta_hdr->ta_dtm_size_bytes); | 100 | le32_to_cpu(ta_hdr->dtm.size_bytes); |
| 101 | adev->psp.ta_dtm_start_addr = | 101 | adev->psp.dtm.start_addr = |
| 102 | (uint8_t *)adev->psp.ta_hdcp_start_addr + | 102 | (uint8_t *)adev->psp.hdcp.start_addr + |
| 103 | le32_to_cpu(ta_hdr->ta_dtm_offset_bytes); | 103 | le32_to_cpu(ta_hdr->dtm.offset_bytes); |
| 104 | } | 104 | } |
| 105 | 105 | ||
| 106 | return 0; | 106 | return 0; |
| @@ -138,7 +138,7 @@ static int psp_v12_0_bootloader_load_sysdrv(struct psp_context *psp) · 31 unmodified lines | |||
| 138 | return ret; | 138 | return ret; |
| 139 | 139 | ||
| 140 | /* Copy PSP System Driver binary to memory */ | 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 | /* Provide the sys driver to bootloader */ | 143 | /* Provide the sys driver to bootloader */ |
| 144 | WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_36, | 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 | return ret; | 177 | return ret; |
| 178 | 178 | ||
| 179 | /* Copy Secure OS binary to PSP memory */ | 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 | /* Provide the PSP secure OS to bootloader */ | 182 | /* Provide the PSP secure OS to bootloader */ |
| 183 | WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_36, | 183 | WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_36, |
| @@ -35,6 +35,12 @@ MODULE_FIRMWARE("amdgpu/yellow_carp_asd.bin"); · 34 unmodified lines | |||
| 35 | MODULE_FIRMWARE("amdgpu/yellow_carp_toc.bin"); | 35 | MODULE_FIRMWARE("amdgpu/yellow_carp_toc.bin"); |
| 36 | MODULE_FIRMWARE("amdgpu/yellow_carp_ta.bin"); | 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 | static int psp_v13_0_init_microcode(struct psp_context *psp) | 44 | static int psp_v13_0_init_microcode(struct psp_context *psp) |
| 39 | { | 45 | { |
| 40 | struct amdgpu_device *adev = psp->adev; | 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 | return ret; | 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 | int ret; | 124 | int ret; |
| 117 | uint32_t psp_gfxdrv_command_reg = 0; | 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 | memset(psp->fw_pri_buf, 0, PSP_1_MEG); | 138 | memset(psp->fw_pri_buf, 0, PSP_1_MEG); |
| 131 | 139 | ||
| 132 | /* Copy PSP KDB binary to memory */ | 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 | /* Provide the PSP KDB to bootloader */ | 143 | /* Provide the PSP KDB to bootloader */ |
| 136 | WREG32_SOC15(MP0, 0, regMP0_SMN_C2PMSG_36, | 144 | WREG32_SOC15(MP0, 0, regMP0_SMN_C2PMSG_36, |
| 137 | (uint32_t)(psp->fw_pri_mc_addr >> 20)); | 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 | WREG32_SOC15(MP0, 0, regMP0_SMN_C2PMSG_35, | 147 | WREG32_SOC15(MP0, 0, regMP0_SMN_C2PMSG_35, |
| 140 | psp_gfxdrv_command_reg); | 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 | return ret; | 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; | 157 | return psp_v13_0_bootloader_load_component(psp, &psp->kdb, PSP_BL__LOAD_KEY_DATABASE); |
| 150 | uint32_t psp_gfxdrv_command_reg = 0; | 158 | } |
| 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); | ||
| 167 | 159 | ||
| 168 | /* Provide the sys driver to bootloader */ | 160 | static int psp_v13_0_bootloader_load_sysdrv(struct psp_context *psp) |
| 169 | WREG32_SOC15(MP0, 0, regMP0_SMN_C2PMSG_36, | 161 | { |
| 170 | (uint32_t)(psp->fw_pri_mc_addr >> 20)); | 162 | return psp_v13_0_bootloader_load_component(psp, &psp->sys, PSP_BL__LOAD_SYSDRV); |
| 171 | psp_gfxdrv_command_reg = PSP_BL__LOAD_SYSDRV; | 163 | } |
| 172 | WREG32_SOC15(MP0, 0, regMP0_SMN_C2PMSG_35, | ||
| 173 | psp_gfxdrv_command_reg); | ||
| 174 | 164 | ||
| 175 | /* there might be handshake issue with hardware which needs delay */ | 165 | static int psp_v13_0_bootloader_load_soc_drv(struct psp_context *psp) |
| 176 | mdelay(20); | 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 | static int psp_v13_0_bootloader_load_sos(struct psp_context *psp) | 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 | memset(psp->fw_pri_buf, 0, PSP_1_MEG); | 196 | memset(psp->fw_pri_buf, 0, PSP_1_MEG); |
| 200 | 197 | ||
| 201 | /* Copy Secure OS binary to PSP memory */ | 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 | /* Provide the PSP secure OS to bootloader */ | 201 | /* Provide the PSP secure OS to bootloader */ |
| 205 | WREG32_SOC15(MP0, 0, regMP0_SMN_C2PMSG_36, | 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 | WREG32_SOC15(MP0, 0, regMP0_SMN_C2PMSG_67, value); | 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 | static const struct psp_funcs psp_v13_0_funcs = { | 440 | static const struct psp_funcs psp_v13_0_funcs = { |
| 386 | .init_microcode = psp_v13_0_init_microcode, | 441 | .init_microcode = psp_v13_0_init_microcode, |
| 387 | .bootloader_load_kdb = psp_v13_0_bootloader_load_kdb, | 442 | .bootloader_load_kdb = psp_v13_0_bootloader_load_kdb, |
| 388 | .bootloader_load_sysdrv = psp_v13_0_bootloader_load_sysdrv, | 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 | .bootloader_load_sos = psp_v13_0_bootloader_load_sos, | 447 | .bootloader_load_sos = psp_v13_0_bootloader_load_sos, |
| 390 | .ring_init = psp_v13_0_ring_init, | 448 | .ring_init = psp_v13_0_ring_init, |
| 391 | .ring_create = psp_v13_0_ring_create, | 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 | .ring_destroy = psp_v13_0_ring_destroy, | 451 | .ring_destroy = psp_v13_0_ring_destroy, |
| 394 | .ring_get_wptr = psp_v13_0_ring_get_wptr, | 452 | .ring_get_wptr = psp_v13_0_ring_get_wptr, |
| 395 | .ring_set_wptr = psp_v13_0_ring_set_wptr, | 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 | void psp_v13_0_set_psp_funcs(struct psp_context *psp) | 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 | return ret; | 103 | return ret; |
| 104 | 104 | ||
| 105 | /* Copy PSP System Driver binary to memory */ | 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 | /* Provide the sys driver to bootloader */ | 108 | /* Provide the sys driver to bootloader */ |
| 109 | WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_36, | 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 | return ret; | 142 | return ret; |
| 143 | 143 | ||
| 144 | /* Copy Secure OS binary to PSP memory */ | 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 | /* Provide the PSP secure OS to bootloader */ | 147 | /* Provide the PSP secure OS to bootloader */ |
| 148 | WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_36, | 148 | WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_36, |
| @@ -51,6 +51,12 @@ MODULE_FIRMWARE("amdgpu/navi14_sdma1.bin"); · 50 unmodified lines | |||
| 51 | MODULE_FIRMWARE("amdgpu/navi12_sdma.bin"); | 51 | MODULE_FIRMWARE("amdgpu/navi12_sdma.bin"); |
| 52 | MODULE_FIRMWARE("amdgpu/navi12_sdma1.bin"); | 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 | #define SDMA1_REG_OFFSET 0x600 | 60 | #define SDMA1_REG_OFFSET 0x600 |
| 55 | #define SDMA0_HYP_DEC_REG_START 0x5880 | 61 | #define SDMA0_HYP_DEC_REG_START 0x5880 |
| 56 | #define SDMA0_HYP_DEC_REG_END 0x5893 | 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 | SOC15_REG_GOLDEN_VALUE(GC, 0, mmSDMA1_RLC3_RB_WPTR_POLL_CNTL, 0xfffffff7, 0x00403000), | 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 | static u32 sdma_v5_0_get_reg_offset(struct amdgpu_device *adev, u32 instance, u32 internal_offset) | 170 | static u32 sdma_v5_0_get_reg_offset(struct amdgpu_device *adev, u32 instance, u32 internal_offset) |
| 134 | { | 171 | { |
| 135 | u32 base; | 172 | u32 base; |
| @@ -180,6 +217,11 @@ static void sdma_v5_0_init_golden_registers(struct amdgpu_device *adev) · 44 unmodified lines | |||
| 180 | golden_settings_sdma_nv12, | 217 | golden_settings_sdma_nv12, |
| 181 | (const u32)ARRAY_SIZE(golden_settings_sdma_nv12)); | 218 | (const u32)ARRAY_SIZE(golden_settings_sdma_nv12)); |
| 182 | break; | 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 | default: | 225 | default: |
| 184 | break; | 226 | break; |
| 185 | } | 227 | } |
| @@ -200,7 +242,7 @@ static void sdma_v5_0_init_golden_registers(struct amdgpu_device *adev) · 14 unmodified lines | |||
| 200 | static int sdma_v5_0_init_microcode(struct amdgpu_device *adev) | 242 | static int sdma_v5_0_init_microcode(struct amdgpu_device *adev) |
| 201 | { | 243 | { |
| 202 | const char *chip_name; | 244 | const char *chip_name; |
| 203 | char fw_name[30]; | 245 | char fw_name[40]; |
| 204 | int err = 0, i; | 246 | int err = 0, i; |
| 205 | struct amdgpu_firmware_info *info = NULL; | 247 | struct amdgpu_firmware_info *info = NULL; |
| 206 | const struct common_firmware_header *header = NULL; | 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 | case CHIP_NAVI12: | 263 | case CHIP_NAVI12: |
| 222 | chip_name = "navi12"; | 264 | chip_name = "navi12"; |
| 223 | break; | 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 | default: | 272 | default: |
| 225 | BUG(); | 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 | return base + internal_offset; | 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 | static int sdma_v5_2_init_inst_ctx(struct amdgpu_sdma_instance *sdma_inst) | 90 | static int sdma_v5_2_init_inst_ctx(struct amdgpu_sdma_instance *sdma_inst) |
| 106 | { | 91 | { |
| 107 | int err = 0; | 92 | int err = 0; |
| @@ -1345,8 +1330,6 @@ static int sdma_v5_2_hw_init(void *handle) · 1237 unmodified lines | |||
| 1345 | int r; | 1330 | int r; |
| 1346 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; | 1331 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; |
| 1347 | 1332 | ||
| 1348 | sdma_v5_2_init_golden_registers(adev); | ||
| 1349 | |||
| 1350 | r = sdma_v5_2_start(adev); | 1333 | r = sdma_v5_2_start(adev); |
| 1351 | 1334 | ||
| 1352 | return r; | 1335 | return r; |
| @@ -44,7 +44,7 @@ · 43 unmodified lines | |||
| 44 | #include "dce_v6_0.h" | 44 | #include "dce_v6_0.h" |
| 45 | #include "si.h" | 45 | #include "si.h" |
| 46 | #include "uvd_v3_1.h" | 46 | #include "uvd_v3_1.h" |
| 47 | #include "dce_virtual.h" | 47 | #include "amdgpu_vkms.h" |
| 48 | #include "gca/gfx_6_0_d.h" | 48 | #include "gca/gfx_6_0_d.h" |
| 49 | #include "oss/oss_1_0_d.h" | 49 | #include "oss/oss_1_0_d.h" |
| 50 | #include "oss/oss_1_0_sh_mask.h" | 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 | amdgpu_device_ip_block_add(adev, &si_dma_ip_block); | 2759 | amdgpu_device_ip_block_add(adev, &si_dma_ip_block); |
| 2760 | amdgpu_device_ip_block_add(adev, &si_smu_ip_block); | 2760 | amdgpu_device_ip_block_add(adev, &si_smu_ip_block); |
| 2761 | if (adev->enable_virtual_display) | 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 | #if defined(CONFIG_DRM_AMD_DC) && defined(CONFIG_DRM_AMD_DC_SI) | 2763 | #if defined(CONFIG_DRM_AMD_DC) && defined(CONFIG_DRM_AMD_DC_SI) |
| 2764 | else if (amdgpu_device_has_dc_support(adev)) | 2764 | else if (amdgpu_device_has_dc_support(adev)) |
| 2765 | amdgpu_device_ip_block_add(adev, &dm_ip_block); | 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 | amdgpu_device_ip_block_add(adev, &si_dma_ip_block); | 2777 | amdgpu_device_ip_block_add(adev, &si_dma_ip_block); |
| 2778 | amdgpu_device_ip_block_add(adev, &si_smu_ip_block); | 2778 | amdgpu_device_ip_block_add(adev, &si_smu_ip_block); |
| 2779 | if (adev->enable_virtual_display) | 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 | #if defined(CONFIG_DRM_AMD_DC) && defined(CONFIG_DRM_AMD_DC_SI) | 2781 | #if defined(CONFIG_DRM_AMD_DC) && defined(CONFIG_DRM_AMD_DC_SI) |
| 2782 | else if (amdgpu_device_has_dc_support(adev)) | 2782 | else if (amdgpu_device_has_dc_support(adev)) |
| 2783 | amdgpu_device_ip_block_add(adev, &dm_ip_block); | 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 | amdgpu_device_ip_block_add(adev, &si_dma_ip_block); | 2795 | amdgpu_device_ip_block_add(adev, &si_dma_ip_block); |
| 2796 | amdgpu_device_ip_block_add(adev, &si_smu_ip_block); | 2796 | amdgpu_device_ip_block_add(adev, &si_smu_ip_block); |
| 2797 | if (adev->enable_virtual_display) | 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 | break; | 2799 | break; |
| 2800 | default: | 2800 | default: |
| 2801 | BUG(); | 2801 | BUG(); |
| @@ -41,9 +41,7 @@ · 40 unmodified lines | |||
| 41 | #define I2C_SW_TIMEOUT 8 | 41 | #define I2C_SW_TIMEOUT 8 |
| 42 | #define I2C_ABORT 0x10 | 42 | #define I2C_ABORT 0x10 |
| 43 | 43 | ||
| 44 | /* I2C transaction flags */ | 44 | #define I2C_X_RESTART BIT(31) |
| 45 | #define I2C_NO_STOP 1 | ||
| 46 | #define I2C_RESTART 2 | ||
| 47 | 45 | ||
| 48 | #define to_amdgpu_device(x) (container_of(x, struct amdgpu_device, pm.smu_i2c)) | 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 | WREG32_SOC15(SMUIO, 0, mmSMUIO_PWRMGT, reg); | 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 | struct amdgpu_device *adev = to_amdgpu_device(control); | 78 | struct amdgpu_device *adev = to_amdgpu_device(control); |
| 63 | 79 | ||
| 64 | WREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_ENABLE, enable ? 1 : 0); | 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 | static void smu_v11_0_i2c_clear_status(struct i2c_adapter *control) | 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 | reg = REG_SET_FIELD(reg, CKSVII2C_IC_CON, IC_RESTART_EN, 1); | 117 | reg = REG_SET_FIELD(reg, CKSVII2C_IC_CON, IC_RESTART_EN, 1); |
| 84 | reg = REG_SET_FIELD(reg, CKSVII2C_IC_CON, IC_10BITADDR_MASTER, 0); | 118 | reg = REG_SET_FIELD(reg, CKSVII2C_IC_CON, IC_10BITADDR_MASTER, 0); |
| 85 | reg = REG_SET_FIELD(reg, CKSVII2C_IC_CON, IC_10BITADDR_SLAVE, 0); | 119 | reg = REG_SET_FIELD(reg, CKSVII2C_IC_CON, IC_10BITADDR_SLAVE, 0); |
| 86 | /* Standard mode */ | 120 | /* The values of IC_MAX_SPEED_MODE are, |
| 87 | reg = REG_SET_FIELD(reg, CKSVII2C_IC_CON, IC_MAX_SPEED_MODE, 2); | 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 | reg = REG_SET_FIELD(reg, CKSVII2C_IC_CON, IC_MASTER_MODE, 1); | 127 | reg = REG_SET_FIELD(reg, CKSVII2C_IC_CON, IC_MASTER_MODE, 1); |
| 89 | 128 | ||
| 90 | WREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_CON, reg); | 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 | WREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_SDA_HOLD, 20); | 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 | struct amdgpu_device *adev = to_amdgpu_device(control); | 157 | struct amdgpu_device *adev = to_amdgpu_device(control); |
| 119 | 158 | ||
| 120 | /* Convert fromr 8-bit to 7-bit address */ | 159 | /* The IC_TAR::IC_TAR field is 10-bits wide. |
| 121 | address >>= 1; | 160 | * It takes a 7-bit or 10-bit addresses as an address, |
| 122 | WREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_TAR, (address & 0xFF)); | 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 | static uint32_t smu_v11_0_i2c_poll_tx_status(struct i2c_adapter *control) | 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 | return ret; | 247 | return ret; |
| 207 | } | 248 | } |
| 208 | 249 | ||
| 209 | |||
| 210 | |||
| 211 | |||
| 212 | /** | 250 | /** |
| 213 | * smu_v11_0_i2c_transmit - Send a block of data over the I2C bus to a slave device. | 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 | * Returns 0 on success or error. | 259 | * Returns 0 on success or error. |
| 222 | */ | 260 | */ |
| 223 | static uint32_t smu_v11_0_i2c_transmit(struct i2c_adapter *control, | 261 | static uint32_t smu_v11_0_i2c_transmit(struct i2c_adapter *control, |
| 224 | uint8_t address, uint8_t *data, | 262 | u16 address, u8 *data, |
| 225 | uint32_t numbytes, uint32_t i2c_flag) | 263 | u32 numbytes, u32 i2c_flag) |
| 226 | { | 264 | { |
| 227 | struct amdgpu_device *adev = to_amdgpu_device(control); | 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 | unsigned long timeout_counter; | 267 | unsigned long timeout_counter; |
| 230 | 268 | ||
| 231 | bytes_sent = 0; | 269 | bytes_sent = 0; |
| 232 | 270 | ||
| 233 | DRM_DEBUG_DRIVER("I2C_Transmit(), address = %x, bytes = %d , data: ", | 271 | DRM_DEBUG_DRIVER("I2C_Transmit(), address = %x, bytes = %d , data: ", |
| 234 | (uint16_t)address, numbytes); | 272 | address, numbytes); |
| 235 | 273 | ||
| 236 | if (drm_debug_enabled(DRM_UT_DRIVER)) { | 274 | if (drm_debug_enabled(DRM_UT_DRIVER)) { |
| 237 | print_hex_dump(KERN_INFO, "data: ", DUMP_PREFIX_NONE, | 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 | /* Clear status bits */ | 284 | /* Clear status bits */ |
| 247 | smu_v11_0_i2c_clear_status(control); | 285 | smu_v11_0_i2c_clear_status(control); |
| 248 | 286 | ||
| 249 | |||
| 250 | timeout_counter = jiffies + msecs_to_jiffies(20); | 287 | timeout_counter = jiffies + msecs_to_jiffies(20); |
| 251 | 288 | ||
| 252 | while (numbytes > 0) { | 289 | while (numbytes > 0) { |
| 253 | reg = RREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_STATUS); | 290 | reg = RREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_STATUS); |
| 254 | if (REG_GET_FIELD(reg, CKSVII2C_IC_STATUS, TFNF)) { | 291 | if (!REG_GET_FIELD(reg, CKSVII2C_IC_STATUS, TFNF)) { |
| 255 | do { | 292 | /* |
| 256 | reg = 0; | 293 | * We waited for too long for the transmission |
| 257 | /* | 294 | * FIFO to become not-full. Exit the loop |
| 258 | * Prepare transaction, no need to set RESTART. I2C engine will send | 295 | * with error. |
| 259 | * START as soon as it sees data in TXFIFO | 296 | */ |
| 260 | */ | 297 | if (time_after(jiffies, timeout_counter)) { |
| 261 | if (bytes_sent == 0) | 298 | ret |= I2C_SW_TIMEOUT; |
| 262 | reg = REG_SET_FIELD(reg, CKSVII2C_IC_DATA_CMD, RESTART, | 299 | goto Err; |
| 263 | (i2c_flag & I2C_RESTART) ? 1 : 0); | 300 | } |
| 264 | reg = REG_SET_FIELD(reg, CKSVII2C_IC_DATA_CMD, DAT, data[bytes_sent]); | 301 | } else { |
| 265 | 302 | reg = REG_SET_FIELD(reg, CKSVII2C_IC_DATA_CMD, DAT, | |
| 266 | /* determine if we need to send STOP bit or not */ | 303 | data[bytes_sent]); |
| 267 | if (numbytes == 1) | 304 | |
| 268 | /* Final transaction, so send stop unless I2C_NO_STOP */ | 305 | /* Final message, final byte, must generate a |
| 269 | reg = REG_SET_FIELD(reg, CKSVII2C_IC_DATA_CMD, STOP, | 306 | * STOP to release the bus, i.e. don't hold |
| 270 | (i2c_flag & I2C_NO_STOP) ? 0 : 1); | 307 | * SCL low. |
| 271 | /* Write */ | 308 | */ |
| 272 | reg = REG_SET_FIELD(reg, CKSVII2C_IC_DATA_CMD, CMD, 0); | 309 | if (numbytes == 1 && i2c_flag & I2C_M_STOP) |
| 273 | WREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_DATA_CMD, reg); | 310 | reg = REG_SET_FIELD(reg, |
| 274 | 311 | CKSVII2C_IC_DATA_CMD, | |
| 275 | /* Record that the bytes were transmitted */ | 312 | STOP, 1); |
| 276 | bytes_sent++; | 313 | |
| 277 | numbytes--; | 314 | if (bytes_sent == 0 && i2c_flag & I2C_X_RESTART) |
| 278 | 315 | reg = REG_SET_FIELD(reg, | |
| 279 | reg = RREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_STATUS); | 316 | CKSVII2C_IC_DATA_CMD, |
| 280 | 317 | RESTART, 1); | |
| 281 | } while (numbytes && REG_GET_FIELD(reg, CKSVII2C_IC_STATUS, TFNF)); | 318 | |
| 282 | } | 319 | /* Write */ |
| 283 | 320 | reg = REG_SET_FIELD(reg, CKSVII2C_IC_DATA_CMD, CMD, 0); | |
| 284 | /* | 321 | WREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_DATA_CMD, reg); |
| 285 | * We waited too long for the transmission FIFO to become not-full. | 322 | |
| 286 | * Exit the loop with error. | 323 | /* Record that the bytes were transmitted */ |
| 287 | */ | 324 | bytes_sent++; |
| 288 | if (time_after(jiffies, timeout_counter)) { | 325 | numbytes--; |
| 289 | ret |= I2C_SW_TIMEOUT; | ||
| 290 | goto Err; | ||
| 291 | } | 326 | } |
| 292 | } | 327 | } |
| 293 | 328 | ||
| 294 | ret = smu_v11_0_i2c_poll_tx_status(control); | 329 | ret = smu_v11_0_i2c_poll_tx_status(control); |
| 295 | |||
| 296 | Err: | 330 | Err: |
| 297 | /* Any error, no point in proceeding */ | 331 | /* Any error, no point in proceeding */ |
| 298 | if (ret != I2C_OK) { | 332 | if (ret != I2C_OK) { |
| @@ -323,8 +357,8 @@ Err: · 24 unmodified lines | |||
| 323 | * Returns 0 on success or error. | 357 | * Returns 0 on success or error. |
| 324 | */ | 358 | */ |
| 325 | static uint32_t smu_v11_0_i2c_receive(struct i2c_adapter *control, | 359 | static uint32_t smu_v11_0_i2c_receive(struct i2c_adapter *control, |
| 326 | uint8_t address, uint8_t *data, | 360 | u16 address, u8 *data, |
| 327 | uint32_t numbytes, uint8_t i2c_flag) | 361 | u32 numbytes, u32 i2c_flag) |
| 328 | { | 362 | { |
| 329 | struct amdgpu_device *adev = to_amdgpu_device(control); | 363 | struct amdgpu_device *adev = to_amdgpu_device(control); |
| 330 | uint32_t bytes_received, ret = I2C_OK; | 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 | smu_v11_0_i2c_clear_status(control); | 377 | smu_v11_0_i2c_clear_status(control); |
| 344 | 378 | ||
| 345 | |||
| 346 | /* Prepare transaction */ | 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 | reg = REG_SET_FIELD(reg, CKSVII2C_IC_DATA_CMD, DAT, 0); | 380 | reg = REG_SET_FIELD(reg, CKSVII2C_IC_DATA_CMD, DAT, 0); |
| 354 | /* Read */ | 381 | /* Read */ |
| 355 | reg = REG_SET_FIELD(reg, CKSVII2C_IC_DATA_CMD, CMD, 1); | 382 | reg = REG_SET_FIELD(reg, CKSVII2C_IC_DATA_CMD, CMD, 1); |
| 356 | 383 | ||
| 357 | /* Transmitting last byte */ | 384 | /* Final message, final byte, must generate a STOP |
| 358 | if (numbytes == 1) | 385 | * to release the bus, i.e. don't hold SCL low. |
| 359 | /* Final transaction, so send stop if requested */ | 386 | */ |
| 360 | reg = REG_SET_FIELD(reg, CKSVII2C_IC_DATA_CMD, STOP, | 387 | if (numbytes == 1 && i2c_flag & I2C_M_STOP) |
| 361 | (i2c_flag & I2C_NO_STOP) ? 0 : 1); | 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 | WREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_DATA_CMD, reg); | 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 | DRM_DEBUG_DRIVER("I2C_Abort() Done."); | 445 | DRM_DEBUG_DRIVER("I2C_Abort() Done."); |
| 414 | } | 446 | } |
| 415 | 447 | ||
| 416 | |||
| 417 | static bool smu_v11_0_i2c_activity_done(struct i2c_adapter *control) | 448 | static bool smu_v11_0_i2c_activity_done(struct i2c_adapter *control) |
| 418 | { | 449 | { |
| 419 | struct amdgpu_device *adev = to_amdgpu_device(control); | 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 | reg_ic_enable_status = RREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_ENABLE_STATUS); | 456 | reg_ic_enable_status = RREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_ENABLE_STATUS); |
| 426 | reg_ic_enable = RREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_ENABLE); | 457 | reg_ic_enable = RREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_ENABLE); |
| 427 | 458 | ||
| 428 | |||
| 429 | if ((REG_GET_FIELD(reg_ic_enable, CKSVII2C_IC_ENABLE, ENABLE) == 0) && | 459 | if ((REG_GET_FIELD(reg_ic_enable, CKSVII2C_IC_ENABLE, ENABLE) == 0) && |
| 430 | (REG_GET_FIELD(reg_ic_enable_status, CKSVII2C_IC_ENABLE_STATUS, IC_EN) == 1)) { | 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 | static void smu_v11_0_i2c_init(struct i2c_adapter *control) | 486 | static void smu_v11_0_i2c_init(struct i2c_adapter *control) |
| 457 | { | 487 | { |
| 488 | int res; | ||
| 489 | |||
| 458 | /* Disable clock gating */ | 490 | /* Disable clock gating */ |
| 459 | smu_v11_0_i2c_set_clock_gating(control, false); | 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 | DRM_WARN("I2C busy !"); | 494 | DRM_WARN("I2C busy !"); |
| 463 | 495 | ||
| 464 | /* Disable I2C */ | 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 | /* Configure I2C to operate as master and in standard mode */ | 501 | /* Configure I2C to operate as master and in standard mode */ |
| 468 | smu_v11_0_i2c_configure(control); | 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 | static void smu_v11_0_i2c_fini(struct i2c_adapter *control) | 509 | static void smu_v11_0_i2c_fini(struct i2c_adapter *control) |
| 476 | { | 510 | { |
| 477 | struct amdgpu_device *adev = to_amdgpu_device(control); | 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 */ | 521 | /* Nobody is using the I2C engine, yet it remains |
| 483 | reg_ic_enable_status = RREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_ENABLE_STATUS); | 522 | * active, possibly because someone missed to send |
| 484 | reg_ic_enable = RREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_ENABLE); | 523 | * STOP. |
| 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 | ||
| 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 | smu_v11_0_i2c_abort(control); | 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 | /***************************** I2C GLUE ****************************/ | 566 | /***************************** I2C GLUE ****************************/ |
| 532 | 567 | ||
| 533 | static uint32_t smu_v11_0_i2c_read_data(struct i2c_adapter *control, | 568 | static uint32_t smu_v11_0_i2c_read_data(struct i2c_adapter *control, |
| 534 | uint8_t address, | 569 | struct i2c_msg *msg, uint32_t i2c_flag) |
| 535 | uint8_t *data, | ||
| 536 | uint32_t numbytes) | ||
| 537 | { | 570 | { |
| 538 | uint32_t ret = 0; | 571 | uint32_t ret; |
| 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; | ||
| 544 | 572 | ||
| 545 | /* Now read data starting with that address */ | 573 | ret = smu_v11_0_i2c_receive(control, msg->addr, msg->buf, msg->len, i2c_flag); |
| 546 | ret = smu_v11_0_i2c_receive(control, address, data + 2, numbytes - 2, | ||
| 547 | I2C_RESTART); | ||
| 548 | 574 | ||
| 549 | Fail: | ||
| 550 | if (ret != I2C_OK) | 575 | if (ret != I2C_OK) |
| 551 | DRM_ERROR("ReadData() - I2C error occurred :%x", ret); | 576 | DRM_ERROR("ReadData() - I2C error occurred :%x", ret); |
| 552 | 577 | ||
| @@ -554,28 +579,15 @@ Fail: · 1 unmodified line | |||
| 554 | } | 579 | } |
| 555 | 580 | ||
| 556 | static uint32_t smu_v11_0_i2c_write_data(struct i2c_adapter *control, | 581 | static uint32_t smu_v11_0_i2c_write_data(struct i2c_adapter *control, |
| 557 | uint8_t address, | 582 | struct i2c_msg *msg, uint32_t i2c_flag) |
| 558 | uint8_t *data, | ||
| 559 | uint32_t numbytes) | ||
| 560 | { | 583 | { |
| 561 | uint32_t ret; | 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 | if (ret != I2C_OK) | 588 | if (ret != I2C_OK) |
| 566 | DRM_ERROR("WriteI2CData() - I2C error occurred :%x", ret); | 589 | DRM_ERROR("WriteI2CData() - I2C error occurred :%x", ret); |
| 567 | else | 590 | |
| 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 | |||
| 579 | return ret; | 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 | struct amdgpu_device *adev = to_amdgpu_device(i2c); | 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 | DRM_ERROR("Failed to lock the bus from SMU"); | 601 | DRM_ERROR("Failed to lock the bus from SMU"); |
| 589 | return; | 602 | else |
| 590 | } | 603 | adev->pm.bus_locked = true; |
| 591 | |||
| 592 | adev->pm.bus_locked = true; | ||
| 593 | } | 604 | } |
| 594 | 605 | ||
| 595 | static int trylock_bus(struct i2c_adapter *i2c, unsigned int flags) | 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 | struct amdgpu_device *adev = to_amdgpu_device(i2c); | 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 | DRM_ERROR("Failed to unlock the bus from SMU"); | 617 | DRM_ERROR("Failed to unlock the bus from SMU"); |
| 607 | return; | 618 | else |
| 608 | } | 619 | adev->pm.bus_locked = false; |
| 609 | 620 | mutex_unlock(&adev->pm.smu_i2c_mutex); | |
| 610 | adev->pm.bus_locked = false; | ||
| 611 | } | 621 | } |
| 612 | 622 | ||
| 613 | static const struct i2c_lock_operations smu_v11_0_i2c_i2c_lock_ops = { | 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 | static int smu_v11_0_i2c_xfer(struct i2c_adapter *i2c_adap, | 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 | int i, ret; | 632 | int i, ret; |
| 623 | struct amdgpu_device *adev = to_amdgpu_device(i2c_adap); | 633 | u16 addr, dir; |
| 624 | |||
| 625 | if (!adev->pm.bus_locked) { | ||
| 626 | DRM_ERROR("I2C bus unlocked, stopping transaction!"); | ||
| 627 | return -EIO; | ||
| 628 | } | ||
| 629 | 634 | ||
| 630 | smu_v11_0_i2c_init(i2c_adap); | 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 | for (i = 0; i < num; i++) { | 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 | ret = smu_v11_0_i2c_read_data(i2c_adap, | 677 | ret = smu_v11_0_i2c_read_data(i2c_adap, |
| 635 | (uint8_t)msgs[i].addr, | 678 | msg + i, |
| 636 | msgs[i].buf, msgs[i].len); | 679 | i2c_flag); |
| 637 | else | 680 | else |
| 638 | ret = smu_v11_0_i2c_write_data(i2c_adap, | 681 | ret = smu_v11_0_i2c_write_data(i2c_adap, |
| 639 | (uint8_t)msgs[i].addr, | 682 | msg + i, |
| 640 | msgs[i].buf, msgs[i].len); | 683 | i2c_flag); |
| 641 | 684 | ||
| 642 | if (ret != I2C_OK) { | 685 | if (ret != I2C_OK) { |
| 643 | num = -EIO; | 686 | num = -EIO; |
| @@ -654,23 +697,28 @@ static u32 smu_v11_0_i2c_func(struct i2c_adapter *adap) · 10 unmodified lines | |||
| 654 | return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; | 697 | return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; |
| 655 | } | 698 | } |
| 656 | 699 | ||
| 657 | |||
| 658 | static const struct i2c_algorithm smu_v11_0_i2c_algo = { | 700 | static const struct i2c_algorithm smu_v11_0_i2c_algo = { |
| 659 | .master_xfer = smu_v11_0_i2c_xfer, | 701 | .master_xfer = smu_v11_0_i2c_xfer, |
| 660 | .functionality = smu_v11_0_i2c_func, | 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 | int smu_v11_0_i2c_control_init(struct i2c_adapter *control) | 709 | int smu_v11_0_i2c_control_init(struct i2c_adapter *control) |
| 664 | { | 710 | { |
| 665 | struct amdgpu_device *adev = to_amdgpu_device(control); | 711 | struct amdgpu_device *adev = to_amdgpu_device(control); |
| 666 | int res; | 712 | int res; |
| 667 | 713 | ||
| 714 | mutex_init(&adev->pm.smu_i2c_mutex); | ||
| 668 | control->owner = THIS_MODULE; | 715 | control->owner = THIS_MODULE; |
| 669 | control->class = I2C_CLASS_SPD; | 716 | control->class = I2C_CLASS_HWMON; |
| 670 | control->dev.parent = &adev->pdev->dev; | 717 | control->dev.parent = &adev->pdev->dev; |
| 671 | control->algo = &smu_v11_0_i2c_algo; | 718 | control->algo = &smu_v11_0_i2c_algo; |
| 672 | snprintf(control->name, sizeof(control->name), "AMDGPU SMU"); | 719 | snprintf(control->name, sizeof(control->name), "AMDGPU SMU"); |
| 673 | control->lock_ops = &smu_v11_0_i2c_i2c_lock_ops; | 720 | control->lock_ops = &smu_v11_0_i2c_i2c_lock_ops; |
| 721 | control->quirks = &smu_v11_0_i2c_control_quirks; | ||
| 674 | 722 | ||
| 675 | res = i2c_add_adapter(control); | 723 | res = i2c_add_adapter(control); |
| 676 | if (res) | 724 | if (res) |
| @@ -74,7 +74,7 @@ · 73 unmodified lines | |||
| 74 | #include "smuio_v9_0.h" | 74 | #include "smuio_v9_0.h" |
| 75 | #include "smuio_v11_0.h" | 75 | #include "smuio_v11_0.h" |
| 76 | #include "smuio_v13_0.h" | 76 | #include "smuio_v13_0.h" |
| 77 | #include "dce_virtual.h" | 77 | #include "amdgpu_vkms.h" |
| 78 | #include "mxgpu_ai.h" | 78 | #include "mxgpu_ai.h" |
| 79 | #include "amdgpu_ras.h" | 79 | #include "amdgpu_ras.h" |
| 80 | #include "amdgpu_xgmi.h" | 80 | #include "amdgpu_xgmi.h" |
| @@ -575,7 +575,7 @@ soc15_asic_reset_method(struct amdgpu_device *adev) · 494 unmodified lines | |||
| 575 | baco_reset = amdgpu_dpm_is_baco_supported(adev); | 575 | baco_reset = amdgpu_dpm_is_baco_supported(adev); |
| 576 | break; | 576 | break; |
| 577 | case CHIP_VEGA20: | 577 | case CHIP_VEGA20: |
| 578 | if (adev->psp.sos_fw_version >= 0x80067) | 578 | if (adev->psp.sos.fw_version >= 0x80067) |
| 579 | baco_reset = amdgpu_dpm_is_baco_supported(adev); | 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 | case CHIP_ARCTURUS: | 635 | case CHIP_ARCTURUS: |
| 636 | return amdgpu_dpm_is_baco_supported(adev); | 636 | return amdgpu_dpm_is_baco_supported(adev); |
| 637 | case CHIP_VEGA20: | 637 | case CHIP_VEGA20: |
| 638 | if (adev->psp.sos_fw_version >= 0x80067) | 638 | if (adev->psp.sos.fw_version >= 0x80067) |
| 639 | return amdgpu_dpm_is_baco_supported(adev); | 639 | return amdgpu_dpm_is_baco_supported(adev); |
| 640 | return false; | 640 | return false; |
| 641 | default: | 641 | default: |
| @@ -843,7 +843,7 @@ int soc15_set_ip_blocks(struct amdgpu_device *adev) · 201 unmodified lines | |||
| 843 | amdgpu_device_ip_block_add(adev, &pp_smu_ip_block); | 843 | amdgpu_device_ip_block_add(adev, &pp_smu_ip_block); |
| 844 | } | 844 | } |
| 845 | if (adev->enable_virtual_display || amdgpu_sriov_vf(adev)) | 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 | #if defined(CONFIG_DRM_AMD_DC) | 847 | #if defined(CONFIG_DRM_AMD_DC) |
| 848 | else if (amdgpu_device_has_dc_support(adev)) | 848 | else if (amdgpu_device_has_dc_support(adev)) |
| 849 | amdgpu_device_ip_block_add(adev, &dm_ip_block); | 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 | amdgpu_device_ip_block_add(adev, &sdma_v4_0_ip_block); | 863 | amdgpu_device_ip_block_add(adev, &sdma_v4_0_ip_block); |
| 864 | amdgpu_device_ip_block_add(adev, &pp_smu_ip_block); | 864 | amdgpu_device_ip_block_add(adev, &pp_smu_ip_block); |
| 865 | if (adev->enable_virtual_display || amdgpu_sriov_vf(adev)) | 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 | #if defined(CONFIG_DRM_AMD_DC) | 867 | #if defined(CONFIG_DRM_AMD_DC) |
| 868 | else if (amdgpu_device_has_dc_support(adev)) | 868 | else if (amdgpu_device_has_dc_support(adev)) |
| 869 | amdgpu_device_ip_block_add(adev, &dm_ip_block); | 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 | if (adev->enable_virtual_display || amdgpu_sriov_vf(adev)) | 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 | amdgpu_device_ip_block_add(adev, &gfx_v9_0_ip_block); | 889 | amdgpu_device_ip_block_add(adev, &gfx_v9_0_ip_block); |
| 890 | amdgpu_device_ip_block_add(adev, &sdma_v4_0_ip_block); | 890 | amdgpu_device_ip_block_add(adev, &sdma_v4_0_ip_block); |
| 891 | amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block); | 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 | amdgpu_device_ip_block_add(adev, &gfx_v9_0_ip_block); | 909 | amdgpu_device_ip_block_add(adev, &gfx_v9_0_ip_block); |
| 910 | amdgpu_device_ip_block_add(adev, &sdma_v4_0_ip_block); | 910 | amdgpu_device_ip_block_add(adev, &sdma_v4_0_ip_block); |
| 911 | if (adev->enable_virtual_display || amdgpu_sriov_vf(adev)) | 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 | #if defined(CONFIG_DRM_AMD_DC) | 913 | #if defined(CONFIG_DRM_AMD_DC) |
| 914 | else if (amdgpu_device_has_dc_support(adev)) | 914 | else if (amdgpu_device_has_dc_support(adev)) |
| 915 | amdgpu_device_ip_block_add(adev, &dm_ip_block); | 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 | adev->asic_funcs = &vega20_asic_funcs; | 1353 | adev->asic_funcs = &vega20_asic_funcs; |
| 1354 | adev->cg_flags = AMD_CG_SUPPORT_GFX_MGCG | | 1354 | adev->cg_flags = AMD_CG_SUPPORT_GFX_MGCG | |
| 1355 | AMD_CG_SUPPORT_GFX_MGLS | | 1355 | AMD_CG_SUPPORT_GFX_MGLS | |
| 1356 | AMD_CG_SUPPORT_GFX_CGCG | | ||
| 1357 | AMD_CG_SUPPORT_GFX_CGLS | | ||
| 1358 | AMD_CG_SUPPORT_GFX_CP_LS | | 1356 | AMD_CG_SUPPORT_GFX_CP_LS | |
| 1359 | AMD_CG_SUPPORT_HDP_LS | | 1357 | AMD_CG_SUPPORT_HDP_LS | |
| 1360 | AMD_CG_SUPPORT_SDMA_MGCG | | 1358 | AMD_CG_SUPPORT_SDMA_MGCG | |
| @@ -28,13 +28,13 @@ · 27 unmodified lines | |||
| 28 | #define SOC15_REG_OFFSET(ip, inst, reg) (adev->reg_offset[ip##_HWIP][inst][reg##_BASE_IDX] + reg) | 28 | #define SOC15_REG_OFFSET(ip, inst, reg) (adev->reg_offset[ip##_HWIP][inst][reg##_BASE_IDX] + reg) |
| 29 | 29 | ||
| 30 | #define __WREG32_SOC15_RLC__(reg, value, flag, hwip) \ | 30 | #define __WREG32_SOC15_RLC__(reg, value, flag, hwip) \ |
| 31 | ((amdgpu_sriov_vf(adev) && adev->gfx.rlc.funcs && adev->gfx.rlc.funcs->rlcg_wreg) ? \ | 31 | ((amdgpu_sriov_vf(adev) && adev->gfx.rlc.funcs && adev->gfx.rlc.funcs->sriov_wreg) ? \ |
| 32 | adev->gfx.rlc.funcs->rlcg_wreg(adev, reg, value, flag, hwip) : \ | 32 | adev->gfx.rlc.funcs->sriov_wreg(adev, reg, value, flag, hwip) : \ |
| 33 | WREG32(reg, value)) | 33 | WREG32(reg, value)) |
| 34 | 34 | ||
| 35 | #define __RREG32_SOC15_RLC__(reg, flag, hwip) \ | 35 | #define __RREG32_SOC15_RLC__(reg, flag, hwip) \ |
| 36 | ((amdgpu_sriov_vf(adev) && adev->gfx.rlc.funcs && adev->gfx.rlc.funcs->rlcg_rreg) ? \ | 36 | ((amdgpu_sriov_vf(adev) && adev->gfx.rlc.funcs && adev->gfx.rlc.funcs->sriov_rreg) ? \ |
| 37 | adev->gfx.rlc.funcs->rlcg_rreg(adev, reg, flag, hwip) : \ | 37 | adev->gfx.rlc.funcs->sriov_rreg(adev, reg, flag, hwip) : \ |
| 38 | RREG32(reg)) | 38 | RREG32(reg)) |
| 39 | 39 | ||
| 40 | #define WREG32_FIELD15(ip, idx, reg, field, val) \ | 40 | #define WREG32_FIELD15(ip, idx, reg, field, val) \ |
| @@ -33,7 +33,8 @@ enum ta_command_xgmi { · 32 unmodified lines | |||
| 33 | TA_COMMAND_XGMI__GET_NODE_ID = 0x01, | 33 | TA_COMMAND_XGMI__GET_NODE_ID = 0x01, |
| 34 | TA_COMMAND_XGMI__GET_HIVE_ID = 0x02, | 34 | TA_COMMAND_XGMI__GET_HIVE_ID = 0x02, |
| 35 | TA_COMMAND_XGMI__GET_GET_TOPOLOGY_INFO = 0x03, | 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 | /* XGMI related enumerations */ | 40 | /* XGMI related enumerations */ |
| @@ -75,6 +76,11 @@ struct ta_xgmi_node_info { · 35 unmodified lines | |||
| 75 | enum ta_xgmi_assigned_sdma_engine sdma_engine; | 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 | struct ta_xgmi_cmd_initialize_output { | 84 | struct ta_xgmi_cmd_initialize_output { |
| 79 | uint32_t status; | 85 | uint32_t status; |
| 80 | }; | 86 | }; |
| @@ -97,6 +103,11 @@ struct ta_xgmi_cmd_get_topology_info_output { · 16 unmodified lines | |||
| 97 | struct ta_xgmi_node_info nodes[TA_XGMI__MAX_CONNECTED_NODES]; | 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 | struct ta_xgmi_cmd_set_topology_info_input { | 111 | struct ta_xgmi_cmd_set_topology_info_input { |
| 101 | uint32_t num_nodes; | 112 | uint32_t num_nodes; |
| 102 | struct ta_xgmi_node_info nodes[TA_XGMI__MAX_CONNECTED_NODES]; | 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 | struct ta_xgmi_cmd_get_node_id_output get_node_id; | 126 | struct ta_xgmi_cmd_get_node_id_output get_node_id; |
| 116 | struct ta_xgmi_cmd_get_hive_id_output get_hive_id; | 127 | struct ta_xgmi_cmd_get_hive_id_output get_hive_id; |
| 117 | struct ta_xgmi_cmd_get_topology_info_output get_topology_info; | 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 | uint32_t cmd_id; | 134 | uint32_t cmd_id; |
| 123 | uint32_t resp_id; | 135 | uint32_t resp_id; |
| 124 | enum ta_xgmi_status xgmi_status; | 136 | enum ta_xgmi_status xgmi_status; |
| 125 | uint32_t reserved; | 137 | uint8_t flag_extend_link_record; |
| 138 | uint8_t reserved0[3]; | ||
| 126 | union ta_xgmi_cmd_input xgmi_in_message; | 139 | union ta_xgmi_cmd_input xgmi_in_message; |
| 127 | union ta_xgmi_cmd_output xgmi_out_message; | 140 | union ta_xgmi_cmd_output xgmi_out_message; |
| 128 | }; | 141 | }; |
| @@ -28,6 +28,21 @@ · 27 unmodified lines | |||
| 28 | #include "umc/umc_6_7_0_offset.h" | 28 | #include "umc/umc_6_7_0_offset.h" |
| 29 | #include "umc/umc_6_7_0_sh_mask.h" | 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 | static inline uint32_t get_umc_v6_7_reg_offset(struct amdgpu_device *adev, | 46 | static inline uint32_t get_umc_v6_7_reg_offset(struct amdgpu_device *adev, |
| 32 | uint32_t umc_inst, | 47 | uint32_t umc_inst, |
| 33 | uint32_t ch_inst) | 48 | uint32_t ch_inst) |
| @@ -23,6 +23,9 @@ · 22 unmodified lines | |||
| 23 | #ifndef __UMC_V6_7_H__ | 23 | #ifndef __UMC_V6_7_H__ |
| 24 | #define __UMC_V6_7_H__ | 24 | #define __UMC_V6_7_H__ |
| 25 | 25 | ||
| 26 | #include "soc15_common.h" | ||
| 27 | #include "amdgpu.h" | ||
| 28 | |||
| 26 | /* EccErrCnt max value */ | 29 | /* EccErrCnt max value */ |
| 27 | #define UMC_V6_7_CE_CNT_MAX 0xffff | 30 | #define UMC_V6_7_CE_CNT_MAX 0xffff |
| 28 | /* umc ce interrupt threshold */ | 31 | /* umc ce interrupt threshold */ |
| @@ -32,6 +35,18 @@ · 3 unmodified lines | |||
| 32 | 35 | ||
| 33 | #define UMC_V6_7_INST_DIST 0x40000 | 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 | extern const struct amdgpu_umc_ras_funcs umc_v6_7_ras_funcs; | 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 | #endif | 52 | #endif |
| @@ -698,6 +698,30 @@ static int uvd_v3_1_hw_fini(void *handle) · 697 unmodified lines | |||
| 698 | { | 698 | { |
| 699 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; | 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 | if (RREG32(mmUVD_STATUS) != 0) | 725 | if (RREG32(mmUVD_STATUS) != 0) |
| 702 | uvd_v3_1_stop(adev); | 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 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; | 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 | if (RREG32(mmUVD_STATUS) != 0) | 239 | if (RREG32(mmUVD_STATUS) != 0) |
| 216 | uvd_v4_2_stop(adev); | 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 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; | 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 | if (RREG32(mmUVD_STATUS) != 0) | 237 | if (RREG32(mmUVD_STATUS) != 0) |
| 214 | uvd_v5_0_stop(adev); | 238 | uvd_v5_0_stop(adev); |
| 215 | 239 | ||
| @@ -224,7 +248,6 @@ static int uvd_v5_0_suspend(void *handle) · 8 unmodified lines | |||
| 224 | r = uvd_v5_0_hw_fini(adev); | 248 | r = uvd_v5_0_hw_fini(adev); |
| 225 | if (r) | 249 | if (r) |
| 226 | return r; | 250 | return r; |
| 227 | uvd_v5_0_set_clockgating_state(adev, AMD_CG_STATE_GATE); | ||
| 228 | 251 | ||
| 229 | return amdgpu_uvd_suspend(adev); | 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 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; | 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 | if (RREG32(mmUVD_STATUS) != 0) | 570 | if (RREG32(mmUVD_STATUS) != 0) |
| 547 | uvd_v6_0_stop(adev); | 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 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; | 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 | if (!amdgpu_sriov_vf(adev)) | 633 | if (!amdgpu_sriov_vf(adev)) |
| 610 | uvd_v7_0_stop(adev); | 634 | uvd_v7_0_stop(adev); |
| 611 | else { | 635 | else { |
| @@ -477,6 +477,31 @@ static int vce_v2_0_hw_init(void *handle) · 476 unmodified lines | |||
| 477 | 477 | ||
| 478 | static int vce_v2_0_hw_fini(void *handle) | 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 | return 0; | 505 | return 0; |
| 481 | } | 506 | } |
| 482 | 507 | ||
| @@ -490,6 +490,29 @@ static int vce_v3_0_hw_fini(void *handle) · 489 unmodified lines | |||
| 490 | int r; | 490 | int r; |
| 491 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; | 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 | r = vce_v3_0_wait_for_idle(handle); | 516 | r = vce_v3_0_wait_for_idle(handle); |
| 494 | if (r) | 517 | if (r) |
| 495 | return r; | 518 | return r; |
| @@ -542,6 +542,29 @@ static int vce_v4_0_hw_fini(void *handle) · 541 unmodified lines | |||
| 542 | { | 542 | { |
| 543 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; | 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 | if (!amdgpu_sriov_vf(adev)) { | 568 | if (!amdgpu_sriov_vf(adev)) { |
| 546 | /* vce_v4_0_wait_for_idle(handle); */ | 569 | /* vce_v4_0_wait_for_idle(handle); */ |
| 547 | vce_v4_0_stop(adev); | 570 | vce_v4_0_stop(adev); |
| @@ -119,7 +119,7 @@ static int vcn_v1_0_sw_init(void *handle) · 118 unmodified lines | |||
| 119 | adev->firmware.ucode[AMDGPU_UCODE_ID_VCN].fw = adev->vcn.fw; | 119 | adev->firmware.ucode[AMDGPU_UCODE_ID_VCN].fw = adev->vcn.fw; |
| 120 | adev->firmware.fw_size += | 120 | adev->firmware.fw_size += |
| 121 | ALIGN(le32_to_cpu(hdr->ucode_size_bytes), PAGE_SIZE); | 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 | r = amdgpu_vcn_resume(adev); | 125 | r = amdgpu_vcn_resume(adev); |
| @@ -122,7 +122,7 @@ static int vcn_v2_0_sw_init(void *handle) · 121 unmodified lines | |||
| 122 | adev->firmware.ucode[AMDGPU_UCODE_ID_VCN].fw = adev->vcn.fw; | 122 | adev->firmware.ucode[AMDGPU_UCODE_ID_VCN].fw = adev->vcn.fw; |
| 123 | adev->firmware.fw_size += | 123 | adev->firmware.fw_size += |
| 124 | ALIGN(le32_to_cpu(hdr->ucode_size_bytes), PAGE_SIZE); | 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 | r = amdgpu_vcn_resume(adev); | 128 | r = amdgpu_vcn_resume(adev); |
| @@ -152,7 +152,7 @@ static int vcn_v2_5_sw_init(void *handle) · 151 unmodified lines | |||
| 152 | adev->firmware.fw_size += | 152 | adev->firmware.fw_size += |
| 153 | ALIGN(le32_to_cpu(hdr->ucode_size_bytes), PAGE_SIZE); | 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 | r = amdgpu_vcn_resume(adev); | 158 | r = amdgpu_vcn_resume(adev); |
| @@ -90,9 +90,7 @@ static int vcn_v3_0_early_init(void *handle) · 89 unmodified lines | |||
| 90 | int i; | 90 | int i; |
| 91 | 91 | ||
| 92 | if (amdgpu_sriov_vf(adev)) { | 92 | if (amdgpu_sriov_vf(adev)) { |
| 93 | for (i = 0; i < VCN_INSTANCES_SIENNA_CICHLID; i++) | 93 | adev->vcn.num_vcn_inst = VCN_INSTANCES_SIENNA_CICHLID; |
| 94 | if (amdgpu_vcn_is_disabled_vcn(adev, VCN_DECODE_RING, i)) | ||
| 95 | adev->vcn.num_vcn_inst++; | ||
| 96 | adev->vcn.harvest_config = 0; | 94 | adev->vcn.harvest_config = 0; |
| 97 | adev->vcn.num_enc_rings = 1; | 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 | adev->firmware.fw_size += | 151 | adev->firmware.fw_size += |
| 154 | ALIGN(le32_to_cpu(hdr->ucode_size_bytes), PAGE_SIZE); | 152 | ALIGN(le32_to_cpu(hdr->ucode_size_bytes), PAGE_SIZE); |
| 155 | 153 | ||
| 156 | if ((adev->vcn.num_vcn_inst == VCN_INSTANCES_SIENNA_CICHLID) || | 154 | if (adev->vcn.num_vcn_inst == VCN_INSTANCES_SIENNA_CICHLID) { |
| 157 | (amdgpu_sriov_vf(adev) && adev->asic_type == CHIP_SIENNA_CICHLID)) { | ||
| 158 | adev->firmware.ucode[AMDGPU_UCODE_ID_VCN1].ucode_id = AMDGPU_UCODE_ID_VCN1; | 155 | adev->firmware.ucode[AMDGPU_UCODE_ID_VCN1].ucode_id = AMDGPU_UCODE_ID_VCN1; |
| 159 | adev->firmware.ucode[AMDGPU_UCODE_ID_VCN1].fw = adev->vcn.fw; | 156 | adev->firmware.ucode[AMDGPU_UCODE_ID_VCN1].fw = adev->vcn.fw; |
| 160 | adev->firmware.fw_size += | 157 | adev->firmware.fw_size += |
| 161 | ALIGN(le32_to_cpu(hdr->ucode_size_bytes), PAGE_SIZE); | 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 | r = amdgpu_vcn_resume(adev); | 163 | r = amdgpu_vcn_resume(adev); |
| @@ -328,18 +325,28 @@ static int vcn_v3_0_hw_init(void *handle) · 161 unmodified lines | |||
| 328 | continue; | 325 | continue; |
| 329 | 326 | ||
| 330 | ring = &adev->vcn.inst[i].ring_dec; | 327 | ring = &adev->vcn.inst[i].ring_dec; |
| 331 | ring->wptr = 0; | 328 | if (amdgpu_vcn_is_disabled_vcn(adev, VCN_DECODE_RING, i)) { |
| 332 | ring->wptr_old = 0; | 329 | ring->sched.ready = false; |
| 333 | vcn_v3_0_dec_ring_set_wptr(ring); | 330 | dev_info(adev->dev, "ring %s is disabled by hypervisor\n", ring->name); |
| 334 | ring->sched.ready = true; | 331 | } else { |
| 335 | |||
| 336 | for (j = 0; j < adev->vcn.num_enc_rings; ++j) { | ||
| 337 | ring = &adev->vcn.inst[i].ring_enc[j]; | ||
| 338 | ring->wptr = 0; | 332 | ring->wptr = 0; |
| 339 | ring->wptr_old = 0; | 333 | ring->wptr_old = 0; |
| 340 | vcn_v3_0_enc_ring_set_wptr(ring); | 334 | vcn_v3_0_dec_ring_set_wptr(ring); |
| 341 | ring->sched.ready = true; | 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 | } else { | 351 | } else { |
| 345 | for (i = 0; i < adev->vcn.num_vcn_inst; ++i) { | 352 | for (i = 0; i < adev->vcn.num_vcn_inst; ++i) { |
| @@ -77,7 +77,7 @@ · 76 unmodified lines | |||
| 77 | #if defined(CONFIG_DRM_AMD_ACP) | 77 | #if defined(CONFIG_DRM_AMD_ACP) |
| 78 | #include "amdgpu_acp.h" | 78 | #include "amdgpu_acp.h" |
| 79 | #endif | 79 | #endif |
| 80 | #include "dce_virtual.h" | 80 | #include "amdgpu_vkms.h" |
| 81 | #include "mxgpu_vi.h" | 81 | #include "mxgpu_vi.h" |
| 82 | #include "amdgpu_dm.h" | 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 | case CHIP_POLARIS11: | 904 | case CHIP_POLARIS11: |
| 905 | case CHIP_POLARIS12: | 905 | case CHIP_POLARIS12: |
| 906 | case CHIP_TOPAZ: | 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 | default: | 915 | default: |
| 909 | return false; | 916 | return false; |
| 910 | } | 917 | } |
| @@ -2102,7 +2109,7 @@ int vi_set_ip_blocks(struct amdgpu_device *adev) · 1191 unmodified lines | |||
| 2102 | amdgpu_device_ip_block_add(adev, &sdma_v2_4_ip_block); | 2109 | amdgpu_device_ip_block_add(adev, &sdma_v2_4_ip_block); |
| 2103 | amdgpu_device_ip_block_add(adev, &pp_smu_ip_block); | 2110 | amdgpu_device_ip_block_add(adev, &pp_smu_ip_block); |
| 2104 | if (adev->enable_virtual_display) | 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 | break; | 2113 | break; |
| 2107 | case CHIP_FIJI: | 2114 | case CHIP_FIJI: |
| 2108 | amdgpu_device_ip_block_add(adev, &vi_common_ip_block); | 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 | amdgpu_device_ip_block_add(adev, &sdma_v3_0_ip_block); | 2119 | amdgpu_device_ip_block_add(adev, &sdma_v3_0_ip_block); |
| 2113 | amdgpu_device_ip_block_add(adev, &pp_smu_ip_block); | 2120 | amdgpu_device_ip_block_add(adev, &pp_smu_ip_block); |
| 2114 | if (adev->enable_virtual_display || amdgpu_sriov_vf(adev)) | 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 | #if defined(CONFIG_DRM_AMD_DC) | 2123 | #if defined(CONFIG_DRM_AMD_DC) |
| 2117 | else if (amdgpu_device_has_dc_support(adev)) | 2124 | else if (amdgpu_device_has_dc_support(adev)) |
| 2118 | amdgpu_device_ip_block_add(adev, &dm_ip_block); | 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 | amdgpu_device_ip_block_add(adev, &sdma_v3_0_ip_block); | 2139 | amdgpu_device_ip_block_add(adev, &sdma_v3_0_ip_block); |
| 2133 | amdgpu_device_ip_block_add(adev, &pp_smu_ip_block); | 2140 | amdgpu_device_ip_block_add(adev, &pp_smu_ip_block); |
| 2134 | if (adev->enable_virtual_display || amdgpu_sriov_vf(adev)) | 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 | #if defined(CONFIG_DRM_AMD_DC) | 2143 | #if defined(CONFIG_DRM_AMD_DC) |
| 2137 | else if (amdgpu_device_has_dc_support(adev)) | 2144 | else if (amdgpu_device_has_dc_support(adev)) |
| 2138 | amdgpu_device_ip_block_add(adev, &dm_ip_block); | 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 | amdgpu_device_ip_block_add(adev, &sdma_v3_1_ip_block); | 2162 | amdgpu_device_ip_block_add(adev, &sdma_v3_1_ip_block); |
| 2156 | amdgpu_device_ip_block_add(adev, &pp_smu_ip_block); | 2163 | amdgpu_device_ip_block_add(adev, &pp_smu_ip_block); |
| 2157 | if (adev->enable_virtual_display) | 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 | #if defined(CONFIG_DRM_AMD_DC) | 2166 | #if defined(CONFIG_DRM_AMD_DC) |
| 2160 | else if (amdgpu_device_has_dc_support(adev)) | 2167 | else if (amdgpu_device_has_dc_support(adev)) |
| 2161 | amdgpu_device_ip_block_add(adev, &dm_ip_block); | 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 | amdgpu_device_ip_block_add(adev, &sdma_v3_0_ip_block); | 2180 | amdgpu_device_ip_block_add(adev, &sdma_v3_0_ip_block); |
| 2174 | amdgpu_device_ip_block_add(adev, &pp_smu_ip_block); | 2181 | amdgpu_device_ip_block_add(adev, &pp_smu_ip_block); |
| 2175 | if (adev->enable_virtual_display) | 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 | #if defined(CONFIG_DRM_AMD_DC) | 2184 | #if defined(CONFIG_DRM_AMD_DC) |
| 2178 | else if (amdgpu_device_has_dc_support(adev)) | 2185 | else if (amdgpu_device_has_dc_support(adev)) |
| 2179 | amdgpu_device_ip_block_add(adev, &dm_ip_block); | 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 | amdgpu_device_ip_block_add(adev, &sdma_v3_0_ip_block); | 2201 | amdgpu_device_ip_block_add(adev, &sdma_v3_0_ip_block); |
| 2195 | amdgpu_device_ip_block_add(adev, &pp_smu_ip_block); | 2202 | amdgpu_device_ip_block_add(adev, &pp_smu_ip_block); |
| 2196 | if (adev->enable_virtual_display) | 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 | #if defined(CONFIG_DRM_AMD_DC) | 2205 | #if defined(CONFIG_DRM_AMD_DC) |
| 2199 | else if (amdgpu_device_has_dc_support(adev)) | 2206 | else if (amdgpu_device_has_dc_support(adev)) |
| 2200 | amdgpu_device_ip_block_add(adev, &dm_ip_block); | 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 | long err = 0; | 1393 | long err = 0; |
| 1394 | int i; | 1394 | int i; |
| 1395 | uint32_t *devices_arr = NULL; | 1395 | uint32_t *devices_arr = NULL; |
| 1396 | bool table_freed = false; | ||
| 1396 | 1397 | ||
| 1397 | dev = kfd_device_by_id(GET_GPU_ID(args->handle)); | 1398 | dev = kfd_device_by_id(GET_GPU_ID(args->handle)); |
| 1398 | if (!dev) | 1399 | if (!dev) |
| @@ -1450,7 +1451,8 @@ static int kfd_ioctl_map_memory_to_gpu(struct file *filep, · 51 unmodified lines | |||
| 1450 | goto get_mem_obj_from_handle_failed; | 1451 | goto get_mem_obj_from_handle_failed; |
| 1451 | } | 1452 | } |
| 1452 | err = amdgpu_amdkfd_gpuvm_map_memory_to_gpu( | 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 | if (err) { | 1456 | if (err) { |
| 1455 | pr_err("Failed to map to gpu %d/%d\n", | 1457 | pr_err("Failed to map to gpu %d/%d\n", |
| 1456 | i, args->n_devices); | 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 | /* Flush TLBs after waiting for the page table updates to complete */ | 1472 | /* Flush TLBs after waiting for the page table updates to complete */ |
| 1471 | for (i = 0; i < args->n_devices; i++) { | 1473 | if (table_freed) { |
| 1472 | peer = kfd_device_by_id(devices_arr[i]); | 1474 | for (i = 0; i < args->n_devices; i++) { |
| 1473 | if (WARN_ON_ONCE(!peer)) | 1475 | peer = kfd_device_by_id(devices_arr[i]); |
| 1474 | continue; | 1476 | if (WARN_ON_ONCE(!peer)) |
| 1475 | peer_pdd = kfd_get_process_device_data(peer, p); | 1477 | continue; |
| 1476 | if (WARN_ON_ONCE(!peer_pdd)) | 1478 | peer_pdd = kfd_get_process_device_data(peer, p); |
| 1477 | continue; | 1479 | if (WARN_ON_ONCE(!peer_pdd)) |
| 1478 | kfd_flush_tlb(peer_pdd, TLB_FLUSH_LEGACY); | 1480 | continue; |
| 1481 | kfd_flush_tlb(peer_pdd, TLB_FLUSH_LEGACY); | ||
| 1482 | } | ||
| 1479 | } | 1483 | } |
| 1480 | |||
| 1481 | kfree(devices_arr); | 1484 | kfree(devices_arr); |
| 1482 | 1485 | ||
| 1483 | return err; | 1486 | return err; |
| @@ -1565,10 +1568,29 @@ static int kfd_ioctl_unmap_memory_from_gpu(struct file *filep, · 81 unmodified lines | |||
| 1565 | } | 1568 | } |
| 1566 | args->n_success = i+1; | 1569 | args->n_success = i+1; |
| 1567 | } | 1570 | } |
| 1568 | kfree(devices_arr); | ||
| 1569 | |||
| 1570 | mutex_unlock(&p->mutex); | 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 | return 0; | 1594 | return 0; |
| 1573 | 1595 | ||
| 1574 | bind_process_to_device_failed: | 1596 | bind_process_to_device_failed: |
| @@ -1576,6 +1598,7 @@ get_mem_obj_from_handle_failed: · 1 unmodified line | |||
| 1576 | unmap_memory_from_gpu_failed: | 1598 | unmap_memory_from_gpu_failed: |
| 1577 | mutex_unlock(&p->mutex); | 1599 | mutex_unlock(&p->mutex); |
| 1578 | copy_from_user_failed: | 1600 | copy_from_user_failed: |
| 1601 | sync_memory_failed: | ||
| 1579 | kfree(devices_arr); | 1602 | kfree(devices_arr); |
| 1580 | return err; | 1603 | return err; |
| 1581 | } | 1604 | } |
| @@ -1404,6 +1404,7 @@ static int kfd_fill_gpu_cache_info(struct kfd_dev *kdev, · 1403 unmodified lines | |||
| 1404 | break; | 1404 | break; |
| 1405 | case CHIP_NAVI10: | 1405 | case CHIP_NAVI10: |
| 1406 | case CHIP_NAVI12: | 1406 | case CHIP_NAVI12: |
| 1407 | case CHIP_CYAN_SKILLFISH: | ||
| 1407 | pcache_info = navi10_cache_info; | 1408 | pcache_info = navi10_cache_info; |
| 1408 | num_of_cache_types = ARRAY_SIZE(navi10_cache_info); | 1409 | num_of_cache_types = ARRAY_SIZE(navi10_cache_info); |
| 1409 | break; | 1410 | break; |
| @@ -1989,8 +1990,19 @@ static int kfd_fill_gpu_direct_io_link_to_cpu(int *avail_size, · 579 unmodified lines | |||
| 1989 | sub_type_hdr->flags |= CRAT_IOLINK_FLAGS_BI_DIRECTIONAL; | 1990 | sub_type_hdr->flags |= CRAT_IOLINK_FLAGS_BI_DIRECTIONAL; |
| 1990 | sub_type_hdr->io_interface_type = CRAT_IOLINK_TYPE_XGMI; | 1991 | sub_type_hdr->io_interface_type = CRAT_IOLINK_TYPE_XGMI; |
| 1991 | sub_type_hdr->num_hops_xgmi = 1; | 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 | } else { | 2000 | } else { |
| 1993 | sub_type_hdr->io_interface_type = CRAT_IOLINK_TYPE_PCIEXPRESS; | 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 | sub_type_hdr->proximity_domain_from = proximity_domain; | 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 | sub_type_hdr->proximity_domain_to = proximity_domain_to; | 2045 | sub_type_hdr->proximity_domain_to = proximity_domain_to; |
| 2034 | sub_type_hdr->num_hops_xgmi = | 2046 | sub_type_hdr->num_hops_xgmi = |
| 2035 | amdgpu_amdkfd_get_xgmi_hops_count(kdev->kgd, peer_kdev->kgd); | 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 | return 0; | 2053 | return 0; |
| 2037 | } | 2054 | } |
| 2038 | 2055 | ||
| @@ -84,12 +84,14 @@ static const struct kfd2kgd_calls *kfd2kgd_funcs[] = { · 83 unmodified lines | |||
| 84 | [CHIP_DIMGREY_CAVEFISH] = &gfx_v10_3_kfd2kgd, | 84 | [CHIP_DIMGREY_CAVEFISH] = &gfx_v10_3_kfd2kgd, |
| 85 | [CHIP_BEIGE_GOBY] = &gfx_v10_3_kfd2kgd, | 85 | [CHIP_BEIGE_GOBY] = &gfx_v10_3_kfd2kgd, |
| 86 | [CHIP_YELLOW_CARP] = &gfx_v10_3_kfd2kgd, | 86 | [CHIP_YELLOW_CARP] = &gfx_v10_3_kfd2kgd, |
| 87 | [CHIP_CYAN_SKILLFISH] = &gfx_v10_kfd2kgd, | ||
| 87 | }; | 88 | }; |
| 88 | 89 | ||
| 89 | #ifdef KFD_SUPPORT_IOMMU_V2 | 90 | #ifdef KFD_SUPPORT_IOMMU_V2 |
| 90 | static const struct kfd_device_info kaveri_device_info = { | 91 | static const struct kfd_device_info kaveri_device_info = { |
| 91 | .asic_family = CHIP_KAVERI, | 92 | .asic_family = CHIP_KAVERI, |
| 92 | .asic_name = "kaveri", | 93 | .asic_name = "kaveri", |
| 94 | .gfx_target_version = 70000, | ||
| 93 | .max_pasid_bits = 16, | 95 | .max_pasid_bits = 16, |
| 94 | /* max num of queues for KV.TODO should be a dynamic value */ | 96 | /* max num of queues for KV.TODO should be a dynamic value */ |
| 95 | .max_no_of_hqd = 24, | 97 | .max_no_of_hqd = 24, |
| @@ -109,6 +111,7 @@ static const struct kfd_device_info kaveri_device_info = { · 13 unmodified lines | |||
| 109 | static const struct kfd_device_info carrizo_device_info = { | 111 | static const struct kfd_device_info carrizo_device_info = { |
| 110 | .asic_family = CHIP_CARRIZO, | 112 | .asic_family = CHIP_CARRIZO, |
| 111 | .asic_name = "carrizo", | 113 | .asic_name = "carrizo", |
| 114 | .gfx_target_version = 80001, | ||
| 112 | .max_pasid_bits = 16, | 115 | .max_pasid_bits = 16, |
| 113 | /* max num of queues for CZ.TODO should be a dynamic value */ | 116 | /* max num of queues for CZ.TODO should be a dynamic value */ |
| 114 | .max_no_of_hqd = 24, | 117 | .max_no_of_hqd = 24, |
| @@ -129,6 +132,7 @@ static const struct kfd_device_info carrizo_device_info = { · 14 unmodified lines | |||
| 129 | static const struct kfd_device_info raven_device_info = { | 132 | static const struct kfd_device_info raven_device_info = { |
| 130 | .asic_family = CHIP_RAVEN, | 133 | .asic_family = CHIP_RAVEN, |
| 131 | .asic_name = "raven", | 134 | .asic_name = "raven", |
| 135 | .gfx_target_version = 90002, | ||
| 132 | .max_pasid_bits = 16, | 136 | .max_pasid_bits = 16, |
| 133 | .max_no_of_hqd = 24, | 137 | .max_no_of_hqd = 24, |
| 134 | .doorbell_size = 8, | 138 | .doorbell_size = 8, |
| @@ -147,6 +151,7 @@ static const struct kfd_device_info raven_device_info = { · 12 unmodified lines | |||
| 147 | static const struct kfd_device_info hawaii_device_info = { | 151 | static const struct kfd_device_info hawaii_device_info = { |
| 148 | .asic_family = CHIP_HAWAII, | 152 | .asic_family = CHIP_HAWAII, |
| 149 | .asic_name = "hawaii", | 153 | .asic_name = "hawaii", |
| 154 | .gfx_target_version = 70001, | ||
| 150 | .max_pasid_bits = 16, | 155 | .max_pasid_bits = 16, |
| 151 | /* max num of queues for KV.TODO should be a dynamic value */ | 156 | /* max num of queues for KV.TODO should be a dynamic value */ |
| 152 | .max_no_of_hqd = 24, | 157 | .max_no_of_hqd = 24, |
| @@ -166,6 +171,7 @@ static const struct kfd_device_info hawaii_device_info = { · 13 unmodified lines | |||
| 166 | static const struct kfd_device_info tonga_device_info = { | 171 | static const struct kfd_device_info tonga_device_info = { |
| 167 | .asic_family = CHIP_TONGA, | 172 | .asic_family = CHIP_TONGA, |
| 168 | .asic_name = "tonga", | 173 | .asic_name = "tonga", |
| 174 | .gfx_target_version = 80002, | ||
| 169 | .max_pasid_bits = 16, | 175 | .max_pasid_bits = 16, |
| 170 | .max_no_of_hqd = 24, | 176 | .max_no_of_hqd = 24, |
| 171 | .doorbell_size = 4, | 177 | .doorbell_size = 4, |
| @@ -184,6 +190,7 @@ static const struct kfd_device_info tonga_device_info = { · 12 unmodified lines | |||
| 184 | static const struct kfd_device_info fiji_device_info = { | 190 | static const struct kfd_device_info fiji_device_info = { |
| 185 | .asic_family = CHIP_FIJI, | 191 | .asic_family = CHIP_FIJI, |
| 186 | .asic_name = "fiji", | 192 | .asic_name = "fiji", |
| 193 | .gfx_target_version = 80003, | ||
| 187 | .max_pasid_bits = 16, | 194 | .max_pasid_bits = 16, |
| 188 | .max_no_of_hqd = 24, | 195 | .max_no_of_hqd = 24, |
| 189 | .doorbell_size = 4, | 196 | .doorbell_size = 4, |
| @@ -202,6 +209,7 @@ static const struct kfd_device_info fiji_device_info = { · 12 unmodified lines | |||
| 202 | static const struct kfd_device_info fiji_vf_device_info = { | 209 | static const struct kfd_device_info fiji_vf_device_info = { |
| 203 | .asic_family = CHIP_FIJI, | 210 | .asic_family = CHIP_FIJI, |
| 204 | .asic_name = "fiji", | 211 | .asic_name = "fiji", |
| 212 | .gfx_target_version = 80003, | ||
| 205 | .max_pasid_bits = 16, | 213 | .max_pasid_bits = 16, |
| 206 | .max_no_of_hqd = 24, | 214 | .max_no_of_hqd = 24, |
| 207 | .doorbell_size = 4, | 215 | .doorbell_size = 4, |
| @@ -221,6 +229,7 @@ static const struct kfd_device_info fiji_vf_device_info = { · 13 unmodified lines | |||
| 221 | static const struct kfd_device_info polaris10_device_info = { | 229 | static const struct kfd_device_info polaris10_device_info = { |
| 222 | .asic_family = CHIP_POLARIS10, | 230 | .asic_family = CHIP_POLARIS10, |
| 223 | .asic_name = "polaris10", | 231 | .asic_name = "polaris10", |
| 232 | .gfx_target_version = 80003, | ||
| 224 | .max_pasid_bits = 16, | 233 | .max_pasid_bits = 16, |
| 225 | .max_no_of_hqd = 24, | 234 | .max_no_of_hqd = 24, |
| 226 | .doorbell_size = 4, | 235 | .doorbell_size = 4, |
| @@ -239,6 +248,7 @@ static const struct kfd_device_info polaris10_device_info = { · 12 unmodified lines | |||
| 239 | static const struct kfd_device_info polaris10_vf_device_info = { | 248 | static const struct kfd_device_info polaris10_vf_device_info = { |
| 240 | .asic_family = CHIP_POLARIS10, | 249 | .asic_family = CHIP_POLARIS10, |
| 241 | .asic_name = "polaris10", | 250 | .asic_name = "polaris10", |
| 251 | .gfx_target_version = 80003, | ||
| 242 | .max_pasid_bits = 16, | 252 | .max_pasid_bits = 16, |
| 243 | .max_no_of_hqd = 24, | 253 | .max_no_of_hqd = 24, |
| 244 | .doorbell_size = 4, | 254 | .doorbell_size = 4, |
| @@ -257,6 +267,7 @@ static const struct kfd_device_info polaris10_vf_device_info = { · 12 unmodified lines | |||
| 257 | static const struct kfd_device_info polaris11_device_info = { | 267 | static const struct kfd_device_info polaris11_device_info = { |
| 258 | .asic_family = CHIP_POLARIS11, | 268 | .asic_family = CHIP_POLARIS11, |
| 259 | .asic_name = "polaris11", | 269 | .asic_name = "polaris11", |
| 270 | .gfx_target_version = 80003, | ||
| 260 | .max_pasid_bits = 16, | 271 | .max_pasid_bits = 16, |
| 261 | .max_no_of_hqd = 24, | 272 | .max_no_of_hqd = 24, |
| 262 | .doorbell_size = 4, | 273 | .doorbell_size = 4, |
| @@ -275,6 +286,7 @@ static const struct kfd_device_info polaris11_device_info = { · 12 unmodified lines | |||
| 275 | static const struct kfd_device_info polaris12_device_info = { | 286 | static const struct kfd_device_info polaris12_device_info = { |
| 276 | .asic_family = CHIP_POLARIS12, | 287 | .asic_family = CHIP_POLARIS12, |
| 277 | .asic_name = "polaris12", | 288 | .asic_name = "polaris12", |
| 289 | .gfx_target_version = 80003, | ||
| 278 | .max_pasid_bits = 16, | 290 | .max_pasid_bits = 16, |
| 279 | .max_no_of_hqd = 24, | 291 | .max_no_of_hqd = 24, |
| 280 | .doorbell_size = 4, | 292 | .doorbell_size = 4, |
| @@ -293,6 +305,7 @@ static const struct kfd_device_info polaris12_device_info = { · 12 unmodified lines | |||
| 293 | static const struct kfd_device_info vegam_device_info = { | 305 | static const struct kfd_device_info vegam_device_info = { |
| 294 | .asic_family = CHIP_VEGAM, | 306 | .asic_family = CHIP_VEGAM, |
| 295 | .asic_name = "vegam", | 307 | .asic_name = "vegam", |
| 308 | .gfx_target_version = 80003, | ||
| 296 | .max_pasid_bits = 16, | 309 | .max_pasid_bits = 16, |
| 297 | .max_no_of_hqd = 24, | 310 | .max_no_of_hqd = 24, |
| 298 | .doorbell_size = 4, | 311 | .doorbell_size = 4, |
| @@ -311,6 +324,7 @@ static const struct kfd_device_info vegam_device_info = { · 12 unmodified lines | |||
| 311 | static const struct kfd_device_info vega10_device_info = { | 324 | static const struct kfd_device_info vega10_device_info = { |
| 312 | .asic_family = CHIP_VEGA10, | 325 | .asic_family = CHIP_VEGA10, |
| 313 | .asic_name = "vega10", | 326 | .asic_name = "vega10", |
| 327 | .gfx_target_version = 90000, | ||
| 314 | .max_pasid_bits = 16, | 328 | .max_pasid_bits = 16, |
| 315 | .max_no_of_hqd = 24, | 329 | .max_no_of_hqd = 24, |
| 316 | .doorbell_size = 8, | 330 | .doorbell_size = 8, |
| @@ -329,6 +343,7 @@ static const struct kfd_device_info vega10_device_info = { · 12 unmodified lines | |||
| 329 | static const struct kfd_device_info vega10_vf_device_info = { | 343 | static const struct kfd_device_info vega10_vf_device_info = { |
| 330 | .asic_family = CHIP_VEGA10, | 344 | .asic_family = CHIP_VEGA10, |
| 331 | .asic_name = "vega10", | 345 | .asic_name = "vega10", |
| 346 | .gfx_target_version = 90000, | ||
| 332 | .max_pasid_bits = 16, | 347 | .max_pasid_bits = 16, |
| 333 | .max_no_of_hqd = 24, | 348 | .max_no_of_hqd = 24, |
| 334 | .doorbell_size = 8, | 349 | .doorbell_size = 8, |
| @@ -347,6 +362,7 @@ static const struct kfd_device_info vega10_vf_device_info = { · 12 unmodified lines | |||
| 347 | static const struct kfd_device_info vega12_device_info = { | 362 | static const struct kfd_device_info vega12_device_info = { |
| 348 | .asic_family = CHIP_VEGA12, | 363 | .asic_family = CHIP_VEGA12, |
| 349 | .asic_name = "vega12", | 364 | .asic_name = "vega12", |
| 365 | .gfx_target_version = 90004, | ||
| 350 | .max_pasid_bits = 16, | 366 | .max_pasid_bits = 16, |
| 351 | .max_no_of_hqd = 24, | 367 | .max_no_of_hqd = 24, |
| 352 | .doorbell_size = 8, | 368 | .doorbell_size = 8, |
| @@ -365,6 +381,7 @@ static const struct kfd_device_info vega12_device_info = { · 12 unmodified lines | |||
| 365 | static const struct kfd_device_info vega20_device_info = { | 381 | static const struct kfd_device_info vega20_device_info = { |
| 366 | .asic_family = CHIP_VEGA20, | 382 | .asic_family = CHIP_VEGA20, |
| 367 | .asic_name = "vega20", | 383 | .asic_name = "vega20", |
| 384 | .gfx_target_version = 90006, | ||
| 368 | .max_pasid_bits = 16, | 385 | .max_pasid_bits = 16, |
| 369 | .max_no_of_hqd = 24, | 386 | .max_no_of_hqd = 24, |
| 370 | .doorbell_size = 8, | 387 | .doorbell_size = 8, |
| @@ -383,6 +400,7 @@ static const struct kfd_device_info vega20_device_info = { · 12 unmodified lines | |||
| 383 | static const struct kfd_device_info arcturus_device_info = { | 400 | static const struct kfd_device_info arcturus_device_info = { |
| 384 | .asic_family = CHIP_ARCTURUS, | 401 | .asic_family = CHIP_ARCTURUS, |
| 385 | .asic_name = "arcturus", | 402 | .asic_name = "arcturus", |
| 403 | .gfx_target_version = 90008, | ||
| 386 | .max_pasid_bits = 16, | 404 | .max_pasid_bits = 16, |
| 387 | .max_no_of_hqd = 24, | 405 | .max_no_of_hqd = 24, |
| 388 | .doorbell_size = 8, | 406 | .doorbell_size = 8, |
| @@ -401,6 +419,7 @@ static const struct kfd_device_info arcturus_device_info = { · 12 unmodified lines | |||
| 401 | static const struct kfd_device_info aldebaran_device_info = { | 419 | static const struct kfd_device_info aldebaran_device_info = { |
| 402 | .asic_family = CHIP_ALDEBARAN, | 420 | .asic_family = CHIP_ALDEBARAN, |
| 403 | .asic_name = "aldebaran", | 421 | .asic_name = "aldebaran", |
| 422 | .gfx_target_version = 90010, | ||
| 404 | .max_pasid_bits = 16, | 423 | .max_pasid_bits = 16, |
| 405 | .max_no_of_hqd = 24, | 424 | .max_no_of_hqd = 24, |
| 406 | .doorbell_size = 8, | 425 | .doorbell_size = 8, |
| @@ -419,6 +438,7 @@ static const struct kfd_device_info aldebaran_device_info = { · 12 unmodified lines | |||
| 419 | static const struct kfd_device_info renoir_device_info = { | 438 | static const struct kfd_device_info renoir_device_info = { |
| 420 | .asic_family = CHIP_RENOIR, | 439 | .asic_family = CHIP_RENOIR, |
| 421 | .asic_name = "renoir", | 440 | .asic_name = "renoir", |
| 441 | .gfx_target_version = 90002, | ||
| 422 | .max_pasid_bits = 16, | 442 | .max_pasid_bits = 16, |
| 423 | .max_no_of_hqd = 24, | 443 | .max_no_of_hqd = 24, |
| 424 | .doorbell_size = 8, | 444 | .doorbell_size = 8, |
| @@ -437,6 +457,7 @@ static const struct kfd_device_info renoir_device_info = { · 12 unmodified lines | |||
| 437 | static const struct kfd_device_info navi10_device_info = { | 457 | static const struct kfd_device_info navi10_device_info = { |
| 438 | .asic_family = CHIP_NAVI10, | 458 | .asic_family = CHIP_NAVI10, |
| 439 | .asic_name = "navi10", | 459 | .asic_name = "navi10", |
| 460 | .gfx_target_version = 100100, | ||
| 440 | .max_pasid_bits = 16, | 461 | .max_pasid_bits = 16, |
| 441 | .max_no_of_hqd = 24, | 462 | .max_no_of_hqd = 24, |
| 442 | .doorbell_size = 8, | 463 | .doorbell_size = 8, |
| @@ -455,6 +476,7 @@ static const struct kfd_device_info navi10_device_info = { · 12 unmodified lines | |||
| 455 | static const struct kfd_device_info navi12_device_info = { | 476 | static const struct kfd_device_info navi12_device_info = { |
| 456 | .asic_family = CHIP_NAVI12, | 477 | .asic_family = CHIP_NAVI12, |
| 457 | .asic_name = "navi12", | 478 | .asic_name = "navi12", |
| 479 | .gfx_target_version = 100101, | ||
| 458 | .max_pasid_bits = 16, | 480 | .max_pasid_bits = 16, |
| 459 | .max_no_of_hqd = 24, | 481 | .max_no_of_hqd = 24, |
| 460 | .doorbell_size = 8, | 482 | .doorbell_size = 8, |
| @@ -473,6 +495,7 @@ static const struct kfd_device_info navi12_device_info = { · 12 unmodified lines | |||
| 473 | static const struct kfd_device_info navi14_device_info = { | 495 | static const struct kfd_device_info navi14_device_info = { |
| 474 | .asic_family = CHIP_NAVI14, | 496 | .asic_family = CHIP_NAVI14, |
| 475 | .asic_name = "navi14", | 497 | .asic_name = "navi14", |
| 498 | .gfx_target_version = 100102, | ||
| 476 | .max_pasid_bits = 16, | 499 | .max_pasid_bits = 16, |
| 477 | .max_no_of_hqd = 24, | 500 | .max_no_of_hqd = 24, |
| 478 | .doorbell_size = 8, | 501 | .doorbell_size = 8, |
| @@ -491,6 +514,7 @@ static const struct kfd_device_info navi14_device_info = { · 12 unmodified lines | |||
| 491 | static const struct kfd_device_info sienna_cichlid_device_info = { | 514 | static const struct kfd_device_info sienna_cichlid_device_info = { |
| 492 | .asic_family = CHIP_SIENNA_CICHLID, | 515 | .asic_family = CHIP_SIENNA_CICHLID, |
| 493 | .asic_name = "sienna_cichlid", | 516 | .asic_name = "sienna_cichlid", |
| 517 | .gfx_target_version = 100300, | ||
| 494 | .max_pasid_bits = 16, | 518 | .max_pasid_bits = 16, |
| 495 | .max_no_of_hqd = 24, | 519 | .max_no_of_hqd = 24, |
| 496 | .doorbell_size = 8, | 520 | .doorbell_size = 8, |
| @@ -509,6 +533,7 @@ static const struct kfd_device_info sienna_cichlid_device_info = { · 12 unmodified lines | |||
| 509 | static const struct kfd_device_info navy_flounder_device_info = { | 533 | static const struct kfd_device_info navy_flounder_device_info = { |
| 510 | .asic_family = CHIP_NAVY_FLOUNDER, | 534 | .asic_family = CHIP_NAVY_FLOUNDER, |
| 511 | .asic_name = "navy_flounder", | 535 | .asic_name = "navy_flounder", |
| 536 | .gfx_target_version = 100301, | ||
| 512 | .max_pasid_bits = 16, | 537 | .max_pasid_bits = 16, |
| 513 | .max_no_of_hqd = 24, | 538 | .max_no_of_hqd = 24, |
| 514 | .doorbell_size = 8, | 539 | .doorbell_size = 8, |
| @@ -527,6 +552,7 @@ static const struct kfd_device_info navy_flounder_device_info = { · 12 unmodified lines | |||
| 527 | static const struct kfd_device_info vangogh_device_info = { | 552 | static const struct kfd_device_info vangogh_device_info = { |
| 528 | .asic_family = CHIP_VANGOGH, | 553 | .asic_family = CHIP_VANGOGH, |
| 529 | .asic_name = "vangogh", | 554 | .asic_name = "vangogh", |
| 555 | .gfx_target_version = 100303, | ||
| 530 | .max_pasid_bits = 16, | 556 | .max_pasid_bits = 16, |
| 531 | .max_no_of_hqd = 24, | 557 | .max_no_of_hqd = 24, |
| 532 | .doorbell_size = 8, | 558 | .doorbell_size = 8, |
| @@ -545,6 +571,7 @@ static const struct kfd_device_info vangogh_device_info = { · 12 unmodified lines | |||
| 545 | static const struct kfd_device_info dimgrey_cavefish_device_info = { | 571 | static const struct kfd_device_info dimgrey_cavefish_device_info = { |
| 546 | .asic_family = CHIP_DIMGREY_CAVEFISH, | 572 | .asic_family = CHIP_DIMGREY_CAVEFISH, |
| 547 | .asic_name = "dimgrey_cavefish", | 573 | .asic_name = "dimgrey_cavefish", |
| 574 | .gfx_target_version = 100302, | ||
| 548 | .max_pasid_bits = 16, | 575 | .max_pasid_bits = 16, |
| 549 | .max_no_of_hqd = 24, | 576 | .max_no_of_hqd = 24, |
| 550 | .doorbell_size = 8, | 577 | .doorbell_size = 8, |
| @@ -563,6 +590,7 @@ static const struct kfd_device_info dimgrey_cavefish_device_info = { · 12 unmodified lines | |||
| 563 | static const struct kfd_device_info beige_goby_device_info = { | 590 | static const struct kfd_device_info beige_goby_device_info = { |
| 564 | .asic_family = CHIP_BEIGE_GOBY, | 591 | .asic_family = CHIP_BEIGE_GOBY, |
| 565 | .asic_name = "beige_goby", | 592 | .asic_name = "beige_goby", |
| 593 | .gfx_target_version = 100304, | ||
| 566 | .max_pasid_bits = 16, | 594 | .max_pasid_bits = 16, |
| 567 | .max_no_of_hqd = 24, | 595 | .max_no_of_hqd = 24, |
| 568 | .doorbell_size = 8, | 596 | .doorbell_size = 8, |
| @@ -581,6 +609,7 @@ static const struct kfd_device_info beige_goby_device_info = { · 12 unmodified lines | |||
| 581 | static const struct kfd_device_info yellow_carp_device_info = { | 609 | static const struct kfd_device_info yellow_carp_device_info = { |
| 582 | .asic_family = CHIP_YELLOW_CARP, | 610 | .asic_family = CHIP_YELLOW_CARP, |
| 583 | .asic_name = "yellow_carp", | 611 | .asic_name = "yellow_carp", |
| 612 | .gfx_target_version = 100305, | ||
| 584 | .max_pasid_bits = 16, | 613 | .max_pasid_bits = 16, |
| 585 | .max_no_of_hqd = 24, | 614 | .max_no_of_hqd = 24, |
| 586 | .doorbell_size = 8, | 615 | .doorbell_size = 8, |
| @@ -596,6 +625,25 @@ static const struct kfd_device_info yellow_carp_device_info = { · 9 unmodified lines | |||
| 596 | .num_sdma_queues_per_engine = 2, | 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 | /* For each entry, [0] is regular and [1] is virtualisation device. */ | 647 | /* For each entry, [0] is regular and [1] is virtualisation device. */ |
| 600 | static const struct kfd_device_info *kfd_supported_devices[][2] = { | 648 | static const struct kfd_device_info *kfd_supported_devices[][2] = { |
| 601 | #ifdef KFD_SUPPORT_IOMMU_V2 | 649 | #ifdef KFD_SUPPORT_IOMMU_V2 |
| @@ -625,6 +673,7 @@ static const struct kfd_device_info *kfd_supported_devices[][2] = { · 23 unmodified lines | |||
| 625 | [CHIP_DIMGREY_CAVEFISH] = {&dimgrey_cavefish_device_info, &dimgrey_cavefish_device_info}, | 673 | [CHIP_DIMGREY_CAVEFISH] = {&dimgrey_cavefish_device_info, &dimgrey_cavefish_device_info}, |
| 626 | [CHIP_BEIGE_GOBY] = {&beige_goby_device_info, &beige_goby_device_info}, | 674 | [CHIP_BEIGE_GOBY] = {&beige_goby_device_info, &beige_goby_device_info}, |
| 627 | [CHIP_YELLOW_CARP] = {&yellow_carp_device_info, NULL}, | 675 | [CHIP_YELLOW_CARP] = {&yellow_carp_device_info, NULL}, |
| 676 | [CHIP_CYAN_SKILLFISH] = {&cyan_skillfish_device_info, NULL}, | ||
| 628 | }; | 677 | }; |
| 629 | 678 | ||
| 630 | static int kfd_gtt_sa_init(struct kfd_dev *kfd, unsigned int buf_size, | 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 | WARN_ONCE(count < 0, "Compute profile ref. count error"); | 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 | if (kfd && kfd->init_complete) | 1423 | if (kfd && kfd->init_complete) |
| 1375 | kfd_smi_event_update_thermal_throttling(kfd, throttle_bitmask); | 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 | int kfd_debugfs_hang_hws(struct kfd_dev *dev) | 1432 | int kfd_debugfs_hang_hws(struct kfd_dev *dev) |
| 1384 | { | 1433 | { |
| 1385 | int r = 0; | ||
| 1386 | |||
| 1387 | if (dev->dqm->sched_policy != KFD_SCHED_POLICY_HWS) { | 1434 | if (dev->dqm->sched_policy != KFD_SCHED_POLICY_HWS) { |
| 1388 | pr_err("HWS is not enabled"); | 1435 | pr_err("HWS is not enabled"); |
| 1389 | return -EINVAL; | 1436 | return -EINVAL; |
| 1390 | } | 1437 | } |
| 1391 | 1438 | ||
| 1392 | r = pm_debugfs_hang_hws(&dev->dqm->packets); | 1439 | return dqm_debugfs_hang_hws(dev->dqm); |
| 1393 | if (!r) | ||
| 1394 | r = dqm_debugfs_execute_queues(dev->dqm); | ||
| 1395 | |||
| 1396 | return r; | ||
| 1397 | } | 1440 | } |
| 1398 | 1441 | ||
| 1399 | #endif | 1442 | #endif |
| @@ -211,6 +211,15 @@ static void deallocate_doorbell(struct qcm_process_device *qpd, · 210 unmodified lines | |||
| 211 | WARN_ON(!old); | 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 | static int allocate_vmid(struct device_queue_manager *dqm, | 223 | static int allocate_vmid(struct device_queue_manager *dqm, |
| 215 | struct qcm_process_device *qpd, | 224 | struct qcm_process_device *qpd, |
| 216 | struct queue *q) | 225 | struct queue *q) |
| @@ -241,6 +250,10 @@ static int allocate_vmid(struct device_queue_manager *dqm, · 24 unmodified lines | |||
| 241 | 250 | ||
| 242 | program_sh_mem_settings(dqm, qpd); | 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 | /* qpd->page_table_base is set earlier when register_process() | 257 | /* qpd->page_table_base is set earlier when register_process() |
| 245 | * is called, i.e. when the first queue is created. | 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 | static int flush_texture_cache_nocpsch(struct kfd_dev *kdev, | 273 | static int flush_texture_cache_nocpsch(struct kfd_dev *kdev, |
| 261 | struct qcm_process_device *qpd) | 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 | int ret; | 277 | int ret; |
| 265 | 278 | ||
| 266 | if (!qpd->ib_kaddr) | 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 | retval = mqd_mgr->destroy_mqd(mqd_mgr, q->mqd, | 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 | KFD_UNMAP_LATENCY_MS, q->pipe, q->queue); | 601 | KFD_UNMAP_LATENCY_MS, q->pipe, q->queue); |
| 587 | if (retval) { | 602 | if (retval) { |
| 588 | pr_err("destroy mqd failed\n"); | 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 | continue; | 690 | continue; |
| 676 | 691 | ||
| 677 | retval = mqd_mgr->destroy_mqd(mqd_mgr, q->mqd, | 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 | KFD_UNMAP_LATENCY_MS, q->pipe, q->queue); | 696 | KFD_UNMAP_LATENCY_MS, q->pipe, q->queue); |
| 680 | if (retval && !ret) | 697 | if (retval && !ret) |
| 681 | /* Return the first error, but keep going to | 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 | init_interrupts(dqm); | 1017 | init_interrupts(dqm); |
| 1001 | 1018 | ||
| 1002 | if (dqm->dev->device_info->asic_family == CHIP_HAWAII) | 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 | dqm->sched_running = true; | 1021 | dqm->sched_running = true; |
| 1005 | 1022 | ||
| 1006 | return 0; | 1023 | return 0; |
| @@ -1009,7 +1026,7 @@ static int start_nocpsch(struct device_queue_manager *dqm) · 2 unmodified lines | |||
| 1009 | static int stop_nocpsch(struct device_queue_manager *dqm) | 1026 | static int stop_nocpsch(struct device_queue_manager *dqm) |
| 1010 | { | 1027 | { |
| 1011 | if (dqm->dev->device_info->asic_family == CHIP_HAWAII) | 1028 | if (dqm->dev->device_info->asic_family == CHIP_HAWAII) |
| 1012 | pm_uninit(&dqm->packets, false); | 1029 | pm_uninit(&dqm->packet_mgr, false); |
| 1013 | dqm->sched_running = false; | 1030 | dqm->sched_running = false; |
| 1014 | 1031 | ||
| 1015 | return 0; | 1032 | return 0; |
| @@ -1124,7 +1141,7 @@ static int set_sched_resources(struct device_queue_manager *dqm) · 108 unmodified lines | |||
| 1124 | "queue mask: 0x%8llX\n", | 1141 | "queue mask: 0x%8llX\n", |
| 1125 | res.vmid_mask, res.queue_mask); | 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 | static int initialize_cpsch(struct device_queue_manager *dqm) | 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 | retval = 0; | 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 | if (retval) | 1186 | if (retval) |
| 1169 | goto fail_packet_manager_init; | 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 | init_interrupts(dqm); | 1205 | init_interrupts(dqm); |
| 1188 | 1206 | ||
| 1189 | dqm_lock(dqm); | ||
| 1190 | /* clear hang status when driver try to start the hw scheduler */ | 1207 | /* clear hang status when driver try to start the hw scheduler */ |
| 1191 | dqm->is_hws_hang = false; | 1208 | dqm->is_hws_hang = false; |
| 1192 | dqm->is_resetting = false; | 1209 | dqm->is_resetting = false; |
| @@ -1197,8 +1214,9 @@ static int start_cpsch(struct device_queue_manager *dqm) · 4 unmodified lines | |||
| 1197 | return 0; | 1214 | return 0; |
| 1198 | fail_allocate_vidmem: | 1215 | fail_allocate_vidmem: |
| 1199 | fail_set_sched_resources: | 1216 | fail_set_sched_resources: |
| 1200 | pm_uninit(&dqm->packets, false); | 1217 | pm_uninit(&dqm->packet_mgr, false); |
| 1201 | fail_packet_manager_init: | 1218 | fail_packet_manager_init: |
| 1219 | dqm_unlock(dqm); | ||
| 1202 | return retval; | 1220 | return retval; |
| 1203 | } | 1221 | } |
| 1204 | 1222 | ||
| @@ -1211,12 +1229,12 @@ static int stop_cpsch(struct device_queue_manager *dqm) · 6 unmodified lines | |||
| 1211 | unmap_queues_cpsch(dqm, KFD_UNMAP_QUEUES_FILTER_ALL_QUEUES, 0); | 1229 | unmap_queues_cpsch(dqm, KFD_UNMAP_QUEUES_FILTER_ALL_QUEUES, 0); |
| 1212 | hanging = dqm->is_hws_hang || dqm->is_resetting; | 1230 | hanging = dqm->is_hws_hang || dqm->is_resetting; |
| 1213 | dqm->sched_running = false; | 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 | kfd_gtt_sa_free(dqm->dev, dqm->fence_mem); | 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 | return 0; | 1239 | return 0; |
| 1222 | } | 1240 | } |
| @@ -1390,7 +1408,7 @@ static int map_queues_cpsch(struct device_queue_manager *dqm) · 167 unmodified lines | |||
| 1390 | if (dqm->active_runlist) | 1408 | if (dqm->active_runlist) |
| 1391 | return 0; | 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 | pr_debug("%s sent runlist\n", __func__); | 1412 | pr_debug("%s sent runlist\n", __func__); |
| 1395 | if (retval) { | 1413 | if (retval) { |
| 1396 | pr_err("failed to execute runlist\n"); | 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 | if (!dqm->active_runlist) | 1434 | if (!dqm->active_runlist) |
| 1417 | return retval; | 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 | filter, filter_param, false, 0); | 1438 | filter, filter_param, false, 0); |
| 1421 | if (retval) | 1439 | if (retval) |
| 1422 | return retval; | 1440 | return retval; |
| 1423 | 1441 | ||
| 1424 | *dqm->fence_addr = KFD_FENCE_INIT; | 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 | KFD_FENCE_COMPLETED); | 1444 | KFD_FENCE_COMPLETED); |
| 1427 | /* should be timed out */ | 1445 | /* should be timed out */ |
| 1428 | retval = amdkfd_fence_wait_timeout(dqm->fence_addr, KFD_FENCE_COMPLETED, | 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 | * check those fields | 1466 | * check those fields |
| 1449 | */ | 1467 | */ |
| 1450 | mqd_mgr = dqm->mqd_mgrs[KFD_MQD_TYPE_HIQ]; | 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 | pr_err("HIQ MQD's queue_doorbell_id0 is not 0, Queue preemption time out\n"); | 1470 | pr_err("HIQ MQD's queue_doorbell_id0 is not 0, Queue preemption time out\n"); |
| 1453 | while (halt_if_hws_hang) | 1471 | while (halt_if_hws_hang) |
| 1454 | schedule(); | 1472 | schedule(); |
| 1455 | return -ETIME; | 1473 | return -ETIME; |
| 1456 | } | 1474 | } |
| 1457 | 1475 | ||
| 1458 | pm_release_ib(&dqm->packets); | 1476 | pm_release_ib(&dqm->packet_mgr); |
| 1459 | dqm->active_runlist = false; | 1477 | dqm->active_runlist = false; |
| 1460 | 1478 | ||
| 1461 | return retval; | 1479 | return retval; |
| @@ -1946,6 +1964,7 @@ struct device_queue_manager *device_queue_manager_init(struct kfd_dev *dev) · 484 unmodified lines | |||
| 1946 | case CHIP_DIMGREY_CAVEFISH: | 1964 | case CHIP_DIMGREY_CAVEFISH: |
| 1947 | case CHIP_BEIGE_GOBY: | 1965 | case CHIP_BEIGE_GOBY: |
| 1948 | case CHIP_YELLOW_CARP: | 1966 | case CHIP_YELLOW_CARP: |
| 1967 | case CHIP_CYAN_SKILLFISH: | ||
| 1949 | device_queue_manager_init_v10_navi10(&dqm->asic_ops); | 1968 | device_queue_manager_init_v10_navi10(&dqm->asic_ops); |
| 1950 | break; | 1969 | break; |
| 1951 | default: | 1970 | default: |
| @@ -2099,11 +2118,16 @@ int dqm_debugfs_hqds(struct seq_file *m, void *data) · 147 unmodified lines | |||
| 2099 | return r; | 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 | int r = 0; | 2123 | int r = 0; |
| 2105 | 2124 | ||
| 2106 | dqm_lock(dqm); | 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 | dqm->active_runlist = true; | 2131 | dqm->active_runlist = true; |
| 2108 | r = execute_queues_cpsch(dqm, KFD_UNMAP_QUEUES_FILTER_ALL_QUEUES, 0); | 2132 | r = execute_queues_cpsch(dqm, KFD_UNMAP_QUEUES_FILTER_ALL_QUEUES, 0); |
| 2109 | dqm_unlock(dqm); | 2133 | dqm_unlock(dqm); |
| @@ -169,7 +169,7 @@ struct device_queue_manager { · 168 unmodified lines | |||
| 169 | struct device_queue_manager_asic_ops asic_ops; | 169 | struct device_queue_manager_asic_ops asic_ops; |
| 170 | 170 | ||
| 171 | struct mqd_manager *mqd_mgrs[KFD_MQD_TYPE_MAX]; | 171 | struct mqd_manager *mqd_mgrs[KFD_MQD_TYPE_MAX]; |
| 172 | struct packet_manager packets; | 172 | struct packet_manager packet_mgr; |
| 173 | struct kfd_dev *dev; | 173 | struct kfd_dev *dev; |
| 174 | struct mutex lock_hidden; /* use dqm_lock/unlock(dqm) */ | 174 | struct mutex lock_hidden; /* use dqm_lock/unlock(dqm) */ |
| 175 | struct list_head queues; | 175 | struct list_head queues; |
| @@ -422,6 +422,7 @@ int kfd_init_apertures(struct kfd_process *process) · 421 unmodified lines | |||
| 422 | case CHIP_DIMGREY_CAVEFISH: | 422 | case CHIP_DIMGREY_CAVEFISH: |
| 423 | case CHIP_BEIGE_GOBY: | 423 | case CHIP_BEIGE_GOBY: |
| 424 | case CHIP_YELLOW_CARP: | 424 | case CHIP_YELLOW_CARP: |
| 425 | case CHIP_CYAN_SKILLFISH: | ||
| 425 | kfd_init_apertures_v9(pdd, id); | 426 | kfd_init_apertures_v9(pdd, id); |
| 426 | break; | 427 | break; |
| 427 | default: | 428 | default: |
| @@ -98,36 +98,78 @@ void mqd_symmetrically_map_cu_mask(struct mqd_manager *mm, · 97 unmodified lines | |||
| 98 | uint32_t *se_mask) | 98 | uint32_t *se_mask) |
| 99 | { | 99 | { |
| 100 | struct kfd_cu_info cu_info; | 100 | struct kfd_cu_info cu_info; |
| 101 | uint32_t cu_per_se[KFD_MAX_NUM_SE] = {0}; | 101 | uint32_t cu_per_sh[KFD_MAX_NUM_SE][KFD_MAX_NUM_SH_PER_SE] = {0}; |
| 102 | int i, se, sh, cu = 0; | 102 | int i, se, sh, cu; |
| 103 | |||
| 104 | amdgpu_amdkfd_get_cu_info(mm->dev->kgd, &cu_info); | 103 | amdgpu_amdkfd_get_cu_info(mm->dev->kgd, &cu_info); |
| 105 | 104 | ||
| 106 | if (cu_mask_count > cu_info.cu_active_number) | 105 | if (cu_mask_count > cu_info.cu_active_number) |
| 107 | cu_mask_count = cu_info.cu_active_number; | 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 | for (se = 0; se < cu_info.num_shader_engines; se++) | 131 | for (se = 0; se < cu_info.num_shader_engines; se++) |
| 110 | for (sh = 0; sh < cu_info.num_shader_arrays_per_engine; sh++) | 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)]); | 133 | cu_per_sh[se][sh] = hweight32(cu_info.cu_bitmap[se % 4][sh + (se / 4)]); |
| 112 | 134 | ||
| 113 | /* Symmetrically map cu_mask to all SEs: | 135 | /* Symmetrically map cu_mask to all SEs & SHs: |
| 114 | * cu_mask[0] bit0 -> se_mask[0] bit0; | 136 | * se_mask programs up to 2 SH in the upper and lower 16 bits. |
| 115 | * cu_mask[0] bit1 -> se_mask[1] bit0; | 137 | * |
| 116 | * ... (if # SE is 4) | 138 | * Examples |
| 117 | * cu_mask[0] bit4 -> se_mask[0] bit1; | 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; | 158 | for (i = 0; i < cu_info.num_shader_engines; i++) |
| 121 | for (i = 0; i < cu_mask_count; i++) { | 159 | se_mask[i] = 0; |
| 122 | if (cu_mask[i / 32] & (1 << (i % 32))) | 160 | |
| 123 | se_mask[se] |= 1 << cu; | 161 | i = 0; |
| 124 | 162 | for (cu = 0; cu < 16; cu++) { | |
| 125 | do { | 163 | for (sh = 0; sh < cu_info.num_shader_arrays_per_engine; sh++) { |
| 126 | se++; | 164 | for (se = 0; se < cu_info.num_shader_engines; se++) { |
| 127 | if (se == cu_info.num_shader_engines) { | 165 | if (cu_per_sh[se][sh] > cu) { |
| 128 | se = 0; | 166 | if (cu_mask[i / 32] & (1 << (i % 32))) |
| 129 | cu++; | 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 | #include "kfd_priv.h" | 27 | #include "kfd_priv.h" |
| 28 | 28 | ||
| 29 | #define KFD_MAX_NUM_SE 8 | 29 | #define KFD_MAX_NUM_SE 8 |
| 30 | #define KFD_MAX_NUM_SH_PER_SE 2 | ||
| 30 | 31 | ||
| 31 | /** | 32 | /** |
| 32 | * struct mqd_manager | 33 | * struct mqd_manager |
| @@ -251,6 +251,7 @@ int pm_init(struct packet_manager *pm, struct device_queue_manager *dqm) · 250 unmodified lines | |||
| 251 | case CHIP_DIMGREY_CAVEFISH: | 251 | case CHIP_DIMGREY_CAVEFISH: |
| 252 | case CHIP_BEIGE_GOBY: | 252 | case CHIP_BEIGE_GOBY: |
| 253 | case CHIP_YELLOW_CARP: | 253 | case CHIP_YELLOW_CARP: |
| 254 | case CHIP_CYAN_SKILLFISH: | ||
| 254 | pm->pmf = &kfd_v9_pm_funcs; | 255 | pm->pmf = &kfd_v9_pm_funcs; |
| 255 | break; | 256 | break; |
| 256 | case CHIP_ALDEBARAN: | 257 | case CHIP_ALDEBARAN: |
| @@ -278,6 +279,7 @@ void pm_uninit(struct packet_manager *pm, bool hanging) · 21 unmodified lines | |||
| 278 | { | 279 | { |
| 279 | mutex_destroy(&pm->lock); | 280 | mutex_destroy(&pm->lock); |
| 280 | kernel_queue_uninit(pm->priv_queue, hanging); | 281 | kernel_queue_uninit(pm->priv_queue, hanging); |
| 282 | pm->priv_queue = NULL; | ||
| 281 | } | 283 | } |
| 282 | 284 | ||
| 283 | int pm_send_set_resources(struct packet_manager *pm, | 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 | uint32_t *buffer, size; | 449 | uint32_t *buffer, size; |
| 448 | int r = 0; | 450 | int r = 0; |
| 449 | 451 | ||
| 452 | if (!pm->priv_queue) | ||
| 453 | return -EAGAIN; | ||
| 454 | |||
| 450 | size = pm->pmf->query_status_size; | 455 | size = pm->pmf->query_status_size; |
| 451 | mutex_lock(&pm->lock); | 456 | mutex_lock(&pm->lock); |
| 452 | kq_acquire_packet_buffer(pm->priv_queue, | 457 | kq_acquire_packet_buffer(pm->priv_queue, |
| @@ -196,6 +196,7 @@ struct kfd_event_interrupt_class { · 195 unmodified lines | |||
| 196 | struct kfd_device_info { | 196 | struct kfd_device_info { |
| 197 | enum amd_asic_type asic_family; | 197 | enum amd_asic_type asic_family; |
| 198 | const char *asic_name; | 198 | const char *asic_name; |
| 199 | uint32_t gfx_target_version; | ||
| 199 | const struct kfd_event_interrupt_class *event_interrupt_class; | 200 | const struct kfd_event_interrupt_class *event_interrupt_class; |
| 200 | unsigned int max_pasid_bits; | 201 | unsigned int max_pasid_bits; |
| 201 | unsigned int max_no_of_hqd; | 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 | int kfd_debugfs_hang_hws(struct kfd_dev *dev); | 1196 | int kfd_debugfs_hang_hws(struct kfd_dev *dev); |
| 1196 | int pm_debugfs_hang_hws(struct packet_manager *pm); | 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 | #else | 1200 | #else |
| 1200 | 1201 | ||
| @@ -714,7 +714,8 @@ static int kfd_process_alloc_gpuvm(struct kfd_process_device *pdd, · 713 unmodified lines | |||
| 714 | if (err) | 714 | if (err) |
| 715 | goto err_alloc_mem; | 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 | if (err) | 719 | if (err) |
| 719 | goto err_map_mem; | 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 | void kfd_smi_event_update_thermal_throttling(struct kfd_dev *dev, | 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 | struct amdgpu_device *adev = (struct amdgpu_device *)dev->kgd; | 210 | struct amdgpu_device *adev = (struct amdgpu_device *)dev->kgd; |
| 211 | /* | 211 | /* |
| 212 | * ThermalThrottle msg = throttle_bitmask(8): | 212 | * ThermalThrottle msg = throttle_bitmask(8): |
| 213 | * thermal_interrupt_count(16): | 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 | * 1 byte : + 16 byte thermal_interupt_counter + 1 byte \n + | 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 | int len; | 219 | int len; |
| 220 | 220 | ||
| 221 | if (list_empty(&dev->smi_clients)) | 221 | if (list_empty(&dev->smi_clients)) |
| 222 | return; | 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 | KFD_SMI_EVENT_THERMAL_THROTTLE, throttle_bitmask, | 225 | KFD_SMI_EVENT_THERMAL_THROTTLE, throttle_bitmask, |
| 226 | atomic64_read(&adev->smu.throttle_int_counter)); | 226 | atomic64_read(&adev->smu.throttle_int_counter)); |
| 227 | 227 | ||
| @@ -26,7 +26,7 @@ · 25 unmodified lines | |||
| 26 | int kfd_smi_event_open(struct kfd_dev *dev, uint32_t *fd); | 26 | int kfd_smi_event_open(struct kfd_dev *dev, uint32_t *fd); |
| 27 | void kfd_smi_event_update_vmfault(struct kfd_dev *dev, uint16_t pasid); | 27 | void kfd_smi_event_update_vmfault(struct kfd_dev *dev, uint16_t pasid); |
| 28 | void kfd_smi_event_update_thermal_throttling(struct kfd_dev *dev, | 28 | void kfd_smi_event_update_thermal_throttling(struct kfd_dev *dev, |
| 29 | uint32_t throttle_bitmask); | 29 | uint64_t throttle_bitmask); |
| 30 | void kfd_smi_event_update_gpu_reset(struct kfd_dev *dev, bool post_reset); | 30 | void kfd_smi_event_update_gpu_reset(struct kfd_dev *dev, bool post_reset); |
| 31 | 31 | ||
| 32 | #endif | 32 | #endif |
| @@ -120,6 +120,7 @@ static void svm_range_remove_notifier(struct svm_range *prange) · 119 unmodified lines | |||
| 120 | 120 | ||
| 121 | static int | 121 | static int |
| 122 | svm_range_dma_map_dev(struct amdgpu_device *adev, struct svm_range *prange, | 122 | svm_range_dma_map_dev(struct amdgpu_device *adev, struct svm_range *prange, |
| 123 | unsigned long offset, unsigned long npages, | ||
| 123 | unsigned long *hmm_pfns, uint32_t gpuidx) | 124 | unsigned long *hmm_pfns, uint32_t gpuidx) |
| 124 | { | 125 | { |
| 125 | enum dma_data_direction dir = DMA_BIDIRECTIONAL; | 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 | prange->dma_addr[gpuidx] = addr; | 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 | if (WARN_ONCE(addr[i] && !dma_mapping_error(dev, addr[i]), | 142 | if (WARN_ONCE(addr[i] && !dma_mapping_error(dev, addr[i]), |
| 141 | "leaking dma mapping\n")) | 143 | "leaking dma mapping\n")) |
| 142 | dma_unmap_page(dev, addr[i], PAGE_SIZE, dir); | 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 | static int | 170 | static int |
| 169 | svm_range_dma_map(struct svm_range *prange, unsigned long *bitmap, | 171 | svm_range_dma_map(struct svm_range *prange, unsigned long *bitmap, |
| 172 | unsigned long offset, unsigned long npages, | ||
| 170 | unsigned long *hmm_pfns) | 173 | unsigned long *hmm_pfns) |
| 171 | { | 174 | { |
| 172 | struct kfd_process *p; | 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 | adev = (struct amdgpu_device *)pdd->dev->kgd; | 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 | if (r) | 195 | if (r) |
| 192 | break; | 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 | pte_flags |= snoop ? AMDGPU_PTE_SNOOPED : 0; | 1092 | pte_flags |= snoop ? AMDGPU_PTE_SNOOPED : 0; |
| 1089 | 1093 | ||
| 1090 | pte_flags |= amdgpu_gem_va_map_flags(adev, mapping_flags); | 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 | return pte_flags; | 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 | static int | 1156 | static int |
| 1158 | svm_range_map_to_gpu(struct amdgpu_device *adev, struct amdgpu_vm *vm, | 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 | struct amdgpu_device *bo_adev, struct dma_fence **fence) | 1160 | struct amdgpu_device *bo_adev, struct dma_fence **fence) |
| 1161 | { | 1161 | { |
| 1162 | struct amdgpu_bo_va bo_va; | 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 | int r = 0; | 1167 | int r = 0; |
| 1168 | int64_t i; | 1168 | int64_t i; |
| 1169 | 1169 | ||
| 1170 | pr_debug("svms 0x%p [0x%lx 0x%lx]\n", prange->svms, prange->start, | 1170 | last_start = prange->start + offset; |
| 1171 | prange->last); | 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 | if (prange->svm_bo && prange->ttm_res) | 1175 | if (prange->svm_bo && prange->ttm_res) |
| 1174 | bo_va.is_xgmi = amdgpu_xgmi_same_hive(adev, bo_adev); | 1176 | bo_va.is_xgmi = amdgpu_xgmi_same_hive(adev, bo_adev); |
| 1175 | 1177 | ||
| 1176 | last_start = prange->start; | 1178 | for (i = offset; i < offset + npages; i++) { |
| 1177 | for (i = 0; i < prange->npages; i++) { | ||
| 1178 | last_domain = dma_addr[i] & SVM_RANGE_VRAM_DOMAIN; | 1179 | last_domain = dma_addr[i] & SVM_RANGE_VRAM_DOMAIN; |
| 1179 | dma_addr[i] &= ~SVM_RANGE_VRAM_DOMAIN; | 1180 | dma_addr[i] &= ~SVM_RANGE_VRAM_DOMAIN; |
| 1180 | if ((prange->start + i) < prange->last && | 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 | pr_debug("Mapping range [0x%lx 0x%llx] on domain: %s\n", | 1185 | pr_debug("Mapping range [0x%lx 0x%llx] on domain: %s\n", |
| 1185 | last_start, prange->start + i, last_domain ? "GPU" : "CPU"); | 1186 | last_start, prange->start + i, last_domain ? "GPU" : "CPU"); |
| 1187 | |||
| 1186 | pte_flags = svm_range_get_pte_flags(adev, prange, last_domain); | 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, | 1189 | if (readonly) |
| 1188 | last_start, | 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 | prange->start + i, pte_flags, | 1199 | prange->start + i, pte_flags, |
| 1190 | last_start - prange->start, | 1200 | last_start - prange->start, |
| 1191 | NULL, | 1201 | NULL, dma_addr, |
| 1192 | dma_addr, | ||
| 1193 | &vm->last_update, | 1202 | &vm->last_update, |
| 1194 | &table_freed); | 1203 | &table_freed); |
| 1195 | if (r) { | 1204 | if (r) { |
| @@ -1220,8 +1229,10 @@ out: · 24 unmodified lines | |||
| 1220 | return r; | 1229 | return r; |
| 1221 | } | 1230 | } |
| 1222 | 1231 | ||
| 1223 | static int svm_range_map_to_gpus(struct svm_range *prange, | 1232 | static int |
| 1224 | unsigned long *bitmap, bool wait) | 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 | struct kfd_process_device *pdd; | 1237 | struct kfd_process_device *pdd; |
| 1227 | struct amdgpu_device *bo_adev; | 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 | r = svm_range_map_to_gpu(adev, drm_priv_to_vm(pdd->drm_priv), | 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 | bo_adev, wait ? &fence : NULL); | 1273 | bo_adev, wait ? &fence : NULL); |
| 1262 | if (r) | 1274 | if (r) |
| 1263 | break; | 1275 | break; |
| @@ -1390,7 +1402,7 @@ static int svm_range_validate_and_map(struct mm_struct *mm, · 126 unmodified lines | |||
| 1390 | int32_t gpuidx, bool intr, bool wait) | 1402 | int32_t gpuidx, bool intr, bool wait) |
| 1391 | { | 1403 | { |
| 1392 | struct svm_validate_context ctx; | 1404 | struct svm_validate_context ctx; |
| 1393 | struct hmm_range *hmm_range; | 1405 | unsigned long start, end, addr; |
| 1394 | struct kfd_process *p; | 1406 | struct kfd_process *p; |
| 1395 | void *owner; | 1407 | void *owner; |
| 1396 | int32_t idx; | 1408 | int32_t idx; |
| @@ -1448,40 +1460,66 @@ static int svm_range_validate_and_map(struct mm_struct *mm, · 51 unmodified lines | |||
| 1448 | break; | 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, | 1464 | start = prange->start << PAGE_SHIFT; |
| 1461 | hmm_range->hmm_pfns); | 1465 | end = (prange->last + 1) << PAGE_SHIFT; |
| 1462 | if (r) { | 1466 | for (addr = start; addr < end && !r; ) { |
| 1463 | pr_debug("failed %d to dma map range\n", r); | 1467 | struct hmm_range *hmm_range; |
| 1464 | goto unreserve_out; | 1468 | struct vm_area_struct *vma; |
| 1465 | } | 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); | 1481 | next = min(vma->vm_end, end); |
| 1470 | if (amdgpu_hmm_range_get_pages_done(hmm_range)) { | 1482 | npages = (next - addr) >> PAGE_SHIFT; |
| 1471 | pr_debug("hmm update the range, need validate again\n"); | 1483 | r = amdgpu_hmm_range_get_pages(&prange->notifier, mm, NULL, |
| 1472 | r = -EAGAIN; | 1484 | addr, npages, &hmm_range, |
| 1473 | goto unlock_out; | 1485 | readonly, true, owner); |
| 1474 | } | 1486 | if (r) { |
| 1475 | if (!list_empty(&prange->child_list)) { | 1487 | pr_debug("failed %d to get svm range pages\n", r); |
| 1476 | pr_debug("range split by unmap in parallel, validate again\n"); | 1488 | goto unreserve_out; |
| 1477 | r = -EAGAIN; | 1489 | } |
| 1478 | goto unlock_out; | ||
| 1479 | } | ||
| 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 | unlock_out: | 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 | unreserve_out: | 1523 | unreserve_out: |
| 1486 | svm_range_unreserve_bos(&ctx); | 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 | WRITE_ONCE(pdd->faults, pdd->faults + 1); | 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 | int | 2461 | int |
| 2404 | svm_range_restore_pages(struct amdgpu_device *adev, unsigned int pasid, | 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 | struct mm_struct *mm = NULL; | 2465 | struct mm_struct *mm = NULL; |
| 2408 | struct svm_range_list *svms; | 2466 | struct svm_range_list *svms; |
| @@ -2484,6 +2542,13 @@ retry_write_locked: · 75 unmodified lines | |||
| 2484 | goto out_unlock_range; | 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 | best_loc = svm_range_best_restore_location(prange, adev, &gpuidx); | 2552 | best_loc = svm_range_best_restore_location(prange, adev, &gpuidx); |
| 2488 | if (best_loc == -1) { | 2553 | if (best_loc == -1) { |
| 2489 | pr_debug("svms %p failed get best restore loc [0x%lx 0x%lx]\n", | 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 | return 0; | 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 | * @prange: svm range structure | 2745 | * @prange: svm range structure |
| 2680 | * | 2746 | * |
| 2681 | * For xnack off: | 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 | * can be CPU or GPU. | 2749 | * can be CPU or GPU. |
| 2684 | * | 2750 | * |
| 2685 | * If range map to multiple GPUs, only if mGPU connection on xgmi same hive, | 2751 | * If range is ACCESS or ACCESS_IN_PLACE by mGPUs, only if mGPU connection on |
| 2686 | * the best actual location could be prefetch_loc GPU. If mGPU connection on | 2752 | * XGMI same hive, the best prefetch location is prefetch_loc GPU, othervise |
| 2687 | * PCIe, the best actual location is always CPU, because GPU cannot access vram | 2753 | * the best prefetch location is always CPU, because GPU can not have coherent |
| 2688 | * of other GPUs, assuming PCIe small bar (large bar support is not upstream). | 2754 | * mapping VRAM of other GPUs even with large-BAR PCIe connection. |
| 2689 | * | 2755 | * |
| 2690 | * For xnack on: | 2756 | * For xnack on: |
| 2691 | * The best actual location is prefetch location. If mGPU connection on xgmi | 2757 | * If range is not ACCESS_IN_PLACE by mGPUs, the best prefetch location is |
| 2692 | * same hive, range map to multiple GPUs. Otherwise, the range only map to | 2758 | * prefetch_loc, other GPU access will generate vm fault and trigger migration. |
| 2693 | * actual location GPU. Other GPU access vm fault will 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 | * Context: Process context | 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 | p = container_of(prange->svms, struct kfd_process, svms); | 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 | if (!best_loc || best_loc == KFD_IOCTL_SVM_LOCATION_UNDEFINED) | 2782 | if (!best_loc || best_loc == KFD_IOCTL_SVM_LOCATION_UNDEFINED) |
| 2719 | goto out; | 2783 | goto out; |
| 2720 | 2784 | ||
| @@ -2724,8 +2788,12 @@ svm_range_best_prefetch_location(struct svm_range *prange) · 3 unmodified lines | |||
| 2724 | best_loc = 0; | 2788 | best_loc = 0; |
| 2725 | goto out; | 2789 | goto out; |
| 2726 | } | 2790 | } |
| 2727 | bitmap_or(bitmap, prange->bitmap_access, prange->bitmap_aip, | 2791 | |
| 2728 | MAX_GPU_INSTANCE); | 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 | for_each_set_bit(gpuidx, bitmap, MAX_GPU_INSTANCE) { | 2798 | for_each_set_bit(gpuidx, bitmap, MAX_GPU_INSTANCE) { |
| 2731 | pdd = kfd_process_device_from_gpuidx(p, gpuidx); | 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 | struct svm_range *prange; | 3087 | struct svm_range *prange; |
| 3020 | uint32_t prefetch_loc = KFD_IOCTL_SVM_LOCATION_UNDEFINED; | 3088 | uint32_t prefetch_loc = KFD_IOCTL_SVM_LOCATION_UNDEFINED; |
| 3021 | uint32_t location = KFD_IOCTL_SVM_LOCATION_UNDEFINED; | 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 | int gpuidx; | 3092 | int gpuidx; |
| 3024 | uint32_t i; | 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 | get_accessible = true; | 3123 | get_accessible = true; |
| 3055 | break; | 3124 | break; |
| 3056 | case KFD_IOCTL_SVM_ATTR_SET_FLAGS: | 3125 | case KFD_IOCTL_SVM_ATTR_SET_FLAGS: |
| 3126 | case KFD_IOCTL_SVM_ATTR_CLR_FLAGS: | ||
| 3057 | get_flags = true; | 3127 | get_flags = true; |
| 3058 | break; | 3128 | break; |
| 3059 | case KFD_IOCTL_SVM_ATTR_GRANULARITY: | 3129 | case KFD_IOCTL_SVM_ATTR_GRANULARITY: |
| 3060 | get_granularity = true; | 3130 | get_granularity = true; |
| 3061 | break; | 3131 | break; |
| 3062 | case KFD_IOCTL_SVM_ATTR_CLR_FLAGS: | ||
| 3063 | case KFD_IOCTL_SVM_ATTR_ACCESS_IN_PLACE: | 3132 | case KFD_IOCTL_SVM_ATTR_ACCESS_IN_PLACE: |
| 3064 | case KFD_IOCTL_SVM_ATTR_NO_ACCESS: | 3133 | case KFD_IOCTL_SVM_ATTR_NO_ACCESS: |
| 3065 | fallthrough; | 3134 | fallthrough; |
| @@ -3077,7 +3146,8 @@ svm_range_get_attr(struct kfd_process *p, uint64_t start, uint64_t size, · 11 unmodified lines | |||
| 3077 | if (!node) { | 3146 | if (!node) { |
| 3078 | pr_debug("range attrs not found return default values\n"); | 3147 | pr_debug("range attrs not found return default values\n"); |
| 3079 | svm_range_set_default_attributes(&location, &prefetch_loc, | 3148 | svm_range_set_default_attributes(&location, &prefetch_loc, |
| 3080 | &granularity, &flags); | 3149 | &granularity, &flags_and); |
| 3150 | flags_or = flags_and; | ||
| 3081 | if (p->xnack_enabled) | 3151 | if (p->xnack_enabled) |
| 3082 | bitmap_copy(bitmap_access, svms->bitmap_supported, | 3152 | bitmap_copy(bitmap_access, svms->bitmap_supported, |
| 3083 | MAX_GPU_INSTANCE); | 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 | bitmap_and(bitmap_aip, bitmap_aip, | 3193 | bitmap_and(bitmap_aip, bitmap_aip, |
| 3124 | prange->bitmap_aip, MAX_GPU_INSTANCE); | 3194 | prange->bitmap_aip, MAX_GPU_INSTANCE); |
| 3125 | } | 3195 | } |
| 3126 | if (get_flags) | 3196 | if (get_flags) { |
| 3127 | flags &= prange->flags; | 3197 | flags_and &= prange->flags; |
| 3198 | flags_or |= prange->flags; | ||
| 3199 | } | ||
| 3128 | 3200 | ||
| 3129 | if (get_granularity && prange->granularity < granularity) | 3201 | if (get_granularity && prange->granularity < granularity) |
| 3130 | granularity = prange->granularity; | 3202 | granularity = prange->granularity; |
| @@ -3158,7 +3230,10 @@ fill_values: · 27 unmodified lines | |||
| 3158 | attrs[i].type = KFD_IOCTL_SVM_ATTR_NO_ACCESS; | 3230 | attrs[i].type = KFD_IOCTL_SVM_ATTR_NO_ACCESS; |
| 3159 | break; | 3231 | break; |
| 3160 | case KFD_IOCTL_SVM_ATTR_SET_FLAGS: | 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 | break; | 3237 | break; |
| 3163 | case KFD_IOCTL_SVM_ATTR_GRANULARITY: | 3238 | case KFD_IOCTL_SVM_ATTR_GRANULARITY: |
| 3164 | attrs[i].value = (uint32_t)granularity; | 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 | unsigned long addr, struct svm_range *parent, | 175 | unsigned long addr, struct svm_range *parent, |
| 176 | struct svm_range *prange); | 176 | struct svm_range *prange); |
| 177 | int svm_range_restore_pages(struct amdgpu_device *adev, | 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 | int svm_range_schedule_evict_svm_bo(struct amdgpu_amdkfd_fence *fence); | 179 | int svm_range_schedule_evict_svm_bo(struct amdgpu_amdkfd_fence *fence); |
| 180 | void svm_range_add_list_work(struct svm_range_list *svms, | 180 | void svm_range_add_list_work(struct svm_range_list *svms, |
| 181 | struct svm_range *prange, struct mm_struct *mm, | 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 | static inline int svm_range_restore_pages(struct amdgpu_device *adev, | 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 | return -EFAULT; | 215 | return -EFAULT; |
| 215 | } | 216 | } |
| @@ -478,6 +478,8 @@ static ssize_t node_show(struct kobject *kobj, struct attribute *attr, · 477 unmodified lines | |||
| 478 | dev->node_props.simd_per_cu); | 478 | dev->node_props.simd_per_cu); |
| 479 | sysfs_show_32bit_prop(buffer, offs, "max_slots_scratch_cu", | 479 | sysfs_show_32bit_prop(buffer, offs, "max_slots_scratch_cu", |
| 480 | dev->node_props.max_slots_scratch_cu); | 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 | sysfs_show_32bit_prop(buffer, offs, "vendor_id", | 483 | sysfs_show_32bit_prop(buffer, offs, "vendor_id", |
| 482 | dev->node_props.vendor_id); | 484 | dev->node_props.vendor_id); |
| 483 | sysfs_show_32bit_prop(buffer, offs, "device_id", | 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 | dev->node_props.simd_arrays_per_engine = | 1362 | dev->node_props.simd_arrays_per_engine = |
| 1361 | cu_info.num_shader_arrays_per_engine; | 1363 | cu_info.num_shader_arrays_per_engine; |
| 1362 | 1364 | ||
| 1365 | dev->node_props.gfx_target_version = gpu->device_info->gfx_target_version; | ||
| 1363 | dev->node_props.vendor_id = gpu->pdev->vendor; | 1366 | dev->node_props.vendor_id = gpu->pdev->vendor; |
| 1364 | dev->node_props.device_id = gpu->pdev->device; | 1367 | dev->node_props.device_id = gpu->pdev->device; |
| 1365 | dev->node_props.capability |= | 1368 | dev->node_props.capability |= |
| @@ -1424,6 +1427,7 @@ int kfd_topology_add_device(struct kfd_dev *gpu) · 58 unmodified lines | |||
| 1424 | case CHIP_DIMGREY_CAVEFISH: | 1427 | case CHIP_DIMGREY_CAVEFISH: |
| 1425 | case CHIP_BEIGE_GOBY: | 1428 | case CHIP_BEIGE_GOBY: |
| 1426 | case CHIP_YELLOW_CARP: | 1429 | case CHIP_YELLOW_CARP: |
| 1430 | case CHIP_CYAN_SKILLFISH: | ||
| 1427 | dev->node_props.capability |= ((HSA_CAP_DOORBELL_TYPE_2_0 << | 1431 | dev->node_props.capability |= ((HSA_CAP_DOORBELL_TYPE_2_0 << |
| 1428 | HSA_CAP_DOORBELL_TYPE_TOTALBITS_SHIFT) & | 1432 | HSA_CAP_DOORBELL_TYPE_TOTALBITS_SHIFT) & |
| 1429 | HSA_CAP_DOORBELL_TYPE_TOTALBITS_MASK); | 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 | seq_printf(m, "Node %u, gpu_id %x:\n", i++, dev->gpu->id); | 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 | if (r) | 1638 | if (r) |
| 1635 | break; | 1639 | break; |
| 1636 | } | 1640 | } |
| @@ -78,6 +78,7 @@ struct kfd_node_properties { · 77 unmodified lines | |||
| 78 | uint32_t simd_per_cu; | 78 | uint32_t simd_per_cu; |
| 79 | uint32_t max_slots_scratch_cu; | 79 | uint32_t max_slots_scratch_cu; |
| 80 | uint32_t engine_id; | 80 | uint32_t engine_id; |
| 81 | uint32_t gfx_target_version; | ||
| 81 | uint32_t vendor_id; | 82 | uint32_t vendor_id; |
| 82 | uint32_t device_id; | 83 | uint32_t device_id; |
| 83 | uint32_t location_id; | 84 | uint32_t location_id; |
| @@ -27,6 +27,10 @@ · 26 unmodified lines | |||
| 27 | 27 | ||
| 28 | AMDGPUDM = amdgpu_dm.o amdgpu_dm_irq.o amdgpu_dm_mst_types.o amdgpu_dm_color.o | 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 | ifneq ($(CONFIG_DRM_AMD_DC),) | 34 | ifneq ($(CONFIG_DRM_AMD_DC),) |
| 31 | AMDGPUDM += amdgpu_dm_services.o amdgpu_dm_helpers.o amdgpu_dm_pp_smu.o amdgpu_dm_psr.o | 35 | AMDGPUDM += amdgpu_dm_services.o amdgpu_dm_helpers.o amdgpu_dm_pp_smu.o amdgpu_dm_psr.o |
| 32 | endif | 36 | endif |
| @@ -618,6 +618,7 @@ static void dm_dcn_vertical_interrupt0_high_irq(void *interrupt_params) · 617 unmodified lines | |||
| 618 | } | 618 | } |
| 619 | #endif | 619 | #endif |
| 620 | 620 | ||
| 621 | #define DMUB_TRACE_MAX_READ 64 | ||
| 621 | /** | 622 | /** |
| 622 | * dm_dmub_outbox1_low_irq() - Handles Outbox interrupt | 623 | * dm_dmub_outbox1_low_irq() - Handles Outbox interrupt |
| 623 | * @interrupt_params: used for determining the Outbox instance | 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 | * Handles the Outbox Interrupt | 626 | * Handles the Outbox Interrupt |
| 626 | * event handler. | 627 | * event handler. |
| 627 | */ | 628 | */ |
| 628 | #define DMUB_TRACE_MAX_READ 64 | ||
| 629 | static void dm_dmub_outbox1_low_irq(void *interrupt_params) | 629 | static void dm_dmub_outbox1_low_irq(void *interrupt_params) |
| 630 | { | 630 | { |
| 631 | struct dmub_notification notify; | 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 | #endif | 1045 | #endif |
| 1046 | #if defined(CONFIG_DRM_AMD_DC_DCN) | 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 | 1049 | struct vblank_control_work *vblank_work = | |
| 1050 | struct vblank_workqueue *vblank_work = container_of(work, struct vblank_workqueue, mall_work); | 1050 | container_of(work, struct vblank_control_work, work); |
| 1051 | struct amdgpu_display_manager *dm = vblank_work->dm; | 1051 | struct amdgpu_display_manager *dm = vblank_work->dm; |
| 1052 | 1052 | ||
| 1053 | mutex_lock(&dm->dc_lock); | 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 | DRM_DEBUG_KMS("Allow idle optimizations (MALL): %d\n", dm->active_vblank_irq_count == 0); | 1062 | DRM_DEBUG_KMS("Allow idle optimizations (MALL): %d\n", dm->active_vblank_irq_count == 0); |
| 1063 | 1063 | ||
| 1064 | mutex_unlock(&dm->dc_lock); | 1064 | /* Control PSR based on vblank requirements from OS */ |
| 1065 | } | 1065 | if (vblank_work->stream && vblank_work->stream->link) { |
| 1066 | 1066 | if (vblank_work->enable) { | |
| 1067 | static struct vblank_workqueue *vblank_create_workqueue(struct amdgpu_device *adev, struct dc *dc) | 1067 | if (vblank_work->stream->link->psr_settings.psr_allow_active) |
| 1068 | { | 1068 | amdgpu_dm_psr_disable(vblank_work->stream); |
| 1069 | 1069 | } else if (vblank_work->stream->link->psr_settings.psr_feature_enabled && | |
| 1070 | int max_caps = dc->caps.max_links; | 1070 | !vblank_work->stream->link->psr_settings.psr_allow_active && |
| 1071 | struct vblank_workqueue *vblank_work; | 1071 | vblank_work->acrtc->dm_irq_params.allow_psr_entry) { |
| 1072 | int i = 0; | 1072 | amdgpu_dm_psr_enable(vblank_work->stream); |
| 1073 | 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; | ||
| 1078 | } | 1074 | } |
| 1079 | 1075 | ||
| 1080 | for (i = 0; i < max_caps; i++) | 1076 | mutex_unlock(&dm->dc_lock); |
| 1081 | INIT_WORK(&vblank_work[i].mall_work, event_mall_stutter); | 1077 | |
| 1078 | dc_stream_release(vblank_work->stream); | ||
| 1082 | 1079 | ||
| 1083 | return vblank_work; | 1080 | kfree(vblank_work); |
| 1084 | } | 1081 | } |
| 1082 | |||
| 1085 | #endif | 1083 | #endif |
| 1086 | static int amdgpu_dm_init(struct amdgpu_device *adev) | 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 | #if defined(CONFIG_DRM_AMD_DC_DCN) | 1223 | #if defined(CONFIG_DRM_AMD_DC_DCN) |
| 1226 | if (adev->dm.dc->caps.max_links > 0) { | 1224 | if (adev->dm.dc->caps.max_links > 0) { |
| 1227 | adev->dm.vblank_workqueue = vblank_create_workqueue(adev, adev->dm.dc); | 1225 | adev->dm.vblank_control_workqueue = |
| 1228 | 1226 | create_singlethread_workqueue("dm_vblank_control_workqueue"); | |
| 1229 | if (!adev->dm.vblank_workqueue) | 1227 | if (!adev->dm.vblank_control_workqueue) |
| 1230 | DRM_ERROR("amdgpu: failed to initialize vblank_workqueue.\n"); | 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 | #endif | 1230 | #endif |
| 1235 | 1231 | ||
| @@ -1302,6 +1298,13 @@ static void amdgpu_dm_fini(struct amdgpu_device *adev) · 66 unmodified lines | |||
| 1302 | { | 1298 | { |
| 1303 | int i; | 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 | for (i = 0; i < adev->dm.display_indexes_num; i++) { | 1308 | for (i = 0; i < adev->dm.display_indexes_num; i++) { |
| 1306 | drm_encoder_cleanup(&adev->dm.mst_encoders[i].base); | 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 | dc_deinit_callbacks(adev->dm.dc); | 1328 | dc_deinit_callbacks(adev->dm.dc); |
| 1326 | #endif | 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 | dc_dmub_srv_destroy(&adev->dm.dc->ctx->dmub_srv); | 1331 | dc_dmub_srv_destroy(&adev->dm.dc->ctx->dmub_srv); |
| 1337 | 1332 | ||
| 1338 | if (dc_enable_dmub_notifications(adev->dm.dc)) { | 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 | static const u8 pre_computed_values[] = { | 2407 | static const u8 pre_computed_values[] = { |
| 2413 | 50, 51, 52, 53, 55, 56, 57, 58, 59, 61, 62, 63, 65, 66, 68, 69, | 2408 | 50, 51, 52, 53, 55, 56, 57, 58, 59, 61, 62, 63, 65, 66, 68, 69, |
| 2414 | 71, 72, 74, 75, 77, 79, 81, 82, 84, 86, 88, 90, 92, 94, 96, 98}; | 2409 | 71, 72, 74, 75, 77, 79, 81, 82, 84, 86, 88, 90, 92, 94, 96, 98}; |
| 2410 | int i; | ||
| 2415 | 2411 | ||
| 2416 | if (!aconnector || !aconnector->dc_link) | 2412 | if (!aconnector || !aconnector->dc_link) |
| 2417 | return; | 2413 | return; |
| @@ -2423,7 +2419,13 @@ static void update_connector_ext_caps(struct amdgpu_dm_connector *aconnector) · 5 unmodified lines | |||
| 2423 | conn_base = &aconnector->base; | 2419 | conn_base = &aconnector->base; |
| 2424 | adev = drm_to_adev(conn_base->dev); | 2420 | adev = drm_to_adev(conn_base->dev); |
| 2425 | dm = &adev->dm; | 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 | caps->ext_caps = &aconnector->dc_link->dpcd_sink_ext_caps; | 2429 | caps->ext_caps = &aconnector->dc_link->dpcd_sink_ext_caps; |
| 2428 | caps->aux_support = false; | 2430 | caps->aux_support = false; |
| 2429 | max_cll = conn_base->hdr_sink_metadata.hdmi_type1.max_cll; | 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 | #if defined(CONFIG_BACKLIGHT_CLASS_DEVICE) ||\ | 3425 | #if defined(CONFIG_BACKLIGHT_CLASS_DEVICE) ||\ |
| 3424 | defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE) | 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 | #if defined(CONFIG_ACPI) | 3431 | #if defined(CONFIG_ACPI) |
| 3429 | struct amdgpu_dm_backlight_caps caps; | 3432 | struct amdgpu_dm_backlight_caps caps; |
| 3430 | 3433 | ||
| 3431 | memset(&caps, 0, sizeof(caps)); | 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 | return; | 3437 | return; |
| 3435 | 3438 | ||
| 3436 | amdgpu_acpi_get_backlight_caps(&caps); | 3439 | amdgpu_acpi_get_backlight_caps(&caps); |
| 3437 | if (caps.caps_valid) { | 3440 | if (caps.caps_valid) { |
| 3438 | dm->backlight_caps.caps_valid = true; | 3441 | dm->backlight_caps[bl_idx].caps_valid = true; |
| 3439 | if (caps.aux_support) | 3442 | if (caps.aux_support) |
| 3440 | return; | 3443 | return; |
| 3441 | dm->backlight_caps.min_input_signal = caps.min_input_signal; | 3444 | dm->backlight_caps[bl_idx].min_input_signal = caps.min_input_signal; |
| 3442 | dm->backlight_caps.max_input_signal = caps.max_input_signal; | 3445 | dm->backlight_caps[bl_idx].max_input_signal = caps.max_input_signal; |
| 3443 | } else { | 3446 | } else { |
| 3444 | dm->backlight_caps.min_input_signal = | 3447 | dm->backlight_caps[bl_idx].min_input_signal = |
| 3445 | AMDGPU_DM_DEFAULT_MIN_BACKLIGHT; | 3448 | AMDGPU_DM_DEFAULT_MIN_BACKLIGHT; |
| 3446 | dm->backlight_caps.max_input_signal = | 3449 | dm->backlight_caps[bl_idx].max_input_signal = |
| 3447 | AMDGPU_DM_DEFAULT_MAX_BACKLIGHT; | 3450 | AMDGPU_DM_DEFAULT_MAX_BACKLIGHT; |
| 3448 | } | 3451 | } |
| 3449 | #else | 3452 | #else |
| 3450 | if (dm->backlight_caps.aux_support) | 3453 | if (dm->backlight_caps[bl_idx].aux_support) |
| 3451 | return; | 3454 | return; |
| 3452 | 3455 | ||
| 3453 | dm->backlight_caps.min_input_signal = AMDGPU_DM_DEFAULT_MIN_BACKLIGHT; | 3456 | dm->backlight_caps[bl_idx].min_input_signal = AMDGPU_DM_DEFAULT_MIN_BACKLIGHT; |
| 3454 | dm->backlight_caps.max_input_signal = AMDGPU_DM_DEFAULT_MAX_BACKLIGHT; | 3457 | dm->backlight_caps[bl_idx].max_input_signal = AMDGPU_DM_DEFAULT_MAX_BACKLIGHT; |
| 3455 | #endif | 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 | static int amdgpu_dm_backlight_set_level(struct amdgpu_display_manager *dm, | 3507 | static int amdgpu_dm_backlight_set_level(struct amdgpu_display_manager *dm, |
| 3508 | int bl_idx, | ||
| 3505 | u32 user_brightness) | 3509 | u32 user_brightness) |
| 3506 | { | 3510 | { |
| 3507 | struct amdgpu_dm_backlight_caps caps; | 3511 | struct amdgpu_dm_backlight_caps caps; |
| 3508 | struct dc_link *link[AMDGPU_DM_MAX_NUM_EDP]; | 3512 | struct dc_link *link; |
| 3509 | u32 brightness[AMDGPU_DM_MAX_NUM_EDP]; | 3513 | u32 brightness; |
| 3510 | bool rc; | 3514 | bool rc; |
| 3511 | int i; | ||
| 3512 | 3515 | ||
| 3513 | amdgpu_dm_update_backlight_caps(dm); | 3516 | amdgpu_dm_update_backlight_caps(dm, bl_idx); |
| 3514 | caps = dm->backlight_caps; | 3517 | caps = dm->backlight_caps[bl_idx]; |
| 3515 | 3518 | ||
| 3516 | for (i = 0; i < dm->num_of_edps; i++) { | 3519 | dm->brightness[bl_idx] = user_brightness; |
| 3517 | dm->brightness[i] = user_brightness; | 3520 | brightness = convert_brightness_from_user(&caps, dm->brightness[bl_idx]); |
| 3518 | brightness[i] = convert_brightness_from_user(&caps, dm->brightness[i]); | 3521 | link = (struct dc_link *)dm->backlight_link[bl_idx]; |
| 3519 | link[i] = (struct dc_link *)dm->backlight_link[i]; | ||
| 3520 | } | ||
| 3521 | 3522 | ||
| 3522 | /* Change brightness based on AUX property */ | 3523 | /* Change brightness based on AUX property */ |
| 3523 | if (caps.aux_support) { | 3524 | if (caps.aux_support) { |
| 3524 | for (i = 0; i < dm->num_of_edps; i++) { | 3525 | rc = dc_link_set_backlight_level_nits(link, true, brightness, |
| 3525 | rc = dc_link_set_backlight_level_nits(link[i], true, brightness[i], | 3526 | AUX_BL_DEFAULT_TRANSITION_TIME_MS); |
| 3526 | AUX_BL_DEFAULT_TRANSITION_TIME_MS); | 3527 | if (!rc) |
| 3527 | if (!rc) { | 3528 | DRM_DEBUG("DM: Failed to update backlight via AUX on eDP[%d]\n", bl_idx); |
| 3528 | DRM_DEBUG("DM: Failed to update backlight via AUX on eDP[%d]\n", i); | ||
| 3529 | break; | ||
| 3530 | } | ||
| 3531 | } | ||
| 3532 | } else { | 3529 | } else { |
| 3533 | for (i = 0; i < dm->num_of_edps; i++) { | 3530 | rc = dc_link_set_backlight_level(link, brightness, 0); |
| 3534 | rc = dc_link_set_backlight_level(dm->backlight_link[i], brightness[i], 0); | 3531 | if (!rc) |
| 3535 | if (!rc) { | 3532 | DRM_DEBUG("DM: Failed to update backlight on eDP[%d]\n", bl_idx); |
| 3536 | DRM_DEBUG("DM: Failed to update backlight on eDP[%d]\n", i); | ||
| 3537 | break; | ||
| 3538 | } | ||
| 3539 | } | ||
| 3540 | } | 3533 | } |
| 3541 | 3534 | ||
| 3542 | return rc ? 0 : 1; | 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 | static int amdgpu_dm_backlight_update_status(struct backlight_device *bd) | 3538 | static int amdgpu_dm_backlight_update_status(struct backlight_device *bd) |
| 3546 | { | 3539 | { |
| 3547 | struct amdgpu_display_manager *dm = bl_get_data(bd); | 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 | return 0; | 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 | struct amdgpu_dm_backlight_caps caps; | 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); | 3560 | amdgpu_dm_update_backlight_caps(dm, bl_idx); |
| 3559 | caps = dm->backlight_caps; | 3561 | caps = dm->backlight_caps[bl_idx]; |
| 3560 | 3562 | ||
| 3561 | if (caps.aux_support) { | 3563 | if (caps.aux_support) { |
| 3562 | struct dc_link *link = (struct dc_link *)dm->backlight_link[0]; | ||
| 3563 | u32 avg, peak; | 3564 | u32 avg, peak; |
| 3564 | bool rc; | 3565 | bool rc; |
| 3565 | 3566 | ||
| 3566 | rc = dc_link_get_backlight_level_nits(link, &avg, &peak); | 3567 | rc = dc_link_get_backlight_level_nits(link, &avg, &peak); |
| 3567 | if (!rc) | 3568 | if (!rc) |
| 3568 | return dm->brightness[0]; | 3569 | return dm->brightness[bl_idx]; |
| 3569 | return convert_brightness_to_user(&caps, avg); | 3570 | return convert_brightness_to_user(&caps, avg); |
| 3570 | } else { | 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 | if (ret == DC_ERROR_UNEXPECTED) | 3574 | if (ret == DC_ERROR_UNEXPECTED) |
| 3574 | return dm->brightness[0]; | 3575 | return dm->brightness[bl_idx]; |
| 3575 | return convert_brightness_to_user(&caps, ret); | 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 | static int amdgpu_dm_backlight_get_brightness(struct backlight_device *bd) | 3580 | static int amdgpu_dm_backlight_get_brightness(struct backlight_device *bd) |
| 3580 | { | 3581 | { |
| 3581 | struct amdgpu_display_manager *dm = bl_get_data(bd); | 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 | static const struct backlight_ops amdgpu_dm_backlight_ops = { | 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 | char bl_name[16]; | 3603 | char bl_name[16]; |
| 3596 | struct backlight_properties props = { 0 }; | 3604 | struct backlight_properties props = { 0 }; |
| 3597 | int i; | ||
| 3598 | 3605 | ||
| 3599 | amdgpu_dm_update_backlight_caps(dm); | 3606 | amdgpu_dm_update_backlight_caps(dm, dm->num_of_edps); |
| 3600 | for (i = 0; i < dm->num_of_edps; i++) | 3607 | dm->brightness[dm->num_of_edps] = AMDGPU_MAX_BL_LEVEL; |
| 3601 | dm->brightness[i] = AMDGPU_MAX_BL_LEVEL; | ||
| 3602 | 3608 | ||
| 3603 | props.max_brightness = AMDGPU_MAX_BL_LEVEL; | 3609 | props.max_brightness = AMDGPU_MAX_BL_LEVEL; |
| 3604 | props.brightness = AMDGPU_MAX_BL_LEVEL; | 3610 | props.brightness = AMDGPU_MAX_BL_LEVEL; |
| 3605 | props.type = BACKLIGHT_RAW; | 3611 | props.type = BACKLIGHT_RAW; |
| 3606 | 3612 | ||
| 3607 | snprintf(bl_name, sizeof(bl_name), "amdgpu_bl%d", | 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, | 3616 | dm->backlight_dev[dm->num_of_edps] = backlight_device_register(bl_name, |
| 3611 | adev_to_drm(dm->adev)->dev, | 3617 | adev_to_drm(dm->adev)->dev, |
| 3612 | dm, | 3618 | dm, |
| 3613 | &amdgpu_dm_backlight_ops, | 3619 | &amdgpu_dm_backlight_ops, |
| 3614 | &props); | 3620 | &props); |
| 3615 | 3621 | ||
| 3616 | if (IS_ERR(dm->backlight_dev)) | 3622 | if (IS_ERR(dm->backlight_dev[dm->num_of_edps])) |
| 3617 | DRM_ERROR("DM: Backlight registration failed!\n"); | 3623 | DRM_ERROR("DM: Backlight registration failed!\n"); |
| 3618 | else | 3624 | else |
| 3619 | DRM_DEBUG_DRIVER("DM: Registered Backlight device: %s\n", bl_name); | 3625 | DRM_DEBUG_DRIVER("DM: Registered Backlight device: %s\n", bl_name); |
| 3620 | } | 3626 | } |
| 3621 | |||
| 3622 | #endif | 3627 | #endif |
| 3623 | 3628 | ||
| 3624 | static int initialize_plane(struct amdgpu_display_manager *dm, | 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 | * DM initialization because not having a backlight control | 3680 | * DM initialization because not having a backlight control |
| 3676 | * is better then a black screen. | 3681 | * is better then a black screen. |
| 3677 | */ | 3682 | */ |
| 3678 | if (!dm->backlight_dev) | 3683 | if (!dm->backlight_dev[dm->num_of_edps]) |
| 3679 | amdgpu_dm_register_backlight_device(dm); | 3684 | amdgpu_dm_register_backlight_device(dm); |
| 3680 | 3685 | ||
| 3681 | if (dm->backlight_dev) { | 3686 | if (dm->backlight_dev[dm->num_of_edps]) { |
| 3682 | dm->backlight_link[dm->num_of_edps] = link; | 3687 | dm->backlight_link[dm->num_of_edps] = link; |
| 3683 | dm->num_of_edps++; | 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 | const bool force_disable_dcc) | 4752 | const bool force_disable_dcc) |
| 4748 | { | 4753 | { |
| 4749 | const uint64_t modifier = afb->base.modifier; | 4754 | const uint64_t modifier = afb->base.modifier; |
| 4750 | int ret; | 4755 | int ret = 0; |
| 4751 | 4756 | ||
| 4752 | fill_gfx9_tiling_info_from_modifier(adev, tiling_info, modifier); | 4757 | fill_gfx9_tiling_info_from_modifier(adev, tiling_info, modifier); |
| 4753 | tiling_info->gfx9.swizzle = modifier_gfx9_swizzle_mode(modifier); | 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 | ret = validate_dcc(adev, format, rotation, tiling_info, dcc, address, plane_size); | 4771 | ret = validate_dcc(adev, format, rotation, tiling_info, dcc, address, plane_size); |
| 4767 | if (ret) | 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 | static int | 4778 | static int |
| @@ -5994,7 +5999,7 @@ static inline int dm_set_vblank(struct drm_crtc *crtc, bool enable) · 1220 unmodified lines | |||
| 5994 | struct dm_crtc_state *acrtc_state = to_dm_crtc_state(crtc->state); | 5999 | struct dm_crtc_state *acrtc_state = to_dm_crtc_state(crtc->state); |
| 5995 | #if defined(CONFIG_DRM_AMD_DC_DCN) | 6000 | #if defined(CONFIG_DRM_AMD_DC_DCN) |
| 5996 | struct amdgpu_display_manager *dm = &adev->dm; | 6001 | struct amdgpu_display_manager *dm = &adev->dm; |
| 5997 | unsigned long flags; | 6002 | struct vblank_control_work *work; |
| 5998 | #endif | 6003 | #endif |
| 5999 | int rc = 0; | 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 | return 0; | 6024 | return 0; |
| 6020 | 6025 | ||
| 6021 | #if defined(CONFIG_DRM_AMD_DC_DCN) | 6026 | #if defined(CONFIG_DRM_AMD_DC_DCN) |
| 6022 | spin_lock_irqsave(&dm->vblank_lock, flags); | 6027 | work = kzalloc(sizeof(*work), GFP_ATOMIC); |
| 6023 | dm->vblank_workqueue->dm = dm; | 6028 | if (!work) |
| 6024 | dm->vblank_workqueue->otg_inst = acrtc->otg_inst; | 6029 | return -ENOMEM; |
| 6025 | dm->vblank_workqueue->enable = enable; | 6030 | |
| 6026 | spin_unlock_irqrestore(&dm->vblank_lock, flags); | 6031 | INIT_WORK(&work->work, vblank_control_worker); |
| 6027 | schedule_work(&dm->vblank_workqueue->mall_work); | 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 | #endif | 6042 | #endif |
| 6029 | 6043 | ||
| 6030 | return 0; | 6044 | return 0; |
| @@ -6198,6 +6212,7 @@ static void amdgpu_dm_connector_destroy(struct drm_connector *connector) · 167 unmodified lines | |||
| 6198 | const struct dc_link *link = aconnector->dc_link; | 6212 | const struct dc_link *link = aconnector->dc_link; |
| 6199 | struct amdgpu_device *adev = drm_to_adev(connector->dev); | 6213 | struct amdgpu_device *adev = drm_to_adev(connector->dev); |
| 6200 | struct amdgpu_display_manager *dm = &adev->dm; | 6214 | struct amdgpu_display_manager *dm = &adev->dm; |
| 6215 | int i; | ||
| 6201 | 6216 | ||
| 6202 | /* | 6217 | /* |
| 6203 | * Call only if mst_mgr was iniitalized before since it's not done | 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 | #if defined(CONFIG_BACKLIGHT_CLASS_DEVICE) ||\ | 6224 | #if defined(CONFIG_BACKLIGHT_CLASS_DEVICE) ||\ |
| 6210 | defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE) | 6225 | defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE) |
| 6211 | 6226 | for (i = 0; i < dm->num_of_edps; i++) { | |
| 6212 | if ((link->connector_signal & (SIGNAL_TYPE_EDP | SIGNAL_TYPE_LVDS)) && | 6227 | if ((link == dm->backlight_link[i]) && dm->backlight_dev[i]) { |
| 6213 | link->type != dc_connection_none && | 6228 | backlight_device_unregister(dm->backlight_dev[i]); |
| 6214 | dm->backlight_dev) { | 6229 | dm->backlight_dev[i] = NULL; |
| 6215 | backlight_device_unregister(dm->backlight_dev); | 6230 | } |
| 6216 | dm->backlight_dev = NULL; | ||
| 6217 | } | 6231 | } |
| 6218 | #endif | 6232 | #endif |
| 6219 | 6233 | ||
| @@ -7570,8 +7584,10 @@ static uint add_fs_modes(struct amdgpu_dm_connector *aconnector) · 1350 unmodified lines | |||
| 7570 | * 60 - Commonly used | 7584 | * 60 - Commonly used |
| 7571 | * 48,72,96 - Multiples of 24 | 7585 | * 48,72,96 - Multiples of 24 |
| 7572 | */ | 7586 | */ |
| 7573 | const uint32_t common_rates[] = { 23976, 24000, 25000, 29970, 30000, | 7587 | static const uint32_t common_rates[] = { |
| 7574 | 48000, 50000, 60000, 72000, 96000 }; | 7588 | 23976, 24000, 25000, 29970, 30000, |
| 7589 | 48000, 50000, 60000, 72000, 96000 | ||
| 7590 | }; | ||
| 7575 | 7591 | ||
| 7576 | /* | 7592 | /* |
| 7577 | * Find mode with highest refresh rate with the same resolution | 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 | /* Update the planes if changed or disable if we don't have any. */ | 8643 | /* Update the planes if changed or disable if we don't have any. */ |
| 8628 | if ((planes_count || acrtc_state->active_planes == 0) && | 8644 | if ((planes_count || acrtc_state->active_planes == 0) && |
| 8629 | acrtc_state->stream) { | 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 | bundle->stream_update.stream = acrtc_state->stream; | 8654 | bundle->stream_update.stream = acrtc_state->stream; |
| 8631 | if (new_pcrtc_state->mode_changed) { | 8655 | if (new_pcrtc_state->mode_changed) { |
| 8632 | bundle->stream_update.src = acrtc_state->stream->src; | 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 | acrtc_state->stream->link->psr_settings.psr_version != DC_PSR_VERSION_UNSUPPORTED && | 8719 | acrtc_state->stream->link->psr_settings.psr_version != DC_PSR_VERSION_UNSUPPORTED && |
| 8696 | !acrtc_state->stream->link->psr_settings.psr_feature_enabled) | 8720 | !acrtc_state->stream->link->psr_settings.psr_feature_enabled) |
| 8697 | amdgpu_dm_link_setup_psr(acrtc_state->stream); | 8721 | amdgpu_dm_link_setup_psr(acrtc_state->stream); |
| 8698 | else if ((acrtc_state->update_type == UPDATE_TYPE_FAST) && | 8722 | |
| 8699 | acrtc_state->stream->link->psr_settings.psr_feature_enabled && | 8723 | /* Decrement skip count when PSR is enabled and we're doing fast updates. */ |
| 8700 | !acrtc_state->stream->link->psr_settings.psr_allow_active) { | 8724 | if (acrtc_state->update_type == UPDATE_TYPE_FAST && |
| 8701 | struct amdgpu_dm_connector *aconn = (struct amdgpu_dm_connector *) | 8725 | acrtc_state->stream->link->psr_settings.psr_feature_enabled) { |
| 8702 | acrtc_state->stream->dm_stream_context; | 8726 | struct amdgpu_dm_connector *aconn = |
| 8727 | (struct amdgpu_dm_connector *)acrtc_state->stream->dm_stream_context; | ||
| 8703 | 8728 | ||
| 8704 | if (aconn->psr_skip_count > 0) | 8729 | if (aconn->psr_skip_count > 0) |
| 8705 | aconn->psr_skip_count--; | 8730 | aconn->psr_skip_count--; |
| 8706 | else | 8731 | |
| 8707 | amdgpu_dm_psr_enable(acrtc_state->stream); | 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 | mutex_unlock(&dm->dc_lock); | 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 | if (dc_state) { | 8982 | if (dc_state) { |
| 8955 | /* if there mode set or reset, disable eDP PSR */ | 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 | amdgpu_dm_psr_disable_all(dm); | 8988 | amdgpu_dm_psr_disable_all(dm); |
| 8989 | } | ||
| 8958 | 8990 | ||
| 8959 | dm_enable_per_frame_crtc_master_sync(dc_state); | 8991 | dm_enable_per_frame_crtc_master_sync(dc_state); |
| 8960 | mutex_lock(&dm->dc_lock); | 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 | #if defined(CONFIG_BACKLIGHT_CLASS_DEVICE) || \ | 9223 | #if defined(CONFIG_BACKLIGHT_CLASS_DEVICE) || \ |
| 9192 | defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE) | 9224 | defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE) |
| 9193 | /* restore the backlight level */ | 9225 | /* restore the backlight level */ |
| 9194 | if (dm->backlight_dev && (amdgpu_dm_backlight_get_level(dm) != dm->brightness[0])) | 9226 | for (i = 0; i < dm->num_of_edps; i++) { |
| 9195 | amdgpu_dm_backlight_set_level(dm, dm->brightness[0]); | 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 | #endif | 9231 | #endif |
| 9197 | /* | 9232 | /* |
| 9198 | * send vblank event on all events not handled in flip and | 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 | return capable; | 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 | uint8_t *edid_ext, int len, | 10650 | uint8_t *edid_ext, int len, |
| 10559 | struct amdgpu_hdmi_vsdb_info *vsdb_info) | 10651 | struct amdgpu_hdmi_vsdb_info *vsdb_info) |
| 10560 | { | 10652 | { |
| 10561 | int i; | 10653 | int i; |
| 10562 | struct amdgpu_device *adev = drm_to_adev(aconnector->base.dev); | ||
| 10563 | struct dc *dc = adev->dm.dc; | ||
| 10564 | 10654 | ||
| 10565 | /* send extension block to DMCU for parsing */ | 10655 | /* send extension block to DMCU for parsing */ |
| 10566 | for (i = 0; i < len; i += 8) { | 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 | int offset; | 10658 | int offset; |
| 10569 | 10659 | ||
| 10570 | /* send 8 bytes a time */ | 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 | return false; | 10662 | return false; |
| 10573 | 10663 | ||
| 10574 | if (i+8 == len) { | 10664 | if (i+8 == len) { |
| 10575 | /* EDID block sent completed, expect result */ | 10665 | /* EDID block sent completed, expect result */ |
| 10576 | int version, min_rate, max_rate; | 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 | if (res) { | 10669 | if (res) { |
| 10580 | /* amd vsdb found */ | 10670 | /* amd vsdb found */ |
| 10581 | vsdb_info->freesync_supported = 1; | 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 | /* check for ack*/ | 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 | if (!res) | 10683 | if (!res) |
| 10594 | return false; | 10684 | return false; |
| 10595 | } | 10685 | } |
| @@ -10597,6 +10687,34 @@ static bool parse_edid_cea(struct amdgpu_dm_connector *aconnector, · 1 unmodified line | |||
| 10597 | return false; | 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 | static int parse_hdmi_amd_vsdb(struct amdgpu_dm_connector *aconnector, | 10718 | static int parse_hdmi_amd_vsdb(struct amdgpu_dm_connector *aconnector, |
| 10601 | struct edid *edid, struct amdgpu_hdmi_vsdb_info *vsdb_info) | 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 | /* Forward declarations */ | 61 | /* Forward declarations */ |
| 62 | struct amdgpu_device; | 62 | struct amdgpu_device; |
| 63 | struct amdgpu_crtc; | ||
| 63 | struct drm_device; | 64 | struct drm_device; |
| 64 | struct dc; | 65 | struct dc; |
| 65 | struct amdgpu_bo; | 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 | * struct vblank_control_work - Work data for vblank control |
| 90 | * @mall_work: work for mall stutter | 91 | * @work: Kernel work data for the work event |
| 91 | * @dm: amdgpu display manager device | 92 | * @dm: amdgpu display manager device |
| 92 | * @otg_inst: otg instance of which vblank is being set | 93 | * @acrtc: amdgpu CRTC instance for which the event has occurred |
| 93 | * @enable: true if enable vblank | 94 | * @stream: DC stream for which the event has occurred |
| 95 | * @enable: true if enabling vblank | ||
| 94 | */ | 96 | */ |
| 95 | struct vblank_workqueue { | 97 | struct vblank_control_work { |
| 96 | struct work_struct mall_work; | 98 | struct work_struct work; |
| 97 | struct amdgpu_display_manager *dm; | 99 | struct amdgpu_display_manager *dm; |
| 98 | int otg_inst; | 100 | struct amdgpu_crtc *acrtc; |
| 101 | struct dc_stream_state *stream; | ||
| 99 | bool enable; | 102 | bool enable; |
| 100 | }; | 103 | }; |
| 101 | 104 | ||
| @@ -365,13 +368,13 @@ struct amdgpu_display_manager { · 263 unmodified lines | |||
| 365 | 368 | ||
| 366 | spinlock_t irq_handler_list_table_lock; | 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 | const struct dc_link *backlight_link[AMDGPU_DM_MAX_NUM_EDP]; | 373 | const struct dc_link *backlight_link[AMDGPU_DM_MAX_NUM_EDP]; |
| 371 | 374 | ||
| 372 | uint8_t num_of_edps; | 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 | struct mod_freesync *freesync_module; | 379 | struct mod_freesync *freesync_module; |
| 377 | #ifdef CONFIG_DRM_AMD_DC_HDCP | 380 | #ifdef CONFIG_DRM_AMD_DC_HDCP |
| @@ -380,11 +383,11 @@ struct amdgpu_display_manager { · 2 unmodified lines | |||
| 380 | 383 | ||
| 381 | #if defined(CONFIG_DRM_AMD_DC_DCN) | 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 | #endif | 391 | #endif |
| 389 | 392 | ||
| 390 | struct drm_atomic_state *cached_state; | 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 | rd_buf_ptr = rd_buf; | 198 | rd_buf_ptr = rd_buf; |
| 199 | 199 | ||
| 200 | str_len = strlen("Current: %d %d %d "); | 200 | str_len = strlen("Current: %d 0x%x %d "); |
| 201 | snprintf(rd_buf_ptr, str_len, "Current: %d %d %d ", | 201 | snprintf(rd_buf_ptr, str_len, "Current: %d 0x%x %d ", |
| 202 | link->cur_link_settings.lane_count, | 202 | link->cur_link_settings.lane_count, |
| 203 | link->cur_link_settings.link_rate, | 203 | link->cur_link_settings.link_rate, |
| 204 | link->cur_link_settings.link_spread); | 204 | link->cur_link_settings.link_spread); |
| 205 | rd_buf_ptr += str_len; | 205 | rd_buf_ptr += str_len; |
| 206 | 206 | ||
| 207 | str_len = strlen("Verified: %d %d %d "); | 207 | str_len = strlen("Verified: %d 0x%x %d "); |
| 208 | snprintf(rd_buf_ptr, str_len, "Verified: %d %d %d ", | 208 | snprintf(rd_buf_ptr, str_len, "Verified: %d 0x%x %d ", |
| 209 | link->verified_link_cap.lane_count, | 209 | link->verified_link_cap.lane_count, |
| 210 | link->verified_link_cap.link_rate, | 210 | link->verified_link_cap.link_rate, |
| 211 | link->verified_link_cap.link_spread); | 211 | link->verified_link_cap.link_spread); |
| 212 | rd_buf_ptr += str_len; | 212 | rd_buf_ptr += str_len; |
| 213 | 213 | ||
| 214 | str_len = strlen("Reported: %d %d %d "); | 214 | str_len = strlen("Reported: %d 0x%x %d "); |
| 215 | snprintf(rd_buf_ptr, str_len, "Reported: %d %d %d ", | 215 | snprintf(rd_buf_ptr, str_len, "Reported: %d 0x%x %d ", |
| 216 | link->reported_link_cap.lane_count, | 216 | link->reported_link_cap.lane_count, |
| 217 | link->reported_link_cap.link_rate, | 217 | link->reported_link_cap.link_rate, |
| 218 | link->reported_link_cap.link_spread); | 218 | link->reported_link_cap.link_spread); |
| 219 | rd_buf_ptr += str_len; | 219 | rd_buf_ptr += str_len; |
| 220 | 220 | ||
| 221 | str_len = strlen("Preferred: %d %d %d "); | 221 | str_len = strlen("Preferred: %d 0x%x %d "); |
| 222 | snprintf(rd_buf_ptr, str_len, "Preferred: %d %d %d\n", | 222 | snprintf(rd_buf_ptr, str_len, "Preferred: %d 0x%x %d\n", |
| 223 | link->preferred_link_setting.lane_count, | 223 | link->preferred_link_setting.lane_count, |
| 224 | link->preferred_link_setting.link_rate, | 224 | link->preferred_link_setting.link_rate, |
| 225 | link->preferred_link_setting.link_spread); | 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 | if (!rd_buf) | 377 | if (!rd_buf) |
| 378 | return -EINVAL; | 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 | link->cur_lane_setting.VOLTAGE_SWING, | 381 | link->cur_lane_setting.VOLTAGE_SWING, |
| 382 | link->cur_lane_setting.PRE_EMPHASIS, | 382 | link->cur_lane_setting.PRE_EMPHASIS, |
| 383 | link->cur_lane_setting.POST_CURSOR2); | 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 | struct ta_hdcp_shared_memory *hdcp_cmd; | 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 | DRM_WARN("Failed to get hdcp srm. HDCP TA is not initialized."); | 83 | DRM_WARN("Failed to get hdcp srm. HDCP TA is not initialized."); |
| 84 | return NULL; | 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 | memset(hdcp_cmd, 0, sizeof(struct ta_hdcp_shared_memory)); | 88 | memset(hdcp_cmd, 0, sizeof(struct ta_hdcp_shared_memory)); |
| 89 | 89 | ||
| 90 | hdcp_cmd->cmd_id = TA_HDCP_COMMAND__HDCP_GET_SRM; | 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 | struct ta_hdcp_shared_memory *hdcp_cmd; | 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 | DRM_WARN("Failed to get hdcp srm. HDCP TA is not initialized."); | 109 | DRM_WARN("Failed to get hdcp srm. HDCP TA is not initialized."); |
| 110 | return -EINVAL; | 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 | memset(hdcp_cmd, 0, sizeof(struct ta_hdcp_shared_memory)); | 114 | memset(hdcp_cmd, 0, sizeof(struct ta_hdcp_shared_memory)); |
| 115 | 115 | ||
| 116 | memcpy(hdcp_cmd->in_msg.hdcp_set_srm.srm_buf, srm, srm_size); | 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 | struct ta_dtm_shared_memory *dtm_cmd; | 414 | struct ta_dtm_shared_memory *dtm_cmd; |
| 415 | bool res = true; | 415 | bool res = true; |
| 416 | 416 | ||
| 417 | if (!psp->dtm_context.dtm_initialized) { | 417 | if (!psp->dtm_context.context.initialized) { |
| 418 | DRM_INFO("Failed to enable ASSR, DTM TA is not initialized."); | 418 | DRM_INFO("Failed to enable ASSR, DTM TA is not initialized."); |
| 419 | return false; | 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 | mutex_lock(&psp->dtm_context.mutex); | 424 | mutex_lock(&psp->dtm_context.mutex); |
| 425 | memset(dtm_cmd, 0, sizeof(struct ta_dtm_shared_memory)); | 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 | INIT_DELAYED_WORK(&hdcp_work[i].property_validate_dwork, event_property_validate); | 655 | INIT_DELAYED_WORK(&hdcp_work[i].property_validate_dwork, event_property_validate); |
| 656 | 656 | ||
| 657 | hdcp_work[i].hdcp.config.psp.handle = &adev->psp; | 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 | hdcp_work[i].hdcp.config.psp.caps.dtm_v3_supported = 1; | 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 | hdcp_work[i].hdcp.config.ddc.handle = dc_get_link_at_index(dc, i); | 660 | hdcp_work[i].hdcp.config.ddc.handle = dc_get_link_at_index(dc, i); |
| 663 | hdcp_work[i].hdcp.config.ddc.funcs.write_i2c = lp_write_i2c; | 661 | hdcp_work[i].hdcp.config.ddc.funcs.write_i2c = lp_write_i2c; |
| 664 | hdcp_work[i].hdcp.config.ddc.funcs.read_i2c = lp_read_i2c; | 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 | struct mod_vrr_params vrr_params; | 33 | struct mod_vrr_params vrr_params; |
| 34 | struct dc_stream_state *stream; | 34 | struct dc_stream_state *stream; |
| 35 | int active_planes; | 35 | int active_planes; |
| 36 | bool allow_psr_entry; | ||
| 36 | struct mod_freesync_config freesync_config; | 37 | struct mod_freesync_config freesync_config; |
| 37 | 38 | ||
| 38 | #ifdef CONFIG_DEBUG_FS | 39 | #ifdef CONFIG_DEBUG_FS |
| @@ -213,6 +213,29 @@ static int dm_dp_mst_get_modes(struct drm_connector *connector) · 212 unmodified lines | |||
| 213 | drm_connector_update_edid_property( | 213 | drm_connector_update_edid_property( |
| 214 | &aconnector->base, | 214 | &aconnector->base, |
| 215 | NULL); | 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 | return ret; | 239 | return ret; |
| 217 | } | 240 | } |
| 218 | 241 | ||
| @@ -637,6 +637,30 @@ TRACE_EVENT(amdgpu_refresh_rate_track, · 636 unmodified lines | |||
| 637 | __entry->refresh_rate_ns) | 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 | #endif /* _AMDGPU_DM_TRACE_H_ */ | 664 | #endif /* _AMDGPU_DM_TRACE_H_ */ |
| 641 | 665 | ||
| 642 | #undef TRACE_INCLUDE_PATH | 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 | if (pp_smu->set_hard_min_fclk_by_freq && | 264 | if (pp_smu->set_hard_min_fclk_by_freq && |
| 265 | pp_smu->set_hard_min_dcfclk_by_freq && | 265 | pp_smu->set_hard_min_dcfclk_by_freq && |
| 266 | pp_smu->set_min_deep_sleep_dcfclk) { | 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); | 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, new_clocks->dcfclk_khz / 1000); | 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, (new_clocks->dcfclk_deep_sleep_khz + 999) / 1000); | 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 | if (pp_smu->set_hard_min_fclk_by_freq && | 284 | if (pp_smu->set_hard_min_fclk_by_freq && |
| 285 | pp_smu->set_hard_min_dcfclk_by_freq && | 285 | pp_smu->set_hard_min_dcfclk_by_freq && |
| 286 | pp_smu->set_min_deep_sleep_dcfclk) { | 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); | 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, new_clocks->dcfclk_khz / 1000); | 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, (new_clocks->dcfclk_deep_sleep_khz + 999) / 1000); | 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 | actual_dispclk_set_mhz = rv1_vbios_smu_send_msg_with_param( | 130 | actual_dispclk_set_mhz = rv1_vbios_smu_send_msg_with_param( |
| 131 | clk_mgr, | 131 | clk_mgr, |
| 132 | VBIOSSMC_MSG_SetDispclkFreq, | 132 | VBIOSSMC_MSG_SetDispclkFreq, |
| 133 | requested_dispclk_khz / 1000); | 133 | khz_to_mhz_ceil(requested_dispclk_khz)); |
| 134 | 134 | ||
| 135 | if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) { | 135 | if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) { |
| 136 | if (dmcu && dmcu->funcs->is_dmcu_initialized(dmcu)) { | 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 | actual_dprefclk_set_mhz = rv1_vbios_smu_send_msg_with_param( | 150 | actual_dprefclk_set_mhz = rv1_vbios_smu_send_msg_with_param( |
| 151 | clk_mgr, | 151 | clk_mgr, |
| 152 | VBIOSSMC_MSG_SetDprefclkFreq, | 152 | VBIOSSMC_MSG_SetDprefclkFreq, |
| 153 | clk_mgr->base.dprefclk_khz / 1000); | 153 | khz_to_mhz_ceil(clk_mgr->base.dprefclk_khz)); |
| 154 | 154 | ||
| 155 | /* TODO: add code for programing DP DTO, currently this is down by command table */ | 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 | if (should_set_clock(safe_to_lower, new_clocks->dcfclk_khz, clk_mgr_base->clks.dcfclk_khz)) { | 253 | if (should_set_clock(safe_to_lower, new_clocks->dcfclk_khz, clk_mgr_base->clks.dcfclk_khz)) { |
| 254 | clk_mgr_base->clks.dcfclk_khz = new_clocks->dcfclk_khz; | 254 | clk_mgr_base->clks.dcfclk_khz = new_clocks->dcfclk_khz; |
| 255 | if (pp_smu && pp_smu->set_hard_min_dcfclk_by_freq) | 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 | if (should_set_clock(safe_to_lower, | 259 | if (should_set_clock(safe_to_lower, |
| 260 | new_clocks->dcfclk_deep_sleep_khz, clk_mgr_base->clks.dcfclk_deep_sleep_khz)) { | 260 | new_clocks->dcfclk_deep_sleep_khz, clk_mgr_base->clks.dcfclk_deep_sleep_khz)) { |
| 261 | clk_mgr_base->clks.dcfclk_deep_sleep_khz = new_clocks->dcfclk_deep_sleep_khz; | 261 | clk_mgr_base->clks.dcfclk_deep_sleep_khz = new_clocks->dcfclk_deep_sleep_khz; |
| 262 | if (pp_smu && pp_smu->set_min_deep_sleep_dcfclk) | 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 | if (should_set_clock(safe_to_lower, new_clocks->socclk_khz, clk_mgr_base->clks.socclk_khz)) { | 266 | if (should_set_clock(safe_to_lower, new_clocks->socclk_khz, clk_mgr_base->clks.socclk_khz)) { |
| 267 | clk_mgr_base->clks.socclk_khz = new_clocks->socclk_khz; | 267 | clk_mgr_base->clks.socclk_khz = new_clocks->socclk_khz; |
| 268 | if (pp_smu && pp_smu->set_hard_min_socclk_by_freq) | 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 | total_plane_count = clk_mgr_helper_get_active_plane_cnt(dc, context); | 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 | if (should_set_clock(safe_to_lower, new_clocks->dramclk_khz, clk_mgr_base->clks.dramclk_khz)) { | 281 | if (should_set_clock(safe_to_lower, new_clocks->dramclk_khz, clk_mgr_base->clks.dramclk_khz)) { |
| 282 | clk_mgr_base->clks.dramclk_khz = new_clocks->dramclk_khz; | 282 | clk_mgr_base->clks.dramclk_khz = new_clocks->dramclk_khz; |
| 283 | if (pp_smu && pp_smu->set_hard_min_uclk_by_freq) | 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 | if (should_set_clock(safe_to_lower, new_clocks->dppclk_khz, clk_mgr->base.clks.dppclk_khz)) { | 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 | clk_mgr_base->clks.disp_dpp_voltage_level_khz = new_clocks->disp_dpp_voltage_level_khz; | 307 | clk_mgr_base->clks.disp_dpp_voltage_level_khz = new_clocks->disp_dpp_voltage_level_khz; |
| 308 | if (pp_smu && pp_smu->set_voltage_by_freq) | 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 | if (dc->config.forced_clocks == false || (force_reset && safe_to_lower)) { | 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 | if (max_phyclk_req != clk_mgr_base->clks.phyclk_khz) { | 503 | if (max_phyclk_req != clk_mgr_base->clks.phyclk_khz) { |
| 504 | clk_mgr_base->clks.phyclk_khz = max_phyclk_req; | 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 | actual_dispclk_set_mhz = rn_vbios_smu_send_msg_with_param( | 126 | actual_dispclk_set_mhz = rn_vbios_smu_send_msg_with_param( |
| 127 | clk_mgr, | 127 | clk_mgr, |
| 128 | VBIOSSMC_MSG_SetDispclkFreq, | 128 | VBIOSSMC_MSG_SetDispclkFreq, |
| 129 | requested_dispclk_khz / 1000); | 129 | khz_to_mhz_ceil(requested_dispclk_khz)); |
| 130 | 130 | ||
| 131 | if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) { | 131 | if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) { |
| 132 | if (dmcu && dmcu->funcs->is_dmcu_initialized(dmcu)) { | 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 | // pmfw always set clock more than or equal requested clock | 139 | // pmfw always set clock more than or equal requested clock |
| 140 | if (!IS_DIAG_DC(dc->ctx->dce_environment)) | 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 | return actual_dispclk_set_mhz * 1000; | 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 | actual_dprefclk_set_mhz = rn_vbios_smu_send_msg_with_param( | 150 | actual_dprefclk_set_mhz = rn_vbios_smu_send_msg_with_param( |
| 151 | clk_mgr, | 151 | clk_mgr, |
| 152 | VBIOSSMC_MSG_SetDprefclkFreq, | 152 | VBIOSSMC_MSG_SetDprefclkFreq, |
| 153 | clk_mgr->base.dprefclk_khz / 1000); | 153 | khz_to_mhz_ceil(clk_mgr->base.dprefclk_khz)); |
| 154 | 154 | ||
| 155 | /* TODO: add code for programing DP DTO, currently this is down by command table */ | 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 | actual_dcfclk_set_mhz = rn_vbios_smu_send_msg_with_param( | 167 | actual_dcfclk_set_mhz = rn_vbios_smu_send_msg_with_param( |
| 168 | clk_mgr, | 168 | clk_mgr, |
| 169 | VBIOSSMC_MSG_SetHardMinDcfclkByFreq, | 169 | VBIOSSMC_MSG_SetHardMinDcfclkByFreq, |
| 170 | requested_dcfclk_khz / 1000); | 170 | khz_to_mhz_ceil(requested_dcfclk_khz)); |
| 171 | 171 | ||
| 172 | return actual_dcfclk_set_mhz * 1000; | 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 | actual_min_ds_dcfclk_mhz = rn_vbios_smu_send_msg_with_param( | 182 | actual_min_ds_dcfclk_mhz = rn_vbios_smu_send_msg_with_param( |
| 183 | clk_mgr, | 183 | clk_mgr, |
| 184 | VBIOSSMC_MSG_SetMinDeepSleepDcfclk, | 184 | VBIOSSMC_MSG_SetMinDeepSleepDcfclk, |
| 185 | requested_min_ds_dcfclk_khz / 1000); | 185 | khz_to_mhz_ceil(requested_min_ds_dcfclk_khz)); |
| 186 | 186 | ||
| 187 | return actual_min_ds_dcfclk_mhz * 1000; | 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 | rn_vbios_smu_send_msg_with_param( | 192 | rn_vbios_smu_send_msg_with_param( |
| 193 | clk_mgr, | 193 | clk_mgr, |
| 194 | VBIOSSMC_MSG_SetPhyclkVoltageByFreq, | 194 | VBIOSSMC_MSG_SetPhyclkVoltageByFreq, |
| 195 | requested_phyclk_khz / 1000); | 195 | khz_to_mhz_ceil(requested_phyclk_khz)); |
| 196 | } | 196 | } |
| 197 | 197 | ||
| 198 | int rn_vbios_smu_set_dppclk(struct clk_mgr_internal *clk_mgr, int requested_dpp_khz) | 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 | actual_dppclk_set_mhz = rn_vbios_smu_send_msg_with_param( | 203 | actual_dppclk_set_mhz = rn_vbios_smu_send_msg_with_param( |
| 204 | clk_mgr, | 204 | clk_mgr, |
| 205 | VBIOSSMC_MSG_SetDppclkFreq, | 205 | VBIOSSMC_MSG_SetDppclkFreq, |
| 206 | requested_dpp_khz / 1000); | 206 | khz_to_mhz_ceil(requested_dpp_khz)); |
| 207 | 207 | ||
| 208 | if (!IS_DIAG_DC(dc->ctx->dce_environment)) | 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 | return actual_dppclk_set_mhz * 1000; | 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 | if (should_set_clock(safe_to_lower, new_clocks->dcfclk_khz, clk_mgr_base->clks.dcfclk_khz)) { | 285 | if (should_set_clock(safe_to_lower, new_clocks->dcfclk_khz, clk_mgr_base->clks.dcfclk_khz)) { |
| 286 | clk_mgr_base->clks.dcfclk_khz = new_clocks->dcfclk_khz; | 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 | if (should_set_clock(safe_to_lower, new_clocks->dcfclk_deep_sleep_khz, clk_mgr_base->clks.dcfclk_deep_sleep_khz)) { | 290 | if (should_set_clock(safe_to_lower, new_clocks->dcfclk_deep_sleep_khz, clk_mgr_base->clks.dcfclk_deep_sleep_khz)) { |
| 291 | clk_mgr_base->clks.dcfclk_deep_sleep_khz = new_clocks->dcfclk_deep_sleep_khz; | 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 | if (should_set_clock(safe_to_lower, new_clocks->socclk_khz, clk_mgr_base->clks.socclk_khz)) | 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 | /* set UCLK to requested value if P-State switching is supported, or to re-enable P-State switching */ | 317 | /* set UCLK to requested value if P-State switching is supported, or to re-enable P-State switching */ |
| 318 | if (clk_mgr_base->clks.p_state_change_support && | 318 | if (clk_mgr_base->clks.p_state_change_support && |
| 319 | (update_uclk || !clk_mgr_base->clks.prev_p_state_change_support)) | 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 | if (should_set_clock(safe_to_lower, new_clocks->dppclk_khz, clk_mgr_base->clks.dppclk_khz)) { | 322 | if (should_set_clock(safe_to_lower, new_clocks->dppclk_khz, clk_mgr_base->clks.dppclk_khz)) { |
| 323 | if (clk_mgr_base->clks.dppclk_khz > new_clocks->dppclk_khz) | 323 | if (clk_mgr_base->clks.dppclk_khz > new_clocks->dppclk_khz) |
| 324 | dpp_clock_lowered = true; | 324 | dpp_clock_lowered = true; |
| 325 | 325 | ||
| 326 | clk_mgr_base->clks.dppclk_khz = new_clocks->dppclk_khz; | 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 | update_dppclk = true; | 328 | update_dppclk = true; |
| 329 | } | 329 | } |
| 330 | 330 | ||
| 331 | if (should_set_clock(safe_to_lower, new_clocks->dispclk_khz, clk_mgr_base->clks.dispclk_khz)) { | 331 | if (should_set_clock(safe_to_lower, new_clocks->dispclk_khz, clk_mgr_base->clks.dispclk_khz)) { |
| 332 | clk_mgr_base->clks.dispclk_khz = new_clocks->dispclk_khz; | 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 | update_dispclk = true; | 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 | if (!clk_mgr->smu_present) | 396 | if (!clk_mgr->smu_present) |
| 397 | return; | 397 | return; |
| 398 | 398 | ||
| 399 | if (current_mode) | 399 | if (current_mode) { |
| 400 | dcn30_smu_set_hard_min_by_freq(clk_mgr, PPCLK_UCLK, | 400 | if (clk_mgr_base->clks.p_state_change_support) |
| 401 | clk_mgr_base->clks.dramclk_khz / 1000); | 401 | dcn30_smu_set_hard_min_by_freq(clk_mgr, PPCLK_UCLK, |
| 402 | else | 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 | dcn30_smu_set_hard_min_by_freq(clk_mgr, PPCLK_UCLK, | 407 | dcn30_smu_set_hard_min_by_freq(clk_mgr, PPCLK_UCLK, |
| 404 | clk_mgr_base->bw_params->clk_table.entries[0].memclk_mhz); | 408 | clk_mgr_base->bw_params->clk_table.entries[0].memclk_mhz); |
| 409 | } | ||
| 405 | } | 410 | } |
| 406 | 411 | ||
| 407 | /* Set max memclk to highest DPM value */ | 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 | if (max_phyclk_req != clk_mgr_base->clks.phyclk_khz) { | 495 | if (max_phyclk_req != clk_mgr_base->clks.phyclk_khz) { |
| 491 | clk_mgr_base->clks.phyclk_khz = max_phyclk_req; | 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 | actual_dispclk_set_mhz = dcn301_smu_send_msg_with_param( | 133 | actual_dispclk_set_mhz = dcn301_smu_send_msg_with_param( |
| 134 | clk_mgr, | 134 | clk_mgr, |
| 135 | VBIOSSMC_MSG_SetDispclkFreq, | 135 | VBIOSSMC_MSG_SetDispclkFreq, |
| 136 | requested_dispclk_khz / 1000); | 136 | khz_to_mhz_ceil(requested_dispclk_khz)); |
| 137 | 137 | ||
| 138 | return actual_dispclk_set_mhz * 1000; | 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 | actual_dprefclk_set_mhz = dcn301_smu_send_msg_with_param( | 147 | actual_dprefclk_set_mhz = dcn301_smu_send_msg_with_param( |
| 148 | clk_mgr, | 148 | clk_mgr, |
| 149 | VBIOSSMC_MSG_SetDprefclkFreq, | 149 | VBIOSSMC_MSG_SetDprefclkFreq, |
| 150 | clk_mgr->base.dprefclk_khz / 1000); | 150 | khz_to_mhz_ceil(clk_mgr->base.dprefclk_khz)); |
| 151 | 151 | ||
| 152 | /* TODO: add code for programing DP DTO, currently this is down by command table */ | 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 | actual_dcfclk_set_mhz = dcn301_smu_send_msg_with_param( | 163 | actual_dcfclk_set_mhz = dcn301_smu_send_msg_with_param( |
| 164 | clk_mgr, | 164 | clk_mgr, |
| 165 | VBIOSSMC_MSG_SetHardMinDcfclkByFreq, | 165 | VBIOSSMC_MSG_SetHardMinDcfclkByFreq, |
| 166 | requested_dcfclk_khz / 1000); | 166 | khz_to_mhz_ceil(requested_dcfclk_khz)); |
| 167 | 167 | ||
| 168 | return actual_dcfclk_set_mhz * 1000; | 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 | actual_min_ds_dcfclk_mhz = dcn301_smu_send_msg_with_param( | 177 | actual_min_ds_dcfclk_mhz = dcn301_smu_send_msg_with_param( |
| 178 | clk_mgr, | 178 | clk_mgr, |
| 179 | VBIOSSMC_MSG_SetMinDeepSleepDcfclk, | 179 | VBIOSSMC_MSG_SetMinDeepSleepDcfclk, |
| 180 | requested_min_ds_dcfclk_khz / 1000); | 180 | khz_to_mhz_ceil(requested_min_ds_dcfclk_khz)); |
| 181 | 181 | ||
| 182 | return actual_min_ds_dcfclk_mhz * 1000; | 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 | actual_dppclk_set_mhz = dcn301_smu_send_msg_with_param( | 191 | actual_dppclk_set_mhz = dcn301_smu_send_msg_with_param( |
| 192 | clk_mgr, | 192 | clk_mgr, |
| 193 | VBIOSSMC_MSG_SetDppclkFreq, | 193 | VBIOSSMC_MSG_SetDppclkFreq, |
| 194 | requested_dpp_khz / 1000); | 194 | khz_to_mhz_ceil(requested_dpp_khz)); |
| 195 | 195 | ||
| 196 | return actual_dppclk_set_mhz * 1000; | 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 | display_count = vg_get_active_display_cnt_wa(dc, context); | 115 | display_count = vg_get_active_display_cnt_wa(dc, context); |
| 116 | /* if we can go lower, go lower */ | 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 | union display_idle_optimization_u idle_info = { 0 }; | 118 | union display_idle_optimization_u idle_info = { 0 }; |
| 119 | 119 | ||
| 120 | idle_info.idle_info.df_request_disabled = 1; | 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 | actual_dispclk_set_mhz = dcn31_smu_send_msg_with_param( | 147 | actual_dispclk_set_mhz = dcn31_smu_send_msg_with_param( |
| 148 | clk_mgr, | 148 | clk_mgr, |
| 149 | VBIOSSMC_MSG_SetDispclkFreq, | 149 | VBIOSSMC_MSG_SetDispclkFreq, |
| 150 | (requested_dispclk_khz + 999) / 1000); | 150 | khz_to_mhz_ceil(requested_dispclk_khz)); |
| 151 | 151 | ||
| 152 | return actual_dispclk_set_mhz * 1000; | 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 | actual_dprefclk_set_mhz = dcn31_smu_send_msg_with_param( | 162 | actual_dprefclk_set_mhz = dcn31_smu_send_msg_with_param( |
| 163 | clk_mgr, | 163 | clk_mgr, |
| 164 | VBIOSSMC_MSG_SetDprefclkFreq, | 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 | /* TODO: add code for programing DP DTO, currently this is down by command table */ | 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 | actual_dcfclk_set_mhz = dcn31_smu_send_msg_with_param( | 182 | actual_dcfclk_set_mhz = dcn31_smu_send_msg_with_param( |
| 183 | clk_mgr, | 183 | clk_mgr, |
| 184 | VBIOSSMC_MSG_SetHardMinDcfclkByFreq, | 184 | VBIOSSMC_MSG_SetHardMinDcfclkByFreq, |
| 185 | (requested_dcfclk_khz + 999) / 1000); | 185 | khz_to_mhz_ceil(requested_dcfclk_khz)); |
| 186 | 186 | ||
| 187 | return actual_dcfclk_set_mhz * 1000; | 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 | actual_min_ds_dcfclk_mhz = dcn31_smu_send_msg_with_param( | 200 | actual_min_ds_dcfclk_mhz = dcn31_smu_send_msg_with_param( |
| 201 | clk_mgr, | 201 | clk_mgr, |
| 202 | VBIOSSMC_MSG_SetMinDeepSleepDcfclk, | 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 | return actual_min_ds_dcfclk_mhz * 1000; | 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 | actual_dppclk_set_mhz = dcn31_smu_send_msg_with_param( | 215 | actual_dppclk_set_mhz = dcn31_smu_send_msg_with_param( |
| 216 | clk_mgr, | 216 | clk_mgr, |
| 217 | VBIOSSMC_MSG_SetDppclkFreq, | 217 | VBIOSSMC_MSG_SetDppclkFreq, |
| 218 | (requested_dpp_khz + 999) / 1000); | 218 | khz_to_mhz_ceil(requested_dpp_khz)); |
| 219 | 219 | ||
| 220 | return actual_dppclk_set_mhz * 1000; | 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 | return true; | 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 | void dc_enable_stereo( | 1500 | void dc_enable_stereo( |
| 1485 | struct dc *dc, | 1501 | struct dc *dc, |
| 1486 | struct dc_state *context, | 1502 | struct dc_state *context, |
| @@ -1491,12 +1507,15 @@ void dc_enable_stereo( · 4 unmodified lines | |||
| 1491 | struct pipe_ctx *pipe; | 1507 | struct pipe_ctx *pipe; |
| 1492 | 1508 | ||
| 1493 | for (i = 0; i < MAX_PIPES; i++) { | 1509 | for (i = 0; i < MAX_PIPES; i++) { |
| 1494 | if (context != NULL) | 1510 | if (context != NULL) { |
| 1495 | pipe = &context->res_ctx.pipe_ctx[i]; | 1511 | pipe = &context->res_ctx.pipe_ctx[i]; |
| 1496 | else | 1512 | } else { |
| 1513 | context = dc->current_state; | ||
| 1497 | pipe = &dc->current_state->res_ctx.pipe_ctx[i]; | 1514 | pipe = &dc->current_state->res_ctx.pipe_ctx[i]; |
| 1498 | for (j = 0 ; pipe && j < stream_count; j++) { | 1515 | } |
| 1499 | if (streams[j] && streams[j] == pipe->stream && | 1516 | |
| 1517 | for (j = 0; pipe && j < stream_count; j++) { | ||
| 1518 | if (should_update_pipe_for_stream(context, pipe, streams[j]) && | ||
| 1500 | dc->hwss.setup_stereo) | 1519 | dc->hwss.setup_stereo) |
| 1501 | dc->hwss.setup_stereo(pipe, dc); | 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 | int i, j; | 2649 | int i, j; |
| 2631 | struct pipe_ctx *top_pipe_to_program = NULL; | 2650 | struct pipe_ctx *top_pipe_to_program = NULL; |
| 2651 | bool should_lock_all_pipes = (update_type != UPDATE_TYPE_FAST); | ||
| 2632 | 2652 | ||
| 2633 | #if defined(CONFIG_DRM_AMD_DC_DCN) | 2653 | #if defined(CONFIG_DRM_AMD_DC_DCN) |
| 2634 | dc_z10_restore(dc); | 2654 | dc_z10_restore(dc); |
| @@ -2700,7 +2720,7 @@ static void commit_planes_for_stream(struct dc *dc, · 65 unmodified lines | |||
| 2700 | top_pipe_to_program->stream_res.tg); | 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 | dc->hwss.interdependent_update_lock(dc, context, true); | 2724 | dc->hwss.interdependent_update_lock(dc, context, true); |
| 2705 | else | 2725 | else |
| 2706 | /* Lock the top pipe while updating plane addrs, since freesync requires | 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 | if (dc->hwss.program_front_end_for_ctx) | 2743 | if (dc->hwss.program_front_end_for_ctx) |
| 2724 | dc->hwss.program_front_end_for_ctx(dc, context); | 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 | dc->hwss.interdependent_update_lock(dc, context, false); | 2747 | dc->hwss.interdependent_update_lock(dc, context, false); |
| 2728 | else | 2748 | else |
| 2729 | dc->hwss.pipe_control_lock(dc, top_pipe_to_program, false); | 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 | struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; | 2759 | struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; |
| 2740 | if (!pipe_ctx->plane_state) | 2760 | if (!pipe_ctx->plane_state) |
| 2741 | continue; | 2761 | continue; |
| 2742 | if (pipe_ctx->plane_state != plane_state) | 2762 | if (should_update_pipe_for_plane(context, pipe_ctx, plane_state)) |
| 2743 | continue; | 2763 | continue; |
| 2744 | plane_state->triplebuffer_flips = false; | 2764 | pipe_ctx->plane_state->triplebuffer_flips = false; |
| 2745 | if (update_type == UPDATE_TYPE_FAST && | 2765 | if (update_type == UPDATE_TYPE_FAST && |
| 2746 | dc->hwss.program_triplebuffer != NULL && | 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 | /*triple buffer for VUpdate only*/ | 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 | if (update_type == UPDATE_TYPE_FULL) { | 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 | if (!pipe_ctx->top_pipe && | 2783 | if (!pipe_ctx->top_pipe && |
| 2764 | !pipe_ctx->prev_odm_pipe && | 2784 | !pipe_ctx->prev_odm_pipe && |
| 2765 | pipe_ctx->stream && | 2785 | should_update_pipe_for_stream(context, pipe_ctx, stream)) { |
| 2766 | pipe_ctx->stream == stream) { | ||
| 2767 | struct dc_stream_status *stream_status = NULL; | 2786 | struct dc_stream_status *stream_status = NULL; |
| 2768 | 2787 | ||
| 2769 | if (!pipe_ctx->plane_state) | 2788 | if (!pipe_ctx->plane_state) |
| @@ -2816,15 +2835,15 @@ static void commit_planes_for_stream(struct dc *dc, · 46 unmodified lines | |||
| 2816 | for (j = 0; j < dc->res_pool->pipe_count; j++) { | 2835 | for (j = 0; j < dc->res_pool->pipe_count; j++) { |
| 2817 | struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; | 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 | continue; | 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 | continue; | 2842 | continue; |
| 2824 | 2843 | ||
| 2825 | // GSL has to be used for flip immediate | 2844 | // GSL has to be used for flip immediate |
| 2826 | dc->hwss.set_flip_control_gsl(pipe_ctx, | 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 | for (j = 0; j < dc->res_pool->pipe_count; j++) { | 2854 | for (j = 0; j < dc->res_pool->pipe_count; j++) { |
| 2836 | struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; | 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 | continue; | 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 | continue; | 2861 | continue; |
| 2862 | |||
| 2843 | /*program triple buffer after lock based on flip type*/ | 2863 | /*program triple buffer after lock based on flip type*/ |
| 2844 | if (dc->hwss.program_triplebuffer != NULL && dc->debug.enable_tri_buf) { | 2864 | if (dc->hwss.program_triplebuffer != NULL && dc->debug.enable_tri_buf) { |
| 2845 | /*only enable triplebuffer for fast_update*/ | 2865 | /*only enable triplebuffer for fast_update*/ |
| 2846 | dc->hwss.program_triplebuffer( | 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 | dc->hwss.update_plane_addr(dc, pipe_ctx); | 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 | dc->hwss.interdependent_update_lock(dc, context, false); | 2877 | dc->hwss.interdependent_update_lock(dc, context, false); |
| 2858 | else | 2878 | else |
| 2859 | dc->hwss.pipe_control_lock(dc, top_pipe_to_program, false); | 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 | continue; | 2917 | continue; |
| 2898 | 2918 | ||
| 2899 | if (pipe_ctx->bottom_pipe || pipe_ctx->next_odm_pipe || | 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 | !pipe_ctx->plane_state->update_flags.bits.addr_update || | 2921 | !pipe_ctx->plane_state->update_flags.bits.addr_update || |
| 2902 | pipe_ctx->plane_state->skip_manual_trigger) | 2922 | pipe_ctx->plane_state->skip_manual_trigger) |
| 2903 | continue; | 2923 | continue; |
| @@ -541,6 +541,7 @@ static void link_disconnect_sink(struct dc_link *link) · 540 unmodified lines | |||
| 541 | } | 541 | } |
| 542 | 542 | ||
| 543 | link->dpcd_sink_count = 0; | 543 | link->dpcd_sink_count = 0; |
| 544 | //link->dpcd_caps.dpcd_rev.raw = 0; | ||
| 544 | } | 545 | } |
| 545 | 546 | ||
| 546 | static void link_disconnect_remap(struct dc_sink *prev_sink, struct dc_link *link) | 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 | sink_caps, | 743 | sink_caps, |
| 743 | audio_support); | 744 | audio_support); |
| 744 | link->dpcd_caps.dongle_type = sink_caps->dongle_type; | 745 | link->dpcd_caps.dongle_type = sink_caps->dongle_type; |
| 746 | link->dpcd_caps.dpcd_rev.raw = 0; | ||
| 745 | } | 747 | } |
| 746 | 748 | ||
| 747 | return true; | 749 | return true; |
| @@ -1663,6 +1665,12 @@ struct dc_link *link_create(const struct link_init_data *init_params) · 915 unmodified lines | |||
| 1663 | if (false == dc_link_construct(link, init_params)) | 1665 | if (false == dc_link_construct(link, init_params)) |
| 1664 | goto construct_fail; | 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 | return link; | 1674 | return link; |
| 1667 | 1675 | ||
| 1668 | construct_fail: | 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 | void dc_link_set_drive_settings(struct dc *dc, | 3520 | void dc_link_set_drive_settings(struct dc *dc, |
| 3568 | struct link_training_settings *lt_settings, | 3521 | struct link_training_settings *lt_settings, |
| 3569 | const struct dc_link *link) | 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 | return ret; | 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 | static inline void decide_8b_10b_training_settings( | 1241 | static inline void decide_8b_10b_training_settings( |
| 1242 | struct dc_link *link, | 1242 | struct dc_link *link, |
| 1243 | const struct dc_link_settings *link_setting, | 1243 | const struct dc_link_settings *link_setting, |
| 1244 | const struct dc_link_training_overrides *overrides, | ||
| 1245 | struct link_training_settings *lt_settings) | 1244 | struct link_training_settings *lt_settings) |
| 1246 | { | 1245 | { |
| 1247 | uint32_t lane; | ||
| 1248 | |||
| 1249 | memset(lt_settings, '\0', sizeof(struct link_training_settings)); | 1246 | memset(lt_settings, '\0', sizeof(struct link_training_settings)); |
| 1250 | 1247 | ||
| 1251 | /* Initialize link settings */ | 1248 | /* Initialize link settings */ |
| 1252 | lt_settings->link_settings.use_link_rate_set = link_setting->use_link_rate_set; | 1249 | lt_settings->link_settings.use_link_rate_set = link_setting->use_link_rate_set; |
| 1253 | lt_settings->link_settings.link_rate_set = link_setting->link_rate_set; | 1250 | lt_settings->link_settings.link_rate_set = link_setting->link_rate_set; |
| 1254 | 1251 | lt_settings->link_settings.link_rate = link_setting->link_rate; | |
| 1255 | if (link->preferred_link_setting.link_rate != LINK_RATE_UNKNOWN) | 1252 | lt_settings->link_settings.lane_count = link_setting->lane_count; |
| 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 | |||
| 1267 | /* TODO hard coded to SS for now | 1253 | /* TODO hard coded to SS for now |
| 1268 | * lt_settings.link_settings.link_spread = | 1254 | * lt_settings.link_settings.link_spread = |
| 1269 | * dal_display_path_is_ss_supported( | 1255 | * dal_display_path_is_ss_supported( |
| @@ -1271,30 +1257,52 @@ static inline void decide_8b_10b_training_settings( · 1 unmodified line | |||
| 1271 | * LINK_SPREAD_05_DOWNSPREAD_30KHZ : | 1257 | * LINK_SPREAD_05_DOWNSPREAD_30KHZ : |
| 1272 | * LINK_SPREAD_DISABLED; | 1258 | * LINK_SPREAD_DISABLED; |
| 1273 | */ | 1259 | */ |
| 1274 | /* Initialize link spread */ | 1260 | lt_settings->link_settings.link_spread = link->dp_ss_off ? |
| 1275 | if (link->dp_ss_off) | 1261 | LINK_SPREAD_DISABLED : LINK_SPREAD_05_DOWNSPREAD_30KHZ; |
| 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 | |||
| 1285 | lt_settings->lttpr_mode = link->lttpr_mode; | 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 | if (overrides->voltage_swing != NULL) | 1300 | if (overrides->voltage_swing != NULL) |
| 1289 | lt_settings->voltage_swing = overrides->voltage_swing; | 1301 | lt_settings->voltage_swing = overrides->voltage_swing; |
| 1290 | |||
| 1291 | if (overrides->pre_emphasis != NULL) | 1302 | if (overrides->pre_emphasis != NULL) |
| 1292 | lt_settings->pre_emphasis = overrides->pre_emphasis; | 1303 | lt_settings->pre_emphasis = overrides->pre_emphasis; |
| 1293 | |||
| 1294 | if (overrides->post_cursor2 != NULL) | 1304 | if (overrides->post_cursor2 != NULL) |
| 1295 | lt_settings->post_cursor2 = overrides->post_cursor2; | 1305 | lt_settings->post_cursor2 = overrides->post_cursor2; |
| 1296 | |||
| 1297 | /* Initialize lane settings (VS/PE/PC2) */ | ||
| 1298 | for (lane = 0; lane < LANE_COUNT_DP_MAX; lane++) { | 1306 | for (lane = 0; lane < LANE_COUNT_DP_MAX; lane++) { |
| 1299 | lt_settings->lane_settings[lane].VOLTAGE_SWING = | 1307 | lt_settings->lane_settings[lane].VOLTAGE_SWING = |
| 1300 | lt_settings->voltage_swing != NULL ? | 1308 | lt_settings->voltage_swing != NULL ? |
| @@ -1313,45 +1321,22 @@ static inline void decide_8b_10b_training_settings( · 12 unmodified lines | |||
| 1313 | /* Initialize training timings */ | 1321 | /* Initialize training timings */ |
| 1314 | if (overrides->cr_pattern_time != NULL) | 1322 | if (overrides->cr_pattern_time != NULL) |
| 1315 | lt_settings->cr_pattern_time = *overrides->cr_pattern_time; | 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 | if (overrides->eq_pattern_time != NULL) | 1325 | if (overrides->eq_pattern_time != NULL) |
| 1320 | lt_settings->eq_pattern_time = *overrides->eq_pattern_time; | 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 | if (overrides->pattern_for_cr != NULL) | 1328 | if (overrides->pattern_for_cr != NULL) |
| 1325 | lt_settings->pattern_for_cr = *overrides->pattern_for_cr; | 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 | if (overrides->pattern_for_eq != NULL) | 1330 | if (overrides->pattern_for_eq != NULL) |
| 1329 | lt_settings->pattern_for_eq = *overrides->pattern_for_eq; | 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 | if (overrides->enhanced_framing != NULL) | 1333 | if (overrides->enhanced_framing != NULL) |
| 1334 | lt_settings->enhanced_framing = *overrides->enhanced_framing; | 1334 | lt_settings->enhanced_framing = *overrides->enhanced_framing; |
| 1335 | else | ||
| 1336 | lt_settings->enhanced_framing = 1; | ||
| 1337 | 1335 | ||
| 1338 | if (link->preferred_training_settings.fec_enable != NULL) | 1336 | if (link->preferred_training_settings.fec_enable != NULL) |
| 1339 | lt_settings->should_set_fec_ready = *link->preferred_training_settings.fec_enable; | 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 | uint8_t dp_convert_to_count(uint8_t lttpr_repeater_count) | 1340 | uint8_t dp_convert_to_count(uint8_t lttpr_repeater_count) |
| 1356 | { | 1341 | { |
| 1357 | switch (lttpr_repeater_count) { | 1342 | switch (lttpr_repeater_count) { |
| @@ -1581,6 +1566,9 @@ bool dc_link_dp_perform_link_training_skip_aux( · 223 unmodified lines | |||
| 1581 | dp_decide_training_settings( | 1566 | dp_decide_training_settings( |
| 1582 | link, | 1567 | link, |
| 1583 | link_setting, | 1568 | link_setting, |
| 1569 | <_settings); | ||
| 1570 | override_training_settings( | ||
| 1571 | link, | ||
| 1584 | &link->preferred_training_settings, | 1572 | &link->preferred_training_settings, |
| 1585 | <_settings); | 1573 | <_settings); |
| 1586 | 1574 | ||
| @@ -1727,6 +1715,9 @@ enum link_training_result dc_link_dp_perform_link_training( · 140 unmodified lines | |||
| 1727 | dp_decide_training_settings( | 1715 | dp_decide_training_settings( |
| 1728 | link, | 1716 | link, |
| 1729 | link_settings, | 1717 | link_settings, |
| 1718 | <_settings); | ||
| 1719 | override_training_settings( | ||
| 1720 | link, | ||
| 1730 | &link->preferred_training_settings, | 1721 | &link->preferred_training_settings, |
| 1731 | <_settings); | 1722 | <_settings); |
| 1732 | 1723 | ||
| @@ -1939,11 +1930,13 @@ enum link_training_result dc_link_dp_sync_lt_attempt( · 206 unmodified lines | |||
| 1939 | bool fec_enable = false; | 1930 | bool fec_enable = false; |
| 1940 | 1931 | ||
| 1941 | dp_decide_training_settings( | 1932 | dp_decide_training_settings( |
| 1942 | link, | 1933 | link, |
| 1943 | link_settings, | 1934 | link_settings, |
| 1944 | lt_overrides, | 1935 | <_settings); |
| 1945 | <_settings); | 1936 | override_training_settings( |
| 1946 | 1937 | link, | |
| 1938 | lt_overrides, | ||
| 1939 | <_settings); | ||
| 1947 | /* Setup MST Mode */ | 1940 | /* Setup MST Mode */ |
| 1948 | if (lt_overrides->mst_enable) | 1941 | if (lt_overrides->mst_enable) |
| 1949 | set_dp_mst_mode(link, *lt_overrides->mst_enable); | 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 | uint8_t hblank_size = (uint8_t)link->dc->caps.min_horizontal_blanking_period; | 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, | 4772 | if (link->preferred_link_setting.dpcd_source_device_specific_field_support) { |
| 4780 | DP_SOURCE_MINIMUM_HBLANK_SUPPORTED, (uint8_t *)(&hblank_size), | 4773 | result_write_min_hblank = core_link_write_dpcd(link, |
| 4781 | sizeof(hblank_size)); | 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 | DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_INFORMATION, | 4784 | DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_INFORMATION, |
| 4784 | WPP_BIT_FLAG_DC_DETECTION_DP_CAPS, | 4785 | WPP_BIT_FLAG_DC_DETECTION_DP_CAPS, |
| 4785 | "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'", | 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 | #include <inc/core_status.h> | 26 | #include <inc/core_status.h> |
| 2 | #include <dc_link.h> | 27 | #include <dc_link.h> |
| 3 | #include <inc/link_hwss.h> | 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 | const struct dc_state *state) | 305 | const struct dc_state *state) |
| 306 | { | 306 | { |
| 307 | struct link_encoder *link_enc = NULL; | 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 | eng_id = find_first_avail_link_enc(dc->ctx, state); | 310 | eng_id = find_first_avail_link_enc(dc->ctx, state); |
| 311 | if (eng_id != ENGINE_ID_UNKNOWN) | 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 | /* Timing borders are part of vactive that we are also supposed to skip in addition | 1031 | /* Timing borders are part of vactive that we are also supposed to skip in addition |
| 1032 | * to any stream dst offset. Since dm logic assumes dst is in addressable | 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 | * TODO: fix in DM, stream dst is supposed to be in vactive | 1034 | * TODO: fix in DM, stream dst is supposed to be in vactive |
| 1035 | */ | 1035 | */ |
| 1036 | pipe_ctx->stream->dst.x += timing->h_border_left; | 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 | /* depends on scaling ratios and recout, does not calculate offset yet */ | 1051 | /* depends on scaling ratios and recout, does not calculate offset yet */ |
| 1052 | calculate_viewport_size(pipe_ctx); | 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 | * LB calculations depend on vp size, h/v_active and scaling ratios | 1060 | * LB calculations depend on vp size, h/v_active and scaling ratios |
| 1056 | * Setting line buffer pixel depth to 24bpp yields banding | 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 | status = dmub_srv_stat_get_notification(dmub, notify); | 62 | status = dmub_srv_stat_get_notification(dmub, notify); |
| 63 | ASSERT(status == DMUB_STATUS_OK); | 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 | uint8_t i; | 222 | uint8_t i; |
| 223 | 223 | ||
| 224 | if (state == NULL) | ||
| 225 | return NULL; | ||
| 226 | |||
| 224 | for (i = 0; i < state->stream_count; i++) { | 227 | for (i = 0; i < state->stream_count; i++) { |
| 225 | if (stream == state->streams[i]) | 228 | if (stream == state->streams[i]) |
| 226 | return &state->stream_status[i]; | 229 | return &state->stream_status[i]; |
| @@ -243,6 +246,40 @@ struct dc_stream_status *dc_stream_get_status( · 16 unmodified lines | |||
| 243 | return dc_stream_get_status_from_state(dc->current_state, stream); | 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 | #ifndef TRIM_FSFT | 283 | #ifndef TRIM_FSFT |
| 247 | /* | 284 | /* |
| 248 | * dc_optimize_timing_for_fsft() - dc to optimize timing | 285 | * dc_optimize_timing_for_fsft() - dc to optimize timing |
| @@ -267,10 +304,7 @@ bool dc_stream_set_cursor_attributes( · 18 unmodified lines | |||
| 267 | struct dc_stream_state *stream, | 304 | struct dc_stream_state *stream, |
| 268 | const struct dc_cursor_attributes *attributes) | 305 | const struct dc_cursor_attributes *attributes) |
| 269 | { | 306 | { |
| 270 | int i; | ||
| 271 | struct dc *dc; | 307 | struct dc *dc; |
| 272 | struct resource_context *res_ctx; | ||
| 273 | struct pipe_ctx *pipe_to_program = NULL; | ||
| 274 | #if defined(CONFIG_DRM_AMD_DC_DCN) | 308 | #if defined(CONFIG_DRM_AMD_DC_DCN) |
| 275 | bool reset_idle_optimizations = false; | 309 | bool reset_idle_optimizations = false; |
| 276 | #endif | 310 | #endif |
| @@ -290,7 +324,6 @@ bool dc_stream_set_cursor_attributes( · 13 unmodified lines | |||
| 290 | } | 324 | } |
| 291 | 325 | ||
| 292 | dc = stream->ctx->dc; | 326 | dc = stream->ctx->dc; |
| 293 | res_ctx = &dc->current_state->res_ctx; | ||
| 294 | stream->cursor_attributes = *attributes; | 327 | stream->cursor_attributes = *attributes; |
| 295 | 328 | ||
| 296 | #if defined(CONFIG_DRM_AMD_DC_DCN) | 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 | #endif | 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 | for (i = 0; i < MAX_PIPES; i++) { | 363 | for (i = 0; i < MAX_PIPES; i++) { |
| 307 | struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i]; | 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 | continue; | 371 | continue; |
| 311 | 372 | ||
| 312 | if (!pipe_to_program) { | 373 | if (!pipe_to_program) { |
| @@ -314,31 +375,18 @@ bool dc_stream_set_cursor_attributes( · 1 unmodified line | |||
| 314 | dc->hwss.cursor_lock(dc, pipe_to_program, true); | 375 | dc->hwss.cursor_lock(dc, pipe_to_program, true); |
| 315 | } | 376 | } |
| 316 | 377 | ||
| 317 | dc->hwss.set_cursor_attribute(pipe_ctx); | 378 | dc->hwss.set_cursor_position(pipe_ctx); |
| 318 | if (dc->hwss.set_cursor_sdr_white_level) | ||
| 319 | dc->hwss.set_cursor_sdr_white_level(pipe_ctx); | ||
| 320 | } | 379 | } |
| 321 | 380 | ||
| 322 | if (pipe_to_program) | 381 | if (pipe_to_program) |
| 323 | dc->hwss.cursor_lock(dc, pipe_to_program, false); | 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 | bool dc_stream_set_cursor_position( | 385 | bool dc_stream_set_cursor_position( |
| 335 | struct dc_stream_state *stream, | 386 | struct dc_stream_state *stream, |
| 336 | const struct dc_cursor_position *position) | 387 | const struct dc_cursor_position *position) |
| 337 | { | 388 | { |
| 338 | int i; | ||
| 339 | struct dc *dc; | 389 | struct dc *dc; |
| 340 | struct resource_context *res_ctx; | ||
| 341 | struct pipe_ctx *pipe_to_program = NULL; | ||
| 342 | #if defined(CONFIG_DRM_AMD_DC_DCN) | 390 | #if defined(CONFIG_DRM_AMD_DC_DCN) |
| 343 | bool reset_idle_optimizations = false; | 391 | bool reset_idle_optimizations = false; |
| 344 | #endif | 392 | #endif |
| @@ -354,7 +402,6 @@ bool dc_stream_set_cursor_position( · 9 unmodified lines | |||
| 354 | } | 402 | } |
| 355 | 403 | ||
| 356 | dc = stream->ctx->dc; | 404 | dc = stream->ctx->dc; |
| 357 | res_ctx = &dc->current_state->res_ctx; | ||
| 358 | #if defined(CONFIG_DRM_AMD_DC_DCN) | 405 | #if defined(CONFIG_DRM_AMD_DC_DCN) |
| 359 | dc_z10_restore(dc); | 406 | dc_z10_restore(dc); |
| 360 | 407 | ||
| @@ -367,27 +414,7 @@ bool dc_stream_set_cursor_position( · 6 unmodified lines | |||
| 367 | #endif | 414 | #endif |
| 368 | stream->cursor_position = *position; | 415 | stream->cursor_position = *position; |
| 369 | 416 | ||
| 370 | for (i = 0; i < MAX_PIPES; i++) { | 417 | program_cursor_position(dc, stream, position); |
| 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 | |||
| 391 | #if defined(CONFIG_DRM_AMD_DC_DCN) | 418 | #if defined(CONFIG_DRM_AMD_DC_DCN) |
| 392 | /* re-enable idle optimizations if necessary */ | 419 | /* re-enable idle optimizations if necessary */ |
| 393 | if (reset_idle_optimizations) | 420 | if (reset_idle_optimizations) |
| @@ -45,7 +45,7 @@ · 44 unmodified lines | |||
| 45 | /* forward declaration */ | 45 | /* forward declaration */ |
| 46 | struct aux_payload; | 46 | struct aux_payload; |
| 47 | 47 | ||
| 48 | #define DC_VER "3.2.141" | 48 | #define DC_VER "3.2.149" |
| 49 | 49 | ||
| 50 | #define MAX_SURFACES 3 | 50 | #define MAX_SURFACES 3 |
| 51 | #define MAX_PLANES 6 | 51 | #define MAX_PLANES 6 |
| @@ -460,7 +460,65 @@ union mem_low_power_enable_options { · 408 unmodified lines | |||
| 460 | uint32_t u32All; | 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 | struct dc_debug_options { | 519 | struct dc_debug_options { |
| 520 | bool native422_support; | ||
| 521 | bool disable_dsc; | ||
| 464 | enum visual_confirm visual_confirm; | 522 | enum visual_confirm visual_confirm; |
| 465 | bool sanity_checks; | 523 | bool sanity_checks; |
| 466 | bool max_disp_clk; | 524 | bool max_disp_clk; |
| @@ -486,7 +544,6 @@ struct dc_debug_options { · 19 unmodified lines | |||
| 486 | bool disable_dsc_power_gate; | 544 | bool disable_dsc_power_gate; |
| 487 | int dsc_min_slice_height_override; | 545 | int dsc_min_slice_height_override; |
| 488 | int dsc_bpp_increment_div; | 546 | int dsc_bpp_increment_div; |
| 489 | bool native422_support; | ||
| 490 | bool disable_pplib_wm_range; | 547 | bool disable_pplib_wm_range; |
| 491 | enum wm_report_mode pplib_wm_report_mode; | 548 | enum wm_report_mode pplib_wm_report_mode; |
| 492 | unsigned int min_disp_clk_khz; | 549 | unsigned int min_disp_clk_khz; |
| @@ -556,7 +613,6 @@ struct dc_debug_options { · 63 unmodified lines | |||
| 556 | bool validate_dml_output; | 613 | bool validate_dml_output; |
| 557 | bool enable_dmcub_surface_flip; | 614 | bool enable_dmcub_surface_flip; |
| 558 | bool usbc_combo_phy_reset_wa; | 615 | bool usbc_combo_phy_reset_wa; |
| 559 | bool disable_dsc; | ||
| 560 | bool enable_dram_clock_change_one_display_vactive; | 616 | bool enable_dram_clock_change_one_display_vactive; |
| 561 | union mem_low_power_enable_options enable_mem_low_power; | 617 | union mem_low_power_enable_options enable_mem_low_power; |
| 562 | bool force_vblank_alignment; | 618 | bool force_vblank_alignment; |
| @@ -574,69 +630,13 @@ struct dc_debug_options { · 11 unmodified lines | |||
| 574 | #endif | 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 | struct gpu_info_soc_bounding_box_v1_0; | 633 | struct gpu_info_soc_bounding_box_v1_0; |
| 634 | struct dc { | 634 | struct dc { |
| 635 | struct dc_debug_options debug; | ||
| 635 | struct dc_versions versions; | 636 | struct dc_versions versions; |
| 636 | struct dc_caps caps; | 637 | struct dc_caps caps; |
| 637 | struct dc_cap_funcs cap_funcs; | 638 | struct dc_cap_funcs cap_funcs; |
| 638 | struct dc_config config; | 639 | struct dc_config config; |
| 639 | struct dc_debug_options debug; | ||
| 640 | struct dc_bounding_box_overrides bb_overrides; | 640 | struct dc_bounding_box_overrides bb_overrides; |
| 641 | struct dc_bug_wa work_arounds; | 641 | struct dc_bug_wa work_arounds; |
| 642 | struct dc_context *ctx; | 642 | struct dc_context *ctx; |
| @@ -109,6 +109,7 @@ struct dc_link_settings { · 108 unmodified lines | |||
| 109 | enum dc_link_spread link_spread; | 109 | enum dc_link_spread link_spread; |
| 110 | bool use_link_rate_set; | 110 | bool use_link_rate_set; |
| 111 | uint8_t link_rate_set; | 111 | uint8_t link_rate_set; |
| 112 | bool dpcd_source_device_specific_field_support; | ||
| 112 | }; | 113 | }; |
| 113 | 114 | ||
| 114 | struct dc_lane_settings { | 115 | struct dc_lane_settings { |
| @@ -38,5 +38,6 @@ · 37 unmodified lines | |||
| 38 | #include "dmub/dmub_srv.h" | 38 | #include "dmub/dmub_srv.h" |
| 39 | 39 | ||
| 40 | void dc_stat_get_dmub_notification(const struct dc *dc, struct dmub_notification *notify); | 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 | #endif /* _DC_STAT_H_ */ | 43 | #endif /* _DC_STAT_H_ */ |
| @@ -37,3 +37,6 @@ · 36 unmodified lines | |||
| 37 | 37 | ||
| 38 | #define TRACE_DCN_CLOCK_STATE(dcn_clocks) \ | 38 | #define TRACE_DCN_CLOCK_STATE(dcn_clocks) \ |
| 39 | trace_amdgpu_dm_dc_clocks_state(dcn_clocks) | 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 | #define IS_DIAG_DC(dce_environment) \ | 75 | #define IS_DIAG_DC(dce_environment) \ |
| 76 | (IS_FPGA_MAXIMUS_DC(dce_environment) || (dce_environment == DCE_ENV_DIAG)) | 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 | struct dc_perf_trace { | 78 | struct dc_perf_trace { |
| 91 | unsigned long read_count; | 79 | unsigned long read_count; |
| 92 | unsigned long write_count; | 80 | unsigned long write_count; |
| @@ -94,36 +82,7 @@ struct dc_perf_trace { · 1 unmodified line | |||
| 94 | unsigned long last_entry_write; | 82 | unsigned long last_entry_write; |
| 95 | }; | 83 | }; |
| 96 | 84 | ||
| 97 | struct dc_context { | 85 | #define DC_MAX_EDID_BUFFER_SIZE 2048 |
| 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 | ||
| 127 | #define DC_EDID_BLOCK_SIZE 128 | 86 | #define DC_EDID_BLOCK_SIZE 128 |
| 128 | #define MAX_SURFACE_NUM 4 | 87 | #define MAX_SURFACE_NUM 4 |
| 129 | #define NUM_PIXEL_FORMATS 10 | 88 | #define NUM_PIXEL_FORMATS 10 |
| @@ -836,6 +795,46 @@ struct dc_clock_config { · 706 unmodified lines | |||
| 836 | uint32_t current_clock_khz;/*current clock in use*/ | 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 | /* DSC DPCD capabilities */ | 838 | /* DSC DPCD capabilities */ |
| 840 | union dsc_slice_caps1 { | 839 | union dsc_slice_caps1 { |
| 841 | struct { | 840 | struct { |
| @@ -42,6 +42,11 @@ · 41 unmodified lines | |||
| 42 | #define DC_LOGGER \ | 42 | #define DC_LOGGER \ |
| 43 | engine->ctx->logger | 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 | #include "reg_helper.h" | 50 | #include "reg_helper.h" |
| 46 | 51 | ||
| 47 | #undef FN | 52 | #undef FN |
| @@ -71,6 +76,8 @@ enum { · 23 unmodified lines | |||
| 71 | #define DEFAULT_AUX_ENGINE_MULT 0 | 76 | #define DEFAULT_AUX_ENGINE_MULT 0 |
| 72 | #define DEFAULT_AUX_ENGINE_LENGTH 69 | 77 | #define DEFAULT_AUX_ENGINE_LENGTH 69 |
| 73 | 78 | ||
| 79 | #define DC_TRACE_LEVEL_MESSAGE(...) /* do nothing */ | ||
| 80 | |||
| 74 | static void release_engine( | 81 | static void release_engine( |
| 75 | struct dce_aux *engine) | 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 | #define AUX_MAX_INVALID_REPLY_RETRIES 2 | 628 | #define AUX_MAX_INVALID_REPLY_RETRIES 2 |
| 622 | #define AUX_MAX_TIMEOUT_RETRIES 3 | 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 | bool dce_aux_transfer_with_retries(struct ddc_service *ddc, | 683 | bool dce_aux_transfer_with_retries(struct ddc_service *ddc, |
| 625 | struct aux_payload *payload) | 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 | for (i = 0; i < AUX_MAX_RETRIES; i++) { | 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 | ret = dce_aux_transfer_raw(ddc, payload, &operation_result); | 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 | switch (operation_result) { | 737 | switch (operation_result) { |
| 652 | case AUX_RET_SUCCESS: | 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 | switch (*payload->reply) { | 742 | switch (*payload->reply) { |
| 657 | case AUX_TRANSACTION_REPLY_AUX_ACK: | 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 | if (!payload->write && payload->length != ret) { | 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 | goto fail; | 754 | goto fail; |
| 661 | else | 755 | } else { |
| 662 | udelay(300); | 756 | udelay(300); |
| 757 | } | ||
| 663 | } else | 758 | } else |
| 664 | return true; | 759 | return true; |
| 665 | break; | 760 | break; |
| 666 | 761 | ||
| 667 | case AUX_TRANSACTION_REPLY_AUX_DEFER: | 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 | /* polling_timeout_period is in us */ | 767 | /* polling_timeout_period is in us */ |
| 669 | defer_time_in_ms += aux110->polling_timeout_period / 1000; | 768 | defer_time_in_ms += aux110->polling_timeout_period / 1000; |
| 670 | ++aux_defer_retries; | 769 | ++aux_defer_retries; |
| 671 | fallthrough; | 770 | fallthrough; |
| 672 | case AUX_TRANSACTION_REPLY_I2C_OVER_AUX_DEFER: | 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 | retry_on_defer = true; | 777 | retry_on_defer = true; |
| 674 | fallthrough; | 778 | fallthrough; |
| 675 | case AUX_TRANSACTION_REPLY_I2C_OVER_AUX_NACK: | 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 | if (aux_defer_retries >= AUX_MIN_DEFER_RETRIES | 785 | if (aux_defer_retries >= AUX_MIN_DEFER_RETRIES |
| 677 | && defer_time_in_ms >= AUX_MAX_DEFER_TIMEOUT_MS) { | 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 | goto fail; | 794 | goto fail; |
| 679 | } else { | 795 | } else { |
| 680 | if ((*payload->reply == AUX_TRANSACTION_REPLY_AUX_DEFER) || | 796 | if ((*payload->reply == AUX_TRANSACTION_REPLY_AUX_DEFER) || |
| 681 | (*payload->reply == AUX_TRANSACTION_REPLY_I2C_OVER_AUX_DEFER)) { | 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 | if (payload->defer_delay > 1) { | 802 | if (payload->defer_delay > 1) { |
| 683 | msleep(payload->defer_delay); | 803 | msleep(payload->defer_delay); |
| 684 | defer_time_in_ms += payload->defer_delay; | 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 | break; | 811 | break; |
| 692 | 812 | ||
| 693 | case AUX_TRANSACTION_REPLY_I2C_DEFER: | 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 | aux_defer_retries = 0; | 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 | goto fail; | 825 | goto fail; |
| 826 | } | ||
| 697 | break; | 827 | break; |
| 698 | 828 | ||
| 699 | case AUX_TRANSACTION_REPLY_AUX_NACK: | 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 | case AUX_TRANSACTION_REPLY_HPD_DISCON: | 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 | default: | 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 | goto fail; | 845 | goto fail; |
| 703 | } | 846 | } |
| 704 | break; | 847 | break; |
| 705 | 848 | ||
| 706 | case AUX_RET_ERROR_INVALID_REPLY: | 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 | goto fail; | 859 | goto fail; |
| 709 | else | 860 | } else |
| 710 | udelay(400); | 861 | udelay(400); |
| 711 | break; | 862 | break; |
| 712 | 863 | ||
| 713 | case AUX_RET_ERROR_TIMEOUT: | 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 | // Check whether a DEFER had occurred before the timeout. | 868 | // Check whether a DEFER had occurred before the timeout. |
| 715 | // If so, treat timeout as a DEFER. | 869 | // If so, treat timeout as a DEFER. |
| 716 | if (retry_on_defer) { | 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 | goto fail; | 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 | msleep(payload->defer_delay); | 883 | msleep(payload->defer_delay); |
| 884 | } | ||
| 721 | } else { | 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 | goto fail; | 892 | goto fail; |
| 724 | else { | 893 | } else { |
| 725 | /* | 894 | /* |
| 726 | * DP 1.4, 2.8.2: AUX Transaction Response/Reply Timeouts | 895 | * DP 1.4, 2.8.2: AUX Transaction Response/Reply Timeouts |
| 727 | * According to the DP spec there should be 3 retries total | 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 | case AUX_RET_ERROR_ENGINE_ACQUIRE: | 905 | case AUX_RET_ERROR_ENGINE_ACQUIRE: |
| 737 | case AUX_RET_ERROR_UNKNOWN: | 906 | case AUX_RET_ERROR_UNKNOWN: |
| 738 | default: | 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 | goto fail; | 912 | goto fail; |
| 740 | } | 913 | } |
| 741 | } | 914 | } |
| 742 | 915 | ||
| 743 | fail: | 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.