mirror of
https://github.com/torvalds/linux.git
synced 2026-07-29 10:41:49 +02:00
Merge drm/drm-next into drm-misc-next
Backmerging to get fixes from -rc7. Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
This commit is contained in:
commit
00e3939ec8
|
|
@ -1,6 +1,7 @@
|
|||
Alan Cox <alan@lxorguk.ukuu.org.uk>
|
||||
Alan Cox <root@hraefn.swansea.linux.org.uk>
|
||||
Alyssa Rosenzweig <alyssa@rosenzweig.io>
|
||||
Askar Safin <safinaskar@gmail.com>
|
||||
Christoph Hellwig <hch@lst.de>
|
||||
Jeff Kirsher <jeffrey.t.kirsher@intel.com>
|
||||
Marc Gonzalez <marc.w.gonzalez@free.fr>
|
||||
|
|
|
|||
1
.mailmap
1
.mailmap
|
|
@ -196,6 +196,7 @@ Christophe Leroy <chleroy@kernel.org> <christophe.leroy2@cs-soprasteria.com>
|
|||
Christophe Ricard <christophe.ricard@gmail.com>
|
||||
Christopher Obbard <christopher.obbard@linaro.org> <chris.obbard@collabora.com>
|
||||
Christoph Hellwig <hch@lst.de>
|
||||
Christoph Manszewski <c.manszewski@gmail.com> <christoph.manszewski@intel.com>
|
||||
Chuck Lever <chuck.lever@oracle.com> <cel@kernel.org>
|
||||
Chuck Lever <chuck.lever@oracle.com> <cel@netapp.com>
|
||||
Chuck Lever <chuck.lever@oracle.com> <cel@citi.umich.edu>
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@ then:
|
|||
required:
|
||||
- refresh-rate-hz
|
||||
|
||||
additionalProperties: false
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
|
|
|
|||
|
|
@ -301,6 +301,7 @@ properties:
|
|||
maxItems: 4
|
||||
|
||||
dependencies:
|
||||
pd-disable: [typec-power-opmode]
|
||||
sink-vdos-v1: [ sink-vdos ]
|
||||
sink-vdos: [ sink-vdos-v1 ]
|
||||
|
||||
|
|
|
|||
|
|
@ -67,6 +67,7 @@ properties:
|
|||
|
||||
- items:
|
||||
- enum:
|
||||
- qcom,eliza-dp
|
||||
- qcom,sm8750-dp
|
||||
- const: qcom,sm8650-dp
|
||||
|
||||
|
|
|
|||
|
|
@ -49,8 +49,13 @@ properties:
|
|||
- items:
|
||||
- enum:
|
||||
- qcom,qcs8300-dsi-ctrl
|
||||
- qcom,sc8280xp-dsi-ctrl
|
||||
- const: qcom,sa8775p-dsi-ctrl
|
||||
- const: qcom,mdss-dsi-ctrl
|
||||
- items:
|
||||
- const: qcom,eliza-dsi-ctrl
|
||||
- const: qcom,sm8750-dsi-ctrl
|
||||
- const: qcom,mdss-dsi-ctrl
|
||||
- enum:
|
||||
- qcom,dsi-ctrl-6g-qcm2290
|
||||
- qcom,mdss-dsi-ctrl # This should always come with an SoC-specific compatible
|
||||
|
|
|
|||
|
|
@ -91,6 +91,7 @@ allOf:
|
|||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- qcom,adreno-gmu-615.0
|
||||
- qcom,adreno-gmu-618.0
|
||||
- qcom,adreno-gmu-630.2
|
||||
then:
|
||||
|
|
|
|||
|
|
@ -440,13 +440,6 @@ allOf:
|
|||
clocks: false
|
||||
clock-names: false
|
||||
|
||||
reg-names:
|
||||
minItems: 1
|
||||
items:
|
||||
- const: kgsl_3d0_reg_memory
|
||||
- const: cx_mem
|
||||
- const: cx_dbgc
|
||||
|
||||
examples:
|
||||
- |
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,494 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/msm/qcom,eliza-mdss.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Qualcomm Eliza SoC Display MDSS
|
||||
|
||||
maintainers:
|
||||
- Krzysztof Kozlowski <krzk@kernel.org>
|
||||
|
||||
description:
|
||||
Eliza SoC Mobile Display Subsystem (MDSS) encapsulates sub-blocks like DPU
|
||||
display controller, DSI and DP interfaces etc.
|
||||
|
||||
$ref: /schemas/display/msm/mdss-common.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: qcom,eliza-mdss
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: Display AHB
|
||||
- description: Display hf AXI
|
||||
- description: Display core
|
||||
|
||||
iommus:
|
||||
maxItems: 1
|
||||
|
||||
interconnects:
|
||||
items:
|
||||
- description: Interconnect path from mdp0 port to the data bus
|
||||
- description: Interconnect path from CPU to the reg bus
|
||||
|
||||
interconnect-names:
|
||||
items:
|
||||
- const: mdp0-mem
|
||||
- const: cpu-cfg
|
||||
|
||||
patternProperties:
|
||||
"^display-controller@[0-9a-f]+$":
|
||||
type: object
|
||||
additionalProperties: true
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
const: qcom,eliza-dpu
|
||||
|
||||
"^displayport-controller@[0-9a-f]+$":
|
||||
type: object
|
||||
additionalProperties: true
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
const: qcom,eliza-dp
|
||||
|
||||
"^dsi@[0-9a-f]+$":
|
||||
type: object
|
||||
additionalProperties: true
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
const: qcom,eliza-dsi-ctrl
|
||||
|
||||
"^phy@[0-9a-f]+$":
|
||||
type: object
|
||||
additionalProperties: true
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
const: qcom,eliza-dsi-phy-4nm
|
||||
|
||||
required:
|
||||
- compatible
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/qcom,dsi-phy-28nm.h>
|
||||
#include <dt-bindings/clock/qcom,rpmh.h>
|
||||
#include <dt-bindings/interconnect/qcom,icc.h>
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
#include <dt-bindings/phy/phy-qcom-qmp.h>
|
||||
#include <dt-bindings/power/qcom,rpmhpd.h>
|
||||
|
||||
display-subsystem@ae00000 {
|
||||
compatible = "qcom,eliza-mdss";
|
||||
reg = <0x0ae00000 0x1000>;
|
||||
reg-names = "mdss";
|
||||
ranges;
|
||||
|
||||
interrupts = <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>;
|
||||
|
||||
clocks = <&disp_cc_mdss_ahb_clk>,
|
||||
<&gcc_disp_hf_axi_clk>,
|
||||
<&disp_cc_mdss_mdp_clk>;
|
||||
|
||||
resets = <&disp_cc_mdss_core_bcr>;
|
||||
|
||||
interconnects = <&mmss_noc_master_mdp QCOM_ICC_TAG_ALWAYS
|
||||
&mc_virt_slave_ebi1 QCOM_ICC_TAG_ALWAYS>,
|
||||
<&gem_noc_master_appss_proc QCOM_ICC_TAG_ACTIVE_ONLY
|
||||
&config_noc_slave_display_cfg QCOM_ICC_TAG_ACTIVE_ONLY>;
|
||||
interconnect-names = "mdp0-mem",
|
||||
"cpu-cfg";
|
||||
|
||||
power-domains = <&mdss_gdsc>;
|
||||
|
||||
iommus = <&apps_smmu 0x800 0x2>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <1>;
|
||||
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
mdss_mdp: display-controller@ae01000 {
|
||||
compatible = "qcom,eliza-dpu";
|
||||
reg = <0x0ae01000 0x93000>,
|
||||
<0x0aeb0000 0x2008>;
|
||||
reg-names = "mdp",
|
||||
"vbif";
|
||||
|
||||
interrupts-extended = <&mdss 0>;
|
||||
|
||||
clocks = <&gcc_disp_hf_axi_clk>,
|
||||
<&disp_cc_mdss_ahb_clk>,
|
||||
<&disp_cc_mdss_mdp_lut_clk>,
|
||||
<&disp_cc_mdss_mdp_clk>,
|
||||
<&disp_cc_mdss_vsync_clk>;
|
||||
clock-names = "nrt_bus",
|
||||
"iface",
|
||||
"lut",
|
||||
"core",
|
||||
"vsync";
|
||||
|
||||
assigned-clocks = <&disp_cc_mdss_vsync_clk>;
|
||||
assigned-clock-rates = <19200000>;
|
||||
|
||||
operating-points-v2 = <&mdp_opp_table>;
|
||||
|
||||
power-domains = <&rpmhpd RPMHPD_MMCX>;
|
||||
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
port@0 {
|
||||
reg = <0>;
|
||||
|
||||
dpu_intf1_out: endpoint {
|
||||
remote-endpoint = <&mdss_dsi0_in>;
|
||||
};
|
||||
};
|
||||
|
||||
port@1 {
|
||||
reg = <1>;
|
||||
|
||||
dpu_intf2_out: endpoint {
|
||||
remote-endpoint = <&mdss_dsi1_in>;
|
||||
};
|
||||
};
|
||||
|
||||
port@2 {
|
||||
reg = <2>;
|
||||
|
||||
dpu_intf0_out: endpoint {
|
||||
remote-endpoint = <&mdss_dp0_in>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
mdp_opp_table: opp-table {
|
||||
compatible = "operating-points-v2";
|
||||
|
||||
opp-150000000 {
|
||||
opp-hz = /bits/ 64 <150000000>;
|
||||
required-opps = <&rpmhpd_opp_low_svs_d1>;
|
||||
};
|
||||
|
||||
opp-207000000 {
|
||||
opp-hz = /bits/ 64 <207000000>;
|
||||
required-opps = <&rpmhpd_opp_low_svs>;
|
||||
};
|
||||
|
||||
opp-342000000 {
|
||||
opp-hz = /bits/ 64 <342000000>;
|
||||
required-opps = <&rpmhpd_opp_svs>;
|
||||
};
|
||||
|
||||
opp-417000000 {
|
||||
opp-hz = /bits/ 64 <417000000>;
|
||||
required-opps = <&rpmhpd_opp_svs_l1>;
|
||||
};
|
||||
|
||||
opp-532000000 {
|
||||
opp-hz = /bits/ 64 <532000000>;
|
||||
required-opps = <&rpmhpd_opp_nom>;
|
||||
};
|
||||
|
||||
opp-600000000 {
|
||||
opp-hz = /bits/ 64 <600000000>;
|
||||
required-opps = <&rpmhpd_opp_nom_l1>;
|
||||
};
|
||||
|
||||
opp-660000000 {
|
||||
opp-hz = /bits/ 64 <660000000>;
|
||||
required-opps = <&rpmhpd_opp_turbo>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
dsi@ae94000 {
|
||||
compatible = "qcom,eliza-dsi-ctrl", "qcom,sm8750-dsi-ctrl", "qcom,mdss-dsi-ctrl";
|
||||
reg = <0x0ae94000 0x400>;
|
||||
reg-names = "dsi_ctrl";
|
||||
|
||||
interrupts-extended = <&mdss 4>;
|
||||
|
||||
clocks = <&disp_cc_mdss_byte0_clk>,
|
||||
<&disp_cc_mdss_byte0_intf_clk>,
|
||||
<&disp_cc_mdss_pclk0_clk>,
|
||||
<&disp_cc_mdss_esc0_clk>,
|
||||
<&disp_cc_mdss_ahb_clk>,
|
||||
<&gcc_disp_hf_axi_clk>,
|
||||
<&mdss_dsi0_phy DSI_PIXEL_PLL_CLK>,
|
||||
<&mdss_dsi0_phy DSI_BYTE_PLL_CLK>,
|
||||
<&disp_cc_esync0_clk>,
|
||||
<&disp_cc_osc_clk>,
|
||||
<&disp_cc_mdss_byte0_clk_src>,
|
||||
<&disp_cc_mdss_pclk0_clk_src>;
|
||||
clock-names = "byte",
|
||||
"byte_intf",
|
||||
"pixel",
|
||||
"core",
|
||||
"iface",
|
||||
"bus",
|
||||
"dsi_pll_pixel",
|
||||
"dsi_pll_byte",
|
||||
"esync",
|
||||
"osc",
|
||||
"byte_src",
|
||||
"pixel_src";
|
||||
|
||||
operating-points-v2 = <&mdss_dsi_opp_table>;
|
||||
|
||||
power-domains = <&rpmhpd RPMHPD_MMCX>;
|
||||
|
||||
phys = <&mdss_dsi0_phy>;
|
||||
phy-names = "dsi";
|
||||
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
port@0 {
|
||||
reg = <0>;
|
||||
|
||||
mdss_dsi0_in: endpoint {
|
||||
remote-endpoint = <&dpu_intf1_out>;
|
||||
};
|
||||
};
|
||||
|
||||
port@1 {
|
||||
reg = <1>;
|
||||
|
||||
mdss_dsi0_out: endpoint {
|
||||
remote-endpoint = <&panel0_in>;
|
||||
data-lanes = <0 1 2 3>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
mdss_dsi_opp_table: opp-table {
|
||||
compatible = "operating-points-v2";
|
||||
|
||||
opp-140630000 {
|
||||
opp-hz = /bits/ 64 <140630000>;
|
||||
required-opps = <&rpmhpd_opp_low_svs_d1>;
|
||||
};
|
||||
|
||||
opp-187500000 {
|
||||
opp-hz = /bits/ 64 <187500000>;
|
||||
required-opps = <&rpmhpd_opp_low_svs>;
|
||||
};
|
||||
|
||||
opp-300000000 {
|
||||
opp-hz = /bits/ 64 <300000000>;
|
||||
required-opps = <&rpmhpd_opp_svs>;
|
||||
};
|
||||
|
||||
opp-358000000 {
|
||||
opp-hz = /bits/ 64 <358000000>;
|
||||
required-opps = <&rpmhpd_opp_svs_l1>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
mdss_dsi0_phy: phy@ae95000 {
|
||||
compatible = "qcom,eliza-dsi-phy-4nm", "qcom,sm8650-dsi-phy-4nm";
|
||||
reg = <0x0ae95000 0x200>,
|
||||
<0x0ae95200 0x280>,
|
||||
<0x0ae95500 0x400>;
|
||||
reg-names = "dsi_phy",
|
||||
"dsi_phy_lane",
|
||||
"dsi_pll";
|
||||
|
||||
clocks = <&disp_cc_mdss_ahb_clk>,
|
||||
<&bi_tcxo_div2>;
|
||||
clock-names = "iface",
|
||||
"ref";
|
||||
|
||||
#clock-cells = <1>;
|
||||
#phy-cells = <0>;
|
||||
|
||||
vdds-supply = <&vreg_l2b>;
|
||||
};
|
||||
|
||||
dsi@ae96000 {
|
||||
compatible = "qcom,eliza-dsi-ctrl", "qcom,sm8750-dsi-ctrl", "qcom,mdss-dsi-ctrl";
|
||||
reg = <0x0ae96000 0x400>;
|
||||
reg-names = "dsi_ctrl";
|
||||
|
||||
interrupts-extended = <&mdss 5>;
|
||||
|
||||
clocks = <&disp_cc_mdss_byte1_clk>,
|
||||
<&disp_cc_mdss_byte1_intf_clk>,
|
||||
<&disp_cc_mdss_pclk1_clk>,
|
||||
<&disp_cc_mdss_esc1_clk>,
|
||||
<&disp_cc_mdss_ahb_clk>,
|
||||
<&gcc_disp_hf_axi_clk>,
|
||||
<&mdss_dsi1_phy DSI_PIXEL_PLL_CLK>,
|
||||
<&mdss_dsi1_phy DSI_BYTE_PLL_CLK>,
|
||||
<&disp_cc_esync1_clk>,
|
||||
<&disp_cc_osc_clk>,
|
||||
<&disp_cc_mdss_byte1_clk_src>,
|
||||
<&disp_cc_mdss_pclk1_clk_src>;
|
||||
clock-names = "byte",
|
||||
"byte_intf",
|
||||
"pixel",
|
||||
"core",
|
||||
"iface",
|
||||
"bus",
|
||||
"dsi_pll_pixel",
|
||||
"dsi_pll_byte",
|
||||
"esync",
|
||||
"osc",
|
||||
"byte_src",
|
||||
"pixel_src";
|
||||
|
||||
operating-points-v2 = <&mdss_dsi_opp_table>;
|
||||
|
||||
power-domains = <&rpmhpd RPMHPD_MMCX>;
|
||||
|
||||
phys = <&mdss_dsi1_phy>;
|
||||
phy-names = "dsi";
|
||||
|
||||
vdda-supply = <&vreg_l4b>;
|
||||
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
port@0 {
|
||||
reg = <0>;
|
||||
|
||||
mdss_dsi1_in: endpoint {
|
||||
remote-endpoint = <&dpu_intf2_out>;
|
||||
};
|
||||
};
|
||||
|
||||
port@1 {
|
||||
reg = <1>;
|
||||
|
||||
mdss_dsi1_out: endpoint {
|
||||
remote-endpoint = <&panel1_in>;
|
||||
data-lanes = <0 1 2 3>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
mdss_dsi1_phy: phy@ae97000 {
|
||||
compatible = "qcom,eliza-dsi-phy-4nm", "qcom,sm8650-dsi-phy-4nm";
|
||||
reg = <0x0ae97000 0x200>,
|
||||
<0x0ae97200 0x280>,
|
||||
<0x0ae97500 0x400>;
|
||||
reg-names = "dsi_phy",
|
||||
"dsi_phy_lane",
|
||||
"dsi_pll";
|
||||
|
||||
clocks = <&disp_cc_mdss_ahb_clk>,
|
||||
<&rpmhcc RPMH_CXO_CLK>;
|
||||
clock-names = "iface",
|
||||
"ref";
|
||||
|
||||
#clock-cells = <1>;
|
||||
#phy-cells = <0>;
|
||||
|
||||
vdds-supply = <&vreg_l2b>;
|
||||
};
|
||||
|
||||
displayport-controller@af54000 {
|
||||
compatible = "qcom,eliza-dp", "qcom,sm8650-dp";
|
||||
reg = <0xaf54000 0x104>,
|
||||
<0xaf54200 0xc0>,
|
||||
<0xaf55000 0x770>,
|
||||
<0xaf56000 0x9c>,
|
||||
<0xaf57000 0x9c>;
|
||||
|
||||
interrupts-extended = <&mdss 12>;
|
||||
|
||||
clocks = <&disp_cc_mdss_ahb_clk>,
|
||||
<&disp_cc_mdss_dptx0_aux_clk>,
|
||||
<&disp_cc_mdss_dptx0_link_clk>,
|
||||
<&disp_cc_mdss_dptx0_link_intf_clk>,
|
||||
<&disp_cc_mdss_dptx0_pixel0_clk>,
|
||||
<&disp_cc_mdss_dptx0_pixel1_clk>;
|
||||
clock-names = "core_iface",
|
||||
"core_aux",
|
||||
"ctrl_link",
|
||||
"ctrl_link_iface",
|
||||
"stream_pixel",
|
||||
"stream_1_pixel";
|
||||
|
||||
assigned-clocks = <&disp_cc_mdss_dptx0_link_clk_src>,
|
||||
<&disp_cc_mdss_dptx0_pixel0_clk_src>,
|
||||
<&disp_cc_mdss_dptx0_pixel1_clk_src>;
|
||||
assigned-clock-parents = <&usb_dp_qmpphy QMP_USB43DP_DP_LINK_CLK>,
|
||||
<&usb_dp_qmpphy QMP_USB43DP_DP_VCO_DIV_CLK>,
|
||||
<&usb_dp_qmpphy QMP_USB43DP_DP_VCO_DIV_CLK>;
|
||||
|
||||
operating-points-v2 = <&dp_opp_table>;
|
||||
|
||||
power-domains = <&rpmhpd RPMHPD_MMCX>;
|
||||
|
||||
phys = <&usb_dp_qmpphy QMP_USB43DP_DP_PHY>;
|
||||
phy-names = "dp";
|
||||
|
||||
#sound-dai-cells = <0>;
|
||||
|
||||
dp_opp_table: opp-table {
|
||||
compatible = "operating-points-v2";
|
||||
|
||||
opp-192000000 {
|
||||
opp-hz = /bits/ 64 <192000000>;
|
||||
required-opps = <&rpmhpd_opp_low_svs_d1>;
|
||||
};
|
||||
|
||||
opp-270000000 {
|
||||
opp-hz = /bits/ 64 <270000000>;
|
||||
required-opps = <&rpmhpd_opp_low_svs>;
|
||||
};
|
||||
|
||||
opp-540000000 {
|
||||
opp-hz = /bits/ 64 <540000000>;
|
||||
required-opps = <&rpmhpd_opp_svs_l1>;
|
||||
};
|
||||
|
||||
opp-810000000 {
|
||||
opp-hz = /bits/ 64 <810000000>;
|
||||
required-opps = <&rpmhpd_opp_nom>;
|
||||
};
|
||||
};
|
||||
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
port@0 {
|
||||
reg = <0>;
|
||||
|
||||
mdss_dp0_in: endpoint {
|
||||
remote-endpoint = <&dpu_intf0_out>;
|
||||
};
|
||||
};
|
||||
|
||||
port@1 {
|
||||
reg = <1>;
|
||||
|
||||
mdss_dp0_out: endpoint {
|
||||
data-lanes = <0 1 2 3>;
|
||||
remote-endpoint = <&usb_dp_qmpphy_dp_in>;
|
||||
link-frequencies = /bits/ 64 <1620000000 2700000000 5400000000 8100000000>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
@ -50,6 +50,22 @@ patternProperties:
|
|||
- qcom,sc8280xp-dp
|
||||
- qcom,sc8280xp-edp
|
||||
|
||||
"^dsi@[0-9a-f]+$":
|
||||
type: object
|
||||
additionalProperties: true
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
const: qcom,sc8280xp-dsi-ctrl
|
||||
|
||||
"^phy@[0-9a-f]+$":
|
||||
type: object
|
||||
additionalProperties: true
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
const: qcom,sc8280xp-dsi-phy-5nm
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
|
|
@ -129,6 +145,20 @@ examples:
|
|||
};
|
||||
};
|
||||
|
||||
port@1 {
|
||||
reg = <1>;
|
||||
dpu_intf1_out: endpoint {
|
||||
remote-endpoint = <&mdss0_dsi0_in>;
|
||||
};
|
||||
};
|
||||
|
||||
port@2 {
|
||||
reg = <2>;
|
||||
dpu_intf2_out: endpoint {
|
||||
remote-endpoint = <&mdss0_dsi1_in>;
|
||||
};
|
||||
};
|
||||
|
||||
port@4 {
|
||||
reg = <4>;
|
||||
endpoint {
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ properties:
|
|||
compatible:
|
||||
oneOf:
|
||||
- enum:
|
||||
- qcom,eliza-dpu
|
||||
- qcom,glymur-dpu
|
||||
- qcom,kaanapali-dpu
|
||||
- qcom,sa8775p-dpu
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ properties:
|
|||
const: 2
|
||||
|
||||
"#interrupt-cells":
|
||||
const: 1
|
||||
const: 2
|
||||
|
||||
ngpios:
|
||||
description:
|
||||
|
|
@ -86,7 +86,7 @@ examples:
|
|||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <1>;
|
||||
#interrupt-cells = <2>;
|
||||
interrupts = <53>, <53>, <53>, <53>,
|
||||
<53>, <53>, <53>, <53>,
|
||||
<53>, <53>, <53>, <53>,
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/msm/dsi-phy-10nm.yaml#
|
||||
$id: http://devicetree.org/schemas/phy/qcom,dsi-phy-10nm.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Qualcomm Display DSI 10nm PHY
|
||||
|
|
@ -10,7 +10,7 @@ maintainers:
|
|||
- Krishna Manikandan <quic_mkrishn@quicinc.com>
|
||||
|
||||
allOf:
|
||||
- $ref: dsi-phy-common.yaml#
|
||||
- $ref: qcom,dsi-phy-common.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/msm/dsi-phy-14nm.yaml#
|
||||
$id: http://devicetree.org/schemas/phy/qcom,dsi-phy-14nm.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Qualcomm Display DSI 14nm PHY
|
||||
|
|
@ -10,7 +10,7 @@ maintainers:
|
|||
- Krishna Manikandan <quic_mkrishn@quicinc.com>
|
||||
|
||||
allOf:
|
||||
- $ref: dsi-phy-common.yaml#
|
||||
- $ref: qcom,dsi-phy-common.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/msm/dsi-phy-20nm.yaml#
|
||||
$id: http://devicetree.org/schemas/phy/qcom,dsi-phy-20nm.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Qualcomm Display DSI 20nm PHY
|
||||
|
|
@ -10,7 +10,7 @@ maintainers:
|
|||
- Krishna Manikandan <quic_mkrishn@quicinc.com>
|
||||
|
||||
allOf:
|
||||
- $ref: dsi-phy-common.yaml#
|
||||
- $ref: qcom,dsi-phy-common.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/msm/dsi-phy-28nm.yaml#
|
||||
$id: http://devicetree.org/schemas/phy/qcom,dsi-phy-28nm.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Qualcomm Display DSI 28nm PHY
|
||||
|
|
@ -10,7 +10,7 @@ maintainers:
|
|||
- Krishna Manikandan <quic_mkrishn@quicinc.com>
|
||||
|
||||
allOf:
|
||||
- $ref: dsi-phy-common.yaml#
|
||||
- $ref: qcom,dsi-phy-common.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/msm/dsi-phy-7nm.yaml#
|
||||
$id: http://devicetree.org/schemas/phy/qcom,dsi-phy-7nm.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Qualcomm Display DSI 7nm PHY
|
||||
|
|
@ -10,7 +10,7 @@ maintainers:
|
|||
- Jonathan Marek <jonathan@marek.ca>
|
||||
|
||||
allOf:
|
||||
- $ref: dsi-phy-common.yaml#
|
||||
- $ref: qcom,dsi-phy-common.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
|
|
@ -29,9 +29,14 @@ properties:
|
|||
- qcom,sm8550-dsi-phy-4nm
|
||||
- qcom,sm8650-dsi-phy-4nm
|
||||
- qcom,sm8750-dsi-phy-3nm
|
||||
- items:
|
||||
- enum:
|
||||
- qcom,eliza-dsi-phy-4nm
|
||||
- const: qcom,sm8650-dsi-phy-4nm
|
||||
- items:
|
||||
- enum:
|
||||
- qcom,qcs8300-dsi-phy-5nm
|
||||
- qcom,sc8280xp-dsi-phy-5nm
|
||||
- const: qcom,sa8775p-dsi-phy-5nm
|
||||
|
||||
reg:
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/msm/dsi-phy-common.yaml#
|
||||
$id: http://devicetree.org/schemas/phy/qcom,dsi-phy-common.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Qualcomm Display DSI PHY Common Properties
|
||||
|
|
@ -1089,6 +1089,8 @@ Example output. You may not have all of these fields.
|
|||
CmaFree: 0 kB
|
||||
Unaccepted: 0 kB
|
||||
Balloon: 0 kB
|
||||
GPUActive: 0 kB
|
||||
GPUReclaim: 0 kB
|
||||
HugePages_Total: 0
|
||||
HugePages_Free: 0
|
||||
HugePages_Rsvd: 0
|
||||
|
|
@ -1269,6 +1271,12 @@ Unaccepted
|
|||
Memory that has not been accepted by the guest
|
||||
Balloon
|
||||
Memory returned to Host by VM Balloon Drivers
|
||||
GPUActive
|
||||
System memory allocated to active GPU objects
|
||||
GPUReclaim
|
||||
System memory stored in GPU pools for reuse. This memory is not
|
||||
counted in GPUActive. It is shrinker reclaimable memory kept in a reuse
|
||||
pool because it has non-standard page table attributes, like WC or UC.
|
||||
HugePages_Total, HugePages_Free, HugePages_Rsvd, HugePages_Surp, Hugepagesize, Hugetlb
|
||||
See Documentation/admin-guide/mm/hugetlbpage.rst.
|
||||
DirectMap4k, DirectMap2M, DirectMap1G
|
||||
|
|
|
|||
|
|
@ -51,82 +51,6 @@ There also have been considerations of ToPrimitive [2].
|
|||
| Link: https://lore.kernel.org/all/cover.1750689857.git.y.j3ms.n@gmail.com/ [1]
|
||||
| Link: https://rust-for-linux.zulipchat.com/#narrow/channel/288089-General/topic/Implement.20.60FromPrimitive.60.20trait.20.2B.20derive.20macro.20for.20nova-core/with/541971854 [2]
|
||||
|
||||
Generic register abstraction [REGA]
|
||||
-----------------------------------
|
||||
|
||||
Work out how register constants and structures can be automatically generated
|
||||
through generalized macros.
|
||||
|
||||
Example:
|
||||
|
||||
.. code-block:: rust
|
||||
|
||||
register!(BOOT0, 0x0, u32, pci::Bar<SIZE>, Fields [
|
||||
MINOR_REVISION(3:0, RO),
|
||||
MAJOR_REVISION(7:4, RO),
|
||||
REVISION(7:0, RO), // Virtual register combining major and minor rev.
|
||||
])
|
||||
|
||||
This could expand to something like:
|
||||
|
||||
.. code-block:: rust
|
||||
|
||||
const BOOT0_OFFSET: usize = 0x00000000;
|
||||
const BOOT0_MINOR_REVISION_SHIFT: u8 = 0;
|
||||
const BOOT0_MINOR_REVISION_MASK: u32 = 0x0000000f;
|
||||
const BOOT0_MAJOR_REVISION_SHIFT: u8 = 4;
|
||||
const BOOT0_MAJOR_REVISION_MASK: u32 = 0x000000f0;
|
||||
const BOOT0_REVISION_SHIFT: u8 = BOOT0_MINOR_REVISION_SHIFT;
|
||||
const BOOT0_REVISION_MASK: u32 = BOOT0_MINOR_REVISION_MASK | BOOT0_MAJOR_REVISION_MASK;
|
||||
|
||||
struct Boot0(u32);
|
||||
|
||||
impl Boot0 {
|
||||
#[inline]
|
||||
fn read(bar: &RevocableGuard<'_, pci::Bar<SIZE>>) -> Self {
|
||||
Self(bar.readl(BOOT0_OFFSET))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn minor_revision(&self) -> u32 {
|
||||
(self.0 & BOOT0_MINOR_REVISION_MASK) >> BOOT0_MINOR_REVISION_SHIFT
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn major_revision(&self) -> u32 {
|
||||
(self.0 & BOOT0_MAJOR_REVISION_MASK) >> BOOT0_MAJOR_REVISION_SHIFT
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn revision(&self) -> u32 {
|
||||
(self.0 & BOOT0_REVISION_MASK) >> BOOT0_REVISION_SHIFT
|
||||
}
|
||||
}
|
||||
|
||||
Usage:
|
||||
|
||||
.. code-block:: rust
|
||||
|
||||
let bar = bar.try_access().ok_or(ENXIO)?;
|
||||
|
||||
let boot0 = Boot0::read(&bar);
|
||||
pr_info!("Revision: {}\n", boot0.revision());
|
||||
|
||||
A work-in-progress implementation currently resides in
|
||||
`drivers/gpu/nova-core/regs/macros.rs` and is used in nova-core. It would be
|
||||
nice to improve it (possibly using proc macros) and move it to the `kernel`
|
||||
crate so it can be used by other components as well.
|
||||
|
||||
Features desired before this happens:
|
||||
|
||||
* Make I/O optional I/O (for field values that are not registers),
|
||||
* Support other sizes than `u32`,
|
||||
* Allow visibility control for registers and individual fields,
|
||||
* Use Rust slice syntax to express fields ranges.
|
||||
|
||||
| Complexity: Advanced
|
||||
| Contact: Alexandre Courbot
|
||||
|
||||
Numerical operations [NUMM]
|
||||
---------------------------
|
||||
|
||||
|
|
|
|||
|
|
@ -5,8 +5,138 @@ Security bugs
|
|||
|
||||
Linux kernel developers take security very seriously. As such, we'd
|
||||
like to know when a security bug is found so that it can be fixed and
|
||||
disclosed as quickly as possible. Please report security bugs to the
|
||||
Linux kernel security team.
|
||||
disclosed as quickly as possible.
|
||||
|
||||
Preparing your report
|
||||
---------------------
|
||||
|
||||
Like with any bug report, a security bug report requires a lot of analysis work
|
||||
from the developers, so the more information you can share about the issue, the
|
||||
better. Please review the procedure outlined in
|
||||
Documentation/admin-guide/reporting-issues.rst if you are unclear about what
|
||||
information is helpful. The following information are absolutely necessary in
|
||||
**any** security bug report:
|
||||
|
||||
* **affected kernel version range**: with no version indication, your report
|
||||
will not be processed. A significant part of reports are for bugs that
|
||||
have already been fixed, so it is extremely important that vulnerabilities
|
||||
are verified on recent versions (development tree or latest stable
|
||||
version), at least by verifying that the code has not changed since the
|
||||
version where it was detected.
|
||||
|
||||
* **description of the problem**: a detailed description of the problem, with
|
||||
traces showing its manifestation, and why you consider that the observed
|
||||
behavior as a problem in the kernel, is necessary.
|
||||
|
||||
* **reproducer**: developers will need to be able to reproduce the problem to
|
||||
consider a fix as effective. This includes both a way to trigger the issue
|
||||
and a way to confirm it happens. A reproducer with low complexity
|
||||
dependencies will be needed (source code, shell script, sequence of
|
||||
instructions, file-system image etc). Binary-only executables are not
|
||||
accepted. Working exploits are extremely helpful and will not be released
|
||||
without consent from the reporter, unless they are already public. By
|
||||
definition if an issue cannot be reproduced, it is not exploitable, thus it
|
||||
is not a security bug.
|
||||
|
||||
* **conditions**: if the bug depends on certain configuration options,
|
||||
sysctls, permissions, timing, code modifications etc, these should be
|
||||
indicated.
|
||||
|
||||
In addition, the following information are highly desirable:
|
||||
|
||||
* **suspected location of the bug**: the file names and functions where the
|
||||
bug is suspected to be present are very important, at least to help forward
|
||||
the report to the appropriate maintainers. When not possible (for example,
|
||||
"system freezes each time I run this command"), the security team will help
|
||||
identify the source of the bug.
|
||||
|
||||
* **a proposed fix**: bug reporters who have analyzed the cause of a bug in
|
||||
the source code almost always have an accurate idea on how to fix it,
|
||||
because they spent a long time studying it and its implications. Proposing
|
||||
a tested fix will save maintainers a lot of time, even if the fix ends up
|
||||
not being the right one, because it helps understand the bug. When
|
||||
proposing a tested fix, please always format it in a way that can be
|
||||
immediately merged (see Documentation/process/submitting-patches.rst).
|
||||
This will save some back-and-forth exchanges if it is accepted, and you
|
||||
will be credited for finding and fixing this issue. Note that in this case
|
||||
only a ``Signed-off-by:`` tag is needed, without ``Reported-by:`` when the
|
||||
reporter and author are the same.
|
||||
|
||||
* **mitigations**: very often during a bug analysis, some ways of mitigating
|
||||
the issue appear. It is useful to share them, as they can be helpful to
|
||||
keep end users protected during the time it takes them to apply the fix.
|
||||
|
||||
Identifying contacts
|
||||
--------------------
|
||||
|
||||
The most effective way to report a security bug is to send it directly to the
|
||||
affected subsystem's maintainers and Cc: the Linux kernel security team. Do
|
||||
not send it to a public list at this stage, unless you have good reasons to
|
||||
consider the issue as being public or trivial to discover (e.g. result of a
|
||||
widely available automated vulnerability scanning tool that can be repeated by
|
||||
anyone).
|
||||
|
||||
If you're sending a report for issues affecting multiple parts in the kernel,
|
||||
even if they're fairly similar issues, please send individual messages (think
|
||||
that maintainers will not all work on the issues at the same time). The only
|
||||
exception is when an issue concerns closely related parts maintained by the
|
||||
exact same subset of maintainers, and these parts are expected to be fixed all
|
||||
at once by the same commit, then it may be acceptable to report them at once.
|
||||
|
||||
One difficulty for most first-time reporters is to figure the right list of
|
||||
recipients to send a report to. In the Linux kernel, all official maintainers
|
||||
are trusted, so the consequences of accidentally including the wrong maintainer
|
||||
are essentially a bit more noise for that person, i.e. nothing dramatic. As
|
||||
such, a suitable method to figure the list of maintainers (which kernel
|
||||
security officers use) is to rely on the get_maintainer.pl script, tuned to
|
||||
only report maintainers. This script, when passed a file name, will look for
|
||||
its path in the MAINTAINERS file to figure a hierarchical list of relevant
|
||||
maintainers. Calling it a first time with the finest level of filtering will
|
||||
most of the time return a short list of this specific file's maintainers::
|
||||
|
||||
$ ./scripts/get_maintainer.pl --no-l --no-r --pattern-depth 1 \
|
||||
drivers/example.c
|
||||
Developer One <dev1@example.com> (maintainer:example driver)
|
||||
Developer Two <dev2@example.org> (maintainer:example driver)
|
||||
|
||||
These two maintainers should then receive the message. If the command does not
|
||||
return anything, it means the affected file is part of a wider subsystem, so we
|
||||
should be less specific::
|
||||
|
||||
$ ./scripts/get_maintainer.pl --no-l --no-r drivers/example.c
|
||||
Developer One <dev1@example.com> (maintainer:example subsystem)
|
||||
Developer Two <dev2@example.org> (maintainer:example subsystem)
|
||||
Developer Three <dev3@example.com> (maintainer:example subsystem [GENERAL])
|
||||
Developer Four <dev4@example.org> (maintainer:example subsystem [GENERAL])
|
||||
|
||||
Here, picking the first, most specific ones, is sufficient. When the list is
|
||||
long, it is possible to produce a comma-delimited e-mail address list on a
|
||||
single line suitable for use in the To: field of a mailer like this::
|
||||
|
||||
$ ./scripts/get_maintainer.pl --no-tree --no-l --no-r --no-n --m \
|
||||
--no-git-fallback --no-substatus --no-rolestats --no-multiline \
|
||||
--pattern-depth 1 drivers/example.c
|
||||
dev1@example.com, dev2@example.org
|
||||
|
||||
or this for the wider list::
|
||||
|
||||
$ ./scripts/get_maintainer.pl --no-tree --no-l --no-r --no-n --m \
|
||||
--no-git-fallback --no-substatus --no-rolestats --no-multiline \
|
||||
drivers/example.c
|
||||
dev1@example.com, dev2@example.org, dev3@example.com, dev4@example.org
|
||||
|
||||
If at this point you're still facing difficulties spotting the right
|
||||
maintainers, **and only in this case**, it's possible to send your report to
|
||||
the Linux kernel security team only. Your message will be triaged, and you
|
||||
will receive instructions about whom to contact, if needed. Your message may
|
||||
equally be forwarded as-is to the relevant maintainers.
|
||||
|
||||
Sending the report
|
||||
------------------
|
||||
|
||||
Reports are to be sent over e-mail exclusively. Please use a working e-mail
|
||||
address, preferably the same that you want to appear in ``Reported-by`` tags
|
||||
if any. If unsure, send your report to yourself first.
|
||||
|
||||
The security team and maintainers almost always require additional
|
||||
information beyond what was initially provided in a report and rely on
|
||||
|
|
@ -18,20 +148,12 @@ run additional tests. Reports where the reporter does not respond promptly
|
|||
or cannot effectively discuss their findings may be abandoned if the
|
||||
communication does not quickly improve.
|
||||
|
||||
As it is with any bug, the more information provided the easier it
|
||||
will be to diagnose and fix. Please review the procedure outlined in
|
||||
'Documentation/admin-guide/reporting-issues.rst' if you are unclear about what
|
||||
information is helpful. Any exploit code is very helpful and will not
|
||||
be released without consent from the reporter unless it has already been
|
||||
made public.
|
||||
|
||||
The report must be sent to maintainers, with the security team in ``Cc:``.
|
||||
The Linux kernel security team can be contacted by email at
|
||||
<security@kernel.org>. This is a private list of security officers
|
||||
who will help verify the bug report and develop and release a fix.
|
||||
If you already have a fix, please include it with your report, as
|
||||
that can speed up the process considerably. It is possible that the
|
||||
security team will bring in extra help from area maintainers to
|
||||
understand and fix the security vulnerability.
|
||||
who will help verify the bug report and assist developers working on a fix.
|
||||
It is possible that the security team will bring in extra help from area
|
||||
maintainers to understand and fix the security vulnerability.
|
||||
|
||||
Please send **plain text** emails without attachments where possible.
|
||||
It is much harder to have a context-quoted discussion about a complex
|
||||
|
|
@ -42,7 +164,9 @@ reproduction steps, and follow it with a proposed fix, all in plain text.
|
|||
Markdown, HTML and RST formatted reports are particularly frowned upon since
|
||||
they're quite hard to read for humans and encourage to use dedicated viewers,
|
||||
sometimes online, which by definition is not acceptable for a confidential
|
||||
security report.
|
||||
security report. Note that some mailers tend to mangle formatting of plain
|
||||
text by default, please consult Documentation/process/email-clients.rst for
|
||||
more info.
|
||||
|
||||
Disclosure and embargoed information
|
||||
------------------------------------
|
||||
|
|
|
|||
19
MAINTAINERS
19
MAINTAINERS
|
|
@ -2195,6 +2195,7 @@ L: dri-devel@lists.freedesktop.org
|
|||
S: Supported
|
||||
T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
|
||||
F: Documentation/devicetree/bindings/gpu/arm,mali-valhall-csf.yaml
|
||||
F: drivers/gpu/drm/ci/xfails/panthor*
|
||||
F: drivers/gpu/drm/panthor/
|
||||
F: include/uapi/drm/panthor_drm.h
|
||||
|
||||
|
|
@ -7534,6 +7535,7 @@ F: include/linux/*fence.h
|
|||
F: include/linux/dma-buf.h
|
||||
F: include/linux/dma-buf/
|
||||
F: include/linux/dma-resv.h
|
||||
F: rust/helpers/dma-resv.c
|
||||
K: \bdma_(?:buf|fence|resv)\b
|
||||
|
||||
DMA GENERIC OFFLOAD ENGINE SUBSYSTEM
|
||||
|
|
@ -8513,7 +8515,10 @@ T: git https://gitlab.freedesktop.org/drm/rust/kernel.git
|
|||
F: drivers/gpu/drm/nova/
|
||||
F: drivers/gpu/drm/tyr/
|
||||
F: drivers/gpu/nova-core/
|
||||
F: rust/helpers/gpu.c
|
||||
F: rust/kernel/drm/
|
||||
F: rust/kernel/gpu.rs
|
||||
F: rust/kernel/gpu/
|
||||
|
||||
DRM DRIVERS FOR ALLWINNER A10
|
||||
M: Chen-Yu Tsai <wens@kernel.org>
|
||||
|
|
@ -8931,7 +8936,7 @@ F: include/drm/ttm/
|
|||
GPU BUDDY ALLOCATOR
|
||||
M: Matthew Auld <matthew.auld@intel.com>
|
||||
M: Arun Pravin <arunpravin.paneerselvam@amd.com>
|
||||
R: Christian Koenig <christian.koenig@amd.com>
|
||||
R: Joel Fernandes <joelagnelf@nvidia.com>
|
||||
L: dri-devel@lists.freedesktop.org
|
||||
S: Maintained
|
||||
T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
|
||||
|
|
@ -8940,6 +8945,9 @@ F: drivers/gpu/drm/drm_buddy.c
|
|||
F: drivers/gpu/tests/gpu_buddy_test.c
|
||||
F: include/drm/drm_buddy.h
|
||||
F: include/linux/gpu_buddy.h
|
||||
F: rust/helpers/gpu.c
|
||||
F: rust/kernel/gpu.rs
|
||||
F: rust/kernel/gpu/
|
||||
|
||||
DRM AUTOMATED TESTING
|
||||
M: Helen Koike <helen.fornazier@gmail.com>
|
||||
|
|
@ -23208,6 +23216,15 @@ T: git https://github.com/Rust-for-Linux/linux.git alloc-next
|
|||
F: rust/kernel/alloc.rs
|
||||
F: rust/kernel/alloc/
|
||||
|
||||
RUST [INTEROP]
|
||||
M: Joel Fernandes <joelagnelf@nvidia.com>
|
||||
M: Alexandre Courbot <acourbot@nvidia.com>
|
||||
L: rust-for-linux@vger.kernel.org
|
||||
S: Maintained
|
||||
T: git https://github.com/Rust-for-Linux/linux.git interop-next
|
||||
F: rust/kernel/interop.rs
|
||||
F: rust/kernel/interop/
|
||||
|
||||
RUST [NUM]
|
||||
M: Alexandre Courbot <acourbot@nvidia.com>
|
||||
R: Yury Norov <yury.norov@gmail.com>
|
||||
|
|
|
|||
2
Makefile
2
Makefile
|
|
@ -2,7 +2,7 @@
|
|||
VERSION = 7
|
||||
PATCHLEVEL = 0
|
||||
SUBLEVEL = 0
|
||||
EXTRAVERSION = -rc6
|
||||
EXTRAVERSION = -rc7
|
||||
NAME = Baby Opossum Posse
|
||||
|
||||
# *DOCUMENTATION*
|
||||
|
|
|
|||
|
|
@ -252,6 +252,7 @@ config ARM64
|
|||
select HAVE_RSEQ
|
||||
select HAVE_RUST if RUSTC_SUPPORTS_ARM64
|
||||
select HAVE_STACKPROTECTOR
|
||||
select HAVE_STATIC_CALL if CFI
|
||||
select HAVE_SYSCALL_TRACEPOINTS
|
||||
select HAVE_KPROBES
|
||||
select HAVE_KRETPROBES
|
||||
|
|
|
|||
31
arch/arm64/include/asm/static_call.h
Normal file
31
arch/arm64/include/asm/static_call.h
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef _ASM_STATIC_CALL_H
|
||||
#define _ASM_STATIC_CALL_H
|
||||
|
||||
#define __ARCH_DEFINE_STATIC_CALL_TRAMP(name, target) \
|
||||
asm(" .pushsection .static_call.text, \"ax\" \n" \
|
||||
" .align 4 \n" \
|
||||
" .globl " name " \n" \
|
||||
name ": \n" \
|
||||
" hint 34 /* BTI C */ \n" \
|
||||
" adrp x16, 1f \n" \
|
||||
" ldr x16, [x16, :lo12:1f] \n" \
|
||||
" br x16 \n" \
|
||||
" .type " name ", %function \n" \
|
||||
" .size " name ", . - " name " \n" \
|
||||
" .popsection \n" \
|
||||
" .pushsection .rodata, \"a\" \n" \
|
||||
" .align 3 \n" \
|
||||
"1: .quad " target " \n" \
|
||||
" .popsection \n")
|
||||
|
||||
#define ARCH_DEFINE_STATIC_CALL_TRAMP(name, func) \
|
||||
__ARCH_DEFINE_STATIC_CALL_TRAMP(STATIC_CALL_TRAMP_STR(name), #func)
|
||||
|
||||
#define ARCH_DEFINE_STATIC_CALL_NULL_TRAMP(name) \
|
||||
ARCH_DEFINE_STATIC_CALL_TRAMP(name, __static_call_return0)
|
||||
|
||||
#define ARCH_DEFINE_STATIC_CALL_RET0_TRAMP(name) \
|
||||
ARCH_DEFINE_STATIC_CALL_TRAMP(name, __static_call_return0)
|
||||
|
||||
#endif /* _ASM_STATIC_CALL_H */
|
||||
|
|
@ -46,6 +46,7 @@ obj-$(CONFIG_MODULES) += module.o module-plts.o
|
|||
obj-$(CONFIG_PERF_EVENTS) += perf_regs.o perf_callchain.o
|
||||
obj-$(CONFIG_HARDLOCKUP_DETECTOR_PERF) += watchdog_hld.o
|
||||
obj-$(CONFIG_HAVE_HW_BREAKPOINT) += hw_breakpoint.o
|
||||
obj-$(CONFIG_HAVE_STATIC_CALL) += static_call.o
|
||||
obj-$(CONFIG_CPU_PM) += sleep.o suspend.o
|
||||
obj-$(CONFIG_KGDB) += kgdb.o
|
||||
obj-$(CONFIG_EFI) += efi.o efi-rt-wrapper.o
|
||||
|
|
|
|||
23
arch/arm64/kernel/static_call.c
Normal file
23
arch/arm64/kernel/static_call.c
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
#include <linux/static_call.h>
|
||||
#include <linux/memory.h>
|
||||
#include <asm/text-patching.h>
|
||||
|
||||
void arch_static_call_transform(void *site, void *tramp, void *func, bool tail)
|
||||
{
|
||||
u64 literal;
|
||||
int ret;
|
||||
|
||||
if (!func)
|
||||
func = __static_call_return0;
|
||||
|
||||
/* decode the instructions to discover the literal address */
|
||||
literal = ALIGN_DOWN((u64)tramp + 4, SZ_4K) +
|
||||
aarch64_insn_adrp_get_offset(le32_to_cpup(tramp + 4)) +
|
||||
8 * aarch64_insn_decode_immediate(AARCH64_INSN_IMM_12,
|
||||
le32_to_cpup(tramp + 8));
|
||||
|
||||
ret = aarch64_insn_write_literal_u64((void *)literal, (u64)func);
|
||||
WARN_ON_ONCE(ret);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(arch_static_call_transform);
|
||||
|
|
@ -191,6 +191,7 @@ SECTIONS
|
|||
LOCK_TEXT
|
||||
KPROBES_TEXT
|
||||
HYPERVISOR_TEXT
|
||||
STATIC_CALL_TEXT
|
||||
*(.gnu.warning)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -484,7 +484,6 @@
|
|||
# endif
|
||||
# ifndef cpu_vmbits
|
||||
# define cpu_vmbits cpu_data[0].vmbits
|
||||
# define __NEED_VMBITS_PROBE
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -80,9 +80,7 @@ struct cpuinfo_mips {
|
|||
int srsets; /* Shadow register sets */
|
||||
int package;/* physical package number */
|
||||
unsigned int globalnumber;
|
||||
#ifdef CONFIG_64BIT
|
||||
int vmbits; /* Virtual memory size in bits */
|
||||
#endif
|
||||
void *data; /* Additional data */
|
||||
unsigned int watch_reg_count; /* Number that exist */
|
||||
unsigned int watch_reg_use_cnt; /* Usable by ptrace */
|
||||
|
|
|
|||
|
|
@ -1871,6 +1871,8 @@ do { \
|
|||
|
||||
#define read_c0_entryhi() __read_ulong_c0_register($10, 0)
|
||||
#define write_c0_entryhi(val) __write_ulong_c0_register($10, 0, val)
|
||||
#define read_c0_entryhi_64() __read_64bit_c0_register($10, 0)
|
||||
#define write_c0_entryhi_64(val) __write_64bit_c0_register($10, 0, val)
|
||||
|
||||
#define read_c0_guestctl1() __read_32bit_c0_register($10, 4)
|
||||
#define write_c0_guestctl1(val) __write_32bit_c0_register($10, 4, val)
|
||||
|
|
|
|||
|
|
@ -210,11 +210,14 @@ static inline void set_elf_base_platform(const char *plat)
|
|||
|
||||
static inline void cpu_probe_vmbits(struct cpuinfo_mips *c)
|
||||
{
|
||||
#ifdef __NEED_VMBITS_PROBE
|
||||
write_c0_entryhi(0x3fffffffffffe000ULL);
|
||||
back_to_back_c0_hazard();
|
||||
c->vmbits = fls64(read_c0_entryhi() & 0x3fffffffffffe000ULL);
|
||||
#endif
|
||||
int vmbits = 31;
|
||||
|
||||
if (cpu_has_64bits) {
|
||||
write_c0_entryhi_64(0x3fffffffffffe000ULL);
|
||||
back_to_back_c0_hazard();
|
||||
vmbits = fls64(read_c0_entryhi_64() & 0x3fffffffffffe000ULL);
|
||||
}
|
||||
c->vmbits = vmbits;
|
||||
}
|
||||
|
||||
static void set_isa(struct cpuinfo_mips *c, unsigned int isa)
|
||||
|
|
|
|||
|
|
@ -137,6 +137,8 @@ void cpu_probe(void)
|
|||
else
|
||||
cpu_set_nofpu_opts(c);
|
||||
|
||||
c->vmbits = 31;
|
||||
|
||||
reserve_exception_space(0, 0x400);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,12 +4,12 @@
|
|||
#include "libgcc.h"
|
||||
|
||||
/*
|
||||
* GCC 7 & older can suboptimally generate __multi3 calls for mips64r6, so for
|
||||
* GCC 9 & older can suboptimally generate __multi3 calls for mips64r6, so for
|
||||
* that specific case only we implement that intrinsic here.
|
||||
*
|
||||
* See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82981
|
||||
*/
|
||||
#if defined(CONFIG_64BIT) && defined(CONFIG_CPU_MIPSR6) && (__GNUC__ < 8)
|
||||
#if defined(CONFIG_64BIT) && defined(CONFIG_CPU_MIPSR6) && (__GNUC__ < 10)
|
||||
|
||||
/* multiply 64-bit values, low 64-bits returned */
|
||||
static inline long long notrace dmulu(long long a, long long b)
|
||||
|
|
@ -51,4 +51,4 @@ ti_type notrace __multi3(ti_type a, ti_type b)
|
|||
}
|
||||
EXPORT_SYMBOL(__multi3);
|
||||
|
||||
#endif /* 64BIT && CPU_MIPSR6 && GCC7 */
|
||||
#endif /* 64BIT && CPU_MIPSR6 && GCC9 */
|
||||
|
|
|
|||
|
|
@ -17,7 +17,9 @@
|
|||
#include <linux/dma-map-ops.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/libfdt.h>
|
||||
#include <linux/minmax.h>
|
||||
#include <linux/pci_ids.h>
|
||||
#include <linux/serial_core.h>
|
||||
#include <linux/string_choices.h>
|
||||
#include <asm/bootinfo.h>
|
||||
#include <loongson.h>
|
||||
|
|
@ -106,9 +108,23 @@ static void __init lefi_fixup_fdt(struct system_loongson *system)
|
|||
|
||||
is_loongson64g = (read_c0_prid() & PRID_IMP_MASK) == PRID_IMP_LOONGSON_64G;
|
||||
|
||||
for (i = 0; i < system->nr_uarts; i++) {
|
||||
for (i = 0; i < min(system->nr_uarts, MAX_UARTS); i++) {
|
||||
uartdev = &system->uarts[i];
|
||||
|
||||
/*
|
||||
* Some firmware does not set nr_uarts properly and passes empty
|
||||
* items. Ignore them silently.
|
||||
*/
|
||||
if (uartdev->uart_base == 0)
|
||||
continue;
|
||||
|
||||
/* Our DT only works with UPIO_MEM. */
|
||||
if (uartdev->iotype != UPIO_MEM) {
|
||||
pr_warn("Ignore UART 0x%llx with iotype %u passed by firmware\n",
|
||||
uartdev->uart_base, uartdev->iotype);
|
||||
continue;
|
||||
}
|
||||
|
||||
ret = lefi_fixup_fdt_serial(fdt_buf, uartdev->uart_base,
|
||||
uartdev->uartclk);
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -207,7 +207,8 @@ void cpu_cache_init(void)
|
|||
{
|
||||
if (IS_ENABLED(CONFIG_CPU_R3000) && cpu_has_3k_cache)
|
||||
r3k_cache_init();
|
||||
if (IS_ENABLED(CONFIG_CPU_R4K_CACHE_TLB) && cpu_has_4k_cache)
|
||||
if ((IS_ENABLED(CONFIG_CPU_R4K_CACHE_TLB) ||
|
||||
IS_ENABLED(CONFIG_CPU_SB1)) && cpu_has_4k_cache)
|
||||
r4k_cache_init();
|
||||
|
||||
if (IS_ENABLED(CONFIG_CPU_CAVIUM_OCTEON) && cpu_has_octeon_cache)
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@
|
|||
#include <linux/sched.h>
|
||||
#include <linux/smp.h>
|
||||
#include <linux/memblock.h>
|
||||
#include <linux/minmax.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/hugetlb.h>
|
||||
#include <linux/export.h>
|
||||
|
|
@ -24,6 +25,7 @@
|
|||
#include <asm/hazards.h>
|
||||
#include <asm/mmu_context.h>
|
||||
#include <asm/tlb.h>
|
||||
#include <asm/tlbdebug.h>
|
||||
#include <asm/tlbex.h>
|
||||
#include <asm/tlbmisc.h>
|
||||
#include <asm/setup.h>
|
||||
|
|
@ -511,12 +513,229 @@ static int __init set_ntlb(char *str)
|
|||
__setup("ntlb=", set_ntlb);
|
||||
|
||||
|
||||
/* Comparison function for EntryHi VPN fields. */
|
||||
static int r4k_vpn_cmp(const void *a, const void *b)
|
||||
/* The start bit position of VPN2 and Mask in EntryHi/PageMask registers. */
|
||||
#define VPN2_SHIFT 13
|
||||
|
||||
/* Read full EntryHi even with CONFIG_32BIT. */
|
||||
static inline unsigned long long read_c0_entryhi_native(void)
|
||||
{
|
||||
long v = *(unsigned long *)a - *(unsigned long *)b;
|
||||
int s = sizeof(long) > sizeof(int) ? sizeof(long) * 8 - 1: 0;
|
||||
return s ? (v != 0) | v >> s : v;
|
||||
return cpu_has_64bits ? read_c0_entryhi_64() : read_c0_entryhi();
|
||||
}
|
||||
|
||||
/* Write full EntryHi even with CONFIG_32BIT. */
|
||||
static inline void write_c0_entryhi_native(unsigned long long v)
|
||||
{
|
||||
if (cpu_has_64bits)
|
||||
write_c0_entryhi_64(v);
|
||||
else
|
||||
write_c0_entryhi(v);
|
||||
}
|
||||
|
||||
/* TLB entry state for uniquification. */
|
||||
struct tlbent {
|
||||
unsigned long long wired:1;
|
||||
unsigned long long global:1;
|
||||
unsigned long long asid:10;
|
||||
unsigned long long vpn:51;
|
||||
unsigned long long pagesz:5;
|
||||
unsigned long long index:14;
|
||||
};
|
||||
|
||||
/*
|
||||
* Comparison function for TLB entry sorting. Place wired entries first,
|
||||
* then global entries, then order by the increasing VPN/ASID and the
|
||||
* decreasing page size. This lets us avoid clashes with wired entries
|
||||
* easily and get entries for larger pages out of the way first.
|
||||
*
|
||||
* We could group bits so as to reduce the number of comparisons, but this
|
||||
* is seldom executed and not performance-critical, so prefer legibility.
|
||||
*/
|
||||
static int r4k_entry_cmp(const void *a, const void *b)
|
||||
{
|
||||
struct tlbent ea = *(struct tlbent *)a, eb = *(struct tlbent *)b;
|
||||
|
||||
if (ea.wired > eb.wired)
|
||||
return -1;
|
||||
else if (ea.wired < eb.wired)
|
||||
return 1;
|
||||
else if (ea.global > eb.global)
|
||||
return -1;
|
||||
else if (ea.global < eb.global)
|
||||
return 1;
|
||||
else if (ea.vpn < eb.vpn)
|
||||
return -1;
|
||||
else if (ea.vpn > eb.vpn)
|
||||
return 1;
|
||||
else if (ea.asid < eb.asid)
|
||||
return -1;
|
||||
else if (ea.asid > eb.asid)
|
||||
return 1;
|
||||
else if (ea.pagesz > eb.pagesz)
|
||||
return -1;
|
||||
else if (ea.pagesz < eb.pagesz)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Fetch all the TLB entries. Mask individual VPN values retrieved with
|
||||
* the corresponding page mask and ignoring any 1KiB extension as we'll
|
||||
* be using 4KiB pages for uniquification.
|
||||
*/
|
||||
static void __ref r4k_tlb_uniquify_read(struct tlbent *tlb_vpns, int tlbsize)
|
||||
{
|
||||
int start = num_wired_entries();
|
||||
unsigned long long vpn_mask;
|
||||
bool global;
|
||||
int i;
|
||||
|
||||
vpn_mask = GENMASK(current_cpu_data.vmbits - 1, VPN2_SHIFT);
|
||||
vpn_mask |= cpu_has_64bits ? 3ULL << 62 : 1 << 31;
|
||||
|
||||
for (i = 0; i < tlbsize; i++) {
|
||||
unsigned long long entryhi, vpn, mask, asid;
|
||||
unsigned int pagesz;
|
||||
|
||||
write_c0_index(i);
|
||||
mtc0_tlbr_hazard();
|
||||
tlb_read();
|
||||
tlb_read_hazard();
|
||||
|
||||
global = !!(read_c0_entrylo0() & ENTRYLO_G);
|
||||
entryhi = read_c0_entryhi_native();
|
||||
mask = read_c0_pagemask();
|
||||
|
||||
asid = entryhi & cpu_asid_mask(¤t_cpu_data);
|
||||
vpn = (entryhi & vpn_mask & ~mask) >> VPN2_SHIFT;
|
||||
pagesz = ilog2((mask >> VPN2_SHIFT) + 1);
|
||||
|
||||
tlb_vpns[i].global = global;
|
||||
tlb_vpns[i].asid = global ? 0 : asid;
|
||||
tlb_vpns[i].vpn = vpn;
|
||||
tlb_vpns[i].pagesz = pagesz;
|
||||
tlb_vpns[i].wired = i < start;
|
||||
tlb_vpns[i].index = i;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Write unique values to all but the wired TLB entries each, using
|
||||
* the 4KiB page size. This size might not be supported with R6, but
|
||||
* EHINV is mandatory for R6, so we won't ever be called in that case.
|
||||
*
|
||||
* A sorted table is supplied with any wired entries at the beginning,
|
||||
* followed by any global entries, and then finally regular entries.
|
||||
* We start at the VPN and ASID values of zero and only assign user
|
||||
* addresses, therefore guaranteeing no clash with addresses produced
|
||||
* by UNIQUE_ENTRYHI. We avoid any VPN values used by wired or global
|
||||
* entries, by increasing the VPN value beyond the span of such entry.
|
||||
*
|
||||
* When a VPN/ASID clash is found with a regular entry we increment the
|
||||
* ASID instead until no VPN/ASID clash has been found or the ASID space
|
||||
* has been exhausted, in which case we increase the VPN value beyond
|
||||
* the span of the largest clashing entry.
|
||||
*
|
||||
* We do not need to be concerned about FTLB or MMID configurations as
|
||||
* those are required to implement the EHINV feature.
|
||||
*/
|
||||
static void __ref r4k_tlb_uniquify_write(struct tlbent *tlb_vpns, int tlbsize)
|
||||
{
|
||||
unsigned long long asid, vpn, vpn_size, pagesz;
|
||||
int widx, gidx, idx, sidx, lidx, i;
|
||||
|
||||
vpn_size = 1ULL << (current_cpu_data.vmbits - VPN2_SHIFT);
|
||||
pagesz = ilog2((PM_4K >> VPN2_SHIFT) + 1);
|
||||
|
||||
write_c0_pagemask(PM_4K);
|
||||
write_c0_entrylo0(0);
|
||||
write_c0_entrylo1(0);
|
||||
|
||||
asid = 0;
|
||||
vpn = 0;
|
||||
widx = 0;
|
||||
gidx = 0;
|
||||
for (sidx = 0; sidx < tlbsize && tlb_vpns[sidx].wired; sidx++)
|
||||
;
|
||||
for (lidx = sidx; lidx < tlbsize && tlb_vpns[lidx].global; lidx++)
|
||||
;
|
||||
idx = gidx = sidx + 1;
|
||||
for (i = sidx; i < tlbsize; i++) {
|
||||
unsigned long long entryhi, vpn_pagesz = 0;
|
||||
|
||||
while (1) {
|
||||
if (WARN_ON(vpn >= vpn_size)) {
|
||||
dump_tlb_all();
|
||||
/* Pray local_flush_tlb_all() will cope. */
|
||||
return;
|
||||
}
|
||||
|
||||
/* VPN must be below the next wired entry. */
|
||||
if (widx < sidx && vpn >= tlb_vpns[widx].vpn) {
|
||||
vpn = max(vpn,
|
||||
(tlb_vpns[widx].vpn +
|
||||
(1ULL << tlb_vpns[widx].pagesz)));
|
||||
asid = 0;
|
||||
widx++;
|
||||
continue;
|
||||
}
|
||||
/* VPN must be below the next global entry. */
|
||||
if (gidx < lidx && vpn >= tlb_vpns[gidx].vpn) {
|
||||
vpn = max(vpn,
|
||||
(tlb_vpns[gidx].vpn +
|
||||
(1ULL << tlb_vpns[gidx].pagesz)));
|
||||
asid = 0;
|
||||
gidx++;
|
||||
continue;
|
||||
}
|
||||
/* Try to find a free ASID so as to conserve VPNs. */
|
||||
if (idx < tlbsize && vpn == tlb_vpns[idx].vpn &&
|
||||
asid == tlb_vpns[idx].asid) {
|
||||
unsigned long long idx_pagesz;
|
||||
|
||||
idx_pagesz = tlb_vpns[idx].pagesz;
|
||||
vpn_pagesz = max(vpn_pagesz, idx_pagesz);
|
||||
do
|
||||
idx++;
|
||||
while (idx < tlbsize &&
|
||||
vpn == tlb_vpns[idx].vpn &&
|
||||
asid == tlb_vpns[idx].asid);
|
||||
asid++;
|
||||
if (asid > cpu_asid_mask(¤t_cpu_data)) {
|
||||
vpn += vpn_pagesz;
|
||||
asid = 0;
|
||||
vpn_pagesz = 0;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
/* VPN mustn't be above the next regular entry. */
|
||||
if (idx < tlbsize && vpn > tlb_vpns[idx].vpn) {
|
||||
vpn = max(vpn,
|
||||
(tlb_vpns[idx].vpn +
|
||||
(1ULL << tlb_vpns[idx].pagesz)));
|
||||
asid = 0;
|
||||
idx++;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
entryhi = (vpn << VPN2_SHIFT) | asid;
|
||||
write_c0_entryhi_native(entryhi);
|
||||
write_c0_index(tlb_vpns[i].index);
|
||||
mtc0_tlbw_hazard();
|
||||
tlb_write_indexed();
|
||||
|
||||
tlb_vpns[i].asid = asid;
|
||||
tlb_vpns[i].vpn = vpn;
|
||||
tlb_vpns[i].pagesz = pagesz;
|
||||
|
||||
asid++;
|
||||
if (asid > cpu_asid_mask(¤t_cpu_data)) {
|
||||
vpn += 1ULL << pagesz;
|
||||
asid = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -527,70 +746,25 @@ static void __ref r4k_tlb_uniquify(void)
|
|||
{
|
||||
int tlbsize = current_cpu_data.tlbsize;
|
||||
bool use_slab = slab_is_available();
|
||||
int start = num_wired_entries();
|
||||
phys_addr_t tlb_vpn_size;
|
||||
unsigned long *tlb_vpns;
|
||||
unsigned long vpn_mask;
|
||||
int cnt, ent, idx, i;
|
||||
|
||||
vpn_mask = GENMASK(cpu_vmbits - 1, 13);
|
||||
vpn_mask |= IS_ENABLED(CONFIG_64BIT) ? 3ULL << 62 : 1 << 31;
|
||||
struct tlbent *tlb_vpns;
|
||||
|
||||
tlb_vpn_size = tlbsize * sizeof(*tlb_vpns);
|
||||
tlb_vpns = (use_slab ?
|
||||
kmalloc(tlb_vpn_size, GFP_KERNEL) :
|
||||
kmalloc(tlb_vpn_size, GFP_ATOMIC) :
|
||||
memblock_alloc_raw(tlb_vpn_size, sizeof(*tlb_vpns)));
|
||||
if (WARN_ON(!tlb_vpns))
|
||||
return; /* Pray local_flush_tlb_all() is good enough. */
|
||||
|
||||
htw_stop();
|
||||
|
||||
for (i = start, cnt = 0; i < tlbsize; i++, cnt++) {
|
||||
unsigned long vpn;
|
||||
r4k_tlb_uniquify_read(tlb_vpns, tlbsize);
|
||||
|
||||
write_c0_index(i);
|
||||
mtc0_tlbr_hazard();
|
||||
tlb_read();
|
||||
tlb_read_hazard();
|
||||
vpn = read_c0_entryhi();
|
||||
vpn &= vpn_mask & PAGE_MASK;
|
||||
tlb_vpns[cnt] = vpn;
|
||||
sort(tlb_vpns, tlbsize, sizeof(*tlb_vpns), r4k_entry_cmp, NULL);
|
||||
|
||||
/* Prevent any large pages from overlapping regular ones. */
|
||||
write_c0_pagemask(read_c0_pagemask() & PM_DEFAULT_MASK);
|
||||
mtc0_tlbw_hazard();
|
||||
tlb_write_indexed();
|
||||
tlbw_use_hazard();
|
||||
}
|
||||
|
||||
sort(tlb_vpns, cnt, sizeof(tlb_vpns[0]), r4k_vpn_cmp, NULL);
|
||||
r4k_tlb_uniquify_write(tlb_vpns, tlbsize);
|
||||
|
||||
write_c0_pagemask(PM_DEFAULT_MASK);
|
||||
write_c0_entrylo0(0);
|
||||
write_c0_entrylo1(0);
|
||||
|
||||
idx = 0;
|
||||
ent = tlbsize;
|
||||
for (i = start; i < tlbsize; i++)
|
||||
while (1) {
|
||||
unsigned long entryhi, vpn;
|
||||
|
||||
entryhi = UNIQUE_ENTRYHI(ent);
|
||||
vpn = entryhi & vpn_mask & PAGE_MASK;
|
||||
|
||||
if (idx >= cnt || vpn < tlb_vpns[idx]) {
|
||||
write_c0_entryhi(entryhi);
|
||||
write_c0_index(i);
|
||||
mtc0_tlbw_hazard();
|
||||
tlb_write_indexed();
|
||||
ent++;
|
||||
break;
|
||||
} else if (vpn == tlb_vpns[idx]) {
|
||||
ent++;
|
||||
} else {
|
||||
idx++;
|
||||
}
|
||||
}
|
||||
|
||||
tlbw_use_hazard();
|
||||
htw_start();
|
||||
|
|
@ -640,7 +814,8 @@ static void r4k_tlb_configure(void)
|
|||
temp_tlb_entry = current_cpu_data.tlbsize - 1;
|
||||
|
||||
/* From this point on the ARC firmware is dead. */
|
||||
r4k_tlb_uniquify();
|
||||
if (!cpu_has_tlbinv)
|
||||
r4k_tlb_uniquify();
|
||||
local_flush_tlb_all();
|
||||
|
||||
/* Did I tell you that ARC SUCKS? */
|
||||
|
|
|
|||
|
|
@ -21,16 +21,16 @@ static const char *clk_cpu(int *idx)
|
|||
{
|
||||
switch (ralink_soc) {
|
||||
case RT2880_SOC:
|
||||
*idx = 0;
|
||||
*idx = 1;
|
||||
return "ralink,rt2880-sysc";
|
||||
case RT3883_SOC:
|
||||
*idx = 0;
|
||||
*idx = 1;
|
||||
return "ralink,rt3883-sysc";
|
||||
case RT305X_SOC_RT3050:
|
||||
*idx = 0;
|
||||
*idx = 1;
|
||||
return "ralink,rt3050-sysc";
|
||||
case RT305X_SOC_RT3052:
|
||||
*idx = 0;
|
||||
*idx = 1;
|
||||
return "ralink,rt3052-sysc";
|
||||
case RT305X_SOC_RT3350:
|
||||
*idx = 1;
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ bool arch_dma_unmap_sg_direct(struct device *dev, struct scatterlist *sg,
|
|||
}
|
||||
bool arch_dma_alloc_direct(struct device *dev)
|
||||
{
|
||||
if (dev->dma_ops_bypass)
|
||||
if (dev->dma_ops_bypass && dev->bus_dma_limit)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
|
|
@ -75,7 +75,7 @@ bool arch_dma_alloc_direct(struct device *dev)
|
|||
|
||||
bool arch_dma_free_direct(struct device *dev, dma_addr_t dma_handle)
|
||||
{
|
||||
if (!dev->dma_ops_bypass)
|
||||
if (!dev->dma_ops_bypass || !dev->bus_dma_limit)
|
||||
return false;
|
||||
|
||||
return is_direct_handle(dev, dma_handle);
|
||||
|
|
|
|||
|
|
@ -2,6 +2,10 @@
|
|||
#ifndef _ASM_RISCV_RUNTIME_CONST_H
|
||||
#define _ASM_RISCV_RUNTIME_CONST_H
|
||||
|
||||
#ifdef MODULE
|
||||
#error "Cannot use runtime-const infrastructure from modules"
|
||||
#endif
|
||||
|
||||
#include <asm/asm.h>
|
||||
#include <asm/alternative.h>
|
||||
#include <asm/cacheflush.h>
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
#ifndef __ASSEMBLER__
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/const.h>
|
||||
|
||||
#define PTRACE_GETFDPIC 33
|
||||
|
||||
|
|
@ -138,12 +139,12 @@ struct __sc_riscv_cfi_state {
|
|||
#define PTRACE_CFI_SS_LOCK_BIT 4
|
||||
#define PTRACE_CFI_SS_PTR_BIT 5
|
||||
|
||||
#define PTRACE_CFI_LP_EN_STATE BIT(PTRACE_CFI_LP_EN_BIT)
|
||||
#define PTRACE_CFI_LP_LOCK_STATE BIT(PTRACE_CFI_LP_LOCK_BIT)
|
||||
#define PTRACE_CFI_ELP_STATE BIT(PTRACE_CFI_ELP_BIT)
|
||||
#define PTRACE_CFI_SS_EN_STATE BIT(PTRACE_CFI_SS_EN_BIT)
|
||||
#define PTRACE_CFI_SS_LOCK_STATE BIT(PTRACE_CFI_SS_LOCK_BIT)
|
||||
#define PTRACE_CFI_SS_PTR_STATE BIT(PTRACE_CFI_SS_PTR_BIT)
|
||||
#define PTRACE_CFI_LP_EN_STATE _BITUL(PTRACE_CFI_LP_EN_BIT)
|
||||
#define PTRACE_CFI_LP_LOCK_STATE _BITUL(PTRACE_CFI_LP_LOCK_BIT)
|
||||
#define PTRACE_CFI_ELP_STATE _BITUL(PTRACE_CFI_ELP_BIT)
|
||||
#define PTRACE_CFI_SS_EN_STATE _BITUL(PTRACE_CFI_SS_EN_BIT)
|
||||
#define PTRACE_CFI_SS_LOCK_STATE _BITUL(PTRACE_CFI_SS_LOCK_BIT)
|
||||
#define PTRACE_CFI_SS_PTR_STATE _BITUL(PTRACE_CFI_SS_PTR_BIT)
|
||||
|
||||
#define PRACE_CFI_STATE_INVALID_MASK ~(PTRACE_CFI_LP_EN_STATE | \
|
||||
PTRACE_CFI_LP_LOCK_STATE | \
|
||||
|
|
|
|||
|
|
@ -175,7 +175,7 @@ struct dbg_reg_def_t dbg_reg_def[DBG_MAX_REG_NUM] = {
|
|||
{DBG_REG_T1, GDB_SIZEOF_REG, offsetof(struct pt_regs, t1)},
|
||||
{DBG_REG_T2, GDB_SIZEOF_REG, offsetof(struct pt_regs, t2)},
|
||||
{DBG_REG_FP, GDB_SIZEOF_REG, offsetof(struct pt_regs, s0)},
|
||||
{DBG_REG_S1, GDB_SIZEOF_REG, offsetof(struct pt_regs, a1)},
|
||||
{DBG_REG_S1, GDB_SIZEOF_REG, offsetof(struct pt_regs, s1)},
|
||||
{DBG_REG_A0, GDB_SIZEOF_REG, offsetof(struct pt_regs, a0)},
|
||||
{DBG_REG_A1, GDB_SIZEOF_REG, offsetof(struct pt_regs, a1)},
|
||||
{DBG_REG_A2, GDB_SIZEOF_REG, offsetof(struct pt_regs, a2)},
|
||||
|
|
@ -244,8 +244,9 @@ sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *task)
|
|||
gdb_regs[DBG_REG_S6_OFF] = task->thread.s[6];
|
||||
gdb_regs[DBG_REG_S7_OFF] = task->thread.s[7];
|
||||
gdb_regs[DBG_REG_S8_OFF] = task->thread.s[8];
|
||||
gdb_regs[DBG_REG_S9_OFF] = task->thread.s[10];
|
||||
gdb_regs[DBG_REG_S10_OFF] = task->thread.s[11];
|
||||
gdb_regs[DBG_REG_S9_OFF] = task->thread.s[9];
|
||||
gdb_regs[DBG_REG_S10_OFF] = task->thread.s[10];
|
||||
gdb_regs[DBG_REG_S11_OFF] = task->thread.s[11];
|
||||
gdb_regs[DBG_REG_EPC_OFF] = task->thread.ra;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -42,19 +42,20 @@ static inline bool is_kernel_exittext(uintptr_t addr)
|
|||
static __always_inline void *patch_map(void *addr, const unsigned int fixmap)
|
||||
{
|
||||
uintptr_t uintaddr = (uintptr_t) addr;
|
||||
struct page *page;
|
||||
phys_addr_t phys;
|
||||
|
||||
if (core_kernel_text(uintaddr) || is_kernel_exittext(uintaddr))
|
||||
page = phys_to_page(__pa_symbol(addr));
|
||||
else if (IS_ENABLED(CONFIG_STRICT_MODULE_RWX))
|
||||
page = vmalloc_to_page(addr);
|
||||
else
|
||||
if (core_kernel_text(uintaddr) || is_kernel_exittext(uintaddr)) {
|
||||
phys = __pa_symbol(addr);
|
||||
} else if (IS_ENABLED(CONFIG_STRICT_MODULE_RWX)) {
|
||||
struct page *page = vmalloc_to_page(addr);
|
||||
|
||||
BUG_ON(!page);
|
||||
phys = page_to_phys(page) + offset_in_page(addr);
|
||||
} else {
|
||||
return addr;
|
||||
}
|
||||
|
||||
BUG_ON(!page);
|
||||
|
||||
return (void *)set_fixmap_offset(fixmap, page_to_phys(page) +
|
||||
offset_in_page(addr));
|
||||
return (void *)set_fixmap_offset(fixmap, phys);
|
||||
}
|
||||
|
||||
static void patch_unmap(int fixmap)
|
||||
|
|
|
|||
|
|
@ -347,8 +347,10 @@ long set_tagged_addr_ctrl(struct task_struct *task, unsigned long arg)
|
|||
if (arg & PR_TAGGED_ADDR_ENABLE && (tagged_addr_disabled || !pmlen))
|
||||
return -EINVAL;
|
||||
|
||||
if (!(arg & PR_TAGGED_ADDR_ENABLE))
|
||||
if (!(arg & PR_TAGGED_ADDR_ENABLE)) {
|
||||
pmlen = PMLEN_0;
|
||||
pmm = ENVCFG_PMM_PMLEN_0;
|
||||
}
|
||||
|
||||
if (mmap_write_lock_killable(mm))
|
||||
return -EINTR;
|
||||
|
|
|
|||
|
|
@ -1168,6 +1168,7 @@ static void hw_collect_samples(struct perf_event *event, unsigned long *sdbt,
|
|||
static void hw_perf_event_update(struct perf_event *event, int flush_all)
|
||||
{
|
||||
unsigned long long event_overflow, sampl_overflow, num_sdb;
|
||||
struct cpu_hw_sf *cpuhw = this_cpu_ptr(&cpu_hw_sf);
|
||||
struct hw_perf_event *hwc = &event->hw;
|
||||
union hws_trailer_header prev, new;
|
||||
struct hws_trailer_entry *te;
|
||||
|
|
@ -1247,8 +1248,11 @@ static void hw_perf_event_update(struct perf_event *event, int flush_all)
|
|||
* are dropped.
|
||||
* Slightly increase the interval to avoid hitting this limit.
|
||||
*/
|
||||
if (event_overflow)
|
||||
if (event_overflow) {
|
||||
SAMPL_RATE(hwc) += DIV_ROUND_UP(SAMPL_RATE(hwc), 10);
|
||||
if (SAMPL_RATE(hwc) > cpuhw->qsi.max_sampl_rate)
|
||||
SAMPL_RATE(hwc) = cpuhw->qsi.max_sampl_rate;
|
||||
}
|
||||
}
|
||||
|
||||
static inline unsigned long aux_sdb_index(struct aux_buffer *aux,
|
||||
|
|
|
|||
|
|
@ -4855,8 +4855,10 @@ static int intel_pmu_hw_config(struct perf_event *event)
|
|||
intel_pmu_set_acr_caused_constr(leader, idx++, cause_mask);
|
||||
|
||||
if (leader->nr_siblings) {
|
||||
for_each_sibling_event(sibling, leader)
|
||||
intel_pmu_set_acr_caused_constr(sibling, idx++, cause_mask);
|
||||
for_each_sibling_event(sibling, leader) {
|
||||
if (is_x86_event(sibling))
|
||||
intel_pmu_set_acr_caused_constr(sibling, idx++, cause_mask);
|
||||
}
|
||||
}
|
||||
|
||||
if (leader != event)
|
||||
|
|
|
|||
|
|
@ -44,6 +44,20 @@ KCOV_INSTRUMENT_unwind_orc.o := n
|
|||
KCOV_INSTRUMENT_unwind_frame.o := n
|
||||
KCOV_INSTRUMENT_unwind_guess.o := n
|
||||
|
||||
# Disable KCOV to prevent crashes during kexec: load_segments() invalidates
|
||||
# the GS base, which KCOV relies on for per-CPU data.
|
||||
#
|
||||
# As KCOV and KEXEC compatibility should be preserved (e.g. syzkaller is
|
||||
# using it to collect crash dumps during kernel fuzzing), disabling
|
||||
# KCOV for KEXEC kernels is not an option. Selectively disabling KCOV
|
||||
# instrumentation for individual affected functions can be fragile, while
|
||||
# adding more checks to KCOV would slow it down.
|
||||
#
|
||||
# As a compromise solution, disable KCOV instrumentation for the whole
|
||||
# source code file. If its coverage is ever needed, other approaches
|
||||
# should be considered.
|
||||
KCOV_INSTRUMENT_machine_kexec_64.o := n
|
||||
|
||||
CFLAGS_head32.o := -fno-stack-protector
|
||||
CFLAGS_head64.o := -fno-stack-protector
|
||||
CFLAGS_irq.o := -I $(src)/../include/asm/trace
|
||||
|
|
|
|||
|
|
@ -4,6 +4,8 @@ KCOV_INSTRUMENT_tlb.o := n
|
|||
KCOV_INSTRUMENT_mem_encrypt.o := n
|
||||
KCOV_INSTRUMENT_mem_encrypt_amd.o := n
|
||||
KCOV_INSTRUMENT_pgprot.o := n
|
||||
# See the "Disable KCOV" comment in arch/x86/kernel/Makefile.
|
||||
KCOV_INSTRUMENT_physaddr.o := n
|
||||
|
||||
KASAN_SANITIZE_mem_encrypt.o := n
|
||||
KASAN_SANITIZE_mem_encrypt_amd.o := n
|
||||
|
|
|
|||
|
|
@ -28,8 +28,10 @@ static const struct software_node geode_gpio_keys_node = {
|
|||
.properties = geode_gpio_keys_props,
|
||||
};
|
||||
|
||||
static struct property_entry geode_restart_key_props[] = {
|
||||
{ /* Placeholder for GPIO property */ },
|
||||
static struct software_node_ref_args geode_restart_gpio_ref;
|
||||
|
||||
static const struct property_entry geode_restart_key_props[] = {
|
||||
PROPERTY_ENTRY_REF_ARRAY_LEN("gpios", &geode_restart_gpio_ref, 1),
|
||||
PROPERTY_ENTRY_U32("linux,code", KEY_RESTART),
|
||||
PROPERTY_ENTRY_STRING("label", "Reset button"),
|
||||
PROPERTY_ENTRY_U32("debounce-interval", 100),
|
||||
|
|
@ -64,8 +66,7 @@ int __init geode_create_restart_key(unsigned int pin)
|
|||
struct platform_device *pd;
|
||||
int err;
|
||||
|
||||
geode_restart_key_props[0] = PROPERTY_ENTRY_GPIO("gpios",
|
||||
&geode_gpiochip_node,
|
||||
geode_restart_gpio_ref = SOFTWARE_NODE_REFERENCE(&geode_gpiochip_node,
|
||||
pin, GPIO_ACTIVE_LOW);
|
||||
|
||||
err = software_node_register_node_group(geode_gpio_keys_swnodes);
|
||||
|
|
@ -99,6 +100,7 @@ int __init geode_create_leds(const char *label, const struct geode_led *leds,
|
|||
const struct software_node *group[MAX_LEDS + 2] = { 0 };
|
||||
struct software_node *swnodes;
|
||||
struct property_entry *props;
|
||||
struct software_node_ref_args *gpio_refs;
|
||||
struct platform_device_info led_info = {
|
||||
.name = "leds-gpio",
|
||||
.id = PLATFORM_DEVID_NONE,
|
||||
|
|
@ -127,6 +129,12 @@ int __init geode_create_leds(const char *label, const struct geode_led *leds,
|
|||
goto err_free_swnodes;
|
||||
}
|
||||
|
||||
gpio_refs = kzalloc_objs(*gpio_refs, n_leds);
|
||||
if (!gpio_refs) {
|
||||
err = -ENOMEM;
|
||||
goto err_free_props;
|
||||
}
|
||||
|
||||
group[0] = &geode_gpio_leds_node;
|
||||
for (i = 0; i < n_leds; i++) {
|
||||
node_name = kasprintf(GFP_KERNEL, "%s:%d", label, i);
|
||||
|
|
@ -135,9 +143,11 @@ int __init geode_create_leds(const char *label, const struct geode_led *leds,
|
|||
goto err_free_names;
|
||||
}
|
||||
|
||||
gpio_refs[i] = SOFTWARE_NODE_REFERENCE(&geode_gpiochip_node,
|
||||
leds[i].pin,
|
||||
GPIO_ACTIVE_LOW);
|
||||
props[i * 3 + 0] =
|
||||
PROPERTY_ENTRY_GPIO("gpios", &geode_gpiochip_node,
|
||||
leds[i].pin, GPIO_ACTIVE_LOW);
|
||||
PROPERTY_ENTRY_REF_ARRAY_LEN("gpios", &gpio_refs[i], 1);
|
||||
props[i * 3 + 1] =
|
||||
PROPERTY_ENTRY_STRING("linux,default-trigger",
|
||||
leds[i].default_on ?
|
||||
|
|
@ -171,6 +181,8 @@ int __init geode_create_leds(const char *label, const struct geode_led *leds,
|
|||
err_free_names:
|
||||
while (--i >= 0)
|
||||
kfree(swnodes[i].name);
|
||||
kfree(gpio_refs);
|
||||
err_free_props:
|
||||
kfree(props);
|
||||
err_free_swnodes:
|
||||
kfree(swnodes);
|
||||
|
|
|
|||
|
|
@ -623,8 +623,10 @@ static int af_alg_alloc_tsgl(struct sock *sk)
|
|||
sg_init_table(sgl->sg, MAX_SGL_ENTS + 1);
|
||||
sgl->cur = 0;
|
||||
|
||||
if (sg)
|
||||
if (sg) {
|
||||
sg_unmark_end(sg + MAX_SGL_ENTS - 1);
|
||||
sg_chain(sg, MAX_SGL_ENTS + 1, sgl->sg);
|
||||
}
|
||||
|
||||
list_add_tail(&sgl->list, &ctx->tsgl_list);
|
||||
}
|
||||
|
|
@ -635,15 +637,13 @@ static int af_alg_alloc_tsgl(struct sock *sk)
|
|||
/**
|
||||
* af_alg_count_tsgl - Count number of TX SG entries
|
||||
*
|
||||
* The counting starts from the beginning of the SGL to @bytes. If
|
||||
* an @offset is provided, the counting of the SG entries starts at the @offset.
|
||||
* The counting starts from the beginning of the SGL to @bytes.
|
||||
*
|
||||
* @sk: socket of connection to user space
|
||||
* @bytes: Count the number of SG entries holding given number of bytes.
|
||||
* @offset: Start the counting of SG entries from the given offset.
|
||||
* Return: Number of TX SG entries found given the constraints
|
||||
*/
|
||||
unsigned int af_alg_count_tsgl(struct sock *sk, size_t bytes, size_t offset)
|
||||
unsigned int af_alg_count_tsgl(struct sock *sk, size_t bytes)
|
||||
{
|
||||
const struct alg_sock *ask = alg_sk(sk);
|
||||
const struct af_alg_ctx *ctx = ask->private;
|
||||
|
|
@ -658,25 +658,11 @@ unsigned int af_alg_count_tsgl(struct sock *sk, size_t bytes, size_t offset)
|
|||
const struct scatterlist *sg = sgl->sg;
|
||||
|
||||
for (i = 0; i < sgl->cur; i++) {
|
||||
size_t bytes_count;
|
||||
|
||||
/* Skip offset */
|
||||
if (offset >= sg[i].length) {
|
||||
offset -= sg[i].length;
|
||||
bytes -= sg[i].length;
|
||||
continue;
|
||||
}
|
||||
|
||||
bytes_count = sg[i].length - offset;
|
||||
|
||||
offset = 0;
|
||||
sgl_count++;
|
||||
|
||||
/* If we have seen requested number of bytes, stop */
|
||||
if (bytes_count >= bytes)
|
||||
if (sg[i].length >= bytes)
|
||||
return sgl_count;
|
||||
|
||||
bytes -= bytes_count;
|
||||
bytes -= sg[i].length;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -688,19 +674,14 @@ EXPORT_SYMBOL_GPL(af_alg_count_tsgl);
|
|||
* af_alg_pull_tsgl - Release the specified buffers from TX SGL
|
||||
*
|
||||
* If @dst is non-null, reassign the pages to @dst. The caller must release
|
||||
* the pages. If @dst_offset is given only reassign the pages to @dst starting
|
||||
* at the @dst_offset (byte). The caller must ensure that @dst is large
|
||||
* enough (e.g. by using af_alg_count_tsgl with the same offset).
|
||||
* the pages.
|
||||
*
|
||||
* @sk: socket of connection to user space
|
||||
* @used: Number of bytes to pull from TX SGL
|
||||
* @dst: If non-NULL, buffer is reassigned to dst SGL instead of releasing. The
|
||||
* caller must release the buffers in dst.
|
||||
* @dst_offset: Reassign the TX SGL from given offset. All buffers before
|
||||
* reaching the offset is released.
|
||||
*/
|
||||
void af_alg_pull_tsgl(struct sock *sk, size_t used, struct scatterlist *dst,
|
||||
size_t dst_offset)
|
||||
void af_alg_pull_tsgl(struct sock *sk, size_t used, struct scatterlist *dst)
|
||||
{
|
||||
struct alg_sock *ask = alg_sk(sk);
|
||||
struct af_alg_ctx *ctx = ask->private;
|
||||
|
|
@ -725,18 +706,10 @@ void af_alg_pull_tsgl(struct sock *sk, size_t used, struct scatterlist *dst,
|
|||
* SG entries in dst.
|
||||
*/
|
||||
if (dst) {
|
||||
if (dst_offset >= plen) {
|
||||
/* discard page before offset */
|
||||
dst_offset -= plen;
|
||||
} else {
|
||||
/* reassign page to dst after offset */
|
||||
get_page(page);
|
||||
sg_set_page(dst + j, page,
|
||||
plen - dst_offset,
|
||||
sg[i].offset + dst_offset);
|
||||
dst_offset = 0;
|
||||
j++;
|
||||
}
|
||||
/* reassign page to dst after offset */
|
||||
get_page(page);
|
||||
sg_set_page(dst + j, page, plen, sg[i].offset);
|
||||
j++;
|
||||
}
|
||||
|
||||
sg[i].length -= plen;
|
||||
|
|
|
|||
|
|
@ -26,7 +26,6 @@
|
|||
#include <crypto/internal/aead.h>
|
||||
#include <crypto/scatterwalk.h>
|
||||
#include <crypto/if_alg.h>
|
||||
#include <crypto/skcipher.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/kernel.h>
|
||||
|
|
@ -72,9 +71,8 @@ static int _aead_recvmsg(struct socket *sock, struct msghdr *msg,
|
|||
struct alg_sock *pask = alg_sk(psk);
|
||||
struct af_alg_ctx *ctx = ask->private;
|
||||
struct crypto_aead *tfm = pask->private;
|
||||
unsigned int i, as = crypto_aead_authsize(tfm);
|
||||
unsigned int as = crypto_aead_authsize(tfm);
|
||||
struct af_alg_async_req *areq;
|
||||
struct af_alg_tsgl *tsgl, *tmp;
|
||||
struct scatterlist *rsgl_src, *tsgl_src = NULL;
|
||||
int err = 0;
|
||||
size_t used = 0; /* [in] TX bufs to be en/decrypted */
|
||||
|
|
@ -154,23 +152,24 @@ static int _aead_recvmsg(struct socket *sock, struct msghdr *msg,
|
|||
outlen -= less;
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a per request TX SGL for this request which tracks the
|
||||
* SG entries from the global TX SGL.
|
||||
*/
|
||||
processed = used + ctx->aead_assoclen;
|
||||
list_for_each_entry_safe(tsgl, tmp, &ctx->tsgl_list, list) {
|
||||
for (i = 0; i < tsgl->cur; i++) {
|
||||
struct scatterlist *process_sg = tsgl->sg + i;
|
||||
|
||||
if (!(process_sg->length) || !sg_page(process_sg))
|
||||
continue;
|
||||
tsgl_src = process_sg;
|
||||
break;
|
||||
}
|
||||
if (tsgl_src)
|
||||
break;
|
||||
}
|
||||
if (processed && !tsgl_src) {
|
||||
err = -EFAULT;
|
||||
areq->tsgl_entries = af_alg_count_tsgl(sk, processed);
|
||||
if (!areq->tsgl_entries)
|
||||
areq->tsgl_entries = 1;
|
||||
areq->tsgl = sock_kmalloc(sk, array_size(sizeof(*areq->tsgl),
|
||||
areq->tsgl_entries),
|
||||
GFP_KERNEL);
|
||||
if (!areq->tsgl) {
|
||||
err = -ENOMEM;
|
||||
goto free;
|
||||
}
|
||||
sg_init_table(areq->tsgl, areq->tsgl_entries);
|
||||
af_alg_pull_tsgl(sk, processed, areq->tsgl);
|
||||
tsgl_src = areq->tsgl;
|
||||
|
||||
/*
|
||||
* Copy of AAD from source to destination
|
||||
|
|
@ -179,76 +178,15 @@ static int _aead_recvmsg(struct socket *sock, struct msghdr *msg,
|
|||
* when user space uses an in-place cipher operation, the kernel
|
||||
* will copy the data as it does not see whether such in-place operation
|
||||
* is initiated.
|
||||
*
|
||||
* To ensure efficiency, the following implementation ensure that the
|
||||
* ciphers are invoked to perform a crypto operation in-place. This
|
||||
* is achieved by memory management specified as follows.
|
||||
*/
|
||||
|
||||
/* Use the RX SGL as source (and destination) for crypto op. */
|
||||
rsgl_src = areq->first_rsgl.sgl.sgt.sgl;
|
||||
|
||||
if (ctx->enc) {
|
||||
/*
|
||||
* Encryption operation - The in-place cipher operation is
|
||||
* achieved by the following operation:
|
||||
*
|
||||
* TX SGL: AAD || PT
|
||||
* | |
|
||||
* | copy |
|
||||
* v v
|
||||
* RX SGL: AAD || PT || Tag
|
||||
*/
|
||||
memcpy_sglist(areq->first_rsgl.sgl.sgt.sgl, tsgl_src,
|
||||
processed);
|
||||
af_alg_pull_tsgl(sk, processed, NULL, 0);
|
||||
} else {
|
||||
/*
|
||||
* Decryption operation - To achieve an in-place cipher
|
||||
* operation, the following SGL structure is used:
|
||||
*
|
||||
* TX SGL: AAD || CT || Tag
|
||||
* | | ^
|
||||
* | copy | | Create SGL link.
|
||||
* v v |
|
||||
* RX SGL: AAD || CT ----+
|
||||
*/
|
||||
|
||||
/* Copy AAD || CT to RX SGL buffer for in-place operation. */
|
||||
memcpy_sglist(areq->first_rsgl.sgl.sgt.sgl, tsgl_src, outlen);
|
||||
|
||||
/* Create TX SGL for tag and chain it to RX SGL. */
|
||||
areq->tsgl_entries = af_alg_count_tsgl(sk, processed,
|
||||
processed - as);
|
||||
if (!areq->tsgl_entries)
|
||||
areq->tsgl_entries = 1;
|
||||
areq->tsgl = sock_kmalloc(sk, array_size(sizeof(*areq->tsgl),
|
||||
areq->tsgl_entries),
|
||||
GFP_KERNEL);
|
||||
if (!areq->tsgl) {
|
||||
err = -ENOMEM;
|
||||
goto free;
|
||||
}
|
||||
sg_init_table(areq->tsgl, areq->tsgl_entries);
|
||||
|
||||
/* Release TX SGL, except for tag data and reassign tag data. */
|
||||
af_alg_pull_tsgl(sk, processed, areq->tsgl, processed - as);
|
||||
|
||||
/* chain the areq TX SGL holding the tag with RX SGL */
|
||||
if (usedpages) {
|
||||
/* RX SGL present */
|
||||
struct af_alg_sgl *sgl_prev = &areq->last_rsgl->sgl;
|
||||
struct scatterlist *sg = sgl_prev->sgt.sgl;
|
||||
|
||||
sg_unmark_end(sg + sgl_prev->sgt.nents - 1);
|
||||
sg_chain(sg, sgl_prev->sgt.nents + 1, areq->tsgl);
|
||||
} else
|
||||
/* no RX SGL present (e.g. authentication only) */
|
||||
rsgl_src = areq->tsgl;
|
||||
}
|
||||
memcpy_sglist(rsgl_src, tsgl_src, ctx->aead_assoclen);
|
||||
|
||||
/* Initialize the crypto operation */
|
||||
aead_request_set_crypt(&areq->cra_u.aead_req, rsgl_src,
|
||||
aead_request_set_crypt(&areq->cra_u.aead_req, tsgl_src,
|
||||
areq->first_rsgl.sgl.sgt.sgl, used, ctx->iv);
|
||||
aead_request_set_ad(&areq->cra_u.aead_req, ctx->aead_assoclen);
|
||||
aead_request_set_tfm(&areq->cra_u.aead_req, tfm);
|
||||
|
|
@ -450,7 +388,7 @@ static void aead_sock_destruct(struct sock *sk)
|
|||
struct crypto_aead *tfm = pask->private;
|
||||
unsigned int ivlen = crypto_aead_ivsize(tfm);
|
||||
|
||||
af_alg_pull_tsgl(sk, ctx->used, NULL, 0);
|
||||
af_alg_pull_tsgl(sk, ctx->used, NULL);
|
||||
sock_kzfree_s(sk, ctx->iv, ivlen);
|
||||
sock_kfree_s(sk, ctx, ctx->len);
|
||||
af_alg_release_parent(sk);
|
||||
|
|
|
|||
|
|
@ -138,7 +138,7 @@ static int _skcipher_recvmsg(struct socket *sock, struct msghdr *msg,
|
|||
* Create a per request TX SGL for this request which tracks the
|
||||
* SG entries from the global TX SGL.
|
||||
*/
|
||||
areq->tsgl_entries = af_alg_count_tsgl(sk, len, 0);
|
||||
areq->tsgl_entries = af_alg_count_tsgl(sk, len);
|
||||
if (!areq->tsgl_entries)
|
||||
areq->tsgl_entries = 1;
|
||||
areq->tsgl = sock_kmalloc(sk, array_size(sizeof(*areq->tsgl),
|
||||
|
|
@ -149,7 +149,7 @@ static int _skcipher_recvmsg(struct socket *sock, struct msghdr *msg,
|
|||
goto free;
|
||||
}
|
||||
sg_init_table(areq->tsgl, areq->tsgl_entries);
|
||||
af_alg_pull_tsgl(sk, len, areq->tsgl, 0);
|
||||
af_alg_pull_tsgl(sk, len, areq->tsgl);
|
||||
|
||||
/* Initialize the crypto operation */
|
||||
skcipher_request_set_tfm(&areq->cra_u.skcipher_req, tfm);
|
||||
|
|
@ -363,7 +363,7 @@ static void skcipher_sock_destruct(struct sock *sk)
|
|||
struct alg_sock *pask = alg_sk(psk);
|
||||
struct crypto_skcipher *tfm = pask->private;
|
||||
|
||||
af_alg_pull_tsgl(sk, ctx->used, NULL, 0);
|
||||
af_alg_pull_tsgl(sk, ctx->used, NULL);
|
||||
sock_kzfree_s(sk, ctx->iv, crypto_skcipher_ivsize(tfm));
|
||||
if (ctx->state)
|
||||
sock_kzfree_s(sk, ctx->state, crypto_skcipher_statesize(tfm));
|
||||
|
|
|
|||
|
|
@ -207,6 +207,7 @@ static int crypto_authenc_esn_decrypt_tail(struct aead_request *req,
|
|||
u8 *ohash = areq_ctx->tail;
|
||||
unsigned int cryptlen = req->cryptlen - authsize;
|
||||
unsigned int assoclen = req->assoclen;
|
||||
struct scatterlist *src = req->src;
|
||||
struct scatterlist *dst = req->dst;
|
||||
u8 *ihash = ohash + crypto_ahash_digestsize(auth);
|
||||
u32 tmp[2];
|
||||
|
|
@ -214,23 +215,27 @@ static int crypto_authenc_esn_decrypt_tail(struct aead_request *req,
|
|||
if (!authsize)
|
||||
goto decrypt;
|
||||
|
||||
/* Move high-order bits of sequence number back. */
|
||||
scatterwalk_map_and_copy(tmp, dst, 4, 4, 0);
|
||||
scatterwalk_map_and_copy(tmp + 1, dst, assoclen + cryptlen, 4, 0);
|
||||
scatterwalk_map_and_copy(tmp, dst, 0, 8, 1);
|
||||
if (src == dst) {
|
||||
/* Move high-order bits of sequence number back. */
|
||||
scatterwalk_map_and_copy(tmp, dst, 4, 4, 0);
|
||||
scatterwalk_map_and_copy(tmp + 1, dst, assoclen + cryptlen, 4, 0);
|
||||
scatterwalk_map_and_copy(tmp, dst, 0, 8, 1);
|
||||
} else
|
||||
memcpy_sglist(dst, src, assoclen);
|
||||
|
||||
if (crypto_memneq(ihash, ohash, authsize))
|
||||
return -EBADMSG;
|
||||
|
||||
decrypt:
|
||||
|
||||
sg_init_table(areq_ctx->dst, 2);
|
||||
if (src != dst)
|
||||
src = scatterwalk_ffwd(areq_ctx->src, src, assoclen);
|
||||
dst = scatterwalk_ffwd(areq_ctx->dst, dst, assoclen);
|
||||
|
||||
skcipher_request_set_tfm(skreq, ctx->enc);
|
||||
skcipher_request_set_callback(skreq, flags,
|
||||
req->base.complete, req->base.data);
|
||||
skcipher_request_set_crypt(skreq, dst, dst, cryptlen, req->iv);
|
||||
skcipher_request_set_crypt(skreq, src, dst, cryptlen, req->iv);
|
||||
|
||||
return crypto_skcipher_decrypt(skreq);
|
||||
}
|
||||
|
|
@ -255,6 +260,7 @@ static int crypto_authenc_esn_decrypt(struct aead_request *req)
|
|||
unsigned int assoclen = req->assoclen;
|
||||
unsigned int cryptlen = req->cryptlen;
|
||||
u8 *ihash = ohash + crypto_ahash_digestsize(auth);
|
||||
struct scatterlist *src = req->src;
|
||||
struct scatterlist *dst = req->dst;
|
||||
u32 tmp[2];
|
||||
int err;
|
||||
|
|
@ -262,24 +268,28 @@ static int crypto_authenc_esn_decrypt(struct aead_request *req)
|
|||
if (assoclen < 8)
|
||||
return -EINVAL;
|
||||
|
||||
cryptlen -= authsize;
|
||||
|
||||
if (req->src != dst)
|
||||
memcpy_sglist(dst, req->src, assoclen + cryptlen);
|
||||
|
||||
scatterwalk_map_and_copy(ihash, req->src, assoclen + cryptlen,
|
||||
authsize, 0);
|
||||
|
||||
if (!authsize)
|
||||
goto tail;
|
||||
|
||||
/* Move high-order bits of sequence number to the end. */
|
||||
scatterwalk_map_and_copy(tmp, dst, 0, 8, 0);
|
||||
scatterwalk_map_and_copy(tmp, dst, 4, 4, 1);
|
||||
scatterwalk_map_and_copy(tmp + 1, dst, assoclen + cryptlen, 4, 1);
|
||||
cryptlen -= authsize;
|
||||
scatterwalk_map_and_copy(ihash, req->src, assoclen + cryptlen,
|
||||
authsize, 0);
|
||||
|
||||
sg_init_table(areq_ctx->dst, 2);
|
||||
dst = scatterwalk_ffwd(areq_ctx->dst, dst, 4);
|
||||
/* Move high-order bits of sequence number to the end. */
|
||||
scatterwalk_map_and_copy(tmp, src, 0, 8, 0);
|
||||
if (src == dst) {
|
||||
scatterwalk_map_and_copy(tmp, dst, 4, 4, 1);
|
||||
scatterwalk_map_and_copy(tmp + 1, dst, assoclen + cryptlen, 4, 1);
|
||||
dst = scatterwalk_ffwd(areq_ctx->dst, dst, 4);
|
||||
} else {
|
||||
scatterwalk_map_and_copy(tmp, dst, 0, 4, 1);
|
||||
scatterwalk_map_and_copy(tmp + 1, dst, assoclen + cryptlen - 4, 4, 1);
|
||||
|
||||
src = scatterwalk_ffwd(areq_ctx->src, src, 8);
|
||||
dst = scatterwalk_ffwd(areq_ctx->dst, dst, 4);
|
||||
memcpy_sglist(dst, src, assoclen + cryptlen - 8);
|
||||
dst = req->dst;
|
||||
}
|
||||
|
||||
ahash_request_set_tfm(ahreq, auth);
|
||||
ahash_request_set_crypt(ahreq, dst, ohash, assoclen + cryptlen);
|
||||
|
|
|
|||
|
|
@ -164,18 +164,21 @@ static int deflate_decompress_one(struct acomp_req *req,
|
|||
|
||||
do {
|
||||
unsigned int dcur;
|
||||
unsigned long avail_in;
|
||||
|
||||
dcur = acomp_walk_next_dst(&walk);
|
||||
if (!dcur) {
|
||||
out_of_space = true;
|
||||
break;
|
||||
}
|
||||
|
||||
stream->avail_out = dcur;
|
||||
stream->next_out = walk.dst.virt.addr;
|
||||
avail_in = stream->avail_in;
|
||||
|
||||
ret = zlib_inflate(stream, Z_NO_FLUSH);
|
||||
|
||||
if (!dcur && avail_in == stream->avail_in) {
|
||||
out_of_space = true;
|
||||
break;
|
||||
}
|
||||
|
||||
dcur -= stream->avail_out;
|
||||
acomp_walk_done_dst(&walk, dcur);
|
||||
} while (ret == Z_OK && stream->avail_in);
|
||||
|
|
|
|||
|
|
@ -914,7 +914,7 @@ static int decode_deactivate(struct qaic_device *qdev, void *trans, u32 *msg_len
|
|||
*/
|
||||
return -ENODEV;
|
||||
|
||||
if (status) {
|
||||
if (usr && status) {
|
||||
/*
|
||||
* Releasing resources failed on the device side, which puts
|
||||
* us in a bind since they may still be in use, so enable the
|
||||
|
|
@ -1109,6 +1109,9 @@ static void *msg_xfer(struct qaic_device *qdev, struct wrapper_list *wrappers, u
|
|||
mutex_lock(&qdev->cntl_mutex);
|
||||
if (!list_empty(&elem.list))
|
||||
list_del(&elem.list);
|
||||
/* resp_worker() processed the response but the wait was interrupted */
|
||||
else if (ret == -ERESTARTSYS)
|
||||
ret = 0;
|
||||
if (!ret && !elem.buf)
|
||||
ret = -ETIMEDOUT;
|
||||
else if (ret > 0 && !elem.buf)
|
||||
|
|
@ -1419,9 +1422,49 @@ static void resp_worker(struct work_struct *work)
|
|||
}
|
||||
mutex_unlock(&qdev->cntl_mutex);
|
||||
|
||||
if (!found)
|
||||
if (!found) {
|
||||
/*
|
||||
* The user might have gone away at this point without waiting
|
||||
* for QAIC_TRANS_DEACTIVATE_FROM_DEV transaction coming from
|
||||
* the device. If this is not handled correctly, the host will
|
||||
* not know that the DBC[n] has been freed on the device.
|
||||
* Due to this failure in synchronization between the device and
|
||||
* the host, if another user requests to activate a network, and
|
||||
* the device assigns DBC[n] again, save_dbc_buf() will hang,
|
||||
* waiting for dbc[n]->in_use to be set to false, which will not
|
||||
* happen unless the qaic_dev_reset_clean_local_state() gets
|
||||
* called by resetting the device (or re-inserting the module).
|
||||
*
|
||||
* As a solution, we look for QAIC_TRANS_DEACTIVATE_FROM_DEV
|
||||
* transactions in the message before disposing of it, then
|
||||
* handle releasing the DBC resources.
|
||||
*
|
||||
* Since the user has gone away, if the device could not
|
||||
* deactivate the network (status != 0), there is no way to
|
||||
* enable and reassign the DBC to the user. We can put trust in
|
||||
* the device that it will release all the active DBCs in
|
||||
* response to the QAIC_TRANS_TERMINATE_TO_DEV transaction,
|
||||
* otherwise, the user can issue an soc_reset to the device.
|
||||
*/
|
||||
u32 msg_count = le32_to_cpu(msg->hdr.count);
|
||||
u32 msg_len = le32_to_cpu(msg->hdr.len);
|
||||
u32 len = 0;
|
||||
int j;
|
||||
|
||||
for (j = 0; j < msg_count && len < msg_len; ++j) {
|
||||
struct wire_trans_hdr *trans_hdr;
|
||||
|
||||
trans_hdr = (struct wire_trans_hdr *)(msg->data + len);
|
||||
if (le32_to_cpu(trans_hdr->type) == QAIC_TRANS_DEACTIVATE_FROM_DEV) {
|
||||
if (decode_deactivate(qdev, trans_hdr, &len, NULL))
|
||||
len += le32_to_cpu(trans_hdr->len);
|
||||
} else {
|
||||
len += le32_to_cpu(trans_hdr->len);
|
||||
}
|
||||
}
|
||||
/* request must have timed out, drop packet */
|
||||
kfree(msg);
|
||||
}
|
||||
|
||||
kfree(resp);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -263,6 +263,13 @@ static int rimt_iommu_xlate(struct device *dev, struct acpi_rimt_node *node, u32
|
|||
if (!rimt_fwnode)
|
||||
return -EPROBE_DEFER;
|
||||
|
||||
/*
|
||||
* EPROBE_DEFER ensures IOMMU is probed before the devices that
|
||||
* depend on them. During shutdown, however, the IOMMU may be removed
|
||||
* first, leading to issues. To avoid this, a device link is added
|
||||
* which enforces the correct removal order.
|
||||
*/
|
||||
device_link_add(dev, rimt_fwnode->dev, DL_FLAG_AUTOREMOVE_CONSUMER);
|
||||
return acpi_iommu_fwspec_init(dev, deviceid, rimt_fwnode);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -13,6 +13,8 @@
|
|||
//
|
||||
// The shrinker will use trylock methods because it locks them in a different order.
|
||||
|
||||
use crate::AssertSync;
|
||||
|
||||
use core::{
|
||||
marker::PhantomPinned,
|
||||
mem::{size_of, size_of_val, MaybeUninit},
|
||||
|
|
@ -143,14 +145,14 @@ pub(crate) struct ShrinkablePageRange {
|
|||
}
|
||||
|
||||
// We do not define any ops. For now, used only to check identity of vmas.
|
||||
static BINDER_VM_OPS: bindings::vm_operations_struct = pin_init::zeroed();
|
||||
static BINDER_VM_OPS: AssertSync<bindings::vm_operations_struct> = AssertSync(pin_init::zeroed());
|
||||
|
||||
// To ensure that we do not accidentally install pages into or zap pages from the wrong vma, we
|
||||
// check its vm_ops and private data before using it.
|
||||
fn check_vma(vma: &virt::VmaRef, owner: *const ShrinkablePageRange) -> Option<&virt::VmaMixedMap> {
|
||||
// SAFETY: Just reading the vm_ops pointer of any active vma is safe.
|
||||
let vm_ops = unsafe { (*vma.as_ptr()).vm_ops };
|
||||
if !ptr::eq(vm_ops, &BINDER_VM_OPS) {
|
||||
if !ptr::eq(vm_ops, &BINDER_VM_OPS.0) {
|
||||
return None;
|
||||
}
|
||||
|
||||
|
|
@ -342,7 +344,7 @@ pub(crate) fn register_with_vma(&self, vma: &virt::VmaNew) -> Result<usize> {
|
|||
|
||||
// SAFETY: We own the vma, and we don't use any methods on VmaNew that rely on
|
||||
// `vm_ops`.
|
||||
unsafe { (*vma.as_ptr()).vm_ops = &BINDER_VM_OPS };
|
||||
unsafe { (*vma.as_ptr()).vm_ops = &BINDER_VM_OPS.0 };
|
||||
|
||||
Ok(num_pages)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -306,7 +306,7 @@ fn init(_module: &'static kernel::ThisModule) -> Result<Self> {
|
|||
/// Makes the inner type Sync.
|
||||
#[repr(transparent)]
|
||||
pub struct AssertSync<T>(T);
|
||||
// SAFETY: Used only to insert `file_operations` into a global, which is safe.
|
||||
// SAFETY: Used only to insert C bindings types into globals, which is safe.
|
||||
unsafe impl<T> Sync for AssertSync<T> {}
|
||||
|
||||
/// File operations that rust_binderfs.c can use.
|
||||
|
|
|
|||
|
|
@ -99,8 +99,13 @@ static int lcd2s_print(struct charlcd *lcd, int c)
|
|||
{
|
||||
struct lcd2s_data *lcd2s = lcd->drvdata;
|
||||
u8 buf[2] = { LCD2S_CMD_WRITE, c };
|
||||
int ret;
|
||||
|
||||
lcd2s_i2c_master_send(lcd2s->i2c, buf, sizeof(buf));
|
||||
ret = lcd2s_i2c_master_send(lcd2s->i2c, buf, sizeof(buf));
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if (ret != sizeof(buf))
|
||||
return -EIO;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -108,9 +113,13 @@ static int lcd2s_gotoxy(struct charlcd *lcd, unsigned int x, unsigned int y)
|
|||
{
|
||||
struct lcd2s_data *lcd2s = lcd->drvdata;
|
||||
u8 buf[3] = { LCD2S_CMD_CUR_POS, y + 1, x + 1 };
|
||||
int ret;
|
||||
|
||||
lcd2s_i2c_master_send(lcd2s->i2c, buf, sizeof(buf));
|
||||
|
||||
ret = lcd2s_i2c_master_send(lcd2s->i2c, buf, sizeof(buf));
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if (ret != sizeof(buf))
|
||||
return -EIO;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -365,7 +365,7 @@ static DEFINE_IDA(linedisp_id);
|
|||
|
||||
static void linedisp_release(struct device *dev)
|
||||
{
|
||||
struct linedisp *linedisp = to_linedisp(dev);
|
||||
struct linedisp *linedisp = container_of(dev, struct linedisp, dev);
|
||||
|
||||
kfree(linedisp->map);
|
||||
kfree(linedisp->message);
|
||||
|
|
|
|||
|
|
@ -523,6 +523,8 @@ static ssize_t node_read_meminfo(struct device *dev,
|
|||
#ifdef CONFIG_UNACCEPTED_MEMORY
|
||||
"Node %d Unaccepted: %8lu kB\n"
|
||||
#endif
|
||||
"Node %d GPUActive: %8lu kB\n"
|
||||
"Node %d GPUReclaim: %8lu kB\n"
|
||||
,
|
||||
nid, K(node_page_state(pgdat, NR_FILE_DIRTY)),
|
||||
nid, K(node_page_state(pgdat, NR_WRITEBACK)),
|
||||
|
|
@ -556,6 +558,9 @@ static ssize_t node_read_meminfo(struct device *dev,
|
|||
,
|
||||
nid, K(sum_zone_node_page_state(nid, NR_UNACCEPTED))
|
||||
#endif
|
||||
,
|
||||
nid, K(node_page_state(pgdat, NR_GPU_ACTIVE)),
|
||||
nid, K(node_page_state(pgdat, NR_GPU_RECLAIM))
|
||||
);
|
||||
len += hugetlb_report_node_meminfo(buf, len, nid);
|
||||
return len;
|
||||
|
|
|
|||
|
|
@ -109,9 +109,6 @@ static int h4_recv(struct hci_uart *hu, const void *data, int count)
|
|||
{
|
||||
struct h4_struct *h4 = hu->priv;
|
||||
|
||||
if (!test_bit(HCI_UART_REGISTERED, &hu->flags))
|
||||
return -EUNATCH;
|
||||
|
||||
h4->rx_skb = h4_recv_buf(hu, h4->rx_skb, data, count,
|
||||
h4_recv_pkts, ARRAY_SIZE(h4_recv_pkts));
|
||||
if (IS_ERR(h4->rx_skb)) {
|
||||
|
|
|
|||
|
|
@ -793,13 +793,15 @@ static void do_become_nonbusy(struct comedi_device *dev,
|
|||
__comedi_clear_subdevice_runflags(s, COMEDI_SRF_RUNNING |
|
||||
COMEDI_SRF_BUSY);
|
||||
spin_unlock_irqrestore(&s->spin_lock, flags);
|
||||
if (comedi_is_runflags_busy(runflags)) {
|
||||
if (async) {
|
||||
/*
|
||||
* "Run active" counter was set to 1 when setting up the
|
||||
* command. Decrement it and wait for it to become 0.
|
||||
*/
|
||||
comedi_put_is_subdevice_running(s);
|
||||
wait_for_completion(&async->run_complete);
|
||||
if (comedi_is_runflags_busy(runflags)) {
|
||||
comedi_put_is_subdevice_running(s);
|
||||
wait_for_completion(&async->run_complete);
|
||||
}
|
||||
comedi_buf_reset(s);
|
||||
async->inttrig = NULL;
|
||||
kfree(async->cmd.chanlist);
|
||||
|
|
|
|||
|
|
@ -1063,6 +1063,14 @@ int comedi_device_attach(struct comedi_device *dev, struct comedi_devconfig *it)
|
|||
ret = -EIO;
|
||||
goto out;
|
||||
}
|
||||
if (IS_ENABLED(CONFIG_LOCKDEP)) {
|
||||
/*
|
||||
* dev->spinlock is for private use by the attached low-level
|
||||
* driver. Reinitialize it to stop lock-dependency tracking
|
||||
* between attachments to different low-level drivers.
|
||||
*/
|
||||
spin_lock_init(&dev->spinlock);
|
||||
}
|
||||
dev->driver = driv;
|
||||
dev->board_name = dev->board_ptr ? *(const char **)dev->board_ptr
|
||||
: dev->driver->driver_name;
|
||||
|
|
|
|||
|
|
@ -175,6 +175,18 @@ static int dt2815_attach(struct comedi_device *dev, struct comedi_devconfig *it)
|
|||
? current_range_type : voltage_range_type;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if hardware is present before attempting any I/O operations.
|
||||
* Reading 0xff from status register typically indicates no hardware
|
||||
* on the bus (floating bus reads as all 1s).
|
||||
*/
|
||||
if (inb(dev->iobase + DT2815_STATUS) == 0xff) {
|
||||
dev_err(dev->class_dev,
|
||||
"No hardware detected at I/O base 0x%lx\n",
|
||||
dev->iobase);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/* Init the 2815 */
|
||||
outb(0x00, dev->iobase + DT2815_STATUS);
|
||||
for (i = 0; i < 100; i++) {
|
||||
|
|
|
|||
|
|
@ -315,6 +315,18 @@ static int me4000_xilinx_download(struct comedi_device *dev,
|
|||
unsigned int val;
|
||||
unsigned int i;
|
||||
|
||||
/* Get data stream length from header. */
|
||||
if (size >= 4) {
|
||||
file_length = (((unsigned int)data[0] & 0xff) << 24) +
|
||||
(((unsigned int)data[1] & 0xff) << 16) +
|
||||
(((unsigned int)data[2] & 0xff) << 8) +
|
||||
((unsigned int)data[3] & 0xff);
|
||||
}
|
||||
if (size < 16 || file_length > size - 16) {
|
||||
dev_err(dev->class_dev, "Firmware length inconsistency\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!xilinx_iobase)
|
||||
return -ENODEV;
|
||||
|
||||
|
|
@ -346,10 +358,6 @@ static int me4000_xilinx_download(struct comedi_device *dev,
|
|||
outl(val, devpriv->plx_regbase + PLX9052_CNTRL);
|
||||
|
||||
/* Download Xilinx firmware */
|
||||
file_length = (((unsigned int)data[0] & 0xff) << 24) +
|
||||
(((unsigned int)data[1] & 0xff) << 16) +
|
||||
(((unsigned int)data[2] & 0xff) << 8) +
|
||||
((unsigned int)data[3] & 0xff);
|
||||
usleep_range(10, 1000);
|
||||
|
||||
for (i = 0; i < file_length; i++) {
|
||||
|
|
|
|||
|
|
@ -344,6 +344,25 @@ static int me2600_xilinx_download(struct comedi_device *dev,
|
|||
unsigned int file_length;
|
||||
unsigned int i;
|
||||
|
||||
/*
|
||||
* Format of the firmware
|
||||
* Build longs from the byte-wise coded header
|
||||
* Byte 1-3: length of the array
|
||||
* Byte 4-7: version
|
||||
* Byte 8-11: date
|
||||
* Byte 12-15: reserved
|
||||
*/
|
||||
if (size >= 4) {
|
||||
file_length = (((unsigned int)data[0] & 0xff) << 24) +
|
||||
(((unsigned int)data[1] & 0xff) << 16) +
|
||||
(((unsigned int)data[2] & 0xff) << 8) +
|
||||
((unsigned int)data[3] & 0xff);
|
||||
}
|
||||
if (size < 16 || file_length > size - 16) {
|
||||
dev_err(dev->class_dev, "Firmware length inconsistency\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* disable irq's on PLX */
|
||||
writel(0x00, devpriv->plx_regbase + PLX9052_INTCSR);
|
||||
|
||||
|
|
@ -357,22 +376,6 @@ static int me2600_xilinx_download(struct comedi_device *dev,
|
|||
writeb(0x00, dev->mmio + 0x0);
|
||||
sleep(1);
|
||||
|
||||
/*
|
||||
* Format of the firmware
|
||||
* Build longs from the byte-wise coded header
|
||||
* Byte 1-3: length of the array
|
||||
* Byte 4-7: version
|
||||
* Byte 8-11: date
|
||||
* Byte 12-15: reserved
|
||||
*/
|
||||
if (size < 16)
|
||||
return -EINVAL;
|
||||
|
||||
file_length = (((unsigned int)data[0] & 0xff) << 24) +
|
||||
(((unsigned int)data[1] & 0xff) << 16) +
|
||||
(((unsigned int)data[2] & 0xff) << 8) +
|
||||
((unsigned int)data[3] & 0xff);
|
||||
|
||||
/*
|
||||
* Loop for writing firmware byte by byte to xilinx
|
||||
* Firmware data start at offset 16
|
||||
|
|
|
|||
|
|
@ -698,7 +698,8 @@ static int atmio16d_attach(struct comedi_device *dev,
|
|||
|
||||
static void atmio16d_detach(struct comedi_device *dev)
|
||||
{
|
||||
reset_atmio16d(dev);
|
||||
if (dev->private)
|
||||
reset_atmio16d(dev);
|
||||
comedi_legacy_detach(dev);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -107,9 +107,9 @@ static bool rz_mtu3_is_counter_invalid(struct counter_device *counter, int id)
|
|||
struct rz_mtu3_cnt *const priv = counter_priv(counter);
|
||||
unsigned long tmdr;
|
||||
|
||||
pm_runtime_get_sync(priv->ch->dev);
|
||||
pm_runtime_get_sync(counter->parent);
|
||||
tmdr = rz_mtu3_shared_reg_read(priv->ch, RZ_MTU3_TMDR3);
|
||||
pm_runtime_put(priv->ch->dev);
|
||||
pm_runtime_put(counter->parent);
|
||||
|
||||
if (id == RZ_MTU3_32_BIT_CH && test_bit(RZ_MTU3_TMDR3_LWA, &tmdr))
|
||||
return false;
|
||||
|
|
@ -165,12 +165,12 @@ static int rz_mtu3_count_read(struct counter_device *counter,
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
pm_runtime_get_sync(ch->dev);
|
||||
pm_runtime_get_sync(counter->parent);
|
||||
if (count->id == RZ_MTU3_32_BIT_CH)
|
||||
*val = rz_mtu3_32bit_ch_read(ch, RZ_MTU3_TCNTLW);
|
||||
else
|
||||
*val = rz_mtu3_16bit_ch_read(ch, RZ_MTU3_TCNT);
|
||||
pm_runtime_put(ch->dev);
|
||||
pm_runtime_put(counter->parent);
|
||||
mutex_unlock(&priv->lock);
|
||||
|
||||
return 0;
|
||||
|
|
@ -187,26 +187,26 @@ static int rz_mtu3_count_write(struct counter_device *counter,
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
pm_runtime_get_sync(ch->dev);
|
||||
pm_runtime_get_sync(counter->parent);
|
||||
if (count->id == RZ_MTU3_32_BIT_CH)
|
||||
rz_mtu3_32bit_ch_write(ch, RZ_MTU3_TCNTLW, val);
|
||||
else
|
||||
rz_mtu3_16bit_ch_write(ch, RZ_MTU3_TCNT, val);
|
||||
pm_runtime_put(ch->dev);
|
||||
pm_runtime_put(counter->parent);
|
||||
mutex_unlock(&priv->lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rz_mtu3_count_function_read_helper(struct rz_mtu3_channel *const ch,
|
||||
struct rz_mtu3_cnt *const priv,
|
||||
struct counter_device *const counter,
|
||||
enum counter_function *function)
|
||||
{
|
||||
u8 timer_mode;
|
||||
|
||||
pm_runtime_get_sync(ch->dev);
|
||||
pm_runtime_get_sync(counter->parent);
|
||||
timer_mode = rz_mtu3_8bit_ch_read(ch, RZ_MTU3_TMDR1);
|
||||
pm_runtime_put(ch->dev);
|
||||
pm_runtime_put(counter->parent);
|
||||
|
||||
switch (timer_mode & RZ_MTU3_TMDR1_PH_CNT_MODE_MASK) {
|
||||
case RZ_MTU3_TMDR1_PH_CNT_MODE_1:
|
||||
|
|
@ -240,7 +240,7 @@ static int rz_mtu3_count_function_read(struct counter_device *counter,
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = rz_mtu3_count_function_read_helper(ch, priv, function);
|
||||
ret = rz_mtu3_count_function_read_helper(ch, counter, function);
|
||||
mutex_unlock(&priv->lock);
|
||||
|
||||
return ret;
|
||||
|
|
@ -279,9 +279,9 @@ static int rz_mtu3_count_function_write(struct counter_device *counter,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
pm_runtime_get_sync(ch->dev);
|
||||
pm_runtime_get_sync(counter->parent);
|
||||
rz_mtu3_8bit_ch_write(ch, RZ_MTU3_TMDR1, timer_mode);
|
||||
pm_runtime_put(ch->dev);
|
||||
pm_runtime_put(counter->parent);
|
||||
mutex_unlock(&priv->lock);
|
||||
|
||||
return 0;
|
||||
|
|
@ -300,9 +300,9 @@ static int rz_mtu3_count_direction_read(struct counter_device *counter,
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
pm_runtime_get_sync(ch->dev);
|
||||
pm_runtime_get_sync(counter->parent);
|
||||
tsr = rz_mtu3_8bit_ch_read(ch, RZ_MTU3_TSR);
|
||||
pm_runtime_put(ch->dev);
|
||||
pm_runtime_put(counter->parent);
|
||||
|
||||
*direction = (tsr & RZ_MTU3_TSR_TCFD) ?
|
||||
COUNTER_COUNT_DIRECTION_FORWARD : COUNTER_COUNT_DIRECTION_BACKWARD;
|
||||
|
|
@ -377,14 +377,14 @@ static int rz_mtu3_count_ceiling_write(struct counter_device *counter,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
pm_runtime_get_sync(ch->dev);
|
||||
pm_runtime_get_sync(counter->parent);
|
||||
if (count->id == RZ_MTU3_32_BIT_CH)
|
||||
rz_mtu3_32bit_ch_write(ch, RZ_MTU3_TGRALW, ceiling);
|
||||
else
|
||||
rz_mtu3_16bit_ch_write(ch, RZ_MTU3_TGRA, ceiling);
|
||||
|
||||
rz_mtu3_8bit_ch_write(ch, RZ_MTU3_TCR, RZ_MTU3_TCR_CCLR_TGRA);
|
||||
pm_runtime_put(ch->dev);
|
||||
pm_runtime_put(counter->parent);
|
||||
mutex_unlock(&priv->lock);
|
||||
|
||||
return 0;
|
||||
|
|
@ -495,25 +495,28 @@ static int rz_mtu3_count_enable_read(struct counter_device *counter,
|
|||
static int rz_mtu3_count_enable_write(struct counter_device *counter,
|
||||
struct counter_count *count, u8 enable)
|
||||
{
|
||||
struct rz_mtu3_channel *const ch = rz_mtu3_get_ch(counter, count->id);
|
||||
struct rz_mtu3_cnt *const priv = counter_priv(counter);
|
||||
int ret = 0;
|
||||
|
||||
mutex_lock(&priv->lock);
|
||||
|
||||
if (priv->count_is_enabled[count->id] == enable)
|
||||
goto exit;
|
||||
|
||||
if (enable) {
|
||||
mutex_lock(&priv->lock);
|
||||
pm_runtime_get_sync(ch->dev);
|
||||
pm_runtime_get_sync(counter->parent);
|
||||
ret = rz_mtu3_initialize_counter(counter, count->id);
|
||||
if (ret == 0)
|
||||
priv->count_is_enabled[count->id] = true;
|
||||
mutex_unlock(&priv->lock);
|
||||
} else {
|
||||
mutex_lock(&priv->lock);
|
||||
rz_mtu3_terminate_counter(counter, count->id);
|
||||
priv->count_is_enabled[count->id] = false;
|
||||
pm_runtime_put(ch->dev);
|
||||
mutex_unlock(&priv->lock);
|
||||
pm_runtime_put(counter->parent);
|
||||
}
|
||||
|
||||
exit:
|
||||
mutex_unlock(&priv->lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -540,9 +543,9 @@ static int rz_mtu3_cascade_counts_enable_get(struct counter_device *counter,
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
pm_runtime_get_sync(priv->ch->dev);
|
||||
pm_runtime_get_sync(counter->parent);
|
||||
tmdr = rz_mtu3_shared_reg_read(priv->ch, RZ_MTU3_TMDR3);
|
||||
pm_runtime_put(priv->ch->dev);
|
||||
pm_runtime_put(counter->parent);
|
||||
*cascade_enable = test_bit(RZ_MTU3_TMDR3_LWA, &tmdr);
|
||||
mutex_unlock(&priv->lock);
|
||||
|
||||
|
|
@ -559,10 +562,10 @@ static int rz_mtu3_cascade_counts_enable_set(struct counter_device *counter,
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
pm_runtime_get_sync(priv->ch->dev);
|
||||
pm_runtime_get_sync(counter->parent);
|
||||
rz_mtu3_shared_reg_update_bit(priv->ch, RZ_MTU3_TMDR3,
|
||||
RZ_MTU3_TMDR3_LWA, cascade_enable);
|
||||
pm_runtime_put(priv->ch->dev);
|
||||
pm_runtime_put(counter->parent);
|
||||
mutex_unlock(&priv->lock);
|
||||
|
||||
return 0;
|
||||
|
|
@ -579,9 +582,9 @@ static int rz_mtu3_ext_input_phase_clock_select_get(struct counter_device *count
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
pm_runtime_get_sync(priv->ch->dev);
|
||||
pm_runtime_get_sync(counter->parent);
|
||||
tmdr = rz_mtu3_shared_reg_read(priv->ch, RZ_MTU3_TMDR3);
|
||||
pm_runtime_put(priv->ch->dev);
|
||||
pm_runtime_put(counter->parent);
|
||||
*ext_input_phase_clock_select = test_bit(RZ_MTU3_TMDR3_PHCKSEL, &tmdr);
|
||||
mutex_unlock(&priv->lock);
|
||||
|
||||
|
|
@ -598,11 +601,11 @@ static int rz_mtu3_ext_input_phase_clock_select_set(struct counter_device *count
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
pm_runtime_get_sync(priv->ch->dev);
|
||||
pm_runtime_get_sync(counter->parent);
|
||||
rz_mtu3_shared_reg_update_bit(priv->ch, RZ_MTU3_TMDR3,
|
||||
RZ_MTU3_TMDR3_PHCKSEL,
|
||||
ext_input_phase_clock_select);
|
||||
pm_runtime_put(priv->ch->dev);
|
||||
pm_runtime_put(counter->parent);
|
||||
mutex_unlock(&priv->lock);
|
||||
|
||||
return 0;
|
||||
|
|
@ -640,7 +643,7 @@ static int rz_mtu3_action_read(struct counter_device *counter,
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = rz_mtu3_count_function_read_helper(ch, priv, &function);
|
||||
ret = rz_mtu3_count_function_read_helper(ch, counter, &function);
|
||||
if (ret) {
|
||||
mutex_unlock(&priv->lock);
|
||||
return ret;
|
||||
|
|
|
|||
|
|
@ -468,13 +468,13 @@ int cpufreq_dbs_governor_init(struct cpufreq_policy *policy)
|
|||
/* Failure, so roll back. */
|
||||
pr_err("initialization failed (dbs_data kobject init error %d)\n", ret);
|
||||
|
||||
kobject_put(&dbs_data->attr_set.kobj);
|
||||
|
||||
policy->governor_data = NULL;
|
||||
|
||||
if (!have_governor_per_policy())
|
||||
gov->gdbs_data = NULL;
|
||||
gov->exit(dbs_data);
|
||||
|
||||
kobject_put(&dbs_data->attr_set.kobj);
|
||||
goto free_policy_dbs_info;
|
||||
|
||||
free_dbs_data:
|
||||
kfree(dbs_data);
|
||||
|
|
|
|||
|
|
@ -3326,9 +3326,10 @@ static int ahash_setkey(struct crypto_ahash *ahash, const u8 *key,
|
|||
if (aligned_len < keylen)
|
||||
return -EOVERFLOW;
|
||||
|
||||
hashed_key = kmemdup(key, aligned_len, GFP_KERNEL);
|
||||
hashed_key = kmalloc(aligned_len, GFP_KERNEL);
|
||||
if (!hashed_key)
|
||||
return -ENOMEM;
|
||||
memcpy(hashed_key, key, keylen);
|
||||
ret = hash_digest_key(ctx, &keylen, hashed_key, digestsize);
|
||||
if (ret)
|
||||
goto bad_free_key;
|
||||
|
|
|
|||
|
|
@ -441,9 +441,10 @@ static int ahash_setkey(struct crypto_ahash *ahash,
|
|||
if (aligned_len < keylen)
|
||||
return -EOVERFLOW;
|
||||
|
||||
hashed_key = kmemdup(key, keylen, GFP_KERNEL);
|
||||
hashed_key = kmalloc(aligned_len, GFP_KERNEL);
|
||||
if (!hashed_key)
|
||||
return -ENOMEM;
|
||||
memcpy(hashed_key, key, keylen);
|
||||
ret = hash_digest_key(ctx, &keylen, hashed_key, digestsize);
|
||||
if (ret)
|
||||
goto bad_free_key;
|
||||
|
|
|
|||
|
|
@ -529,7 +529,7 @@ static struct tegra_se_alg tegra_aes_algs[] = {
|
|||
.cra_name = "cbc(aes)",
|
||||
.cra_driver_name = "cbc-aes-tegra",
|
||||
.cra_priority = 500,
|
||||
.cra_flags = CRYPTO_ALG_TYPE_SKCIPHER | CRYPTO_ALG_ASYNC,
|
||||
.cra_flags = CRYPTO_ALG_ASYNC,
|
||||
.cra_blocksize = AES_BLOCK_SIZE,
|
||||
.cra_ctxsize = sizeof(struct tegra_aes_ctx),
|
||||
.cra_alignmask = 0xf,
|
||||
|
|
@ -550,7 +550,7 @@ static struct tegra_se_alg tegra_aes_algs[] = {
|
|||
.cra_name = "ecb(aes)",
|
||||
.cra_driver_name = "ecb-aes-tegra",
|
||||
.cra_priority = 500,
|
||||
.cra_flags = CRYPTO_ALG_TYPE_SKCIPHER | CRYPTO_ALG_ASYNC,
|
||||
.cra_flags = CRYPTO_ALG_ASYNC,
|
||||
.cra_blocksize = AES_BLOCK_SIZE,
|
||||
.cra_ctxsize = sizeof(struct tegra_aes_ctx),
|
||||
.cra_alignmask = 0xf,
|
||||
|
|
@ -572,7 +572,7 @@ static struct tegra_se_alg tegra_aes_algs[] = {
|
|||
.cra_name = "ctr(aes)",
|
||||
.cra_driver_name = "ctr-aes-tegra",
|
||||
.cra_priority = 500,
|
||||
.cra_flags = CRYPTO_ALG_TYPE_SKCIPHER | CRYPTO_ALG_ASYNC,
|
||||
.cra_flags = CRYPTO_ALG_ASYNC,
|
||||
.cra_blocksize = 1,
|
||||
.cra_ctxsize = sizeof(struct tegra_aes_ctx),
|
||||
.cra_alignmask = 0xf,
|
||||
|
|
@ -594,6 +594,7 @@ static struct tegra_se_alg tegra_aes_algs[] = {
|
|||
.cra_name = "xts(aes)",
|
||||
.cra_driver_name = "xts-aes-tegra",
|
||||
.cra_priority = 500,
|
||||
.cra_flags = CRYPTO_ALG_ASYNC,
|
||||
.cra_blocksize = AES_BLOCK_SIZE,
|
||||
.cra_ctxsize = sizeof(struct tegra_aes_ctx),
|
||||
.cra_alignmask = (__alignof__(u64) - 1),
|
||||
|
|
@ -1922,6 +1923,7 @@ static struct tegra_se_alg tegra_aead_algs[] = {
|
|||
.cra_name = "gcm(aes)",
|
||||
.cra_driver_name = "gcm-aes-tegra",
|
||||
.cra_priority = 500,
|
||||
.cra_flags = CRYPTO_ALG_ASYNC,
|
||||
.cra_blocksize = 1,
|
||||
.cra_ctxsize = sizeof(struct tegra_aead_ctx),
|
||||
.cra_alignmask = 0xf,
|
||||
|
|
@ -1944,6 +1946,7 @@ static struct tegra_se_alg tegra_aead_algs[] = {
|
|||
.cra_name = "ccm(aes)",
|
||||
.cra_driver_name = "ccm-aes-tegra",
|
||||
.cra_priority = 500,
|
||||
.cra_flags = CRYPTO_ALG_ASYNC,
|
||||
.cra_blocksize = 1,
|
||||
.cra_ctxsize = sizeof(struct tegra_aead_ctx),
|
||||
.cra_alignmask = 0xf,
|
||||
|
|
@ -1971,7 +1974,7 @@ static struct tegra_se_alg tegra_cmac_algs[] = {
|
|||
.cra_name = "cmac(aes)",
|
||||
.cra_driver_name = "tegra-se-cmac",
|
||||
.cra_priority = 300,
|
||||
.cra_flags = CRYPTO_ALG_TYPE_AHASH,
|
||||
.cra_flags = CRYPTO_ALG_ASYNC,
|
||||
.cra_blocksize = AES_BLOCK_SIZE,
|
||||
.cra_ctxsize = sizeof(struct tegra_cmac_ctx),
|
||||
.cra_alignmask = 0,
|
||||
|
|
|
|||
|
|
@ -761,7 +761,7 @@ static struct tegra_se_alg tegra_hash_algs[] = {
|
|||
.cra_name = "sha1",
|
||||
.cra_driver_name = "tegra-se-sha1",
|
||||
.cra_priority = 300,
|
||||
.cra_flags = CRYPTO_ALG_TYPE_AHASH,
|
||||
.cra_flags = CRYPTO_ALG_ASYNC,
|
||||
.cra_blocksize = SHA1_BLOCK_SIZE,
|
||||
.cra_ctxsize = sizeof(struct tegra_sha_ctx),
|
||||
.cra_alignmask = 0,
|
||||
|
|
@ -786,7 +786,7 @@ static struct tegra_se_alg tegra_hash_algs[] = {
|
|||
.cra_name = "sha224",
|
||||
.cra_driver_name = "tegra-se-sha224",
|
||||
.cra_priority = 300,
|
||||
.cra_flags = CRYPTO_ALG_TYPE_AHASH,
|
||||
.cra_flags = CRYPTO_ALG_ASYNC,
|
||||
.cra_blocksize = SHA224_BLOCK_SIZE,
|
||||
.cra_ctxsize = sizeof(struct tegra_sha_ctx),
|
||||
.cra_alignmask = 0,
|
||||
|
|
@ -811,7 +811,7 @@ static struct tegra_se_alg tegra_hash_algs[] = {
|
|||
.cra_name = "sha256",
|
||||
.cra_driver_name = "tegra-se-sha256",
|
||||
.cra_priority = 300,
|
||||
.cra_flags = CRYPTO_ALG_TYPE_AHASH,
|
||||
.cra_flags = CRYPTO_ALG_ASYNC,
|
||||
.cra_blocksize = SHA256_BLOCK_SIZE,
|
||||
.cra_ctxsize = sizeof(struct tegra_sha_ctx),
|
||||
.cra_alignmask = 0,
|
||||
|
|
@ -836,7 +836,7 @@ static struct tegra_se_alg tegra_hash_algs[] = {
|
|||
.cra_name = "sha384",
|
||||
.cra_driver_name = "tegra-se-sha384",
|
||||
.cra_priority = 300,
|
||||
.cra_flags = CRYPTO_ALG_TYPE_AHASH,
|
||||
.cra_flags = CRYPTO_ALG_ASYNC,
|
||||
.cra_blocksize = SHA384_BLOCK_SIZE,
|
||||
.cra_ctxsize = sizeof(struct tegra_sha_ctx),
|
||||
.cra_alignmask = 0,
|
||||
|
|
@ -861,7 +861,7 @@ static struct tegra_se_alg tegra_hash_algs[] = {
|
|||
.cra_name = "sha512",
|
||||
.cra_driver_name = "tegra-se-sha512",
|
||||
.cra_priority = 300,
|
||||
.cra_flags = CRYPTO_ALG_TYPE_AHASH,
|
||||
.cra_flags = CRYPTO_ALG_ASYNC,
|
||||
.cra_blocksize = SHA512_BLOCK_SIZE,
|
||||
.cra_ctxsize = sizeof(struct tegra_sha_ctx),
|
||||
.cra_alignmask = 0,
|
||||
|
|
@ -886,7 +886,7 @@ static struct tegra_se_alg tegra_hash_algs[] = {
|
|||
.cra_name = "sha3-224",
|
||||
.cra_driver_name = "tegra-se-sha3-224",
|
||||
.cra_priority = 300,
|
||||
.cra_flags = CRYPTO_ALG_TYPE_AHASH,
|
||||
.cra_flags = CRYPTO_ALG_ASYNC,
|
||||
.cra_blocksize = SHA3_224_BLOCK_SIZE,
|
||||
.cra_ctxsize = sizeof(struct tegra_sha_ctx),
|
||||
.cra_alignmask = 0,
|
||||
|
|
@ -911,7 +911,7 @@ static struct tegra_se_alg tegra_hash_algs[] = {
|
|||
.cra_name = "sha3-256",
|
||||
.cra_driver_name = "tegra-se-sha3-256",
|
||||
.cra_priority = 300,
|
||||
.cra_flags = CRYPTO_ALG_TYPE_AHASH,
|
||||
.cra_flags = CRYPTO_ALG_ASYNC,
|
||||
.cra_blocksize = SHA3_256_BLOCK_SIZE,
|
||||
.cra_ctxsize = sizeof(struct tegra_sha_ctx),
|
||||
.cra_alignmask = 0,
|
||||
|
|
@ -936,7 +936,7 @@ static struct tegra_se_alg tegra_hash_algs[] = {
|
|||
.cra_name = "sha3-384",
|
||||
.cra_driver_name = "tegra-se-sha3-384",
|
||||
.cra_priority = 300,
|
||||
.cra_flags = CRYPTO_ALG_TYPE_AHASH,
|
||||
.cra_flags = CRYPTO_ALG_ASYNC,
|
||||
.cra_blocksize = SHA3_384_BLOCK_SIZE,
|
||||
.cra_ctxsize = sizeof(struct tegra_sha_ctx),
|
||||
.cra_alignmask = 0,
|
||||
|
|
@ -961,7 +961,7 @@ static struct tegra_se_alg tegra_hash_algs[] = {
|
|||
.cra_name = "sha3-512",
|
||||
.cra_driver_name = "tegra-se-sha3-512",
|
||||
.cra_priority = 300,
|
||||
.cra_flags = CRYPTO_ALG_TYPE_AHASH,
|
||||
.cra_flags = CRYPTO_ALG_ASYNC,
|
||||
.cra_blocksize = SHA3_512_BLOCK_SIZE,
|
||||
.cra_ctxsize = sizeof(struct tegra_sha_ctx),
|
||||
.cra_alignmask = 0,
|
||||
|
|
@ -988,7 +988,8 @@ static struct tegra_se_alg tegra_hash_algs[] = {
|
|||
.cra_name = "hmac(sha224)",
|
||||
.cra_driver_name = "tegra-se-hmac-sha224",
|
||||
.cra_priority = 300,
|
||||
.cra_flags = CRYPTO_ALG_TYPE_AHASH | CRYPTO_ALG_NEED_FALLBACK,
|
||||
.cra_flags = CRYPTO_ALG_ASYNC |
|
||||
CRYPTO_ALG_NEED_FALLBACK,
|
||||
.cra_blocksize = SHA224_BLOCK_SIZE,
|
||||
.cra_ctxsize = sizeof(struct tegra_sha_ctx),
|
||||
.cra_alignmask = 0,
|
||||
|
|
@ -1015,7 +1016,8 @@ static struct tegra_se_alg tegra_hash_algs[] = {
|
|||
.cra_name = "hmac(sha256)",
|
||||
.cra_driver_name = "tegra-se-hmac-sha256",
|
||||
.cra_priority = 300,
|
||||
.cra_flags = CRYPTO_ALG_TYPE_AHASH | CRYPTO_ALG_NEED_FALLBACK,
|
||||
.cra_flags = CRYPTO_ALG_ASYNC |
|
||||
CRYPTO_ALG_NEED_FALLBACK,
|
||||
.cra_blocksize = SHA256_BLOCK_SIZE,
|
||||
.cra_ctxsize = sizeof(struct tegra_sha_ctx),
|
||||
.cra_alignmask = 0,
|
||||
|
|
@ -1042,7 +1044,8 @@ static struct tegra_se_alg tegra_hash_algs[] = {
|
|||
.cra_name = "hmac(sha384)",
|
||||
.cra_driver_name = "tegra-se-hmac-sha384",
|
||||
.cra_priority = 300,
|
||||
.cra_flags = CRYPTO_ALG_TYPE_AHASH | CRYPTO_ALG_NEED_FALLBACK,
|
||||
.cra_flags = CRYPTO_ALG_ASYNC |
|
||||
CRYPTO_ALG_NEED_FALLBACK,
|
||||
.cra_blocksize = SHA384_BLOCK_SIZE,
|
||||
.cra_ctxsize = sizeof(struct tegra_sha_ctx),
|
||||
.cra_alignmask = 0,
|
||||
|
|
@ -1069,7 +1072,8 @@ static struct tegra_se_alg tegra_hash_algs[] = {
|
|||
.cra_name = "hmac(sha512)",
|
||||
.cra_driver_name = "tegra-se-hmac-sha512",
|
||||
.cra_priority = 300,
|
||||
.cra_flags = CRYPTO_ALG_TYPE_AHASH | CRYPTO_ALG_NEED_FALLBACK,
|
||||
.cra_flags = CRYPTO_ALG_ASYNC |
|
||||
CRYPTO_ALG_NEED_FALLBACK,
|
||||
.cra_blocksize = SHA512_BLOCK_SIZE,
|
||||
.cra_ctxsize = sizeof(struct tegra_sha_ctx),
|
||||
.cra_alignmask = 0,
|
||||
|
|
|
|||
|
|
@ -122,6 +122,7 @@ config GPIB_FLUKE
|
|||
depends on OF
|
||||
select GPIB_COMMON
|
||||
select GPIB_NEC7210
|
||||
depends on HAS_IOMEM
|
||||
help
|
||||
GPIB driver for Fluke based cda devices.
|
||||
|
||||
|
|
|
|||
|
|
@ -888,10 +888,6 @@ static int read_ioctl(struct gpib_file_private *file_priv, struct gpib_board *bo
|
|||
if (read_cmd.completed_transfer_count > read_cmd.requested_transfer_count)
|
||||
return -EINVAL;
|
||||
|
||||
desc = handle_to_descriptor(file_priv, read_cmd.handle);
|
||||
if (!desc)
|
||||
return -EINVAL;
|
||||
|
||||
if (WARN_ON_ONCE(sizeof(userbuf) > sizeof(read_cmd.buffer_ptr)))
|
||||
return -EFAULT;
|
||||
|
||||
|
|
@ -904,6 +900,17 @@ static int read_ioctl(struct gpib_file_private *file_priv, struct gpib_board *bo
|
|||
if (!access_ok(userbuf, remain))
|
||||
return -EFAULT;
|
||||
|
||||
/* Lock descriptors to prevent concurrent close from freeing descriptor */
|
||||
if (mutex_lock_interruptible(&file_priv->descriptors_mutex))
|
||||
return -ERESTARTSYS;
|
||||
desc = handle_to_descriptor(file_priv, read_cmd.handle);
|
||||
if (!desc) {
|
||||
mutex_unlock(&file_priv->descriptors_mutex);
|
||||
return -EINVAL;
|
||||
}
|
||||
atomic_inc(&desc->descriptor_busy);
|
||||
mutex_unlock(&file_priv->descriptors_mutex);
|
||||
|
||||
atomic_set(&desc->io_in_progress, 1);
|
||||
|
||||
/* Read buffer loads till we fill the user supplied buffer */
|
||||
|
|
@ -937,6 +944,7 @@ static int read_ioctl(struct gpib_file_private *file_priv, struct gpib_board *bo
|
|||
retval = copy_to_user((void __user *)arg, &read_cmd, sizeof(read_cmd));
|
||||
|
||||
atomic_set(&desc->io_in_progress, 0);
|
||||
atomic_dec(&desc->descriptor_busy);
|
||||
|
||||
wake_up_interruptible(&board->wait);
|
||||
if (retval)
|
||||
|
|
@ -964,10 +972,6 @@ static int command_ioctl(struct gpib_file_private *file_priv,
|
|||
if (cmd.completed_transfer_count > cmd.requested_transfer_count)
|
||||
return -EINVAL;
|
||||
|
||||
desc = handle_to_descriptor(file_priv, cmd.handle);
|
||||
if (!desc)
|
||||
return -EINVAL;
|
||||
|
||||
userbuf = (u8 __user *)(unsigned long)cmd.buffer_ptr;
|
||||
userbuf += cmd.completed_transfer_count;
|
||||
|
||||
|
|
@ -980,6 +984,17 @@ static int command_ioctl(struct gpib_file_private *file_priv,
|
|||
if (!access_ok(userbuf, remain))
|
||||
return -EFAULT;
|
||||
|
||||
/* Lock descriptors to prevent concurrent close from freeing descriptor */
|
||||
if (mutex_lock_interruptible(&file_priv->descriptors_mutex))
|
||||
return -ERESTARTSYS;
|
||||
desc = handle_to_descriptor(file_priv, cmd.handle);
|
||||
if (!desc) {
|
||||
mutex_unlock(&file_priv->descriptors_mutex);
|
||||
return -EINVAL;
|
||||
}
|
||||
atomic_inc(&desc->descriptor_busy);
|
||||
mutex_unlock(&file_priv->descriptors_mutex);
|
||||
|
||||
/*
|
||||
* Write buffer loads till we empty the user supplied buffer.
|
||||
* Call drivers at least once, even if remain is zero, in
|
||||
|
|
@ -1003,6 +1018,7 @@ static int command_ioctl(struct gpib_file_private *file_priv,
|
|||
userbuf += bytes_written;
|
||||
if (retval < 0) {
|
||||
atomic_set(&desc->io_in_progress, 0);
|
||||
atomic_dec(&desc->descriptor_busy);
|
||||
|
||||
wake_up_interruptible(&board->wait);
|
||||
break;
|
||||
|
|
@ -1022,6 +1038,7 @@ static int command_ioctl(struct gpib_file_private *file_priv,
|
|||
*/
|
||||
if (!no_clear_io_in_prog || fault)
|
||||
atomic_set(&desc->io_in_progress, 0);
|
||||
atomic_dec(&desc->descriptor_busy);
|
||||
|
||||
wake_up_interruptible(&board->wait);
|
||||
if (fault)
|
||||
|
|
@ -1047,10 +1064,6 @@ static int write_ioctl(struct gpib_file_private *file_priv, struct gpib_board *b
|
|||
if (write_cmd.completed_transfer_count > write_cmd.requested_transfer_count)
|
||||
return -EINVAL;
|
||||
|
||||
desc = handle_to_descriptor(file_priv, write_cmd.handle);
|
||||
if (!desc)
|
||||
return -EINVAL;
|
||||
|
||||
userbuf = (u8 __user *)(unsigned long)write_cmd.buffer_ptr;
|
||||
userbuf += write_cmd.completed_transfer_count;
|
||||
|
||||
|
|
@ -1060,6 +1073,17 @@ static int write_ioctl(struct gpib_file_private *file_priv, struct gpib_board *b
|
|||
if (!access_ok(userbuf, remain))
|
||||
return -EFAULT;
|
||||
|
||||
/* Lock descriptors to prevent concurrent close from freeing descriptor */
|
||||
if (mutex_lock_interruptible(&file_priv->descriptors_mutex))
|
||||
return -ERESTARTSYS;
|
||||
desc = handle_to_descriptor(file_priv, write_cmd.handle);
|
||||
if (!desc) {
|
||||
mutex_unlock(&file_priv->descriptors_mutex);
|
||||
return -EINVAL;
|
||||
}
|
||||
atomic_inc(&desc->descriptor_busy);
|
||||
mutex_unlock(&file_priv->descriptors_mutex);
|
||||
|
||||
atomic_set(&desc->io_in_progress, 1);
|
||||
|
||||
/* Write buffer loads till we empty the user supplied buffer */
|
||||
|
|
@ -1094,6 +1118,7 @@ static int write_ioctl(struct gpib_file_private *file_priv, struct gpib_board *b
|
|||
fault = copy_to_user((void __user *)arg, &write_cmd, sizeof(write_cmd));
|
||||
|
||||
atomic_set(&desc->io_in_progress, 0);
|
||||
atomic_dec(&desc->descriptor_busy);
|
||||
|
||||
wake_up_interruptible(&board->wait);
|
||||
if (fault)
|
||||
|
|
@ -1276,6 +1301,9 @@ static int close_dev_ioctl(struct file *filep, struct gpib_board *board, unsigne
|
|||
{
|
||||
struct gpib_close_dev_ioctl cmd;
|
||||
struct gpib_file_private *file_priv = filep->private_data;
|
||||
struct gpib_descriptor *desc;
|
||||
unsigned int pad;
|
||||
int sad;
|
||||
int retval;
|
||||
|
||||
retval = copy_from_user(&cmd, (void __user *)arg, sizeof(cmd));
|
||||
|
|
@ -1284,19 +1312,27 @@ static int close_dev_ioctl(struct file *filep, struct gpib_board *board, unsigne
|
|||
|
||||
if (cmd.handle >= GPIB_MAX_NUM_DESCRIPTORS)
|
||||
return -EINVAL;
|
||||
if (!file_priv->descriptors[cmd.handle])
|
||||
|
||||
mutex_lock(&file_priv->descriptors_mutex);
|
||||
desc = file_priv->descriptors[cmd.handle];
|
||||
if (!desc) {
|
||||
mutex_unlock(&file_priv->descriptors_mutex);
|
||||
return -EINVAL;
|
||||
|
||||
retval = decrement_open_device_count(board, &board->device_list,
|
||||
file_priv->descriptors[cmd.handle]->pad,
|
||||
file_priv->descriptors[cmd.handle]->sad);
|
||||
if (retval < 0)
|
||||
return retval;
|
||||
|
||||
kfree(file_priv->descriptors[cmd.handle]);
|
||||
}
|
||||
if (atomic_read(&desc->descriptor_busy)) {
|
||||
mutex_unlock(&file_priv->descriptors_mutex);
|
||||
return -EBUSY;
|
||||
}
|
||||
/* Remove from table while holding lock to prevent new IO from starting */
|
||||
file_priv->descriptors[cmd.handle] = NULL;
|
||||
pad = desc->pad;
|
||||
sad = desc->sad;
|
||||
mutex_unlock(&file_priv->descriptors_mutex);
|
||||
|
||||
return 0;
|
||||
retval = decrement_open_device_count(board, &board->device_list, pad, sad);
|
||||
|
||||
kfree(desc);
|
||||
return retval;
|
||||
}
|
||||
|
||||
static int serial_poll_ioctl(struct gpib_board *board, unsigned long arg)
|
||||
|
|
@ -1331,12 +1367,25 @@ static int wait_ioctl(struct gpib_file_private *file_priv, struct gpib_board *bo
|
|||
if (retval)
|
||||
return -EFAULT;
|
||||
|
||||
/*
|
||||
* Lock descriptors to prevent concurrent close from freeing
|
||||
* descriptor. ibwait() releases big_gpib_mutex when wait_mask
|
||||
* is non-zero, so desc must be pinned with descriptor_busy.
|
||||
*/
|
||||
mutex_lock(&file_priv->descriptors_mutex);
|
||||
desc = handle_to_descriptor(file_priv, wait_cmd.handle);
|
||||
if (!desc)
|
||||
if (!desc) {
|
||||
mutex_unlock(&file_priv->descriptors_mutex);
|
||||
return -EINVAL;
|
||||
}
|
||||
atomic_inc(&desc->descriptor_busy);
|
||||
mutex_unlock(&file_priv->descriptors_mutex);
|
||||
|
||||
retval = ibwait(board, wait_cmd.wait_mask, wait_cmd.clear_mask,
|
||||
wait_cmd.set_mask, &wait_cmd.ibsta, wait_cmd.usec_timeout, desc);
|
||||
|
||||
atomic_dec(&desc->descriptor_busy);
|
||||
|
||||
if (retval < 0)
|
||||
return retval;
|
||||
|
||||
|
|
@ -2035,6 +2084,7 @@ void init_gpib_descriptor(struct gpib_descriptor *desc)
|
|||
desc->is_board = 0;
|
||||
desc->autopoll_enabled = 0;
|
||||
atomic_set(&desc->io_in_progress, 0);
|
||||
atomic_set(&desc->descriptor_busy, 0);
|
||||
}
|
||||
|
||||
int gpib_register_driver(struct gpib_interface *interface, struct module *provider_module)
|
||||
|
|
|
|||
|
|
@ -364,6 +364,14 @@ struct gpib_descriptor {
|
|||
unsigned int pad; /* primary gpib address */
|
||||
int sad; /* secondary gpib address (negative means disabled) */
|
||||
atomic_t io_in_progress;
|
||||
/*
|
||||
* Kernel-only reference count to prevent descriptor from being
|
||||
* freed while IO handlers hold a pointer to it. Incremented
|
||||
* before each IO operation, decremented when done. Unlike
|
||||
* io_in_progress, this cannot be modified from userspace via
|
||||
* general_ibstatus().
|
||||
*/
|
||||
atomic_t descriptor_busy;
|
||||
unsigned is_board : 1;
|
||||
unsigned autopoll_enabled : 1;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -406,7 +406,7 @@ static int usb_gpib_attach(struct gpib_board *board, const struct gpib_board_con
|
|||
for (j = 0 ; j < MAX_DEV ; j++) {
|
||||
if ((assigned_usb_minors & 1 << j) == 0)
|
||||
continue;
|
||||
udev = usb_get_dev(interface_to_usbdev(lpvo_usb_interfaces[j]));
|
||||
udev = interface_to_usbdev(lpvo_usb_interfaces[j]);
|
||||
device_path = kobject_get_path(&udev->dev.kobj, GFP_KERNEL);
|
||||
match = gpib_match_device_path(&lpvo_usb_interfaces[j]->dev,
|
||||
config->device_path);
|
||||
|
|
@ -421,7 +421,7 @@ static int usb_gpib_attach(struct gpib_board *board, const struct gpib_board_con
|
|||
for (j = 0 ; j < MAX_DEV ; j++) {
|
||||
if ((assigned_usb_minors & 1 << j) == 0)
|
||||
continue;
|
||||
udev = usb_get_dev(interface_to_usbdev(lpvo_usb_interfaces[j]));
|
||||
udev = interface_to_usbdev(lpvo_usb_interfaces[j]);
|
||||
DIA_LOG(1, "dev. %d: bus %d -> %d dev: %d -> %d\n", j,
|
||||
udev->bus->busnum, config->pci_bus, udev->devnum, config->pci_slot);
|
||||
if (config->pci_bus == udev->bus->busnum &&
|
||||
|
|
|
|||
|
|
@ -584,12 +584,13 @@ static bool mxc_gpio_set_pad_wakeup(struct mxc_gpio_port *port, bool enable)
|
|||
unsigned long config;
|
||||
bool ret = false;
|
||||
int i, type;
|
||||
bool is_imx8qm = of_device_is_compatible(port->dev->of_node, "fsl,imx8qm-gpio");
|
||||
|
||||
static const u32 pad_type_map[] = {
|
||||
IMX_SCU_WAKEUP_OFF, /* 0 */
|
||||
IMX_SCU_WAKEUP_RISE_EDGE, /* IRQ_TYPE_EDGE_RISING */
|
||||
IMX_SCU_WAKEUP_FALL_EDGE, /* IRQ_TYPE_EDGE_FALLING */
|
||||
IMX_SCU_WAKEUP_FALL_EDGE, /* IRQ_TYPE_EDGE_BOTH */
|
||||
IMX_SCU_WAKEUP_RISE_EDGE, /* IRQ_TYPE_EDGE_BOTH */
|
||||
IMX_SCU_WAKEUP_HIGH_LVL, /* IRQ_TYPE_LEVEL_HIGH */
|
||||
IMX_SCU_WAKEUP_OFF, /* 5 */
|
||||
IMX_SCU_WAKEUP_OFF, /* 6 */
|
||||
|
|
@ -604,6 +605,13 @@ static bool mxc_gpio_set_pad_wakeup(struct mxc_gpio_port *port, bool enable)
|
|||
config = pad_type_map[type];
|
||||
else
|
||||
config = IMX_SCU_WAKEUP_OFF;
|
||||
|
||||
if (is_imx8qm && config == IMX_SCU_WAKEUP_FALL_EDGE) {
|
||||
dev_warn_once(port->dev,
|
||||
"No falling-edge support for wakeup on i.MX8QM\n");
|
||||
config = IMX_SCU_WAKEUP_OFF;
|
||||
}
|
||||
|
||||
ret |= mxc_gpio_generic_config(port, i, config);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -60,8 +60,8 @@ static int qixis_cpld_gpio_probe(struct platform_device *pdev)
|
|||
return PTR_ERR(reg);
|
||||
|
||||
regmap = devm_regmap_init_mmio(&pdev->dev, reg, ®map_config_8r_8v);
|
||||
if (!regmap)
|
||||
return -ENODEV;
|
||||
if (IS_ERR(regmap))
|
||||
return PTR_ERR(regmap);
|
||||
|
||||
/* In this case, the offset of our register is 0 inside the
|
||||
* regmap area that we just created.
|
||||
|
|
|
|||
|
|
@ -443,8 +443,8 @@ static bool gpio_shared_dev_is_reset_gpio(struct device *consumer,
|
|||
}
|
||||
#endif /* CONFIG_RESET_GPIO */
|
||||
|
||||
int gpio_shared_add_proxy_lookup(struct device *consumer, const char *con_id,
|
||||
unsigned long lflags)
|
||||
int gpio_shared_add_proxy_lookup(struct device *consumer, struct fwnode_handle *fwnode,
|
||||
const char *con_id, unsigned long lflags)
|
||||
{
|
||||
const char *dev_id = dev_name(consumer);
|
||||
struct gpiod_lookup_table *lookup;
|
||||
|
|
@ -458,7 +458,7 @@ int gpio_shared_add_proxy_lookup(struct device *consumer, const char *con_id,
|
|||
if (!ref->fwnode && device_is_compatible(consumer, "reset-gpio")) {
|
||||
if (!gpio_shared_dev_is_reset_gpio(consumer, entry, ref))
|
||||
continue;
|
||||
} else if (!device_match_fwnode(consumer, ref->fwnode)) {
|
||||
} else if (fwnode != ref->fwnode) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -506,8 +506,9 @@ static void gpio_shared_remove_adev(struct auxiliary_device *adev)
|
|||
auxiliary_device_uninit(adev);
|
||||
}
|
||||
|
||||
int gpio_device_setup_shared(struct gpio_device *gdev)
|
||||
int gpiochip_setup_shared(struct gpio_chip *gc)
|
||||
{
|
||||
struct gpio_device *gdev = gc->gpiodev;
|
||||
struct gpio_shared_entry *entry;
|
||||
struct gpio_shared_ref *ref;
|
||||
struct gpio_desc *desc;
|
||||
|
|
@ -538,20 +539,42 @@ int gpio_device_setup_shared(struct gpio_device *gdev)
|
|||
if (list_count_nodes(&entry->refs) <= 1)
|
||||
continue;
|
||||
|
||||
desc = &gdev->descs[entry->offset];
|
||||
scoped_guard(mutex, &entry->lock) {
|
||||
#if IS_ENABLED(CONFIG_OF)
|
||||
if (is_of_node(entry->fwnode) && gc->of_xlate) {
|
||||
/*
|
||||
* This is the earliest that we can tranlate the
|
||||
* devicetree offset to the chip offset.
|
||||
*/
|
||||
struct of_phandle_args gpiospec = { };
|
||||
|
||||
__set_bit(GPIOD_FLAG_SHARED, &desc->flags);
|
||||
/*
|
||||
* Shared GPIOs are not requested via the normal path. Make
|
||||
* them inaccessible to anyone even before we register the
|
||||
* chip.
|
||||
*/
|
||||
ret = gpiod_request_commit(desc, "shared");
|
||||
if (ret)
|
||||
return ret;
|
||||
gpiospec.np = to_of_node(entry->fwnode);
|
||||
gpiospec.args_count = 2;
|
||||
gpiospec.args[0] = entry->offset;
|
||||
|
||||
pr_debug("GPIO %u owned by %s is shared by multiple consumers\n",
|
||||
entry->offset, gpio_device_get_label(gdev));
|
||||
ret = gc->of_xlate(gc, &gpiospec, NULL);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
entry->offset = ret;
|
||||
}
|
||||
#endif /* CONFIG_OF */
|
||||
|
||||
desc = &gdev->descs[entry->offset];
|
||||
|
||||
__set_bit(GPIOD_FLAG_SHARED, &desc->flags);
|
||||
/*
|
||||
* Shared GPIOs are not requested via the normal path. Make
|
||||
* them inaccessible to anyone even before we register the
|
||||
* chip.
|
||||
*/
|
||||
ret = gpiod_request_commit(desc, "shared");
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
pr_debug("GPIO %u owned by %s is shared by multiple consumers\n",
|
||||
entry->offset, gpio_device_get_label(gdev));
|
||||
}
|
||||
|
||||
list_for_each_entry(ref, &entry->refs, list) {
|
||||
pr_debug("Setting up a shared GPIO entry for %s (con_id: '%s')\n",
|
||||
|
|
@ -575,6 +598,8 @@ void gpio_device_teardown_shared(struct gpio_device *gdev)
|
|||
struct gpio_shared_ref *ref;
|
||||
|
||||
list_for_each_entry(entry, &gpio_shared_list, list) {
|
||||
guard(mutex)(&entry->lock);
|
||||
|
||||
if (!device_match_fwnode(&gdev->dev, entry->fwnode))
|
||||
continue;
|
||||
|
||||
|
|
|
|||
|
|
@ -11,17 +11,19 @@
|
|||
struct gpio_device;
|
||||
struct gpio_desc;
|
||||
struct device;
|
||||
struct fwnode_handle;
|
||||
|
||||
#if IS_ENABLED(CONFIG_GPIO_SHARED)
|
||||
|
||||
int gpio_device_setup_shared(struct gpio_device *gdev);
|
||||
int gpiochip_setup_shared(struct gpio_chip *gc);
|
||||
void gpio_device_teardown_shared(struct gpio_device *gdev);
|
||||
int gpio_shared_add_proxy_lookup(struct device *consumer, const char *con_id,
|
||||
unsigned long lflags);
|
||||
int gpio_shared_add_proxy_lookup(struct device *consumer,
|
||||
struct fwnode_handle *fwnode,
|
||||
const char *con_id, unsigned long lflags);
|
||||
|
||||
#else
|
||||
|
||||
static inline int gpio_device_setup_shared(struct gpio_device *gdev)
|
||||
static inline int gpiochip_setup_shared(struct gpio_chip *gc)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -29,6 +31,7 @@ static inline int gpio_device_setup_shared(struct gpio_device *gdev)
|
|||
static inline void gpio_device_teardown_shared(struct gpio_device *gdev) { }
|
||||
|
||||
static inline int gpio_shared_add_proxy_lookup(struct device *consumer,
|
||||
struct fwnode_handle *fwnode,
|
||||
const char *con_id,
|
||||
unsigned long lflags)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -892,13 +892,15 @@ static const struct device_type gpio_dev_type = {
|
|||
#define gcdev_unregister(gdev) device_del(&(gdev)->dev)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* An initial reference count has been held in gpiochip_add_data_with_key().
|
||||
* The caller should drop the reference via gpio_device_put() on errors.
|
||||
*/
|
||||
static int gpiochip_setup_dev(struct gpio_device *gdev)
|
||||
{
|
||||
struct fwnode_handle *fwnode = dev_fwnode(&gdev->dev);
|
||||
int ret;
|
||||
|
||||
device_initialize(&gdev->dev);
|
||||
|
||||
/*
|
||||
* If fwnode doesn't belong to another device, it's safe to clear its
|
||||
* initialized flag.
|
||||
|
|
@ -964,9 +966,11 @@ static void gpiochip_setup_devs(void)
|
|||
list_for_each_entry_srcu(gdev, &gpio_devices, list,
|
||||
srcu_read_lock_held(&gpio_devices_srcu)) {
|
||||
ret = gpiochip_setup_dev(gdev);
|
||||
if (ret)
|
||||
if (ret) {
|
||||
gpio_device_put(gdev);
|
||||
dev_err(&gdev->dev,
|
||||
"Failed to initialize gpio device (%d)\n", ret);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1047,33 +1051,65 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data,
|
|||
int base = 0;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* First: allocate and populate the internal stat container, and
|
||||
* set up the struct device.
|
||||
*/
|
||||
gdev = kzalloc(sizeof(*gdev), GFP_KERNEL);
|
||||
if (!gdev)
|
||||
return -ENOMEM;
|
||||
|
||||
gdev->dev.type = &gpio_dev_type;
|
||||
gdev->dev.bus = &gpio_bus_type;
|
||||
gdev->dev.parent = gc->parent;
|
||||
rcu_assign_pointer(gdev->chip, gc);
|
||||
|
||||
gc->gpiodev = gdev;
|
||||
gpiochip_set_data(gc, data);
|
||||
|
||||
device_set_node(&gdev->dev, gpiochip_choose_fwnode(gc));
|
||||
|
||||
ret = ida_alloc(&gpio_ida, GFP_KERNEL);
|
||||
if (ret < 0)
|
||||
goto err_free_gdev;
|
||||
gdev->id = ret;
|
||||
|
||||
ret = dev_set_name(&gdev->dev, GPIOCHIP_NAME "%d", gdev->id);
|
||||
ret = init_srcu_struct(&gdev->srcu);
|
||||
if (ret)
|
||||
goto err_free_ida;
|
||||
rcu_assign_pointer(gdev->chip, gc);
|
||||
|
||||
ret = init_srcu_struct(&gdev->desc_srcu);
|
||||
if (ret)
|
||||
goto err_cleanup_gdev_srcu;
|
||||
|
||||
ret = dev_set_name(&gdev->dev, GPIOCHIP_NAME "%d", gdev->id);
|
||||
if (ret)
|
||||
goto err_cleanup_desc_srcu;
|
||||
|
||||
device_initialize(&gdev->dev);
|
||||
/*
|
||||
* After this point any allocated resources to `gdev` will be
|
||||
* free():ed by gpiodev_release(). If you add new resources
|
||||
* then make sure they get free():ed there.
|
||||
*/
|
||||
gdev->dev.type = &gpio_dev_type;
|
||||
gdev->dev.bus = &gpio_bus_type;
|
||||
gdev->dev.parent = gc->parent;
|
||||
device_set_node(&gdev->dev, gpiochip_choose_fwnode(gc));
|
||||
|
||||
ret = gpiochip_get_ngpios(gc, &gdev->dev);
|
||||
if (ret)
|
||||
goto err_put_device;
|
||||
gdev->ngpio = gc->ngpio;
|
||||
|
||||
gdev->descs = kcalloc(gc->ngpio, sizeof(*gdev->descs), GFP_KERNEL);
|
||||
if (!gdev->descs) {
|
||||
ret = -ENOMEM;
|
||||
goto err_put_device;
|
||||
}
|
||||
|
||||
gdev->label = kstrdup_const(gc->label ?: "unknown", GFP_KERNEL);
|
||||
if (!gdev->label) {
|
||||
ret = -ENOMEM;
|
||||
goto err_put_device;
|
||||
}
|
||||
|
||||
gdev->can_sleep = gc->can_sleep;
|
||||
rwlock_init(&gdev->line_state_lock);
|
||||
RAW_INIT_NOTIFIER_HEAD(&gdev->line_state_notifier);
|
||||
BLOCKING_INIT_NOTIFIER_HEAD(&gdev->device_notifier);
|
||||
#ifdef CONFIG_PINCTRL
|
||||
INIT_LIST_HEAD(&gdev->pin_ranges);
|
||||
#endif
|
||||
if (gc->parent && gc->parent->driver)
|
||||
gdev->owner = gc->parent->driver->owner;
|
||||
else if (gc->owner)
|
||||
|
|
@ -1082,37 +1118,6 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data,
|
|||
else
|
||||
gdev->owner = THIS_MODULE;
|
||||
|
||||
ret = gpiochip_get_ngpios(gc, &gdev->dev);
|
||||
if (ret)
|
||||
goto err_free_dev_name;
|
||||
|
||||
gdev->descs = kcalloc(gc->ngpio, sizeof(*gdev->descs), GFP_KERNEL);
|
||||
if (!gdev->descs) {
|
||||
ret = -ENOMEM;
|
||||
goto err_free_dev_name;
|
||||
}
|
||||
|
||||
gdev->label = kstrdup_const(gc->label ?: "unknown", GFP_KERNEL);
|
||||
if (!gdev->label) {
|
||||
ret = -ENOMEM;
|
||||
goto err_free_descs;
|
||||
}
|
||||
|
||||
gdev->ngpio = gc->ngpio;
|
||||
gdev->can_sleep = gc->can_sleep;
|
||||
|
||||
rwlock_init(&gdev->line_state_lock);
|
||||
RAW_INIT_NOTIFIER_HEAD(&gdev->line_state_notifier);
|
||||
BLOCKING_INIT_NOTIFIER_HEAD(&gdev->device_notifier);
|
||||
|
||||
ret = init_srcu_struct(&gdev->srcu);
|
||||
if (ret)
|
||||
goto err_free_label;
|
||||
|
||||
ret = init_srcu_struct(&gdev->desc_srcu);
|
||||
if (ret)
|
||||
goto err_cleanup_gdev_srcu;
|
||||
|
||||
scoped_guard(mutex, &gpio_devices_lock) {
|
||||
/*
|
||||
* TODO: this allocates a Linux GPIO number base in the global
|
||||
|
|
@ -1127,7 +1132,7 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data,
|
|||
if (base < 0) {
|
||||
ret = base;
|
||||
base = 0;
|
||||
goto err_cleanup_desc_srcu;
|
||||
goto err_put_device;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -1147,14 +1152,10 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data,
|
|||
ret = gpiodev_add_to_list_unlocked(gdev);
|
||||
if (ret) {
|
||||
gpiochip_err(gc, "GPIO integer space overlap, cannot add chip\n");
|
||||
goto err_cleanup_desc_srcu;
|
||||
goto err_put_device;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PINCTRL
|
||||
INIT_LIST_HEAD(&gdev->pin_ranges);
|
||||
#endif
|
||||
|
||||
if (gc->names)
|
||||
gpiochip_set_desc_names(gc);
|
||||
|
||||
|
|
@ -1210,7 +1211,7 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data,
|
|||
if (ret)
|
||||
goto err_remove_irqchip_mask;
|
||||
|
||||
ret = gpio_device_setup_shared(gdev);
|
||||
ret = gpiochip_setup_shared(gc);
|
||||
if (ret)
|
||||
goto err_remove_irqchip;
|
||||
|
||||
|
|
@ -1248,25 +1249,19 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data,
|
|||
scoped_guard(mutex, &gpio_devices_lock)
|
||||
list_del_rcu(&gdev->list);
|
||||
synchronize_srcu(&gpio_devices_srcu);
|
||||
if (gdev->dev.release) {
|
||||
/* release() has been registered by gpiochip_setup_dev() */
|
||||
gpio_device_put(gdev);
|
||||
goto err_print_message;
|
||||
}
|
||||
err_put_device:
|
||||
gpio_device_put(gdev);
|
||||
goto err_print_message;
|
||||
|
||||
err_cleanup_desc_srcu:
|
||||
cleanup_srcu_struct(&gdev->desc_srcu);
|
||||
err_cleanup_gdev_srcu:
|
||||
cleanup_srcu_struct(&gdev->srcu);
|
||||
err_free_label:
|
||||
kfree_const(gdev->label);
|
||||
err_free_descs:
|
||||
kfree(gdev->descs);
|
||||
err_free_dev_name:
|
||||
kfree(dev_name(&gdev->dev));
|
||||
err_free_ida:
|
||||
ida_free(&gpio_ida, gdev->id);
|
||||
err_free_gdev:
|
||||
kfree(gdev);
|
||||
|
||||
err_print_message:
|
||||
/* failures here can mean systems won't boot... */
|
||||
if (ret != -EPROBE_DEFER) {
|
||||
|
|
@ -2465,8 +2460,10 @@ int gpiod_request_commit(struct gpio_desc *desc, const char *label)
|
|||
return -EBUSY;
|
||||
|
||||
offset = gpiod_hwgpio(desc);
|
||||
if (!gpiochip_line_is_valid(guard.gc, offset))
|
||||
return -EINVAL;
|
||||
if (!gpiochip_line_is_valid(guard.gc, offset)) {
|
||||
ret = -EINVAL;
|
||||
goto out_clear_bit;
|
||||
}
|
||||
|
||||
/* NOTE: gpio_request() can be called in early boot,
|
||||
* before IRQs are enabled, for non-sleeping (SOC) GPIOs.
|
||||
|
|
@ -4717,8 +4714,8 @@ struct gpio_desc *gpiod_find_and_request(struct device *consumer,
|
|||
* lookup table for the proxy device as previously
|
||||
* we only knew the consumer's fwnode.
|
||||
*/
|
||||
ret = gpio_shared_add_proxy_lookup(consumer, con_id,
|
||||
lookupflags);
|
||||
ret = gpio_shared_add_proxy_lookup(consumer, fwnode,
|
||||
con_id, lookupflags);
|
||||
if (ret)
|
||||
return ERR_PTR(ret);
|
||||
|
||||
|
|
|
|||
|
|
@ -268,6 +268,13 @@ config DRM_GEM_SHMEM_HELPER
|
|||
help
|
||||
Choose this if you need the GEM shmem helper functions
|
||||
|
||||
config RUST_DRM_GEM_SHMEM_HELPER
|
||||
bool
|
||||
depends on DRM && MMU
|
||||
select DRM_GEM_SHMEM_HELPER
|
||||
help
|
||||
Choose this if you need the GEM shmem helper functions In Rust
|
||||
|
||||
config DRM_SUBALLOC_HELPER
|
||||
tristate
|
||||
depends on DRM
|
||||
|
|
|
|||
|
|
@ -373,17 +373,148 @@ int amdgpu_atomfirmware_get_uma_carveout_info(struct amdgpu_device *adev,
|
|||
return -ENODEV;
|
||||
}
|
||||
|
||||
int
|
||||
amdgpu_atomfirmware_get_vram_info(struct amdgpu_device *adev,
|
||||
int amdgpu_atomfirmware_get_integrated_system_info(struct amdgpu_device *adev,
|
||||
int *vram_width, int *vram_type,
|
||||
int *vram_vendor)
|
||||
{
|
||||
struct amdgpu_mode_info *mode_info = &adev->mode_info;
|
||||
int index;
|
||||
u16 data_offset, size;
|
||||
union igp_info *igp_info;
|
||||
u8 frev, crev;
|
||||
u8 mem_type;
|
||||
u32 mem_channel_number;
|
||||
u32 mem_channel_width;
|
||||
|
||||
index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1,
|
||||
integratedsysteminfo);
|
||||
if (amdgpu_atom_parse_data_header(mode_info->atom_context,
|
||||
index, &size,
|
||||
&frev, &crev, &data_offset)) {
|
||||
igp_info = (union igp_info *)
|
||||
(mode_info->atom_context->bios + data_offset);
|
||||
switch (frev) {
|
||||
case 1:
|
||||
switch (crev) {
|
||||
case 11:
|
||||
case 12:
|
||||
mem_channel_number = igp_info->v11.umachannelnumber;
|
||||
if (!mem_channel_number)
|
||||
mem_channel_number = 1;
|
||||
mem_type = igp_info->v11.memorytype;
|
||||
if (mem_type == LpDdr5MemType)
|
||||
mem_channel_width = 32;
|
||||
else
|
||||
mem_channel_width = 64;
|
||||
if (vram_width)
|
||||
*vram_width = mem_channel_number * mem_channel_width;
|
||||
if (vram_type)
|
||||
*vram_type = convert_atom_mem_type_to_vram_type(adev, mem_type);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
switch (crev) {
|
||||
case 1:
|
||||
case 2:
|
||||
mem_channel_number = igp_info->v21.umachannelnumber;
|
||||
if (!mem_channel_number)
|
||||
mem_channel_number = 1;
|
||||
mem_type = igp_info->v21.memorytype;
|
||||
if (mem_type == LpDdr5MemType)
|
||||
mem_channel_width = 32;
|
||||
else
|
||||
mem_channel_width = 64;
|
||||
if (vram_width)
|
||||
*vram_width = mem_channel_number * mem_channel_width;
|
||||
if (vram_type)
|
||||
*vram_type = convert_atom_mem_type_to_vram_type(adev, mem_type);
|
||||
break;
|
||||
case 3:
|
||||
mem_channel_number = igp_info->v23.umachannelnumber;
|
||||
if (!mem_channel_number)
|
||||
mem_channel_number = 1;
|
||||
mem_type = igp_info->v23.memorytype;
|
||||
if (mem_type == LpDdr5MemType)
|
||||
mem_channel_width = 32;
|
||||
else
|
||||
mem_channel_width = 64;
|
||||
if (vram_width)
|
||||
*vram_width = mem_channel_number * mem_channel_width;
|
||||
if (vram_type)
|
||||
*vram_type = convert_atom_mem_type_to_vram_type(adev, mem_type);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
} else {
|
||||
return -EINVAL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int amdgpu_atomfirmware_get_umc_info(struct amdgpu_device *adev,
|
||||
int *vram_width, int *vram_type,
|
||||
int *vram_vendor)
|
||||
{
|
||||
struct amdgpu_mode_info *mode_info = &adev->mode_info;
|
||||
int index;
|
||||
u16 data_offset, size;
|
||||
union umc_info *umc_info;
|
||||
u8 frev, crev;
|
||||
u8 mem_type;
|
||||
u8 mem_vendor;
|
||||
u32 mem_channel_number;
|
||||
u32 mem_channel_width;
|
||||
|
||||
index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1, umc_info);
|
||||
|
||||
if (amdgpu_atom_parse_data_header(mode_info->atom_context,
|
||||
index, &size,
|
||||
&frev, &crev, &data_offset)) {
|
||||
umc_info = (union umc_info *)(mode_info->atom_context->bios + data_offset);
|
||||
|
||||
if (frev == 4) {
|
||||
switch (crev) {
|
||||
case 0:
|
||||
mem_channel_number = le32_to_cpu(umc_info->v40.channel_num);
|
||||
mem_type = le32_to_cpu(umc_info->v40.vram_type);
|
||||
mem_channel_width = le32_to_cpu(umc_info->v40.channel_width);
|
||||
mem_vendor = RREG32(adev->bios_scratch_reg_offset + 4) & 0xF;
|
||||
if (vram_vendor)
|
||||
*vram_vendor = mem_vendor;
|
||||
if (vram_type)
|
||||
*vram_type = convert_atom_mem_type_to_vram_type(adev, mem_type);
|
||||
if (vram_width)
|
||||
*vram_width = mem_channel_number * (1 << mem_channel_width);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
} else {
|
||||
return -EINVAL;
|
||||
}
|
||||
} else {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int amdgpu_atomfirmware_get_vram_info(struct amdgpu_device *adev,
|
||||
int *vram_width, int *vram_type,
|
||||
int *vram_vendor)
|
||||
{
|
||||
struct amdgpu_mode_info *mode_info = &adev->mode_info;
|
||||
int index, i = 0;
|
||||
u16 data_offset, size;
|
||||
union igp_info *igp_info;
|
||||
union vram_info *vram_info;
|
||||
union umc_info *umc_info;
|
||||
union vram_module *vram_module;
|
||||
u8 frev, crev;
|
||||
u8 mem_type;
|
||||
|
|
@ -392,230 +523,130 @@ amdgpu_atomfirmware_get_vram_info(struct amdgpu_device *adev,
|
|||
u32 mem_channel_width;
|
||||
u32 module_id;
|
||||
|
||||
if (adev->flags & AMD_IS_APU)
|
||||
index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1,
|
||||
integratedsysteminfo);
|
||||
else {
|
||||
switch (amdgpu_ip_version(adev, GC_HWIP, 0)) {
|
||||
case IP_VERSION(12, 0, 0):
|
||||
case IP_VERSION(12, 0, 1):
|
||||
index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1, umc_info);
|
||||
break;
|
||||
default:
|
||||
index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1, vram_info);
|
||||
}
|
||||
}
|
||||
index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1, vram_info);
|
||||
|
||||
if (amdgpu_atom_parse_data_header(mode_info->atom_context,
|
||||
index, &size,
|
||||
&frev, &crev, &data_offset)) {
|
||||
if (adev->flags & AMD_IS_APU) {
|
||||
igp_info = (union igp_info *)
|
||||
(mode_info->atom_context->bios + data_offset);
|
||||
switch (frev) {
|
||||
case 1:
|
||||
switch (crev) {
|
||||
case 11:
|
||||
case 12:
|
||||
mem_channel_number = igp_info->v11.umachannelnumber;
|
||||
if (!mem_channel_number)
|
||||
mem_channel_number = 1;
|
||||
mem_type = igp_info->v11.memorytype;
|
||||
if (mem_type == LpDdr5MemType)
|
||||
mem_channel_width = 32;
|
||||
else
|
||||
mem_channel_width = 64;
|
||||
if (vram_width)
|
||||
*vram_width = mem_channel_number * mem_channel_width;
|
||||
if (vram_type)
|
||||
*vram_type = convert_atom_mem_type_to_vram_type(adev, mem_type);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
vram_info = (union vram_info *)
|
||||
(mode_info->atom_context->bios + data_offset);
|
||||
|
||||
module_id = (RREG32(adev->bios_scratch_reg_offset + 4) & 0x00ff0000) >> 16;
|
||||
if (frev == 3) {
|
||||
switch (crev) {
|
||||
/* v30 */
|
||||
case 0:
|
||||
vram_module = (union vram_module *)vram_info->v30.vram_module;
|
||||
mem_vendor = (vram_module->v30.dram_vendor_id) & 0xF;
|
||||
if (vram_vendor)
|
||||
*vram_vendor = mem_vendor;
|
||||
mem_type = vram_info->v30.memory_type;
|
||||
if (vram_type)
|
||||
*vram_type = convert_atom_mem_type_to_vram_type(adev, mem_type);
|
||||
mem_channel_number = vram_info->v30.channel_num;
|
||||
mem_channel_width = vram_info->v30.channel_width;
|
||||
if (vram_width)
|
||||
*vram_width = mem_channel_number * 16;
|
||||
break;
|
||||
case 2:
|
||||
switch (crev) {
|
||||
case 1:
|
||||
case 2:
|
||||
mem_channel_number = igp_info->v21.umachannelnumber;
|
||||
if (!mem_channel_number)
|
||||
mem_channel_number = 1;
|
||||
mem_type = igp_info->v21.memorytype;
|
||||
if (mem_type == LpDdr5MemType)
|
||||
mem_channel_width = 32;
|
||||
else
|
||||
mem_channel_width = 64;
|
||||
if (vram_width)
|
||||
*vram_width = mem_channel_number * mem_channel_width;
|
||||
if (vram_type)
|
||||
*vram_type = convert_atom_mem_type_to_vram_type(adev, mem_type);
|
||||
break;
|
||||
case 3:
|
||||
mem_channel_number = igp_info->v23.umachannelnumber;
|
||||
if (!mem_channel_number)
|
||||
mem_channel_number = 1;
|
||||
mem_type = igp_info->v23.memorytype;
|
||||
if (mem_type == LpDdr5MemType)
|
||||
mem_channel_width = 32;
|
||||
else
|
||||
mem_channel_width = 64;
|
||||
if (vram_width)
|
||||
*vram_width = mem_channel_number * mem_channel_width;
|
||||
if (vram_type)
|
||||
*vram_type = convert_atom_mem_type_to_vram_type(adev, mem_type);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
} else if (frev == 2) {
|
||||
switch (crev) {
|
||||
/* v23 */
|
||||
case 3:
|
||||
if (module_id > vram_info->v23.vram_module_num)
|
||||
module_id = 0;
|
||||
vram_module = (union vram_module *)vram_info->v23.vram_module;
|
||||
while (i < module_id) {
|
||||
vram_module = (union vram_module *)
|
||||
((u8 *)vram_module + vram_module->v9.vram_module_size);
|
||||
i++;
|
||||
}
|
||||
mem_type = vram_module->v9.memory_type;
|
||||
if (vram_type)
|
||||
*vram_type = convert_atom_mem_type_to_vram_type(adev, mem_type);
|
||||
mem_channel_number = vram_module->v9.channel_num;
|
||||
mem_channel_width = vram_module->v9.channel_width;
|
||||
if (vram_width)
|
||||
*vram_width = mem_channel_number * (1 << mem_channel_width);
|
||||
mem_vendor = (vram_module->v9.vender_rev_id) & 0xF;
|
||||
if (vram_vendor)
|
||||
*vram_vendor = mem_vendor;
|
||||
break;
|
||||
/* v24 */
|
||||
case 4:
|
||||
if (module_id > vram_info->v24.vram_module_num)
|
||||
module_id = 0;
|
||||
vram_module = (union vram_module *)vram_info->v24.vram_module;
|
||||
while (i < module_id) {
|
||||
vram_module = (union vram_module *)
|
||||
((u8 *)vram_module + vram_module->v10.vram_module_size);
|
||||
i++;
|
||||
}
|
||||
mem_type = vram_module->v10.memory_type;
|
||||
if (vram_type)
|
||||
*vram_type = convert_atom_mem_type_to_vram_type(adev, mem_type);
|
||||
mem_channel_number = vram_module->v10.channel_num;
|
||||
mem_channel_width = vram_module->v10.channel_width;
|
||||
if (vram_width)
|
||||
*vram_width = mem_channel_number * (1 << mem_channel_width);
|
||||
mem_vendor = (vram_module->v10.vender_rev_id) & 0xF;
|
||||
if (vram_vendor)
|
||||
*vram_vendor = mem_vendor;
|
||||
break;
|
||||
/* v25 */
|
||||
case 5:
|
||||
if (module_id > vram_info->v25.vram_module_num)
|
||||
module_id = 0;
|
||||
vram_module = (union vram_module *)vram_info->v25.vram_module;
|
||||
while (i < module_id) {
|
||||
vram_module = (union vram_module *)
|
||||
((u8 *)vram_module + vram_module->v11.vram_module_size);
|
||||
i++;
|
||||
}
|
||||
mem_type = vram_module->v11.memory_type;
|
||||
if (vram_type)
|
||||
*vram_type = convert_atom_mem_type_to_vram_type(adev, mem_type);
|
||||
mem_channel_number = vram_module->v11.channel_num;
|
||||
mem_channel_width = vram_module->v11.channel_width;
|
||||
if (vram_width)
|
||||
*vram_width = mem_channel_number * (1 << mem_channel_width);
|
||||
mem_vendor = (vram_module->v11.vender_rev_id) & 0xF;
|
||||
if (vram_vendor)
|
||||
*vram_vendor = mem_vendor;
|
||||
break;
|
||||
/* v26 */
|
||||
case 6:
|
||||
if (module_id > vram_info->v26.vram_module_num)
|
||||
module_id = 0;
|
||||
vram_module = (union vram_module *)vram_info->v26.vram_module;
|
||||
while (i < module_id) {
|
||||
vram_module = (union vram_module *)
|
||||
((u8 *)vram_module + vram_module->v9.vram_module_size);
|
||||
i++;
|
||||
}
|
||||
mem_type = vram_module->v9.memory_type;
|
||||
if (vram_type)
|
||||
*vram_type = convert_atom_mem_type_to_vram_type(adev, mem_type);
|
||||
mem_channel_number = vram_module->v9.channel_num;
|
||||
mem_channel_width = vram_module->v9.channel_width;
|
||||
if (vram_width)
|
||||
*vram_width = mem_channel_number * (1 << mem_channel_width);
|
||||
mem_vendor = (vram_module->v9.vender_rev_id) & 0xF;
|
||||
if (vram_vendor)
|
||||
*vram_vendor = mem_vendor;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
} else {
|
||||
switch (amdgpu_ip_version(adev, GC_HWIP, 0)) {
|
||||
case IP_VERSION(12, 0, 0):
|
||||
case IP_VERSION(12, 0, 1):
|
||||
umc_info = (union umc_info *)(mode_info->atom_context->bios + data_offset);
|
||||
|
||||
if (frev == 4) {
|
||||
switch (crev) {
|
||||
case 0:
|
||||
mem_channel_number = le32_to_cpu(umc_info->v40.channel_num);
|
||||
mem_type = le32_to_cpu(umc_info->v40.vram_type);
|
||||
mem_channel_width = le32_to_cpu(umc_info->v40.channel_width);
|
||||
mem_vendor = RREG32(adev->bios_scratch_reg_offset + 4) & 0xF;
|
||||
if (vram_vendor)
|
||||
*vram_vendor = mem_vendor;
|
||||
if (vram_type)
|
||||
*vram_type = convert_atom_mem_type_to_vram_type(adev, mem_type);
|
||||
if (vram_width)
|
||||
*vram_width = mem_channel_number * (1 << mem_channel_width);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
} else
|
||||
return -EINVAL;
|
||||
break;
|
||||
default:
|
||||
vram_info = (union vram_info *)
|
||||
(mode_info->atom_context->bios + data_offset);
|
||||
|
||||
module_id = (RREG32(adev->bios_scratch_reg_offset + 4) & 0x00ff0000) >> 16;
|
||||
if (frev == 3) {
|
||||
switch (crev) {
|
||||
/* v30 */
|
||||
case 0:
|
||||
vram_module = (union vram_module *)vram_info->v30.vram_module;
|
||||
mem_vendor = (vram_module->v30.dram_vendor_id) & 0xF;
|
||||
if (vram_vendor)
|
||||
*vram_vendor = mem_vendor;
|
||||
mem_type = vram_info->v30.memory_type;
|
||||
if (vram_type)
|
||||
*vram_type = convert_atom_mem_type_to_vram_type(adev, mem_type);
|
||||
mem_channel_number = vram_info->v30.channel_num;
|
||||
mem_channel_width = vram_info->v30.channel_width;
|
||||
if (vram_width)
|
||||
*vram_width = mem_channel_number * 16;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
} else if (frev == 2) {
|
||||
switch (crev) {
|
||||
/* v23 */
|
||||
case 3:
|
||||
if (module_id > vram_info->v23.vram_module_num)
|
||||
module_id = 0;
|
||||
vram_module = (union vram_module *)vram_info->v23.vram_module;
|
||||
while (i < module_id) {
|
||||
vram_module = (union vram_module *)
|
||||
((u8 *)vram_module + vram_module->v9.vram_module_size);
|
||||
i++;
|
||||
}
|
||||
mem_type = vram_module->v9.memory_type;
|
||||
if (vram_type)
|
||||
*vram_type = convert_atom_mem_type_to_vram_type(adev, mem_type);
|
||||
mem_channel_number = vram_module->v9.channel_num;
|
||||
mem_channel_width = vram_module->v9.channel_width;
|
||||
if (vram_width)
|
||||
*vram_width = mem_channel_number * (1 << mem_channel_width);
|
||||
mem_vendor = (vram_module->v9.vender_rev_id) & 0xF;
|
||||
if (vram_vendor)
|
||||
*vram_vendor = mem_vendor;
|
||||
break;
|
||||
/* v24 */
|
||||
case 4:
|
||||
if (module_id > vram_info->v24.vram_module_num)
|
||||
module_id = 0;
|
||||
vram_module = (union vram_module *)vram_info->v24.vram_module;
|
||||
while (i < module_id) {
|
||||
vram_module = (union vram_module *)
|
||||
((u8 *)vram_module + vram_module->v10.vram_module_size);
|
||||
i++;
|
||||
}
|
||||
mem_type = vram_module->v10.memory_type;
|
||||
if (vram_type)
|
||||
*vram_type = convert_atom_mem_type_to_vram_type(adev, mem_type);
|
||||
mem_channel_number = vram_module->v10.channel_num;
|
||||
mem_channel_width = vram_module->v10.channel_width;
|
||||
if (vram_width)
|
||||
*vram_width = mem_channel_number * (1 << mem_channel_width);
|
||||
mem_vendor = (vram_module->v10.vender_rev_id) & 0xF;
|
||||
if (vram_vendor)
|
||||
*vram_vendor = mem_vendor;
|
||||
break;
|
||||
/* v25 */
|
||||
case 5:
|
||||
if (module_id > vram_info->v25.vram_module_num)
|
||||
module_id = 0;
|
||||
vram_module = (union vram_module *)vram_info->v25.vram_module;
|
||||
while (i < module_id) {
|
||||
vram_module = (union vram_module *)
|
||||
((u8 *)vram_module + vram_module->v11.vram_module_size);
|
||||
i++;
|
||||
}
|
||||
mem_type = vram_module->v11.memory_type;
|
||||
if (vram_type)
|
||||
*vram_type = convert_atom_mem_type_to_vram_type(adev, mem_type);
|
||||
mem_channel_number = vram_module->v11.channel_num;
|
||||
mem_channel_width = vram_module->v11.channel_width;
|
||||
if (vram_width)
|
||||
*vram_width = mem_channel_number * (1 << mem_channel_width);
|
||||
mem_vendor = (vram_module->v11.vender_rev_id) & 0xF;
|
||||
if (vram_vendor)
|
||||
*vram_vendor = mem_vendor;
|
||||
break;
|
||||
/* v26 */
|
||||
case 6:
|
||||
if (module_id > vram_info->v26.vram_module_num)
|
||||
module_id = 0;
|
||||
vram_module = (union vram_module *)vram_info->v26.vram_module;
|
||||
while (i < module_id) {
|
||||
vram_module = (union vram_module *)
|
||||
((u8 *)vram_module + vram_module->v9.vram_module_size);
|
||||
i++;
|
||||
}
|
||||
mem_type = vram_module->v9.memory_type;
|
||||
if (vram_type)
|
||||
*vram_type = convert_atom_mem_type_to_vram_type(adev, mem_type);
|
||||
mem_channel_number = vram_module->v9.channel_num;
|
||||
mem_channel_width = vram_module->v9.channel_width;
|
||||
if (vram_width)
|
||||
*vram_width = mem_channel_number * (1 << mem_channel_width);
|
||||
mem_vendor = (vram_module->v9.vender_rev_id) & 0xF;
|
||||
if (vram_vendor)
|
||||
*vram_vendor = mem_vendor;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
} else {
|
||||
/* invalid frev */
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
/* invalid frev */
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
} else {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -30,6 +30,10 @@ uint32_t amdgpu_atomfirmware_query_firmware_capability(struct amdgpu_device *ade
|
|||
bool amdgpu_atomfirmware_gpu_virtualization_supported(struct amdgpu_device *adev);
|
||||
void amdgpu_atomfirmware_scratch_regs_init(struct amdgpu_device *adev);
|
||||
int amdgpu_atomfirmware_allocate_fb_scratch(struct amdgpu_device *adev);
|
||||
int amdgpu_atomfirmware_get_integrated_system_info(struct amdgpu_device *adev,
|
||||
int *vram_width, int *vram_type, int *vram_vendor);
|
||||
int amdgpu_atomfirmware_get_umc_info(struct amdgpu_device *adev,
|
||||
int *vram_width, int *vram_type, int *vram_vendor);
|
||||
int amdgpu_atomfirmware_get_vram_info(struct amdgpu_device *adev,
|
||||
int *vram_width, int *vram_type, int *vram_vendor);
|
||||
int amdgpu_atomfirmware_get_uma_carveout_info(struct amdgpu_device *adev,
|
||||
|
|
|
|||
|
|
@ -908,9 +908,8 @@ static int amdgpu_cs_parser_bos(struct amdgpu_cs_parser *p,
|
|||
goto out_free_user_pages;
|
||||
|
||||
amdgpu_bo_list_for_each_entry(e, p->bo_list) {
|
||||
/* One fence for TTM and one for each CS job */
|
||||
r = drm_exec_prepare_obj(&p->exec, &e->bo->tbo.base,
|
||||
1 + p->gang_size);
|
||||
TTM_NUM_MOVE_FENCES + p->gang_size);
|
||||
drm_exec_retry_on_contention(&p->exec);
|
||||
if (unlikely(r))
|
||||
goto out_free_user_pages;
|
||||
|
|
@ -920,7 +919,7 @@ static int amdgpu_cs_parser_bos(struct amdgpu_cs_parser *p,
|
|||
|
||||
if (p->uf_bo) {
|
||||
r = drm_exec_prepare_obj(&p->exec, &p->uf_bo->tbo.base,
|
||||
1 + p->gang_size);
|
||||
TTM_NUM_MOVE_FENCES + p->gang_size);
|
||||
drm_exec_retry_on_contention(&p->exec);
|
||||
if (unlikely(r))
|
||||
goto out_free_user_pages;
|
||||
|
|
|
|||
|
|
@ -35,6 +35,9 @@ void amdgpu_coredump(struct amdgpu_device *adev, bool skip_vram_check,
|
|||
void amdgpu_coredump_init(struct amdgpu_device *adev)
|
||||
{
|
||||
}
|
||||
void amdgpu_coredump_fini(struct amdgpu_device *adev)
|
||||
{
|
||||
}
|
||||
#else
|
||||
|
||||
#define AMDGPU_CORE_DUMP_SIZE_MAX (256 * 1024 * 1024)
|
||||
|
|
@ -192,12 +195,16 @@ static void amdgpu_devcoredump_fw_info(struct amdgpu_device *adev,
|
|||
drm_printf(p, "VPE feature version: %u, fw version: 0x%08x\n",
|
||||
adev->vpe.feature_version, adev->vpe.fw_version);
|
||||
|
||||
drm_printf(p, "\nVBIOS Information\n");
|
||||
drm_printf(p, "vbios name : %s\n", ctx->name);
|
||||
drm_printf(p, "vbios pn : %s\n", ctx->vbios_pn);
|
||||
drm_printf(p, "vbios version : %d\n", ctx->version);
|
||||
drm_printf(p, "vbios ver_str : %s\n", ctx->vbios_ver_str);
|
||||
drm_printf(p, "vbios date : %s\n", ctx->date);
|
||||
if (adev->bios) {
|
||||
drm_printf(p, "\nVBIOS Information\n");
|
||||
drm_printf(p, "vbios name : %s\n", ctx->name);
|
||||
drm_printf(p, "vbios pn : %s\n", ctx->vbios_pn);
|
||||
drm_printf(p, "vbios version : %d\n", ctx->version);
|
||||
drm_printf(p, "vbios ver_str : %s\n", ctx->vbios_ver_str);
|
||||
drm_printf(p, "vbios date : %s\n", ctx->date);
|
||||
}else {
|
||||
drm_printf(p, "\nVBIOS Information: NA\n");
|
||||
}
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
|
|
@ -436,4 +443,10 @@ void amdgpu_coredump_init(struct amdgpu_device *adev)
|
|||
{
|
||||
INIT_WORK(&adev->coredump_work, amdgpu_devcoredump_deferred_work);
|
||||
}
|
||||
|
||||
void amdgpu_coredump_fini(struct amdgpu_device *adev)
|
||||
{
|
||||
/* Finish deferred coredump formatting before HW/IP teardown. */
|
||||
flush_work(&adev->coredump_work);
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -50,4 +50,5 @@ struct amdgpu_coredump_info {
|
|||
void amdgpu_coredump(struct amdgpu_device *adev, bool skip_vram_check,
|
||||
bool vram_lost, struct amdgpu_job *job);
|
||||
void amdgpu_coredump_init(struct amdgpu_device *adev);
|
||||
void amdgpu_coredump_fini(struct amdgpu_device *adev);
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -4225,6 +4225,7 @@ void amdgpu_device_fini_hw(struct amdgpu_device *adev)
|
|||
if (pci_dev_is_disconnected(adev->pdev))
|
||||
amdgpu_amdkfd_device_fini_sw(adev);
|
||||
|
||||
amdgpu_coredump_fini(adev);
|
||||
amdgpu_device_ip_fini_early(adev);
|
||||
|
||||
amdgpu_irq_fini_hw(adev);
|
||||
|
|
|
|||
|
|
@ -2683,8 +2683,12 @@ static int amdgpu_pmops_freeze(struct device *dev)
|
|||
if (r)
|
||||
return r;
|
||||
|
||||
if (amdgpu_acpi_should_gpu_reset(adev))
|
||||
return amdgpu_asic_reset(adev);
|
||||
if (amdgpu_acpi_should_gpu_reset(adev)) {
|
||||
amdgpu_device_lock_reset_domain(adev->reset_domain);
|
||||
r = amdgpu_asic_reset(adev);
|
||||
amdgpu_device_unlock_reset_domain(adev->reset_domain);
|
||||
return r;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -403,6 +403,50 @@ void amdgpu_gart_map_vram_range(struct amdgpu_device *adev, uint64_t pa,
|
|||
drm_dev_exit(idx);
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_gart_map_gfx9_mqd - map mqd and ctrl_stack dma_addresses into GART entries
|
||||
*
|
||||
* @adev: amdgpu_device pointer
|
||||
* @offset: offset into the GPU's gart aperture
|
||||
* @pages: number of pages to bind
|
||||
* @dma_addr: DMA addresses of pages
|
||||
* @flags: page table entry flags
|
||||
*
|
||||
* Map the MQD and control stack addresses into GART entries with the correct
|
||||
* memory types on gfxv9. The MQD occupies the first 4KB and is followed by
|
||||
* the control stack. The MQD uses UC (uncached) memory, while the control stack
|
||||
* uses NC (non-coherent) memory.
|
||||
*/
|
||||
void amdgpu_gart_map_gfx9_mqd(struct amdgpu_device *adev, uint64_t offset,
|
||||
int pages, dma_addr_t *dma_addr, uint64_t flags)
|
||||
{
|
||||
uint64_t page_base;
|
||||
unsigned int i, j, t;
|
||||
int idx;
|
||||
uint64_t ctrl_flags = AMDGPU_PTE_MTYPE_VG10(flags, AMDGPU_MTYPE_NC);
|
||||
void *dst;
|
||||
|
||||
if (!adev->gart.ptr)
|
||||
return;
|
||||
|
||||
if (!drm_dev_enter(adev_to_drm(adev), &idx))
|
||||
return;
|
||||
|
||||
t = offset / AMDGPU_GPU_PAGE_SIZE;
|
||||
dst = adev->gart.ptr;
|
||||
for (i = 0; i < pages; i++) {
|
||||
page_base = dma_addr[i];
|
||||
for (j = 0; j < AMDGPU_GPU_PAGES_IN_CPU_PAGE; j++, t++) {
|
||||
if ((i == 0) && (j == 0))
|
||||
amdgpu_gmc_set_pte_pde(adev, dst, t, page_base, flags);
|
||||
else
|
||||
amdgpu_gmc_set_pte_pde(adev, dst, t, page_base, ctrl_flags);
|
||||
page_base += AMDGPU_GPU_PAGE_SIZE;
|
||||
}
|
||||
}
|
||||
drm_dev_exit(idx);
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_gart_bind - bind pages into the gart page table
|
||||
*
|
||||
|
|
|
|||
|
|
@ -62,6 +62,8 @@ void amdgpu_gart_unbind(struct amdgpu_device *adev, uint64_t offset,
|
|||
void amdgpu_gart_map(struct amdgpu_device *adev, uint64_t offset,
|
||||
int pages, dma_addr_t *dma_addr, uint64_t flags,
|
||||
void *dst);
|
||||
void amdgpu_gart_map_gfx9_mqd(struct amdgpu_device *adev, uint64_t offset,
|
||||
int pages, dma_addr_t *dma_addr, uint64_t flags);
|
||||
void amdgpu_gart_bind(struct amdgpu_device *adev, uint64_t offset,
|
||||
int pages, dma_addr_t *dma_addr, uint64_t flags);
|
||||
void amdgpu_gart_map_vram_range(struct amdgpu_device *adev, uint64_t pa,
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@
|
|||
#include "amdgpu_ras.h"
|
||||
#include "amdgpu_reset.h"
|
||||
#include "amdgpu_xgmi.h"
|
||||
#include "amdgpu_atomfirmware.h"
|
||||
|
||||
#include <drm/drm_drv.h>
|
||||
#include <drm/ttm/ttm_tt.h>
|
||||
|
|
@ -1747,3 +1748,31 @@ int amdgpu_gmc_init_mem_ranges(struct amdgpu_device *adev)
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int amdgpu_gmc_get_vram_info(struct amdgpu_device *adev,
|
||||
int *vram_width, int *vram_type, int *vram_vendor)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (adev->flags & AMD_IS_APU)
|
||||
return amdgpu_atomfirmware_get_integrated_system_info(adev,
|
||||
vram_width, vram_type, vram_vendor);
|
||||
switch (amdgpu_ip_version(adev, GC_HWIP, 0)) {
|
||||
case IP_VERSION(12, 0, 0):
|
||||
case IP_VERSION(12, 0, 1):
|
||||
return amdgpu_atomfirmware_get_umc_info(adev,
|
||||
vram_width, vram_type, vram_vendor);
|
||||
case IP_VERSION(9, 5, 0):
|
||||
case IP_VERSION(9, 4, 4):
|
||||
case IP_VERSION(9, 4, 3):
|
||||
ret = amdgpu_atomfirmware_get_umc_info(adev,
|
||||
vram_width, vram_type, vram_vendor);
|
||||
if (vram_width && !ret)
|
||||
*vram_width *= hweight32(adev->aid_mask);
|
||||
return ret;
|
||||
default:
|
||||
return amdgpu_atomfirmware_get_vram_info(adev,
|
||||
vram_width, vram_type, vram_vendor);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -482,4 +482,6 @@ amdgpu_gmc_query_memory_partition(struct amdgpu_device *adev);
|
|||
int amdgpu_gmc_init_mem_ranges(struct amdgpu_device *adev);
|
||||
void amdgpu_gmc_init_sw_mem_ranges(struct amdgpu_device *adev,
|
||||
struct amdgpu_mem_partition_info *mem_ranges);
|
||||
int amdgpu_gmc_get_vram_info(struct amdgpu_device *adev,
|
||||
int *vram_width, int *vram_type, int *vram_vendor);
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -68,8 +68,11 @@ int amdgpu_pasid_alloc(unsigned int bits)
|
|||
return -EINVAL;
|
||||
|
||||
spin_lock(&amdgpu_pasid_idr_lock);
|
||||
/* TODO: Need to replace the idr with an xarry, and then
|
||||
* handle the internal locking with ATOMIC safe paths.
|
||||
*/
|
||||
pasid = idr_alloc_cyclic(&amdgpu_pasid_idr, NULL, 1,
|
||||
1U << bits, GFP_KERNEL);
|
||||
1U << bits, GFP_ATOMIC);
|
||||
spin_unlock(&amdgpu_pasid_idr_lock);
|
||||
|
||||
if (pasid >= 0)
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@
|
|||
#include <drm/display/drm_dp_mst_helper.h>
|
||||
#include "modules/inc/mod_freesync.h"
|
||||
#include "amdgpu_dm_irq_params.h"
|
||||
#include "amdgpu_dm_ism.h"
|
||||
|
||||
struct amdgpu_bo;
|
||||
struct amdgpu_device;
|
||||
|
|
@ -486,6 +487,10 @@ struct amdgpu_crtc {
|
|||
int deferred_flip_completion;
|
||||
/* parameters access from DM IRQ handler */
|
||||
struct dm_irq_params dm_irq_params;
|
||||
|
||||
/* DM idle state manager */
|
||||
struct amdgpu_dm_ism ism;
|
||||
|
||||
/* pll sharing */
|
||||
struct amdgpu_atom_ss ss;
|
||||
bool ss_enabled;
|
||||
|
|
|
|||
|
|
@ -1325,7 +1325,8 @@ void amdgpu_bo_release_notify(struct ttm_buffer_object *bo)
|
|||
if (r)
|
||||
goto out;
|
||||
|
||||
r = amdgpu_fill_buffer(&adev->mman.clear_entity, abo, 0, &bo->base._resv,
|
||||
r = amdgpu_fill_buffer(amdgpu_ttm_next_clear_entity(adev),
|
||||
abo, 0, &bo->base._resv,
|
||||
&fence, AMDGPU_KERNEL_JOB_ID_CLEAR_ON_RELEASE);
|
||||
if (WARN_ON(r))
|
||||
goto out;
|
||||
|
|
|
|||
|
|
@ -1558,6 +1558,8 @@ int amdgpu_ras_eeprom_init(struct amdgpu_ras_eeprom_control *control)
|
|||
unsigned char buf[RAS_TABLE_HEADER_SIZE] = { 0 };
|
||||
struct amdgpu_ras_eeprom_table_header *hdr = &control->tbl_hdr;
|
||||
struct amdgpu_ras *ras = amdgpu_ras_get_context(adev);
|
||||
int dev_var = adev->pdev->device & 0xF;
|
||||
uint32_t vram_type = adev->gmc.vram_type;
|
||||
int res;
|
||||
|
||||
if (amdgpu_ras_smu_eeprom_supported(adev))
|
||||
|
|
@ -1597,6 +1599,12 @@ int amdgpu_ras_eeprom_init(struct amdgpu_ras_eeprom_control *control)
|
|||
return amdgpu_ras_eeprom_reset_table(control);
|
||||
}
|
||||
|
||||
if (!(adev->flags & AMD_IS_APU) && (dev_var == 0x5) &&
|
||||
(vram_type == AMDGPU_VRAM_TYPE_HBM3E) &&
|
||||
(hdr->version < RAS_TABLE_VER_V3)) {
|
||||
return amdgpu_ras_eeprom_reset_table(control);
|
||||
}
|
||||
|
||||
switch (hdr->version) {
|
||||
case RAS_TABLE_VER_V2_1:
|
||||
case RAS_TABLE_VER_V3:
|
||||
|
|
|
|||
|
|
@ -387,9 +387,11 @@ static int amdgpu_move_blit(struct ttm_buffer_object *bo,
|
|||
{
|
||||
struct amdgpu_device *adev = amdgpu_ttm_adev(bo->bdev);
|
||||
struct amdgpu_bo *abo = ttm_to_amdgpu_bo(bo);
|
||||
struct amdgpu_ttm_buffer_entity *entity;
|
||||
struct amdgpu_copy_mem src, dst;
|
||||
struct dma_fence *fence = NULL;
|
||||
int r;
|
||||
u32 e;
|
||||
|
||||
src.bo = bo;
|
||||
dst.bo = bo;
|
||||
|
|
@ -398,8 +400,12 @@ static int amdgpu_move_blit(struct ttm_buffer_object *bo,
|
|||
src.offset = 0;
|
||||
dst.offset = 0;
|
||||
|
||||
e = atomic_inc_return(&adev->mman.next_move_entity) %
|
||||
adev->mman.num_move_entities;
|
||||
entity = &adev->mman.move_entities[e];
|
||||
|
||||
r = amdgpu_ttm_copy_mem_to_mem(adev,
|
||||
&adev->mman.move_entity,
|
||||
entity,
|
||||
&src, &dst,
|
||||
new_mem->size,
|
||||
amdgpu_bo_encrypted(abo),
|
||||
|
|
@ -411,9 +417,7 @@ static int amdgpu_move_blit(struct ttm_buffer_object *bo,
|
|||
if (old_mem->mem_type == TTM_PL_VRAM &&
|
||||
(abo->flags & AMDGPU_GEM_CREATE_VRAM_WIPE_ON_RELEASE)) {
|
||||
struct dma_fence *wipe_fence = NULL;
|
||||
|
||||
r = amdgpu_fill_buffer(&adev->mman.move_entity,
|
||||
abo, 0, NULL, &wipe_fence,
|
||||
r = amdgpu_fill_buffer(entity, abo, 0, NULL, &wipe_fence,
|
||||
AMDGPU_KERNEL_JOB_ID_MOVE_BLIT);
|
||||
if (r) {
|
||||
goto error;
|
||||
|
|
@ -854,25 +858,15 @@ static void amdgpu_ttm_gart_bind_gfx9_mqd(struct amdgpu_device *adev,
|
|||
int num_xcc = max(1U, adev->gfx.num_xcc_per_xcp);
|
||||
uint64_t page_idx, pages_per_xcc;
|
||||
int i;
|
||||
uint64_t ctrl_flags = AMDGPU_PTE_MTYPE_VG10(flags, AMDGPU_MTYPE_NC);
|
||||
|
||||
pages_per_xcc = total_pages;
|
||||
do_div(pages_per_xcc, num_xcc);
|
||||
|
||||
for (i = 0, page_idx = 0; i < num_xcc; i++, page_idx += pages_per_xcc) {
|
||||
/* MQD page: use default flags */
|
||||
amdgpu_gart_bind(adev,
|
||||
amdgpu_gart_map_gfx9_mqd(adev,
|
||||
gtt->offset + (page_idx << PAGE_SHIFT),
|
||||
1, >t->ttm.dma_address[page_idx], flags);
|
||||
/*
|
||||
* Ctrl pages - modify the memory type to NC (ctrl_flags) from
|
||||
* the second page of the BO onward.
|
||||
*/
|
||||
amdgpu_gart_bind(adev,
|
||||
gtt->offset + ((page_idx + 1) << PAGE_SHIFT),
|
||||
pages_per_xcc - 1,
|
||||
>t->ttm.dma_address[page_idx + 1],
|
||||
ctrl_flags);
|
||||
pages_per_xcc, >t->ttm.dma_address[page_idx],
|
||||
flags);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2345,8 +2339,9 @@ void amdgpu_ttm_fini(struct amdgpu_device *adev)
|
|||
void amdgpu_ttm_set_buffer_funcs_status(struct amdgpu_device *adev, bool enable)
|
||||
{
|
||||
struct ttm_resource_manager *man = ttm_manager_type(&adev->mman.bdev, TTM_PL_VRAM);
|
||||
u32 num_clear_entities, num_move_entities;
|
||||
uint64_t size;
|
||||
int r;
|
||||
int r, i, j;
|
||||
|
||||
if (!adev->mman.initialized || amdgpu_in_reset(adev) ||
|
||||
adev->mman.buffer_funcs_enabled == enable || adev->gmc.is_app_apu)
|
||||
|
|
@ -2361,6 +2356,8 @@ void amdgpu_ttm_set_buffer_funcs_status(struct amdgpu_device *adev, bool enable)
|
|||
return;
|
||||
}
|
||||
|
||||
num_clear_entities = 1;
|
||||
num_move_entities = 1;
|
||||
ring = adev->mman.buffer_funcs_ring;
|
||||
sched = &ring->sched;
|
||||
r = amdgpu_ttm_buffer_entity_init(&adev->mman.gtt_mgr,
|
||||
|
|
@ -2373,36 +2370,64 @@ void amdgpu_ttm_set_buffer_funcs_status(struct amdgpu_device *adev, bool enable)
|
|||
return;
|
||||
}
|
||||
|
||||
r = amdgpu_ttm_buffer_entity_init(&adev->mman.gtt_mgr,
|
||||
&adev->mman.clear_entity,
|
||||
DRM_SCHED_PRIORITY_NORMAL,
|
||||
&sched, 1, 1);
|
||||
if (r < 0) {
|
||||
dev_err(adev->dev,
|
||||
"Failed setting up TTM BO clear entity (%d)\n", r);
|
||||
adev->mman.clear_entities = kcalloc(num_clear_entities,
|
||||
sizeof(struct amdgpu_ttm_buffer_entity),
|
||||
GFP_KERNEL);
|
||||
atomic_set(&adev->mman.next_clear_entity, 0);
|
||||
if (!adev->mman.clear_entities)
|
||||
goto error_free_default_entity;
|
||||
|
||||
adev->mman.num_clear_entities = num_clear_entities;
|
||||
|
||||
for (i = 0; i < num_clear_entities; i++) {
|
||||
r = amdgpu_ttm_buffer_entity_init(
|
||||
&adev->mman.gtt_mgr, &adev->mman.clear_entities[i],
|
||||
DRM_SCHED_PRIORITY_NORMAL, &sched, 1, 1);
|
||||
|
||||
if (r < 0) {
|
||||
for (j = 0; j < i; j++)
|
||||
amdgpu_ttm_buffer_entity_fini(
|
||||
&adev->mman.gtt_mgr, &adev->mman.clear_entities[j]);
|
||||
kfree(adev->mman.clear_entities);
|
||||
adev->mman.num_clear_entities = 0;
|
||||
adev->mman.clear_entities = NULL;
|
||||
goto error_free_default_entity;
|
||||
}
|
||||
}
|
||||
|
||||
r = amdgpu_ttm_buffer_entity_init(&adev->mman.gtt_mgr,
|
||||
&adev->mman.move_entity,
|
||||
DRM_SCHED_PRIORITY_NORMAL,
|
||||
&sched, 1, 2);
|
||||
if (r < 0) {
|
||||
dev_err(adev->dev,
|
||||
"Failed setting up TTM BO move entity (%d)\n", r);
|
||||
goto error_free_clear_entity;
|
||||
adev->mman.num_move_entities = num_move_entities;
|
||||
atomic_set(&adev->mman.next_move_entity, 0);
|
||||
for (i = 0; i < num_move_entities; i++) {
|
||||
r = amdgpu_ttm_buffer_entity_init(
|
||||
&adev->mman.gtt_mgr,
|
||||
&adev->mman.move_entities[i],
|
||||
DRM_SCHED_PRIORITY_NORMAL, &sched, 1, 2);
|
||||
|
||||
if (r < 0) {
|
||||
for (j = 0; j < i; j++)
|
||||
amdgpu_ttm_buffer_entity_fini(
|
||||
&adev->mman.gtt_mgr, &adev->mman.move_entities[j]);
|
||||
adev->mman.num_move_entities = 0;
|
||||
goto error_free_clear_entities;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
amdgpu_ttm_buffer_entity_fini(&adev->mman.gtt_mgr,
|
||||
&adev->mman.default_entity);
|
||||
amdgpu_ttm_buffer_entity_fini(&adev->mman.gtt_mgr,
|
||||
&adev->mman.clear_entity);
|
||||
amdgpu_ttm_buffer_entity_fini(&adev->mman.gtt_mgr,
|
||||
&adev->mman.move_entity);
|
||||
for (i = 0; i < adev->mman.num_clear_entities; i++)
|
||||
amdgpu_ttm_buffer_entity_fini(&adev->mman.gtt_mgr,
|
||||
&adev->mman.clear_entities[i]);
|
||||
for (i = 0; i < adev->mman.num_move_entities; i++)
|
||||
amdgpu_ttm_buffer_entity_fini(&adev->mman.gtt_mgr,
|
||||
&adev->mman.move_entities[i]);
|
||||
/* Drop all the old fences since re-creating the scheduler entities
|
||||
* will allocate new contexts.
|
||||
*/
|
||||
ttm_resource_manager_cleanup(man);
|
||||
kfree(adev->mman.clear_entities);
|
||||
adev->mman.clear_entities = NULL;
|
||||
adev->mman.num_clear_entities = 0;
|
||||
adev->mman.num_move_entities = 0;
|
||||
}
|
||||
|
||||
/* this just adjusts TTM size idea, which sets lpfn to the correct value */
|
||||
|
|
@ -2415,9 +2440,13 @@ void amdgpu_ttm_set_buffer_funcs_status(struct amdgpu_device *adev, bool enable)
|
|||
|
||||
return;
|
||||
|
||||
error_free_clear_entity:
|
||||
amdgpu_ttm_buffer_entity_fini(&adev->mman.gtt_mgr,
|
||||
&adev->mman.clear_entity);
|
||||
error_free_clear_entities:
|
||||
for (i = 0; i < adev->mman.num_clear_entities; i++)
|
||||
amdgpu_ttm_buffer_entity_fini(&adev->mman.gtt_mgr,
|
||||
&adev->mman.clear_entities[i]);
|
||||
kfree(adev->mman.clear_entities);
|
||||
adev->mman.clear_entities = NULL;
|
||||
adev->mman.num_clear_entities = 0;
|
||||
error_free_default_entity:
|
||||
amdgpu_ttm_buffer_entity_fini(&adev->mman.gtt_mgr,
|
||||
&adev->mman.default_entity);
|
||||
|
|
@ -2567,8 +2596,7 @@ int amdgpu_ttm_clear_buffer(struct amdgpu_bo *bo,
|
|||
|
||||
if (!fence)
|
||||
return -EINVAL;
|
||||
|
||||
entity = &adev->mman.clear_entity;
|
||||
entity = &adev->mman.clear_entities[0];
|
||||
*fence = dma_fence_get_stub();
|
||||
|
||||
amdgpu_res_first(bo->tbo.resource, 0, amdgpu_bo_size(bo), &cursor);
|
||||
|
|
@ -2620,11 +2648,8 @@ int amdgpu_fill_buffer(struct amdgpu_ttm_buffer_entity *entity,
|
|||
struct amdgpu_res_cursor dst;
|
||||
int r;
|
||||
|
||||
if (!adev->mman.buffer_funcs_enabled) {
|
||||
dev_err(adev->dev,
|
||||
"Trying to clear memory with ring turned off.\n");
|
||||
if (!entity)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
amdgpu_res_first(bo->tbo.resource, 0, amdgpu_bo_size(bo), &dst);
|
||||
|
||||
|
|
@ -2660,6 +2685,20 @@ int amdgpu_fill_buffer(struct amdgpu_ttm_buffer_entity *entity,
|
|||
return r;
|
||||
}
|
||||
|
||||
struct amdgpu_ttm_buffer_entity *
|
||||
amdgpu_ttm_next_clear_entity(struct amdgpu_device *adev)
|
||||
{
|
||||
struct amdgpu_mman *mman = &adev->mman;
|
||||
u32 i;
|
||||
|
||||
if (mman->num_clear_entities == 0)
|
||||
return NULL;
|
||||
|
||||
i = atomic_inc_return(&mman->next_clear_entity) %
|
||||
mman->num_clear_entities;
|
||||
return &mman->clear_entities[i];
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_ttm_evict_resources - evict memory buffers
|
||||
* @adev: amdgpu device object
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user