Commit 09d78dde authored by Dave Airlie's avatar Dave Airlie

Merge tag 'drm-msm-fixes-2021-02-25' of https://gitlab.freedesktop.org/drm/msm into drm-fixes

- pll fixes
- shutdown hook fix
- runtime resume fix
- clear_oob fix
- kms locking fix
- display aux retry fix
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
From: Rob Clark <robdclark@gmail.com>
Link: https://patchwork.freedesktop.org/patch/msgid/CAF6AEGvmiMKRms_NVavD=NA_jbuexZUcqqL35ke7umqpp-TxMw@mail.gmail.com
parents 4e8d123f 627dc55c
...@@ -304,7 +304,7 @@ int a5xx_power_init(struct msm_gpu *gpu) ...@@ -304,7 +304,7 @@ int a5xx_power_init(struct msm_gpu *gpu)
/* Set up the limits management */ /* Set up the limits management */
if (adreno_is_a530(adreno_gpu)) if (adreno_is_a530(adreno_gpu))
a530_lm_setup(gpu); a530_lm_setup(gpu);
else else if (adreno_is_a540(adreno_gpu))
a540_lm_setup(gpu); a540_lm_setup(gpu);
/* Set up SP/TP power collpase */ /* Set up SP/TP power collpase */
......
...@@ -339,7 +339,7 @@ void a6xx_gmu_clear_oob(struct a6xx_gmu *gmu, enum a6xx_gmu_oob_state state) ...@@ -339,7 +339,7 @@ void a6xx_gmu_clear_oob(struct a6xx_gmu *gmu, enum a6xx_gmu_oob_state state)
else else
bit = a6xx_gmu_oob_bits[state].ack_new; bit = a6xx_gmu_oob_bits[state].ack_new;
gmu_write(gmu, REG_A6XX_GMU_HOST2GMU_INTR_SET, bit); gmu_write(gmu, REG_A6XX_GMU_HOST2GMU_INTR_SET, 1 << bit);
} }
/* Enable CPU control of SPTP power power collapse */ /* Enable CPU control of SPTP power power collapse */
......
...@@ -522,28 +522,73 @@ static int a6xx_cp_init(struct msm_gpu *gpu) ...@@ -522,28 +522,73 @@ static int a6xx_cp_init(struct msm_gpu *gpu)
return a6xx_idle(gpu, ring) ? 0 : -EINVAL; return a6xx_idle(gpu, ring) ? 0 : -EINVAL;
} }
static void a6xx_ucode_check_version(struct a6xx_gpu *a6xx_gpu, /*
* Check that the microcode version is new enough to include several key
* security fixes. Return true if the ucode is safe.
*/
static bool a6xx_ucode_check_version(struct a6xx_gpu *a6xx_gpu,
struct drm_gem_object *obj) struct drm_gem_object *obj)
{ {
struct adreno_gpu *adreno_gpu = &a6xx_gpu->base;
struct msm_gpu *gpu = &adreno_gpu->base;
u32 *buf = msm_gem_get_vaddr(obj); u32 *buf = msm_gem_get_vaddr(obj);
bool ret = false;
if (IS_ERR(buf)) if (IS_ERR(buf))
return; return false;
/* /*
* If the lowest nibble is 0xa that is an indication that this microcode * Targets up to a640 (a618, a630 and a640) need to check for a
* has been patched. The actual version is in dword [3] but we only care * microcode version that is patched to support the whereami opcode or
* about the patchlevel which is the lowest nibble of dword [3] * one that is new enough to include it by default.
*/
if (adreno_is_a618(adreno_gpu) || adreno_is_a630(adreno_gpu) ||
adreno_is_a640(adreno_gpu)) {
/*
* If the lowest nibble is 0xa that is an indication that this
* microcode has been patched. The actual version is in dword
* [3] but we only care about the patchlevel which is the lowest
* nibble of dword [3]
* *
* Otherwise check that the firmware is greater than or equal to 1.90 * Otherwise check that the firmware is greater than or equal
* which was the first version that had this fix built in * to 1.90 which was the first version that had this fix built
* in
*/ */
if (((buf[0] & 0xf) == 0xa) && (buf[2] & 0xf) >= 1) if ((((buf[0] & 0xf) == 0xa) && (buf[2] & 0xf) >= 1) ||
a6xx_gpu->has_whereami = true; (buf[0] & 0xfff) >= 0x190) {
else if ((buf[0] & 0xfff) > 0x190)
a6xx_gpu->has_whereami = true; a6xx_gpu->has_whereami = true;
ret = true;
goto out;
}
DRM_DEV_ERROR(&gpu->pdev->dev,
"a630 SQE ucode is too old. Have version %x need at least %x\n",
buf[0] & 0xfff, 0x190);
} else {
/*
* a650 tier targets don't need whereami but still need to be
* equal to or newer than 1.95 for other security fixes
*/
if (adreno_is_a650(adreno_gpu)) {
if ((buf[0] & 0xfff) >= 0x195) {
ret = true;
goto out;
}
DRM_DEV_ERROR(&gpu->pdev->dev,
"a650 SQE ucode is too old. Have version %x need at least %x\n",
buf[0] & 0xfff, 0x195);
}
/*
* When a660 is added those targets should return true here
* since those have all the critical security fixes built in
* from the start
*/
}
out:
msm_gem_put_vaddr(obj); msm_gem_put_vaddr(obj);
return ret;
} }
static int a6xx_ucode_init(struct msm_gpu *gpu) static int a6xx_ucode_init(struct msm_gpu *gpu)
...@@ -566,7 +611,13 @@ static int a6xx_ucode_init(struct msm_gpu *gpu) ...@@ -566,7 +611,13 @@ static int a6xx_ucode_init(struct msm_gpu *gpu)
} }
msm_gem_object_set_name(a6xx_gpu->sqe_bo, "sqefw"); msm_gem_object_set_name(a6xx_gpu->sqe_bo, "sqefw");
a6xx_ucode_check_version(a6xx_gpu, a6xx_gpu->sqe_bo); if (!a6xx_ucode_check_version(a6xx_gpu, a6xx_gpu->sqe_bo)) {
msm_gem_unpin_iova(a6xx_gpu->sqe_bo, gpu->aspace);
drm_gem_object_put(a6xx_gpu->sqe_bo);
a6xx_gpu->sqe_bo = NULL;
return -EPERM;
}
} }
gpu_write64(gpu, REG_A6XX_CP_SQE_INSTR_BASE_LO, gpu_write64(gpu, REG_A6XX_CP_SQE_INSTR_BASE_LO,
...@@ -1350,35 +1401,20 @@ static int a6xx_set_supported_hw(struct device *dev, struct a6xx_gpu *a6xx_gpu, ...@@ -1350,35 +1401,20 @@ static int a6xx_set_supported_hw(struct device *dev, struct a6xx_gpu *a6xx_gpu,
u32 revn) u32 revn)
{ {
struct opp_table *opp_table; struct opp_table *opp_table;
struct nvmem_cell *cell;
u32 supp_hw = UINT_MAX; u32 supp_hw = UINT_MAX;
void *buf; u16 speedbin;
int ret;
cell = nvmem_cell_get(dev, "speed_bin");
/*
* -ENOENT means that the platform doesn't support speedbin which is
* fine
*/
if (PTR_ERR(cell) == -ENOENT)
return 0;
else if (IS_ERR(cell)) {
DRM_DEV_ERROR(dev,
"failed to read speed-bin. Some OPPs may not be supported by hardware");
goto done;
}
buf = nvmem_cell_read(cell, NULL); ret = nvmem_cell_read_u16(dev, "speed_bin", &speedbin);
if (IS_ERR(buf)) { if (ret) {
nvmem_cell_put(cell);
DRM_DEV_ERROR(dev, DRM_DEV_ERROR(dev,
"failed to read speed-bin. Some OPPs may not be supported by hardware"); "failed to read speed-bin (%d). Some OPPs may not be supported by hardware",
ret);
goto done; goto done;
} }
speedbin = le16_to_cpu(speedbin);
supp_hw = fuse_to_supp_hw(dev, revn, *((u32 *) buf)); supp_hw = fuse_to_supp_hw(dev, revn, speedbin);
kfree(buf);
nvmem_cell_put(cell);
done: done:
opp_table = dev_pm_opp_set_supported_hw(dev, &supp_hw, 1); opp_table = dev_pm_opp_set_supported_hw(dev, &supp_hw, 1);
......
...@@ -43,6 +43,8 @@ ...@@ -43,6 +43,8 @@
#define DPU_DEBUGFS_DIR "msm_dpu" #define DPU_DEBUGFS_DIR "msm_dpu"
#define DPU_DEBUGFS_HWMASKNAME "hw_log_mask" #define DPU_DEBUGFS_HWMASKNAME "hw_log_mask"
#define MIN_IB_BW 400000000ULL /* Min ib vote 400MB */
static int dpu_kms_hw_init(struct msm_kms *kms); static int dpu_kms_hw_init(struct msm_kms *kms);
static void _dpu_kms_mmu_destroy(struct dpu_kms *dpu_kms); static void _dpu_kms_mmu_destroy(struct dpu_kms *dpu_kms);
...@@ -931,6 +933,9 @@ static int dpu_kms_hw_init(struct msm_kms *kms) ...@@ -931,6 +933,9 @@ static int dpu_kms_hw_init(struct msm_kms *kms)
DPU_DEBUG("REG_DMA is not defined"); DPU_DEBUG("REG_DMA is not defined");
} }
if (of_device_is_compatible(dev->dev->of_node, "qcom,sc7180-mdss"))
dpu_kms_parse_data_bus_icc_path(dpu_kms);
pm_runtime_get_sync(&dpu_kms->pdev->dev); pm_runtime_get_sync(&dpu_kms->pdev->dev);
dpu_kms->core_rev = readl_relaxed(dpu_kms->mmio + 0x0); dpu_kms->core_rev = readl_relaxed(dpu_kms->mmio + 0x0);
...@@ -1032,9 +1037,6 @@ static int dpu_kms_hw_init(struct msm_kms *kms) ...@@ -1032,9 +1037,6 @@ static int dpu_kms_hw_init(struct msm_kms *kms)
dpu_vbif_init_memtypes(dpu_kms); dpu_vbif_init_memtypes(dpu_kms);
if (of_device_is_compatible(dev->dev->of_node, "qcom,sc7180-mdss"))
dpu_kms_parse_data_bus_icc_path(dpu_kms);
pm_runtime_put_sync(&dpu_kms->pdev->dev); pm_runtime_put_sync(&dpu_kms->pdev->dev);
return 0; return 0;
...@@ -1191,10 +1193,10 @@ static int __maybe_unused dpu_runtime_resume(struct device *dev) ...@@ -1191,10 +1193,10 @@ static int __maybe_unused dpu_runtime_resume(struct device *dev)
ddev = dpu_kms->dev; ddev = dpu_kms->dev;
WARN_ON(!(dpu_kms->num_paths));
/* Min vote of BW is required before turning on AXI clk */ /* Min vote of BW is required before turning on AXI clk */
for (i = 0; i < dpu_kms->num_paths; i++) for (i = 0; i < dpu_kms->num_paths; i++)
icc_set_bw(dpu_kms->path[i], 0, icc_set_bw(dpu_kms->path[i], 0, Bps_to_icc(MIN_IB_BW));
dpu_kms->catalog->perf.min_dram_ib);
rc = msm_dss_enable_clk(mp->clk_config, mp->num_clk, true); rc = msm_dss_enable_clk(mp->clk_config, mp->num_clk, true);
if (rc) { if (rc) {
......
...@@ -32,6 +32,8 @@ struct dp_aux_private { ...@@ -32,6 +32,8 @@ struct dp_aux_private {
struct drm_dp_aux dp_aux; struct drm_dp_aux dp_aux;
}; };
#define MAX_AUX_RETRIES 5
static const char *dp_aux_get_error(u32 aux_error) static const char *dp_aux_get_error(u32 aux_error)
{ {
switch (aux_error) { switch (aux_error) {
...@@ -377,6 +379,11 @@ static ssize_t dp_aux_transfer(struct drm_dp_aux *dp_aux, ...@@ -377,6 +379,11 @@ static ssize_t dp_aux_transfer(struct drm_dp_aux *dp_aux,
ret = dp_aux_cmd_fifo_tx(aux, msg); ret = dp_aux_cmd_fifo_tx(aux, msg);
if (ret < 0) { if (ret < 0) {
if (aux->native) {
aux->retry_cnt++;
if (!(aux->retry_cnt % MAX_AUX_RETRIES))
dp_catalog_aux_update_cfg(aux->catalog);
}
usleep_range(400, 500); /* at least 400us to next try */ usleep_range(400, 500); /* at least 400us to next try */
goto unlock_exit; goto unlock_exit;
} }
......
...@@ -163,7 +163,7 @@ struct msm_dsi_pll *msm_dsi_pll_init(struct platform_device *pdev, ...@@ -163,7 +163,7 @@ struct msm_dsi_pll *msm_dsi_pll_init(struct platform_device *pdev,
break; break;
case MSM_DSI_PHY_7NM: case MSM_DSI_PHY_7NM:
case MSM_DSI_PHY_7NM_V4_1: case MSM_DSI_PHY_7NM_V4_1:
pll = msm_dsi_pll_7nm_init(pdev, id); pll = msm_dsi_pll_7nm_init(pdev, type, id);
break; break;
default: default:
pll = ERR_PTR(-ENXIO); pll = ERR_PTR(-ENXIO);
......
...@@ -117,10 +117,12 @@ msm_dsi_pll_10nm_init(struct platform_device *pdev, int id) ...@@ -117,10 +117,12 @@ msm_dsi_pll_10nm_init(struct platform_device *pdev, int id)
} }
#endif #endif
#ifdef CONFIG_DRM_MSM_DSI_7NM_PHY #ifdef CONFIG_DRM_MSM_DSI_7NM_PHY
struct msm_dsi_pll *msm_dsi_pll_7nm_init(struct platform_device *pdev, int id); struct msm_dsi_pll *msm_dsi_pll_7nm_init(struct platform_device *pdev,
enum msm_dsi_phy_type type, int id);
#else #else
static inline struct msm_dsi_pll * static inline struct msm_dsi_pll *
msm_dsi_pll_7nm_init(struct platform_device *pdev, int id) msm_dsi_pll_7nm_init(struct platform_device *pdev,
enum msm_dsi_phy_type type, int id)
{ {
return ERR_PTR(-ENODEV); return ERR_PTR(-ENODEV);
} }
......
...@@ -325,7 +325,7 @@ static void dsi_pll_commit(struct dsi_pll_7nm *pll) ...@@ -325,7 +325,7 @@ static void dsi_pll_commit(struct dsi_pll_7nm *pll)
pll_write(base + REG_DSI_7nm_PHY_PLL_FRAC_DIV_START_LOW_1, reg->frac_div_start_low); pll_write(base + REG_DSI_7nm_PHY_PLL_FRAC_DIV_START_LOW_1, reg->frac_div_start_low);
pll_write(base + REG_DSI_7nm_PHY_PLL_FRAC_DIV_START_MID_1, reg->frac_div_start_mid); pll_write(base + REG_DSI_7nm_PHY_PLL_FRAC_DIV_START_MID_1, reg->frac_div_start_mid);
pll_write(base + REG_DSI_7nm_PHY_PLL_FRAC_DIV_START_HIGH_1, reg->frac_div_start_high); pll_write(base + REG_DSI_7nm_PHY_PLL_FRAC_DIV_START_HIGH_1, reg->frac_div_start_high);
pll_write(base + REG_DSI_7nm_PHY_PLL_PLL_LOCKDET_RATE_1, 0x40); pll_write(base + REG_DSI_7nm_PHY_PLL_PLL_LOCKDET_RATE_1, reg->pll_lockdet_rate);
pll_write(base + REG_DSI_7nm_PHY_PLL_PLL_LOCK_DELAY, 0x06); pll_write(base + REG_DSI_7nm_PHY_PLL_PLL_LOCK_DELAY, 0x06);
pll_write(base + REG_DSI_7nm_PHY_PLL_CMODE_1, 0x10); /* TODO: 0x00 for CPHY */ pll_write(base + REG_DSI_7nm_PHY_PLL_CMODE_1, 0x10); /* TODO: 0x00 for CPHY */
pll_write(base + REG_DSI_7nm_PHY_PLL_CLOCK_INVERTERS, reg->pll_clock_inverters); pll_write(base + REG_DSI_7nm_PHY_PLL_CLOCK_INVERTERS, reg->pll_clock_inverters);
...@@ -509,6 +509,7 @@ static unsigned long dsi_pll_7nm_vco_recalc_rate(struct clk_hw *hw, ...@@ -509,6 +509,7 @@ static unsigned long dsi_pll_7nm_vco_recalc_rate(struct clk_hw *hw,
{ {
struct msm_dsi_pll *pll = hw_clk_to_pll(hw); struct msm_dsi_pll *pll = hw_clk_to_pll(hw);
struct dsi_pll_7nm *pll_7nm = to_pll_7nm(pll); struct dsi_pll_7nm *pll_7nm = to_pll_7nm(pll);
struct dsi_pll_config *config = &pll_7nm->pll_configuration;
void __iomem *base = pll_7nm->mmio; void __iomem *base = pll_7nm->mmio;
u64 ref_clk = pll_7nm->vco_ref_clk_rate; u64 ref_clk = pll_7nm->vco_ref_clk_rate;
u64 vco_rate = 0x0; u64 vco_rate = 0x0;
...@@ -529,9 +530,8 @@ static unsigned long dsi_pll_7nm_vco_recalc_rate(struct clk_hw *hw, ...@@ -529,9 +530,8 @@ static unsigned long dsi_pll_7nm_vco_recalc_rate(struct clk_hw *hw,
/* /*
* TODO: * TODO:
* 1. Assumes prescaler is disabled * 1. Assumes prescaler is disabled
* 2. Multiplier is 2^18. it should be 2^(num_of_frac_bits)
*/ */
multiplier = 1 << 18; multiplier = 1 << config->frac_bits;
pll_freq = dec * (ref_clk * 2); pll_freq = dec * (ref_clk * 2);
tmp64 = (ref_clk * 2 * frac); tmp64 = (ref_clk * 2 * frac);
pll_freq += div_u64(tmp64, multiplier); pll_freq += div_u64(tmp64, multiplier);
...@@ -852,7 +852,8 @@ static int pll_7nm_register(struct dsi_pll_7nm *pll_7nm) ...@@ -852,7 +852,8 @@ static int pll_7nm_register(struct dsi_pll_7nm *pll_7nm)
return ret; return ret;
} }
struct msm_dsi_pll *msm_dsi_pll_7nm_init(struct platform_device *pdev, int id) struct msm_dsi_pll *msm_dsi_pll_7nm_init(struct platform_device *pdev,
enum msm_dsi_phy_type type, int id)
{ {
struct dsi_pll_7nm *pll_7nm; struct dsi_pll_7nm *pll_7nm;
struct msm_dsi_pll *pll; struct msm_dsi_pll *pll;
...@@ -885,7 +886,7 @@ struct msm_dsi_pll *msm_dsi_pll_7nm_init(struct platform_device *pdev, int id) ...@@ -885,7 +886,7 @@ struct msm_dsi_pll *msm_dsi_pll_7nm_init(struct platform_device *pdev, int id)
pll = &pll_7nm->base; pll = &pll_7nm->base;
pll->min_rate = 1000000000UL; pll->min_rate = 1000000000UL;
pll->max_rate = 3500000000UL; pll->max_rate = 3500000000UL;
if (pll->type == MSM_DSI_PHY_7NM_V4_1) { if (type == MSM_DSI_PHY_7NM_V4_1) {
pll->min_rate = 600000000UL; pll->min_rate = 600000000UL;
pll->max_rate = (unsigned long)5000000000ULL; pll->max_rate = (unsigned long)5000000000ULL;
/* workaround for max rate overflowing on 32-bit builds: */ /* workaround for max rate overflowing on 32-bit builds: */
......
...@@ -57,10 +57,13 @@ static void vblank_put(struct msm_kms *kms, unsigned crtc_mask) ...@@ -57,10 +57,13 @@ static void vblank_put(struct msm_kms *kms, unsigned crtc_mask)
static void lock_crtcs(struct msm_kms *kms, unsigned int crtc_mask) static void lock_crtcs(struct msm_kms *kms, unsigned int crtc_mask)
{ {
int crtc_index;
struct drm_crtc *crtc; struct drm_crtc *crtc;
for_each_crtc_mask(kms->dev, crtc, crtc_mask) for_each_crtc_mask(kms->dev, crtc, crtc_mask) {
mutex_lock(&kms->commit_lock[drm_crtc_index(crtc)]); crtc_index = drm_crtc_index(crtc);
mutex_lock_nested(&kms->commit_lock[crtc_index], crtc_index);
}
} }
static void unlock_crtcs(struct msm_kms *kms, unsigned int crtc_mask) static void unlock_crtcs(struct msm_kms *kms, unsigned int crtc_mask)
......
...@@ -1072,6 +1072,10 @@ static int __maybe_unused msm_pm_resume(struct device *dev) ...@@ -1072,6 +1072,10 @@ static int __maybe_unused msm_pm_resume(struct device *dev)
static int __maybe_unused msm_pm_prepare(struct device *dev) static int __maybe_unused msm_pm_prepare(struct device *dev)
{ {
struct drm_device *ddev = dev_get_drvdata(dev); struct drm_device *ddev = dev_get_drvdata(dev);
struct msm_drm_private *priv = ddev ? ddev->dev_private : NULL;
if (!priv || !priv->kms)
return 0;
return drm_mode_config_helper_suspend(ddev); return drm_mode_config_helper_suspend(ddev);
} }
...@@ -1079,6 +1083,10 @@ static int __maybe_unused msm_pm_prepare(struct device *dev) ...@@ -1079,6 +1083,10 @@ static int __maybe_unused msm_pm_prepare(struct device *dev)
static void __maybe_unused msm_pm_complete(struct device *dev) static void __maybe_unused msm_pm_complete(struct device *dev)
{ {
struct drm_device *ddev = dev_get_drvdata(dev); struct drm_device *ddev = dev_get_drvdata(dev);
struct msm_drm_private *priv = ddev ? ddev->dev_private : NULL;
if (!priv || !priv->kms)
return;
drm_mode_config_helper_resume(ddev); drm_mode_config_helper_resume(ddev);
} }
...@@ -1311,6 +1319,10 @@ static int msm_pdev_remove(struct platform_device *pdev) ...@@ -1311,6 +1319,10 @@ static int msm_pdev_remove(struct platform_device *pdev)
static void msm_pdev_shutdown(struct platform_device *pdev) static void msm_pdev_shutdown(struct platform_device *pdev)
{ {
struct drm_device *drm = platform_get_drvdata(pdev); struct drm_device *drm = platform_get_drvdata(pdev);
struct msm_drm_private *priv = drm ? drm->dev_private : NULL;
if (!priv || !priv->kms)
return;
drm_atomic_helper_shutdown(drm); drm_atomic_helper_shutdown(drm);
} }
......
...@@ -45,7 +45,7 @@ int msm_wait_fence(struct msm_fence_context *fctx, uint32_t fence, ...@@ -45,7 +45,7 @@ int msm_wait_fence(struct msm_fence_context *fctx, uint32_t fence,
int ret; int ret;
if (fence > fctx->last_fence) { if (fence > fctx->last_fence) {
DRM_ERROR("%s: waiting on invalid fence: %u (of %u)\n", DRM_ERROR_RATELIMITED("%s: waiting on invalid fence: %u (of %u)\n",
fctx->name, fence, fctx->last_fence); fctx->name, fence, fctx->last_fence);
return -EINVAL; return -EINVAL;
} }
......
...@@ -157,7 +157,6 @@ struct msm_kms { ...@@ -157,7 +157,6 @@ struct msm_kms {
* from the crtc's pending_timer close to end of the frame: * from the crtc's pending_timer close to end of the frame:
*/ */
struct mutex commit_lock[MAX_CRTCS]; struct mutex commit_lock[MAX_CRTCS];
struct lock_class_key commit_lock_keys[MAX_CRTCS];
unsigned pending_crtc_mask; unsigned pending_crtc_mask;
struct msm_pending_timer pending_timers[MAX_CRTCS]; struct msm_pending_timer pending_timers[MAX_CRTCS];
}; };
...@@ -167,11 +166,8 @@ static inline int msm_kms_init(struct msm_kms *kms, ...@@ -167,11 +166,8 @@ static inline int msm_kms_init(struct msm_kms *kms,
{ {
unsigned i, ret; unsigned i, ret;
for (i = 0; i < ARRAY_SIZE(kms->commit_lock); i++) { for (i = 0; i < ARRAY_SIZE(kms->commit_lock); i++)
lockdep_register_key(&kms->commit_lock_keys[i]); mutex_init(&kms->commit_lock[i]);
__mutex_init(&kms->commit_lock[i], "&kms->commit_lock[i]",
&kms->commit_lock_keys[i]);
}
kms->funcs = funcs; kms->funcs = funcs;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment