Loading arch/arm64/boot/dts/qcom/sdmmagpie-npu.dtsi 0 → 100644 +182 −0 Original line number Diff line number Diff line /* Copyright (c) 2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and * only version 2 as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ &soc { msm_npu: qcom,msm_npu@9800000 { compatible = "qcom,msm-npu"; reg = <0x9800000 0x800000>; reg-names = "npu_base"; interrupts = <GIC_SPI 583 IRQ_TYPE_EDGE_RISING>, <GIC_SPI 585 IRQ_TYPE_EDGE_RISING>, <GIC_SPI 587 IRQ_TYPE_EDGE_RISING>; interrupt-names = "error_irq", "wdg_bite_irq", "ipc_irq"; iommus = <&apps_smmu 0x1461 0x0>; cache-slice-names = "npu"; cache-slices = <&llcc 23>; clocks = <&clock_npucc NPU_CC_CAL_DP_CLK>, <&clock_npucc NPU_CC_XO_CLK>, <&clock_npucc NPU_CC_ARMWIC_CORE_CLK>, <&clock_npucc NPU_CC_BTO_CORE_CLK>, <&clock_npucc NPU_CC_BWMON_CLK>, <&clock_npucc NPU_CC_CAL_DP_CDC_CLK>, <&clock_npucc NPU_CC_COMP_NOC_AXI_CLK>, <&clock_npucc NPU_CC_CONF_NOC_AHB_CLK>, <&clock_npucc NPU_CC_NPU_CORE_APB_CLK>, <&clock_npucc NPU_CC_NPU_CORE_ATB_CLK>, <&clock_npucc NPU_CC_NPU_CORE_CLK>, <&clock_npucc NPU_CC_NPU_CORE_CTI_CLK>, <&clock_npucc NPU_CC_NPU_CPC_CLK>, <&clock_npucc NPU_CC_NPU_CPC_TIMER_CLK>, <&clock_npucc NPU_CC_PERF_CNT_CLK>, <&clock_npucc NPU_CC_QTIMER_CORE_CLK>, <&clock_npucc NPU_CC_SLEEP_CLK>, <&clock_aop QDSS_CLK>; clock-names = "cal_dp_clk", "xo_clk", "armwic_core_clk", "bto_core_clk", "bwmon_clk", "cal_dp_cdc_clk", "comp_noc_axi_clk", "conf_noc_ahb_clk", "npu_core_apb_clk", "npu_core_atb_clk", "npu_core_clk", "npu_core_cti_clk", "npu_cpc_clk", "npu_cpc_timer_clk", "perf_cnt_clk", "qtimer_core_clk", "sleep_clk", "qdss_clk"; vdd-supply = <&npu_core_gdsc>; vdd_cx-supply = <&VDD_CX_LEVEL>; qcom,proxy-reg-names ="vdd", "vdd_cx"; qcom,vdd_cx-uV-uA = <RPMH_REGULATOR_LEVEL_TURBO 100000>; mboxes = <&qmp_npu0 0>, <&qmp_npu1 0>; mbox-names = "npu_low", "npu_high"; #cooling-cells = <2>; qcom,npu-pwrlevels { #address-cells = <1>; #size-cells = <0>; compatible = "qcom,npu-pwrlevels"; initial-pwrlevel = <4>; qcom,npu-pwrlevel@0 { reg = <0>; clk-freq = <300000000 19200000 100000000 19200000 19200000 300000000 150000000 30000000 19200000 60000000 100000000 37500000 100000000 19200000 300000000 19200000 0 0>; }; qcom,npu-pwrlevel@1 { reg = <1>; clk-freq = <400000000 19200000 150000000 19200000 19200000 400000000 200000000 37500000 19200000 120000000 150000000 75000000 150000000 19200000 400000000 19200000 0 0>; }; qcom,npu-pwrlevel@2 { reg = <2>; clk-freq = <466500000 19200000 200000000 19200000 19200000 466500000 300000000 37500000 19200000 120000000 200000000 75000000 200000000 19200000 466500000 19200000 0 0>; }; qcom,npu-pwrlevel@3 { reg = <3>; clk-freq = <600000000 19200000 300000000 19200000 19200000 600000000 403000000 75000000 19200000 240000000 300000000 150000000 300000000 19200000 600000000 19200000 0 0>; }; qcom,npu-pwrlevel@4 { reg = <4>; clk-freq = <700000000 19200000 400000000 19200000 19200000 700000000 533000000 75000000 19200000 300000000 400000000 150000000 400000000 19200000 700000000 19200000 0 0>; }; }; }; }; arch/arm64/boot/dts/qcom/sdmmagpie.dtsi +12 −0 Original line number Diff line number Diff line Loading @@ -2176,6 +2176,16 @@ qcom,firmware-name = "venus"; memory-region = <&pil_video_mem>; }; qcom,npu@0x9800000 { compatible = "qcom,pil-tz-generic"; reg = <0x9800000 0x800000>; status = "ok"; qcom,pas-id = <23>; qcom,firmware-name = "npu"; memory-region = <&npu_mem>; }; }; #include "sdmmagpie-pinctrl.dtsi" Loading Loading @@ -2425,3 +2435,5 @@ qcom,hw-settle-time = <200>; }; }; #include "sdmmagpie-npu.dtsi" drivers/media/platform/msm/npu/npu_common.h +3 −3 Original line number Diff line number Diff line Loading @@ -43,7 +43,7 @@ #define ROW_BYTES 16 #define GROUP_BYTES 4 #define NUM_TOTAL_CLKS 20 #define NUM_MAX_CLK_NUM 24 #define NPU_MAX_REGULATOR_NUM 2 #define NPU_MAX_DT_NAME_LEN 21 #define NPU_MAX_PWRLEVELS 8 Loading Loading @@ -108,7 +108,7 @@ struct npu_mbox { * @freq[]: NPU frequency vote in Hz */ struct npu_pwrlevel { long clk_freq[NUM_TOTAL_CLKS]; long clk_freq[NUM_MAX_CLK_NUM]; }; /* Loading Loading @@ -184,7 +184,7 @@ struct npu_device { uint32_t npu_phys; uint32_t core_clk_num; struct npu_clk core_clks[NUM_TOTAL_CLKS]; struct npu_clk core_clks[NUM_MAX_CLK_NUM]; uint32_t regulator_num; struct npu_regulator regulators[NPU_MAX_DT_NAME_LEN]; Loading drivers/media/platform/msm/npu/npu_dev.c +24 −21 Original line number Diff line number Diff line Loading @@ -375,10 +375,10 @@ static int npu_set_power_level(struct npu_device *npu_dev) /* get power level to set */ pwr_level_to_set = npu_calc_power_level(npu_dev); pwr->active_pwrlevel = pwr_level_to_set; if (!pwr->pwr_vote_num) { pr_debug("power is not enabled during set request\n"); pwr->active_pwrlevel = pwr_level_to_set; return 0; } Loading @@ -389,7 +389,7 @@ static int npu_set_power_level(struct npu_device *npu_dev) } pr_debug("setting power level to [%d]\n", pwr_level_to_set); pwr->active_pwrlevel = pwr_level_to_set; pwrlevel = &npu_dev->pwrctrl.pwrlevels[pwr->active_pwrlevel]; for (i = 0; i < npu_dev->core_clk_num; i++) { Loading Loading @@ -468,7 +468,7 @@ static void npu_suspend_devbw(struct npu_device *npu_dev) struct npu_pwrctrl *pwr = &npu_dev->pwrctrl; int ret; if (pwr->bwmon_enabled) { if (pwr->bwmon_enabled && pwr->devbw) { pwr->bwmon_enabled = 0; ret = devfreq_suspend_devbw(pwr->devbw); if (ret) Loading @@ -483,7 +483,7 @@ static void npu_resume_devbw(struct npu_device *npu_dev) struct npu_pwrctrl *pwr = &npu_dev->pwrctrl; int ret; if (!pwr->bwmon_enabled) { if (!pwr->bwmon_enabled && pwr->devbw) { pwr->bwmon_enabled = 1; npu_restore_bw_registers(npu_dev); ret = devfreq_resume_devbw(pwr->devbw); Loading Loading @@ -533,7 +533,10 @@ static int npu_enable_clocks(struct npu_device *npu_dev, bool post_pil) struct npu_pwrlevel *pwrlevel = &npu_dev->pwrctrl.pwrlevels[pwr->active_pwrlevel]; for (i = 0; i < npu_dev->core_clk_num; i++) { for (i = 0; i < ARRAY_SIZE(npu_clock_order); i++) { if (!core_clks[i].clk) continue; if (post_pil) { if (!npu_is_post_clock(core_clks[i].clk_name)) continue; Loading Loading @@ -570,6 +573,9 @@ static int npu_enable_clocks(struct npu_device *npu_dev, bool post_pil) if (rc) { for (i--; i >= 0; i--) { if (!core_clks[i].clk) continue; if (post_pil) { if (!npu_is_post_clock(core_clks[i].clk_name)) continue; Loading @@ -590,7 +596,10 @@ static void npu_disable_clocks(struct npu_device *npu_dev, bool post_pil) int i = 0; struct npu_clk *core_clks = npu_dev->core_clks; for (i = (npu_dev->core_clk_num)-1; i >= 0 ; i--) { for (i = ARRAY_SIZE(npu_clock_order) - 1; i >= 0 ; i--) { if (!core_clks[i].clk) continue; if (post_pil) { if (!npu_is_post_clock(core_clks[i].clk_name)) continue; Loading Loading @@ -751,9 +760,10 @@ int npu_enable_sys_cache(struct npu_device *npu_dev) npu_dev->sys_cache = llcc_slice_getd(&(npu_dev->pdev->dev), "npu"); if (IS_ERR_OR_NULL(npu_dev->sys_cache)) { pr_debug("unable to init sys cache\n"); pr_warn("unable to init sys cache\n"); npu_dev->sys_cache = NULL; return -ENODEV; npu_dev->host_ctx.sys_cache_disable = true; return 0; } /* set npu side regs - program SCID */ Loading Loading @@ -1274,22 +1284,16 @@ static int npu_parse_dt_clock(struct npu_device *npu_dev) rc = -EINVAL; goto clk_err; } if (num_clk != NUM_TOTAL_CLKS) { pr_err("number of clocks is invalid [%d] should be [%d]\n", num_clk, NUM_TOTAL_CLKS); rc = -EINVAL; goto clk_err; } npu_dev->core_clk_num = num_clk; for (i = 0; i < num_clk; i++) { of_property_read_string_index(pdev->dev.of_node, "clock-names", i, &clock_name); for (j = 0; j < num_clk; j++) { for (j = 0; j < ARRAY_SIZE(npu_clock_order); j++) { if (!strcmp(npu_clock_order[j], clock_name)) break; } if (j == num_clk) { if (j == ARRAY_SIZE(npu_clock_order)) { pr_err("clock is not in ordered list\n"); rc = -EINVAL; goto clk_err; Loading Loading @@ -1364,7 +1368,7 @@ static int npu_of_parse_pwrlevels(struct npu_device *npu_dev, uint32_t i = 0; uint32_t j = 0; uint32_t index; uint32_t clk_array_values[NUM_TOTAL_CLKS]; uint32_t clk_array_values[NUM_MAX_CLK_NUM]; uint32_t clk_rate; struct npu_pwrlevel *level; Loading Loading @@ -1396,13 +1400,13 @@ static int npu_of_parse_pwrlevels(struct npu_device *npu_dev, if (npu_is_exclude_rate_clock(clock_name)) continue; for (j = 0; j < npu_dev->core_clk_num; j++) { for (j = 0; j < ARRAY_SIZE(npu_clock_order); j++) { if (!strcmp(npu_clock_order[j], clock_name)) break; } if (j == npu_dev->core_clk_num) { if (j == ARRAY_SIZE(npu_clock_order)) { pr_err("pwrlevel clock is not in ordered list\n"); return -EINVAL; } Loading Loading @@ -1466,9 +1470,8 @@ static int npu_pwrctrl_init(struct npu_device *npu_dev) return ret; } } else { pr_err("bwdev is not defined in dts\n"); pr_warn("bwdev is not defined in dts\n"); pwr->devbw = NULL; ret = -EINVAL; } return ret; Loading Loading
arch/arm64/boot/dts/qcom/sdmmagpie-npu.dtsi 0 → 100644 +182 −0 Original line number Diff line number Diff line /* Copyright (c) 2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and * only version 2 as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ &soc { msm_npu: qcom,msm_npu@9800000 { compatible = "qcom,msm-npu"; reg = <0x9800000 0x800000>; reg-names = "npu_base"; interrupts = <GIC_SPI 583 IRQ_TYPE_EDGE_RISING>, <GIC_SPI 585 IRQ_TYPE_EDGE_RISING>, <GIC_SPI 587 IRQ_TYPE_EDGE_RISING>; interrupt-names = "error_irq", "wdg_bite_irq", "ipc_irq"; iommus = <&apps_smmu 0x1461 0x0>; cache-slice-names = "npu"; cache-slices = <&llcc 23>; clocks = <&clock_npucc NPU_CC_CAL_DP_CLK>, <&clock_npucc NPU_CC_XO_CLK>, <&clock_npucc NPU_CC_ARMWIC_CORE_CLK>, <&clock_npucc NPU_CC_BTO_CORE_CLK>, <&clock_npucc NPU_CC_BWMON_CLK>, <&clock_npucc NPU_CC_CAL_DP_CDC_CLK>, <&clock_npucc NPU_CC_COMP_NOC_AXI_CLK>, <&clock_npucc NPU_CC_CONF_NOC_AHB_CLK>, <&clock_npucc NPU_CC_NPU_CORE_APB_CLK>, <&clock_npucc NPU_CC_NPU_CORE_ATB_CLK>, <&clock_npucc NPU_CC_NPU_CORE_CLK>, <&clock_npucc NPU_CC_NPU_CORE_CTI_CLK>, <&clock_npucc NPU_CC_NPU_CPC_CLK>, <&clock_npucc NPU_CC_NPU_CPC_TIMER_CLK>, <&clock_npucc NPU_CC_PERF_CNT_CLK>, <&clock_npucc NPU_CC_QTIMER_CORE_CLK>, <&clock_npucc NPU_CC_SLEEP_CLK>, <&clock_aop QDSS_CLK>; clock-names = "cal_dp_clk", "xo_clk", "armwic_core_clk", "bto_core_clk", "bwmon_clk", "cal_dp_cdc_clk", "comp_noc_axi_clk", "conf_noc_ahb_clk", "npu_core_apb_clk", "npu_core_atb_clk", "npu_core_clk", "npu_core_cti_clk", "npu_cpc_clk", "npu_cpc_timer_clk", "perf_cnt_clk", "qtimer_core_clk", "sleep_clk", "qdss_clk"; vdd-supply = <&npu_core_gdsc>; vdd_cx-supply = <&VDD_CX_LEVEL>; qcom,proxy-reg-names ="vdd", "vdd_cx"; qcom,vdd_cx-uV-uA = <RPMH_REGULATOR_LEVEL_TURBO 100000>; mboxes = <&qmp_npu0 0>, <&qmp_npu1 0>; mbox-names = "npu_low", "npu_high"; #cooling-cells = <2>; qcom,npu-pwrlevels { #address-cells = <1>; #size-cells = <0>; compatible = "qcom,npu-pwrlevels"; initial-pwrlevel = <4>; qcom,npu-pwrlevel@0 { reg = <0>; clk-freq = <300000000 19200000 100000000 19200000 19200000 300000000 150000000 30000000 19200000 60000000 100000000 37500000 100000000 19200000 300000000 19200000 0 0>; }; qcom,npu-pwrlevel@1 { reg = <1>; clk-freq = <400000000 19200000 150000000 19200000 19200000 400000000 200000000 37500000 19200000 120000000 150000000 75000000 150000000 19200000 400000000 19200000 0 0>; }; qcom,npu-pwrlevel@2 { reg = <2>; clk-freq = <466500000 19200000 200000000 19200000 19200000 466500000 300000000 37500000 19200000 120000000 200000000 75000000 200000000 19200000 466500000 19200000 0 0>; }; qcom,npu-pwrlevel@3 { reg = <3>; clk-freq = <600000000 19200000 300000000 19200000 19200000 600000000 403000000 75000000 19200000 240000000 300000000 150000000 300000000 19200000 600000000 19200000 0 0>; }; qcom,npu-pwrlevel@4 { reg = <4>; clk-freq = <700000000 19200000 400000000 19200000 19200000 700000000 533000000 75000000 19200000 300000000 400000000 150000000 400000000 19200000 700000000 19200000 0 0>; }; }; }; };
arch/arm64/boot/dts/qcom/sdmmagpie.dtsi +12 −0 Original line number Diff line number Diff line Loading @@ -2176,6 +2176,16 @@ qcom,firmware-name = "venus"; memory-region = <&pil_video_mem>; }; qcom,npu@0x9800000 { compatible = "qcom,pil-tz-generic"; reg = <0x9800000 0x800000>; status = "ok"; qcom,pas-id = <23>; qcom,firmware-name = "npu"; memory-region = <&npu_mem>; }; }; #include "sdmmagpie-pinctrl.dtsi" Loading Loading @@ -2425,3 +2435,5 @@ qcom,hw-settle-time = <200>; }; }; #include "sdmmagpie-npu.dtsi"
drivers/media/platform/msm/npu/npu_common.h +3 −3 Original line number Diff line number Diff line Loading @@ -43,7 +43,7 @@ #define ROW_BYTES 16 #define GROUP_BYTES 4 #define NUM_TOTAL_CLKS 20 #define NUM_MAX_CLK_NUM 24 #define NPU_MAX_REGULATOR_NUM 2 #define NPU_MAX_DT_NAME_LEN 21 #define NPU_MAX_PWRLEVELS 8 Loading Loading @@ -108,7 +108,7 @@ struct npu_mbox { * @freq[]: NPU frequency vote in Hz */ struct npu_pwrlevel { long clk_freq[NUM_TOTAL_CLKS]; long clk_freq[NUM_MAX_CLK_NUM]; }; /* Loading Loading @@ -184,7 +184,7 @@ struct npu_device { uint32_t npu_phys; uint32_t core_clk_num; struct npu_clk core_clks[NUM_TOTAL_CLKS]; struct npu_clk core_clks[NUM_MAX_CLK_NUM]; uint32_t regulator_num; struct npu_regulator regulators[NPU_MAX_DT_NAME_LEN]; Loading
drivers/media/platform/msm/npu/npu_dev.c +24 −21 Original line number Diff line number Diff line Loading @@ -375,10 +375,10 @@ static int npu_set_power_level(struct npu_device *npu_dev) /* get power level to set */ pwr_level_to_set = npu_calc_power_level(npu_dev); pwr->active_pwrlevel = pwr_level_to_set; if (!pwr->pwr_vote_num) { pr_debug("power is not enabled during set request\n"); pwr->active_pwrlevel = pwr_level_to_set; return 0; } Loading @@ -389,7 +389,7 @@ static int npu_set_power_level(struct npu_device *npu_dev) } pr_debug("setting power level to [%d]\n", pwr_level_to_set); pwr->active_pwrlevel = pwr_level_to_set; pwrlevel = &npu_dev->pwrctrl.pwrlevels[pwr->active_pwrlevel]; for (i = 0; i < npu_dev->core_clk_num; i++) { Loading Loading @@ -468,7 +468,7 @@ static void npu_suspend_devbw(struct npu_device *npu_dev) struct npu_pwrctrl *pwr = &npu_dev->pwrctrl; int ret; if (pwr->bwmon_enabled) { if (pwr->bwmon_enabled && pwr->devbw) { pwr->bwmon_enabled = 0; ret = devfreq_suspend_devbw(pwr->devbw); if (ret) Loading @@ -483,7 +483,7 @@ static void npu_resume_devbw(struct npu_device *npu_dev) struct npu_pwrctrl *pwr = &npu_dev->pwrctrl; int ret; if (!pwr->bwmon_enabled) { if (!pwr->bwmon_enabled && pwr->devbw) { pwr->bwmon_enabled = 1; npu_restore_bw_registers(npu_dev); ret = devfreq_resume_devbw(pwr->devbw); Loading Loading @@ -533,7 +533,10 @@ static int npu_enable_clocks(struct npu_device *npu_dev, bool post_pil) struct npu_pwrlevel *pwrlevel = &npu_dev->pwrctrl.pwrlevels[pwr->active_pwrlevel]; for (i = 0; i < npu_dev->core_clk_num; i++) { for (i = 0; i < ARRAY_SIZE(npu_clock_order); i++) { if (!core_clks[i].clk) continue; if (post_pil) { if (!npu_is_post_clock(core_clks[i].clk_name)) continue; Loading Loading @@ -570,6 +573,9 @@ static int npu_enable_clocks(struct npu_device *npu_dev, bool post_pil) if (rc) { for (i--; i >= 0; i--) { if (!core_clks[i].clk) continue; if (post_pil) { if (!npu_is_post_clock(core_clks[i].clk_name)) continue; Loading @@ -590,7 +596,10 @@ static void npu_disable_clocks(struct npu_device *npu_dev, bool post_pil) int i = 0; struct npu_clk *core_clks = npu_dev->core_clks; for (i = (npu_dev->core_clk_num)-1; i >= 0 ; i--) { for (i = ARRAY_SIZE(npu_clock_order) - 1; i >= 0 ; i--) { if (!core_clks[i].clk) continue; if (post_pil) { if (!npu_is_post_clock(core_clks[i].clk_name)) continue; Loading Loading @@ -751,9 +760,10 @@ int npu_enable_sys_cache(struct npu_device *npu_dev) npu_dev->sys_cache = llcc_slice_getd(&(npu_dev->pdev->dev), "npu"); if (IS_ERR_OR_NULL(npu_dev->sys_cache)) { pr_debug("unable to init sys cache\n"); pr_warn("unable to init sys cache\n"); npu_dev->sys_cache = NULL; return -ENODEV; npu_dev->host_ctx.sys_cache_disable = true; return 0; } /* set npu side regs - program SCID */ Loading Loading @@ -1274,22 +1284,16 @@ static int npu_parse_dt_clock(struct npu_device *npu_dev) rc = -EINVAL; goto clk_err; } if (num_clk != NUM_TOTAL_CLKS) { pr_err("number of clocks is invalid [%d] should be [%d]\n", num_clk, NUM_TOTAL_CLKS); rc = -EINVAL; goto clk_err; } npu_dev->core_clk_num = num_clk; for (i = 0; i < num_clk; i++) { of_property_read_string_index(pdev->dev.of_node, "clock-names", i, &clock_name); for (j = 0; j < num_clk; j++) { for (j = 0; j < ARRAY_SIZE(npu_clock_order); j++) { if (!strcmp(npu_clock_order[j], clock_name)) break; } if (j == num_clk) { if (j == ARRAY_SIZE(npu_clock_order)) { pr_err("clock is not in ordered list\n"); rc = -EINVAL; goto clk_err; Loading Loading @@ -1364,7 +1368,7 @@ static int npu_of_parse_pwrlevels(struct npu_device *npu_dev, uint32_t i = 0; uint32_t j = 0; uint32_t index; uint32_t clk_array_values[NUM_TOTAL_CLKS]; uint32_t clk_array_values[NUM_MAX_CLK_NUM]; uint32_t clk_rate; struct npu_pwrlevel *level; Loading Loading @@ -1396,13 +1400,13 @@ static int npu_of_parse_pwrlevels(struct npu_device *npu_dev, if (npu_is_exclude_rate_clock(clock_name)) continue; for (j = 0; j < npu_dev->core_clk_num; j++) { for (j = 0; j < ARRAY_SIZE(npu_clock_order); j++) { if (!strcmp(npu_clock_order[j], clock_name)) break; } if (j == npu_dev->core_clk_num) { if (j == ARRAY_SIZE(npu_clock_order)) { pr_err("pwrlevel clock is not in ordered list\n"); return -EINVAL; } Loading Loading @@ -1466,9 +1470,8 @@ static int npu_pwrctrl_init(struct npu_device *npu_dev) return ret; } } else { pr_err("bwdev is not defined in dts\n"); pr_warn("bwdev is not defined in dts\n"); pwr->devbw = NULL; ret = -EINVAL; } return ret; Loading