* [PATCH -next] mtd: rawnand: ingenic: Make jz4725b_ooblayout_ops static
From: Yue Haibing @ 2019-04-10 14:00 UTC (permalink / raw)
To: bbrezillon, miquel.raynal, richard, dwmw2, computersforpeace,
marek.vasut, paul
Cc: linux-kernel, linux-mtd, YueHaibing
From: YueHaibing <yuehaibing@huawei.com>
Fix sparse warning:
drivers/mtd/nand/raw/ingenic/ingenic_nand.c:140:32: warning:
symbol 'jz4725b_ooblayout_ops' was not declared. Should it be static?
Reported-by: Hulk Robot <hulkci@huawei.com>
Signed-off-by: YueHaibing <yuehaibing@huawei.com>
---
drivers/mtd/nand/raw/ingenic/ingenic_nand.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/mtd/nand/raw/ingenic/ingenic_nand.c b/drivers/mtd/nand/raw/ingenic/ingenic_nand.c
index ad0c905..d7b7c0f 100644
--- a/drivers/mtd/nand/raw/ingenic/ingenic_nand.c
+++ b/drivers/mtd/nand/raw/ingenic/ingenic_nand.c
@@ -137,7 +137,7 @@ static int jz4725b_ooblayout_free(struct mtd_info *mtd, int section,
return 0;
}
-const struct mtd_ooblayout_ops jz4725b_ooblayout_ops = {
+static const struct mtd_ooblayout_ops jz4725b_ooblayout_ops = {
.ecc = jz4725b_ooblayout_ecc,
.free = jz4725b_ooblayout_free,
};
--
2.7.4
^ permalink raw reply related
* [dpdk-dev] [PATCH 1/2] build: fix meson binutils workaround
From: Ferruh Yigit @ 2019-04-10 14:00 UTC (permalink / raw)
To: Thomas Monjalon; +Cc: dev, stable, harry.van.haaren
The '-mno-avx512f' compiler flag is not passed to the compiler,
detection of the binutils and setting flags works fine, but the flag
itself not used by compiler.
Removing the interim 'march_opt' variable and using directly
'machine_args' and setting '-mno-avx512f' to 'machine_args'
Fixes: 566b4d7a968f ("build: fix meson check for binutils 2.30")
Cc: stable@dpdk.org
Signed-off-by: Ferruh Yigit <ferruh.yigit@intel.com>
---
Cc: harry.van.haaren@intel.com
---
config/x86/meson.build | 17 +++++++----------
1 file changed, 7 insertions(+), 10 deletions(-)
diff --git a/config/x86/meson.build b/config/x86/meson.build
index 558edfda9..692aebe7a 100644
--- a/config/x86/meson.build
+++ b/config/x86/meson.build
@@ -1,15 +1,12 @@
# SPDX-License-Identifier: BSD-3-Clause
# Copyright(c) 2017-2019 Intel Corporation
-# for checking defines we need to use the correct compiler flags
-march_opt = ['-march=@0@'.format(machine)]
-
# get binutils version for the workaround of Bug 97
if host_machine.system() != 'windows'
ldver = run_command('ld', '-v').stdout().strip()
if ldver.contains('2.30')
if cc.has_argument('-mno-avx512f')
- march_opt += '-mno-avx512f'
+ machine_args += '-mno-avx512f'
message('Binutils 2.30 detected, disabling AVX512 support as workaround for bug #97')
endif
endif
@@ -19,7 +16,7 @@ endif
sse_errormsg = '''SSE4.2 instruction set is required for DPDK.
Please set the machine type to "nehalem" or "corei7" or higher value'''
-if cc.get_define('__SSE4_2__', args: march_opt) == ''
+if cc.get_define('__SSE4_2__', args: machine_args) == ''
error(sse_errormsg)
endif
@@ -38,23 +35,23 @@ else
dpdk_conf.set('RTE_ARCH', 'i686')
endif
-if cc.get_define('__AES__', args: march_opt) != ''
+if cc.get_define('__AES__', args: machine_args) != ''
dpdk_conf.set('RTE_MACHINE_CPUFLAG_AES', 1)
compile_time_cpuflags += ['RTE_CPUFLAG_AES']
endif
-if cc.get_define('__PCLMUL__', args: march_opt) != ''
+if cc.get_define('__PCLMUL__', args: machine_args) != ''
dpdk_conf.set('RTE_MACHINE_CPUFLAG_PCLMULQDQ', 1)
compile_time_cpuflags += ['RTE_CPUFLAG_PCLMULQDQ']
endif
-if cc.get_define('__AVX__', args: march_opt) != ''
+if cc.get_define('__AVX__', args: machine_args) != ''
dpdk_conf.set('RTE_MACHINE_CPUFLAG_AVX', 1)
compile_time_cpuflags += ['RTE_CPUFLAG_AVX']
endif
-if cc.get_define('__AVX2__', args: march_opt) != ''
+if cc.get_define('__AVX2__', args: machine_args) != ''
dpdk_conf.set('RTE_MACHINE_CPUFLAG_AVX2', 1)
compile_time_cpuflags += ['RTE_CPUFLAG_AVX2']
endif
-if cc.get_define('__AVX512F__', args: march_opt) != ''
+if cc.get_define('__AVX512F__', args: machine_args) != ''
dpdk_conf.set('RTE_MACHINE_CPUFLAG_AVX512F', 1)
compile_time_cpuflags += ['RTE_CPUFLAG_AVX512F']
endif
--
2.20.1
^ permalink raw reply related
* [PATCH -next] mtd: rawnand: ingenic: Make jz4725b_ooblayout_ops static
From: Yue Haibing @ 2019-04-10 14:00 UTC (permalink / raw)
To: bbrezillon, miquel.raynal, richard, dwmw2, computersforpeace,
marek.vasut, paul
Cc: YueHaibing, linux-mtd, linux-kernel
From: YueHaibing <yuehaibing@huawei.com>
Fix sparse warning:
drivers/mtd/nand/raw/ingenic/ingenic_nand.c:140:32: warning:
symbol 'jz4725b_ooblayout_ops' was not declared. Should it be static?
Reported-by: Hulk Robot <hulkci@huawei.com>
Signed-off-by: YueHaibing <yuehaibing@huawei.com>
---
drivers/mtd/nand/raw/ingenic/ingenic_nand.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/mtd/nand/raw/ingenic/ingenic_nand.c b/drivers/mtd/nand/raw/ingenic/ingenic_nand.c
index ad0c905..d7b7c0f 100644
--- a/drivers/mtd/nand/raw/ingenic/ingenic_nand.c
+++ b/drivers/mtd/nand/raw/ingenic/ingenic_nand.c
@@ -137,7 +137,7 @@ static int jz4725b_ooblayout_free(struct mtd_info *mtd, int section,
return 0;
}
-const struct mtd_ooblayout_ops jz4725b_ooblayout_ops = {
+static const struct mtd_ooblayout_ops jz4725b_ooblayout_ops = {
.ecc = jz4725b_ooblayout_ecc,
.free = jz4725b_ooblayout_free,
};
--
2.7.4
______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/
^ permalink raw reply related
* [dpdk-dev] [PATCH 2/2] build: fix crash by disabling AVX512 with binutils 2.31
From: Ferruh Yigit @ 2019-04-10 14:00 UTC (permalink / raw)
To: Thomas Monjalon; +Cc: dev, stable
In-Reply-To: <20190410140058.26782-1-ferruh.yigit@intel.com>
On Skylake platform, with native build, KNI kernel module crashes
because of the corrupted values passed to kernel module.
The corruption occurs because the userspace kni library works
unexpectedly. Compiler [1] is using AVX512 instructions and generated
binary is wrong [2].
It turned around gcc does its job correct, but gas is generating binary
wrong. And expected binutils 2.30, 2.31 & 2.31.1 are affected. Issue has
been fixed in binutils 2.32 with:
Commit x86: don't mistakenly scale non-8-bit displacements
AVX512 was already disabled with bintuils 2.30 [3], extending it to
2.31 & 2.31.1 too.
[1] gcc (GCC) 8.3.1 20190223 (Red Hat 8.3.1-2)
[2] gcc bug: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90028
[3] Bugzilla ID 97 has the details.
Bugzilla ID: 249
Cc: stable@dpdk.org
Signed-off-by: Ferruh Yigit <ferruh.yigit@intel.com>
---
config/x86/meson.build | 6 ++++++
mk/toolchain/gcc/rte.toolchain-compat.mk | 9 ++++++++-
2 files changed, 14 insertions(+), 1 deletion(-)
diff --git a/config/x86/meson.build b/config/x86/meson.build
index 692aebe7a..9e9d5dc8c 100644
--- a/config/x86/meson.build
+++ b/config/x86/meson.build
@@ -10,6 +10,12 @@ if host_machine.system() != 'windows'
message('Binutils 2.30 detected, disabling AVX512 support as workaround for bug #97')
endif
endif
+ if ldver.contains('2.31')
+ if cc.has_argument('-mno-avx512f')
+ machine_args += '-mno-avx512f'
+ message('Binutils 2.31 detected, disabling AVX512 support as workaround for bug #249')
+ endif
+ endif
endif
# we require SSE4.2 for DPDK
diff --git a/mk/toolchain/gcc/rte.toolchain-compat.mk b/mk/toolchain/gcc/rte.toolchain-compat.mk
index df71e4a8b..ea40a11c0 100644
--- a/mk/toolchain/gcc/rte.toolchain-compat.mk
+++ b/mk/toolchain/gcc/rte.toolchain-compat.mk
@@ -27,7 +27,14 @@ ifneq ($(filter 2.30%,$(LD_VERSION)),)
FORCE_DISABLE_AVX512 := y
# print warning only once for librte_eal
ifneq ($(filter %librte_eal,$(CURDIR)),)
-$(warning AVX512 support disabled because of ld 2.30. See Bug 97)
+$(warning AVX512 support disabled because of binutils 2.30. See Bug 97)
+endif
+endif
+ifneq ($(filter 2.31%,$(LD_VERSION)),)
+FORCE_DISABLE_AVX512 := y
+# print warning only once for librte_eal
+ifneq ($(filter %librte_eal,$(CURDIR)),)
+$(warning AVX512 support disabled because of binutils 2.31. See Bug 249)
endif
endif
endif
--
2.20.1
^ permalink raw reply related
* Re: [PATCH v5 0/7] sunxi: Add DT representation for the MBUS controller
From: Rob Herring @ 2019-04-10 14:01 UTC (permalink / raw)
To: Maxime Ripard
Cc: Mark Rutland, devicetree, Thomas Petazzoni, Arnd Bergmann,
Robin Murphy, dri-devel, Georgi Djakov, Paul Kocialkowski,
Chen-Yu Tsai, Yong Deng, Frank Rowand, Dave Martin,
linux-arm-kernel
In-Reply-To: <20190408081126.t3blyvtcqslzvki2@flea>
On Mon, Apr 08, 2019 at 10:11:26AM +0200, Maxime Ripard wrote:
> On Sat, Apr 06, 2019 at 01:06:07AM -0500, Rob Herring wrote:
> > On Mon, Apr 01, 2019 at 10:56:40AM +0200, Maxime Ripard wrote:
> > > Hi,
> > >
> > > We've had for quite some time to hack around in our drivers to take into
> > > account the fact that our DMA accesses are not done through the parent
> > > node, but through another bus with a different mapping than the CPU for the
> > > RAM (0 instead of 0x40000000 for most SoCs).
> > >
> > > After some discussion after the submission of a camera device suffering of
> > > the same hacks, I've decided to put together a serie that introduce a
> > > special interconnect name called "dma" that that allows to express the DMA
> > > relationship between a master and its bus, even if they are not direct
> > > parents in the DT.
> > >
> > > Let me know what you think,
> > > Maxime
> >
> > LGTM.
> >
> > How do you propose merging this? I can take 1-5, and 6 and 7 thru
> > arm-soc?
>
> You can merge 1-4, and I'll merge 5 through drm-misc and 6-7 through
> arm-soc
Done.
Rob
^ permalink raw reply
* Re: [PATCH v5 0/7] sunxi: Add DT representation for the MBUS controller
From: Rob Herring @ 2019-04-10 14:01 UTC (permalink / raw)
To: Maxime Ripard
Cc: Mark Rutland, devicetree, Thomas Petazzoni, Arnd Bergmann,
Robin Murphy, dri-devel, Georgi Djakov, Paul Kocialkowski,
Chen-Yu Tsai, Yong Deng, Frank Rowand, Dave Martin,
linux-arm-kernel
In-Reply-To: <20190408081126.t3blyvtcqslzvki2@flea>
On Mon, Apr 08, 2019 at 10:11:26AM +0200, Maxime Ripard wrote:
> On Sat, Apr 06, 2019 at 01:06:07AM -0500, Rob Herring wrote:
> > On Mon, Apr 01, 2019 at 10:56:40AM +0200, Maxime Ripard wrote:
> > > Hi,
> > >
> > > We've had for quite some time to hack around in our drivers to take into
> > > account the fact that our DMA accesses are not done through the parent
> > > node, but through another bus with a different mapping than the CPU for the
> > > RAM (0 instead of 0x40000000 for most SoCs).
> > >
> > > After some discussion after the submission of a camera device suffering of
> > > the same hacks, I've decided to put together a serie that introduce a
> > > special interconnect name called "dma" that that allows to express the DMA
> > > relationship between a master and its bus, even if they are not direct
> > > parents in the DT.
> > >
> > > Let me know what you think,
> > > Maxime
> >
> > LGTM.
> >
> > How do you propose merging this? I can take 1-5, and 6 and 7 thru
> > arm-soc?
>
> You can merge 1-4, and I'll merge 5 through drm-misc and 6-7 through
> arm-soc
Done.
Rob
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH] drm/amdgpu: support dpm level modification under virtualization v2
From: Christian König @ 2019-04-10 14:01 UTC (permalink / raw)
To: Yintian Tao, amd-gfx-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW
In-Reply-To: <1554901357-10377-1-git-send-email-yttao-5C7GfCeVMHo@public.gmane.org>
Am 10.04.19 um 15:02 schrieb Yintian Tao:
> Under vega10 virtualuzation, smu ip block will not be added.
> Therefore, we need add pp clk query and force dpm level function
> at amdgpu_virt_ops to support the feature.
>
> v2: add get_pp_clk existence check and use kzalloc to allocate buf
>
> Change-Id: I713419c57b854082f6f739f1d32a055c7115e620
> Signed-off-by: Yintian Tao <yttao@amd.com>
> ---
> drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 1 +
> drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c | 4 ++
> drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c | 15 ++++++
> drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c | 49 +++++++++++++++++++
> drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h | 11 +++++
> drivers/gpu/drm/amd/amdgpu/mxgpu_ai.c | 78 ++++++++++++++++++++++++++++++
> drivers/gpu/drm/amd/amdgpu/mxgpu_ai.h | 6 +++
> 7 files changed, 164 insertions(+)
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
> index 3ff8899..bb0fd5a 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
> @@ -2486,6 +2486,7 @@ int amdgpu_device_init(struct amdgpu_device *adev,
> mutex_init(&adev->virt.vf_errors.lock);
> hash_init(adev->mn_hash);
> mutex_init(&adev->lock_reset);
> + mutex_init(&adev->virt.dpm_mutex);
>
> amdgpu_device_check_arguments(adev);
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
> index 6190495..29ec28f 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
> @@ -727,6 +727,10 @@ static int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file
> if (adev->pm.dpm_enabled) {
> dev_info.max_engine_clock = amdgpu_dpm_get_sclk(adev, false) * 10;
> dev_info.max_memory_clock = amdgpu_dpm_get_mclk(adev, false) * 10;
> + } else if (amdgpu_sriov_vf(adev) && amdgim_is_hwperf(adev) &&
> + adev->virt.ops->get_pp_clk) {
> + dev_info.max_engine_clock = amdgpu_virt_get_sclk(adev, false) * 10;
> + dev_info.max_memory_clock = amdgpu_virt_get_mclk(adev, false) * 10;
> } else {
> dev_info.max_engine_clock = adev->clock.default_sclk * 10;
> dev_info.max_memory_clock = adev->clock.default_mclk * 10;
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
> index 5540259..0162d1e 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
> @@ -380,6 +380,17 @@ static ssize_t amdgpu_set_dpm_forced_performance_level(struct device *dev,
> goto fail;
> }
>
> + if (amdgpu_sriov_vf(adev)) {
> + if (amdgim_is_hwperf(adev) &&
> + adev->virt.ops->force_dpm_level) {
> + mutex_lock(&adev->pm.mutex);
> + adev->virt.ops->force_dpm_level(adev, level);
> + mutex_unlock(&adev->pm.mutex);
> + return count;
> + } else
> + return -EINVAL;
> + }
> +
> if (current_level == level)
> return count;
>
> @@ -843,6 +854,10 @@ static ssize_t amdgpu_get_pp_dpm_sclk(struct device *dev,
> struct drm_device *ddev = dev_get_drvdata(dev);
> struct amdgpu_device *adev = ddev->dev_private;
>
> + if (amdgpu_sriov_vf(adev) && amdgim_is_hwperf(adev) &&
> + adev->virt.ops->get_pp_clk)
> + return adev->virt.ops->get_pp_clk(adev, PP_SCLK, buf);
> +
> if (is_support_sw_smu(adev))
> return smu_print_clk_levels(&adev->smu, PP_SCLK, buf);
> else if (adev->powerplay.pp_funcs->print_clock_levels)
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c
> index 462a04e..efdb6b7 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c
> @@ -375,4 +375,53 @@ void amdgpu_virt_init_data_exchange(struct amdgpu_device *adev)
> }
> }
>
> +static uint32_t parse_clk(char *buf, bool min)
> +{
> + char *ptr = buf;
> + uint32_t clk = 0;
> +
> + do {
> + ptr = strchr(ptr, ':');
> + if (!ptr)
> + break;
> + ptr+=2;
> + clk = simple_strtoul(ptr, NULL, 10);
> + } while (!min);
> +
> + return clk * 100;
> +}
> +
> +uint32_t amdgpu_virt_get_sclk(struct amdgpu_device *adev, bool lowest)
> +{
> + char *buf = NULL;
> + uint32_t clk = 0;
> +
> + buf = kzalloc(PAGE_SIZE, GFP_KERNEL);
> + if (NULL == buf)
According to coding style rules that should be "if (!buf)".
> + return -EINVAL;
Please return -ENOMEM here.
> +
> + adev->virt.ops->get_pp_clk(adev, PP_SCLK, buf);
> + clk = parse_clk(buf, lowest);
Looks like you are using spaces instead of tabs here.
> +
> + kfree(buf);
> +
> + return clk;
> +}
> +
> +uint32_t amdgpu_virt_get_mclk(struct amdgpu_device *adev, bool lowest)
> +{
> + char *buf = NULL;
> + uint32_t clk = 0;
> +
> + buf = kzalloc(PAGE_SIZE, GFP_KERNEL);
> + if (NULL == buf)
> + return -EINVAL;
> +
> + adev->virt.ops->get_pp_clk(adev, PP_MCLK, buf);
> + clk = parse_clk(buf, lowest);
Dito.
Apart from that looks good to me of hand,
Christian.
> +
> + kfree(buf);
> +
> + return clk;
> +}
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h
> index 722deef..584947b 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h
> @@ -57,6 +57,8 @@ struct amdgpu_virt_ops {
> int (*reset_gpu)(struct amdgpu_device *adev);
> int (*wait_reset)(struct amdgpu_device *adev);
> void (*trans_msg)(struct amdgpu_device *adev, u32 req, u32 data1, u32 data2, u32 data3);
> + int (*get_pp_clk)(struct amdgpu_device *adev, u32 type, char *buf);
> + int (*force_dpm_level)(struct amdgpu_device *adev, u32 level);
> };
>
> /*
> @@ -83,6 +85,8 @@ enum AMDGIM_FEATURE_FLAG {
> AMDGIM_FEATURE_GIM_LOAD_UCODES = 0x2,
> /* VRAM LOST by GIM */
> AMDGIM_FEATURE_GIM_FLR_VRAMLOST = 0x4,
> + /* HW PERF SIM in GIM */
> + AMDGIM_FEATURE_HW_PERF_SIMULATION = (1 << 3),
> };
>
> struct amd_sriov_msg_pf2vf_info_header {
> @@ -252,6 +256,8 @@ struct amdgpu_virt {
> struct amdgpu_vf_error_buffer vf_errors;
> struct amdgpu_virt_fw_reserve fw_reserve;
> uint32_t gim_feature;
> + /* protect DPM events to GIM */
> + struct mutex dpm_mutex;
> };
>
> #define amdgpu_sriov_enabled(adev) \
> @@ -278,6 +284,9 @@ static inline bool is_virtual_machine(void)
> #endif
> }
>
> +#define amdgim_is_hwperf(adev) \
> + ((adev)->virt.gim_feature & AMDGIM_FEATURE_HW_PERF_SIMULATION)
> +
> bool amdgpu_virt_mmio_blocked(struct amdgpu_device *adev);
> void amdgpu_virt_init_setting(struct amdgpu_device *adev);
> uint32_t amdgpu_virt_kiq_rreg(struct amdgpu_device *adev, uint32_t reg);
> @@ -295,5 +304,7 @@ int amdgpu_virt_fw_reserve_get_checksum(void *obj, unsigned long obj_size,
> unsigned int key,
> unsigned int chksum);
> void amdgpu_virt_init_data_exchange(struct amdgpu_device *adev);
> +uint32_t amdgpu_virt_get_sclk(struct amdgpu_device *adev, bool lowest);
> +uint32_t amdgpu_virt_get_mclk(struct amdgpu_device *adev, bool lowest);
>
> #endif
> diff --git a/drivers/gpu/drm/amd/amdgpu/mxgpu_ai.c b/drivers/gpu/drm/amd/amdgpu/mxgpu_ai.c
> index 73851eb..8dbad49 100644
> --- a/drivers/gpu/drm/amd/amdgpu/mxgpu_ai.c
> +++ b/drivers/gpu/drm/amd/amdgpu/mxgpu_ai.c
> @@ -157,6 +157,82 @@ static void xgpu_ai_mailbox_trans_msg (struct amdgpu_device *adev,
> xgpu_ai_mailbox_set_valid(adev, false);
> }
>
> +static int xgpu_ai_get_pp_clk(struct amdgpu_device *adev, u32 type, char *buf)
> +{
> + int r = 0;
> + u32 req, val, size;
> +
> + if (!amdgim_is_hwperf(adev) || buf == NULL)
> + return -EBADRQC;
> +
> + switch(type) {
> + case PP_SCLK:
> + req = IDH_IRQ_GET_PP_SCLK;
> + break;
> + case PP_MCLK:
> + req = IDH_IRQ_GET_PP_MCLK;
> + break;
> + default:
> + return -EBADRQC;
> + }
> +
> + mutex_lock(&adev->virt.dpm_mutex);
> +
> + xgpu_ai_mailbox_trans_msg(adev, req, 0, 0, 0);
> +
> + r = xgpu_ai_poll_msg(adev, IDH_SUCCESS);
> + if (!r && adev->fw_vram_usage.va != NULL) {
> + val = RREG32_NO_KIQ(
> + SOC15_REG_OFFSET(NBIO, 0,
> + mmBIF_BX_PF0_MAILBOX_MSGBUF_RCV_DW1));
> + size = strnlen((((char *)adev->virt.fw_reserve.p_pf2vf) +
> + val), PAGE_SIZE);
> +
> + if (size < PAGE_SIZE)
> + strcpy(buf,((char *)adev->virt.fw_reserve.p_pf2vf + val));
> + else
> + size = 0;
> +
> + r = size;
> + goto out;
> + }
> +
> + r = xgpu_ai_poll_msg(adev, IDH_FAIL);
> + if(r)
> + pr_info("%s DPM request failed",
> + (type == PP_SCLK)? "SCLK" : "MCLK");
> +
> +out:
> + mutex_unlock(&adev->virt.dpm_mutex);
> + return r;
> +}
> +
> +static int xgpu_ai_force_dpm_level(struct amdgpu_device *adev, u32 level)
> +{
> + int r = 0;
> + u32 req = IDH_IRQ_FORCE_DPM_LEVEL;
> +
> + if (!amdgim_is_hwperf(adev))
> + return -EBADRQC;
> +
> + mutex_lock(&adev->virt.dpm_mutex);
> + xgpu_ai_mailbox_trans_msg(adev, req, level, 0, 0);
> +
> + r = xgpu_ai_poll_msg(adev, IDH_SUCCESS);
> + if (!r)
> + goto out;
> +
> + r = xgpu_ai_poll_msg(adev, IDH_FAIL);
> + if (!r)
> + pr_info("DPM request failed");
> + else
> + pr_info("Mailbox is broken");
> +
> +out:
> + mutex_unlock(&adev->virt.dpm_mutex);
> + return r;
> +}
> +
> static int xgpu_ai_send_access_requests(struct amdgpu_device *adev,
> enum idh_request req)
> {
> @@ -375,4 +451,6 @@ const struct amdgpu_virt_ops xgpu_ai_virt_ops = {
> .reset_gpu = xgpu_ai_request_reset,
> .wait_reset = NULL,
> .trans_msg = xgpu_ai_mailbox_trans_msg,
> + .get_pp_clk = xgpu_ai_get_pp_clk,
> + .force_dpm_level = xgpu_ai_force_dpm_level,
> };
> diff --git a/drivers/gpu/drm/amd/amdgpu/mxgpu_ai.h b/drivers/gpu/drm/amd/amdgpu/mxgpu_ai.h
> index b4a9cee..39d151b 100644
> --- a/drivers/gpu/drm/amd/amdgpu/mxgpu_ai.h
> +++ b/drivers/gpu/drm/amd/amdgpu/mxgpu_ai.h
> @@ -35,6 +35,10 @@ enum idh_request {
> IDH_REL_GPU_FINI_ACCESS,
> IDH_REQ_GPU_RESET_ACCESS,
>
> + IDH_IRQ_FORCE_DPM_LEVEL = 10,
> + IDH_IRQ_GET_PP_SCLK,
> + IDH_IRQ_GET_PP_MCLK,
> +
> IDH_LOG_VF_ERROR = 200,
> };
>
> @@ -43,6 +47,8 @@ enum idh_event {
> IDH_READY_TO_ACCESS_GPU,
> IDH_FLR_NOTIFICATION,
> IDH_FLR_NOTIFICATION_CMPL,
> + IDH_SUCCESS,
> + IDH_FAIL,
> IDH_EVENT_MAX
> };
>
_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx
^ permalink raw reply
* Re: [PATCH] ARM: dts: stm32: add ltdc pins muxing on stm32mp157
From: Alexandre Torgue @ 2019-04-10 14:00 UTC (permalink / raw)
To: Yannick Fertré, Maxime Coquelin, Rob Herring, Mark Rutland,
linux-stm32, linux-arm-kernel, devicetree, linux-kernel,
Benjamin Gaignard, Philippe Cornu
In-Reply-To: <1553862515-6005-1-git-send-email-yannick.fertre@st.com>
Hi Yannick
On 3/29/19 1:28 PM, Yannick Fertré wrote:
> Add ltdc pins muxing on stm32mp157.
>
> Signed-off-by: Yannick Fertré <yannick.fertre@st.com>
> ---
> arch/arm/boot/dts/stm32mp157-pinctrl.dtsi | 138 ++++++++++++++++++++++++++++++
> 1 file changed, 138 insertions(+)
>
> diff --git a/arch/arm/boot/dts/stm32mp157-pinctrl.dtsi b/arch/arm/boot/dts/stm32mp157-pinctrl.dtsi
> index 9104896..da4b411 100644
> --- a/arch/arm/boot/dts/stm32mp157-pinctrl.dtsi
> +++ b/arch/arm/boot/dts/stm32mp157-pinctrl.dtsi
> @@ -233,6 +233,144 @@
>
Applied on stm32-next.
Thanks.
Alex
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* [dpdk-dev] [PATCH v2] drivers: ifpga_rawdev: fix fd leak in rte_fpga_do_pr
From: Li Qiang @ 2019-04-10 13:43 UTC (permalink / raw)
To: rosen.xu, tianfei.zhang; +Cc: dev, liq3ea, Li Qiang
In rte_fpga_do_pr() function, if 'stat' return error the
'file_fd' is never closed thus leading a fd leak. This patch
avoids this.
Spotted by Coverity: CID 27441
Signed-off-by: Li Qiang <liq3ea@163.com>
---
Changes since v1: fill ret before goto close_fd per Rosen's review
drivers/raw/ifpga_rawdev/ifpga_rawdev.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/raw/ifpga_rawdev/ifpga_rawdev.c b/drivers/raw/ifpga_rawdev/ifpga_rawdev.c
index da772d026..eff001b59 100644
--- a/drivers/raw/ifpga_rawdev/ifpga_rawdev.c
+++ b/drivers/raw/ifpga_rawdev/ifpga_rawdev.c
@@ -244,7 +244,8 @@ rte_fpga_do_pr(struct rte_rawdev *rawdev, int port_id,
if (ret) {
IFPGA_RAWDEV_PMD_ERR("stat on bitstream file failed: %s\n",
file_name);
- return -EINVAL;
+ ret = -EINVAL;
+ goto close_fd;
}
buffer_size = file_stat.st_size;
IFPGA_RAWDEV_PMD_INFO("bitstream file size: %zu\n", buffer_size);
--
2.17.1
^ permalink raw reply related
* Re: [Qemu-devel] [PATCH for-4.1] q35: acpi: do not create dummy MCFG table
From: Wei Yang @ 2019-04-10 14:01 UTC (permalink / raw)
To: Igor Mammedov; +Cc: Wei Yang, qemu-devel, mst, marcel.apfelbaum, ehabkost
In-Reply-To: <20190410110833.4db9721f@redhat.com>
On Wed, Apr 10, 2019 at 11:08:33AM +0200, Igor Mammedov wrote:
>On Wed, 10 Apr 2019 09:12:31 +0800
>Wei Yang <richardw.yang@linux.intel.com> wrote:
>
>> On Tue, Apr 09, 2019 at 05:00:37PM +0200, Igor Mammedov wrote:
>> >Dummy table (with signature "QEMU") creation came from original SeaBIOS
>> >codebase. And QEMU would have to keep it around if there were Q35 machine
>> >that depended on keeping ACPI tables blob constant size. Luckily there
>> >were no versioned Q35 machine types before commit:
>> > (since 2.3) a1666142db acpi-build: make ROMs RAM blocks resizeable
>> >which obsoleted need to keep ACPI tables blob the same size on source/destination.
>> >
>>
>> I am not sure getting the "versioned Q35" correctly. Seems originally there is
>> q35-1.4?
>>
>> commit bf3caa3dc17552b323cec6831301a22cfc98ecd5
>> Author: Paolo Bonzini <pbonzini@redhat.com>
>> Date: Fri Feb 8 14:06:15 2013 +0100
>>
>> pc: add compatibility machine types for 1.4
>>
>> Adds both pc-i440fx-1.4 and pc-q35-1.4.
>
>current upstream has only pc-q35-2.4 as earliest versioned Q35
>machine type (try to run: qemu-system-x86_64 -M help)
Yes, I see those old type are removed. This means we don't want to support
those old types, right? Because those old types can't be migrated to latest
upstream qemu.
--
Wei Yang
Help you, Help me
^ permalink raw reply
* Re: [dpdk-dev] [Bug 248] Bonding PMD: Invalid array dimension in TX burst for 802.3ad mode with fast queue leads to SEGFAULT
From: Przemysław Ołtarzewski @ 2019-04-10 11:39 UTC (permalink / raw)
To: David Marchand; +Cc: Chas Williams, dev
In-Reply-To: <CAJFAV8y5V9v1dA7Vx3_7ZoqupYvhvD-BtbR1dt5KOsCt5J2S+g@mail.gmail.com>
Hello David,
I can merge these fixes and run our system using patched DPDK version. Then
report back any problems / improvements I observe. I can also walk through
source code changes and check for anything questionable.
Unfortunately I lack deep enough understanding of DPDK source code to test
these fixes comprehensively and I have been short on time recently as well,
so that's the best I can do right now.
Best Regards,
Przemysław Ołtarzewski
On Tue, Apr 9, 2019 at 4:51 PM David Marchand <david.marchand@redhat.com>
wrote:
>
>
> On Tue, Apr 9, 2019 at 4:45 PM <bugzilla@dpdk.org> wrote:
>
>> https://bugs.dpdk.org/show_bug.cgi?id=248
>>
>> Bug ID: 248
>> Summary: Bonding PMD: Invalid array dimension in TX burst for
>> 802.3ad mode with fast queue leads to SEGFAULT
>> Product: DPDK
>> Version: 18.11
>> Hardware: All
>> OS: All
>> Status: CONFIRMED
>> Severity: major
>> Priority: Normal
>> Component: ethdev
>> Assignee: dev@dpdk.org
>> Reporter: p.oltarzewski@gmail.com
>> Target Milestone: ---
>>
>> DPDK 18.11.1
>>
>> In drivers/net/bonding/rte_eth_bond_pmd.c::bond_ethdev_tx_burst_8023ad,
>> bufs_slave_port_idxs array is defined as follows (lines 1293-1294):
>>
>> /* Mapping array generated by hash function to map mbufs to slaves */
>> uint16_t bufs_slave_port_idxs[RTE_MAX_ETHPORTS] = { 0 };
>>
>> Array dimension should be equal to number of packets being transmitted
>> (nb_pkts) - as correctly implemented in
>> rte_eth_bond_pmd.c::bond_ethdev_tx_burst_balance.
>>
>> Invalid array dimension causes overflow when number of transmitted
>> packets is
>> greater than RTE_MAX_ETHPORTS. Some areas of memory end up overwritten
>> (in my
>> particular case, slave_nb_bufs array), which leads to SIGSEGV and crash.
>>
>> To work around the issue, ensure that number of packets transmitted in a
>> single
>> burst is no greater than RTE_MAX_ETHPORTS.
>>
>> To fix it, it should be sufficient to define bufs_slave_port_idxs as a
>> variable-length array, as in bond_ethdev_tx_burst_balance:
>>
>> /* Mapping array generated by hash function to map mbufs to slaves */
>> uint16_t bufs_slave_port_idxs[nb_bufs];
>>
>
> I have a series of fixes for this, and on the rx parts as well but did not
> have time to properly check them.
> Would you have some time to test it if I send it ?
>
>
> --
> David Marchand
>
^ permalink raw reply
* Re: [dpdk-dev] [PATCH 1/2] acl: remove use of weak functions
From: Bruce Richardson @ 2019-04-10 14:02 UTC (permalink / raw)
To: Aaron Conole; +Cc: konstantin.ananyev, dev
In-Reply-To: <f7ttvf6ezk5.fsf@dhcp-25.97.bos.redhat.com>
On Wed, Apr 10, 2019 at 09:54:02AM -0400, Aaron Conole wrote:
> Bruce Richardson <bruce.richardson@intel.com> writes:
>
> > Weak functions don't work well with static libraries and require the
> > use of "whole-archive" flag to ensure that the correct function is used
> > when linking. Since the weak functions are only used as placeholders
> > within this library alone, we can replace them with non-weak functions
> > using preprocessor ifdefs.
> >
> > Signed-off-by: Bruce Richardson <bruce.richardson@intel.com> ---
> > lib/librte_acl/meson.build | 7 ++++++- lib/librte_acl/rte_acl.c | 18
> > ++++++++++++++---- mk/rte.app.mk | 3 --- 3 files changed,
> > 20 insertions(+), 8 deletions(-)
> >
> > diff --git a/lib/librte_acl/meson.build b/lib/librte_acl/meson.build
> > index 2207dbafe..98ece7d85 100644 --- a/lib/librte_acl/meson.build +++
> > b/lib/librte_acl/meson.build @@ -6,7 +6,7 @@ sources =
> > files('acl_bld.c', 'acl_gen.c', 'acl_run_scalar.c', 'rte_acl.c',
> > 'tb_mem.c') headers = files('rte_acl.h', 'rte_acl_osdep.h')
> >
> > -if arch_subdir == 'x86' +if dpdk_conf.has('RTE_ARCH_X86') sources +=
> > files('acl_run_sse.c')
> >
> > # compile AVX2 version if either: @@ -28,4 +28,9 @@ if arch_subdir
> > == 'x86' cflags += '-DCC_AVX2_SUPPORT' endif
> >
> > +elif dpdk_conf.has('RTE_ARCH_ARM') or dpdk_conf.has('RTE_ARCH_ARM64')
> > + cflags += '-flax-vector-conversions' + sources +=
> > files('acl_run_neon.c')
>
> This will also need -Wno-uninitialized (otherwise it will generate
> warnings about the search_neon_4 and search_neon_8 functions).
>
> But I don't like papering over these conversions. I'd prefer instead the
> patches I posted at:
>
> http://mails.dpdk.org/archives/dev/2019-April/129540.html and
> http://mails.dpdk.org/archives/dev/2019-April/129541.html
>
> Are you opposed to merging those?
>
Nope, not in the least. I'm happy enough to rework this patch on top of
those - I'd just had forgotten about them in my rush to get a potential
solution out here. I did these up quickly to show how easy it is to remove
the need for the weak functions and the subsequent linker "--whole-archive"
flag.
/Bruce
PS: I see your patch 2 does not include the Wno-uninitialized flag, is it
not needed in your patch, or just an oversight?
^ permalink raw reply
* Re: [Qemu-devel] [PATCH RESEND v2 2/2] cpus: move hvf_cpu_synchronize* calls to cpu_synchronize* functions
From: Roman Bolshakov @ 2019-04-10 14:02 UTC (permalink / raw)
To: Sukrit Bhatnagar; +Cc: qemu-devel, Paolo Bonzini, Richard Henderson
In-Reply-To: <CAMzgYoMqE20=L+n+tjt8Nb10Tidxr0C6OumQ8vvQ423xJxnN=w@mail.gmail.com>
On Wed, Apr 10, 2019 at 05:35:23PM +0530, Sukrit Bhatnagar wrote:
> On Wed, 10 Apr 2019 at 17:20, Roman Bolshakov <r.bolshakov@yadro.com> wrote:
> >
> > On Sun, Apr 07, 2019 at 05:28:39PM +0530, Sukrit Bhatnagar wrote:
> > > Keep the calls made to synchronize cpu by all hypervisors in one place
> > > inside cpu_synchronize_* functions in include/sysemu/hw_accel.h
> > >
> >
> > The commit itself looks sane but qemu starts to hang during BIOS boot
> > after I've applied it if I run it with hvf accel.
>
> Hi Roman,
> Thanks for reviewing the patches.
> If this is happening, then I assume patches are not ready
> to be merged into qemu-stable.
> Do you have any idea why the problem is not detected
> during tests, but rather at runtime?
> I am not really sure if this patch (2/2) has anything to do with
> the problem but the previous patch (1/2) might.
>
I've applied, built and tested both sequentially. Applying and running
with patch 1/2 alone doesn't result in the behavior I mentioned. I also
tried to apply only the first hunk that moves hvf_cpu_synchronize_state
into cpu_synchronize_state and it also causes the issue with BIOS.
Honestly, I don't know if the tests run qemu with hvf accel. AFAIK
kvm-unit-tests can be used to test an accel itself.
Thanks,
Roman
^ permalink raw reply
* Re: [Qemu-devel] [PATCH v5 2/5] virtio-pmem: Add virtio pmem driver
From: Pankaj Gupta @ 2019-04-10 14:03 UTC (permalink / raw)
To: Michael S. Tsirkin
Cc: jack-AlSwsSmVLrQ, kvm-u79uwXL29TY76Z2rM5mHXA,
david-H+wXaHxf7aLQT0dZR+AlfA, jasowang-H+wXaHxf7aLQT0dZR+AlfA,
david-FqsqvQoI3Ljby3iVrkZq2A, qemu-devel-qX2TKyscuCcdnm+yROfE0A,
virtualization-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA,
adilger kernel, zwisler-DgEjT+Ai2ygdnm+yROfE0A,
aarcange-H+wXaHxf7aLQT0dZR+AlfA,
linux-nvdimm-hn68Rpc1hR1g9hUCZPvPmw, willy-wEGCiKHe2LqWVfeAwA7xHQ,
hch-wEGCiKHe2LqWVfeAwA7xHQ, linux-acpi-u79uwXL29TY76Z2rM5mHXA,
linux-ext4-u79uwXL29TY76Z2rM5mHXA, lenb-DgEjT+Ai2ygdnm+yROfE0A,
kilobyte-b9QjgO8OEXPVItvQsEIGlw, riel-ebMLmSuQjDVBDgjK7y7TUQ,
yuval shaia, stefanha-H+wXaHxf7aLQT0dZR+AlfA,
imammedo-H+wXaHxf7aLQT0dZR+AlfA,
lcapitulino-H+wXaHxf7aLQT0dZR+AlfA, kwolf-H+wXaHxf7aLQT0dZR+AlfA,
nilal-H+wXaHxf7aLQT0dZR+AlfA, tytso-3s7WtUTddSA,
xiaoguangrong eric, cohuck-H+wXaHxf7aLQT0dZR+AlfA,
rjw-LthD3rsA81gm4RdzfppkhA, linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-xfs-u79uwXL29TY76Z2rM5mHXA,
linux-fsdevel-u79uwXL29TY76Z2rM5mHXA,
pbonzini-H+wXaHxf7aLQT0dZR+AlfA, darrick wong
In-Reply-To: <20190410091216-mutt-send-email-mst-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
>
> On Wed, Apr 10, 2019 at 09:38:22AM +0530, Pankaj Gupta wrote:
> > This patch adds virtio-pmem driver for KVM guest.
> >
> > Guest reads the persistent memory range information from
> > Qemu over VIRTIO and registers it on nvdimm_bus. It also
> > creates a nd_region object with the persistent memory
> > range information so that existing 'nvdimm/pmem' driver
> > can reserve this into system memory map. This way
> > 'virtio-pmem' driver uses existing functionality of pmem
> > driver to register persistent memory compatible for DAX
> > capable filesystems.
> >
> > This also provides function to perform guest flush over
> > VIRTIO from 'pmem' driver when userspace performs flush
> > on DAX memory range.
> >
> > Signed-off-by: Pankaj Gupta <pagupta-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
> > ---
> > drivers/nvdimm/virtio_pmem.c | 88 ++++++++++++++++++++++
> > drivers/virtio/Kconfig | 10 +++
> > drivers/virtio/Makefile | 1 +
> > drivers/virtio/pmem.c | 124 +++++++++++++++++++++++++++++++
> > include/linux/virtio_pmem.h | 60 +++++++++++++++
> > include/uapi/linux/virtio_ids.h | 1 +
> > include/uapi/linux/virtio_pmem.h | 10 +++
> > 7 files changed, 294 insertions(+)
> > create mode 100644 drivers/nvdimm/virtio_pmem.c
> > create mode 100644 drivers/virtio/pmem.c
> > create mode 100644 include/linux/virtio_pmem.h
> > create mode 100644 include/uapi/linux/virtio_pmem.h
> >
> > diff --git a/drivers/nvdimm/virtio_pmem.c b/drivers/nvdimm/virtio_pmem.c
> > new file mode 100644
> > index 000000000000..01044cc2f3a3
> > --- /dev/null
> > +++ b/drivers/nvdimm/virtio_pmem.c
> > @@ -0,0 +1,88 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + * virtio_pmem.c: Virtio pmem Driver
> > + *
> > + * Discovers persistent memory range information
> > + * from host and provides a virtio based flushing
> > + * interface.
> > + */
> > +#include <linux/virtio_pmem.h>
> > +#include "nd.h"
> > +
> > + /* The interrupt handler */
> > +void host_ack(struct virtqueue *vq)
> > +{
> > + unsigned int len;
> > + unsigned long flags;
> > + struct virtio_pmem_request *req, *req_buf;
> > + struct virtio_pmem *vpmem = vq->vdev->priv;
> > +
> > + spin_lock_irqsave(&vpmem->pmem_lock, flags);
> > + while ((req = virtqueue_get_buf(vq, &len)) != NULL) {
> > + req->done = true;
> > + wake_up(&req->host_acked);
> > +
> > + if (!list_empty(&vpmem->req_list)) {
> > + req_buf = list_first_entry(&vpmem->req_list,
> > + struct virtio_pmem_request, list);
> > + list_del(&vpmem->req_list);
> > + req_buf->wq_buf_avail = true;
> > + wake_up(&req_buf->wq_buf);
> > + }
> > + }
> > + spin_unlock_irqrestore(&vpmem->pmem_lock, flags);
> > +}
> > +EXPORT_SYMBOL_GPL(host_ack);
> > +
> > + /* The request submission function */
> > +int virtio_pmem_flush(struct nd_region *nd_region)
> > +{
> > + int err;
> > + unsigned long flags;
> > + struct scatterlist *sgs[2], sg, ret;
> > + struct virtio_device *vdev = nd_region->provider_data;
> > + struct virtio_pmem *vpmem = vdev->priv;
> > + struct virtio_pmem_request *req;
> > +
> > + might_sleep();
> > + req = kmalloc(sizeof(*req), GFP_KERNEL);
> > + if (!req)
> > + return -ENOMEM;
> > +
> > + req->done = req->wq_buf_avail = false;
> > + strcpy(req->name, "FLUSH");
> > + init_waitqueue_head(&req->host_acked);
> > + init_waitqueue_head(&req->wq_buf);
> > + sg_init_one(&sg, req->name, strlen(req->name));
> > + sgs[0] = &sg;
> > + sg_init_one(&ret, &req->ret, sizeof(req->ret));
> > + sgs[1] = &ret;
> > +
> > + spin_lock_irqsave(&vpmem->pmem_lock, flags);
> > + err = virtqueue_add_sgs(vpmem->req_vq, sgs, 1, 1, req, GFP_ATOMIC);
> > + if (err) {
> > + dev_err(&vdev->dev, "failed to send command to virtio pmem device\n");
> > +
> > + list_add_tail(&vpmem->req_list, &req->list);
> > + spin_unlock_irqrestore(&vpmem->pmem_lock, flags);
> > +
> > + /* When host has read buffer, this completes via host_ack */
> > + wait_event(req->wq_buf, req->wq_buf_avail);
> > + spin_lock_irqsave(&vpmem->pmem_lock, flags);
> > + }
> > + err = virtqueue_kick(vpmem->req_vq);
> > + spin_unlock_irqrestore(&vpmem->pmem_lock, flags);
> > +
> > + if (!err) {
> > + err = -EIO;
> > + goto ret;
> > + }
> > + /* When host has read buffer, this completes via host_ack */
> > + wait_event(req->host_acked, req->done);
> > + err = req->ret;
> > +ret:
> > + kfree(req);
> > + return err;
> > +};
> > +EXPORT_SYMBOL_GPL(virtio_pmem_flush);
> > +MODULE_LICENSE("GPL");
> > diff --git a/drivers/virtio/Kconfig b/drivers/virtio/Kconfig
> > index 35897649c24f..9f634a2ed638 100644
> > --- a/drivers/virtio/Kconfig
> > +++ b/drivers/virtio/Kconfig
> > @@ -42,6 +42,16 @@ config VIRTIO_PCI_LEGACY
> >
> > If unsure, say Y.
> >
> > +config VIRTIO_PMEM
> > + tristate "Support for virtio pmem driver"
> > + depends on VIRTIO
> > + depends on LIBNVDIMM
> > + help
> > + This driver provides support for virtio based flushing interface
> > + for persistent memory range.
> > +
> > + If unsure, say M.
> > +
> > config VIRTIO_BALLOON
> > tristate "Virtio balloon driver"
> > depends on VIRTIO
> > diff --git a/drivers/virtio/Makefile b/drivers/virtio/Makefile
> > index 3a2b5c5dcf46..143ce91eabe9 100644
> > --- a/drivers/virtio/Makefile
> > +++ b/drivers/virtio/Makefile
> > @@ -6,3 +6,4 @@ virtio_pci-y := virtio_pci_modern.o virtio_pci_common.o
> > virtio_pci-$(CONFIG_VIRTIO_PCI_LEGACY) += virtio_pci_legacy.o
> > obj-$(CONFIG_VIRTIO_BALLOON) += virtio_balloon.o
> > obj-$(CONFIG_VIRTIO_INPUT) += virtio_input.o
> > +obj-$(CONFIG_VIRTIO_PMEM) += pmem.o ../nvdimm/virtio_pmem.o
> > diff --git a/drivers/virtio/pmem.c b/drivers/virtio/pmem.c
> > new file mode 100644
> > index 000000000000..cc9de9589d56
> > --- /dev/null
> > +++ b/drivers/virtio/pmem.c
> > @@ -0,0 +1,124 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + * virtio_pmem.c: Virtio pmem Driver
> > + *
> > + * Discovers persistent memory range information
> > + * from host and registers the virtual pmem device
> > + * with libnvdimm core.
> > + */
> > +#include <linux/virtio_pmem.h>
> > +#include <../../drivers/nvdimm/nd.h>
> > +
> > +static struct virtio_device_id id_table[] = {
> > + { VIRTIO_ID_PMEM, VIRTIO_DEV_ANY_ID },
> > + { 0 },
> > +};
> > +
> > + /* Initialize virt queue */
> > +static int init_vq(struct virtio_pmem *vpmem)
> > +{
> > + struct virtqueue *vq;
> > +
> > + /* single vq */
> > + vpmem->req_vq = vq = virtio_find_single_vq(vpmem->vdev,
> > + host_ack, "flush_queue");
> > + if (IS_ERR(vq))
> > + return PTR_ERR(vq);
> > +
> > + spin_lock_init(&vpmem->pmem_lock);
> > + INIT_LIST_HEAD(&vpmem->req_list);
> > +
> > + return 0;
> > +};
> > +
> > +static int virtio_pmem_probe(struct virtio_device *vdev)
> > +{
> > + int err = 0;
> > + struct resource res;
> > + struct virtio_pmem *vpmem;
> > + struct nvdimm_bus *nvdimm_bus;
> > + struct nd_region_desc ndr_desc = {};
> > + int nid = dev_to_node(&vdev->dev);
> > + struct nd_region *nd_region;
> > +
> > + if (!vdev->config->get) {
> > + dev_err(&vdev->dev, "%s failure: config disabled\n",
> > + __func__);
> > + return -EINVAL;
> > + }
> > +
> > + vdev->priv = vpmem = devm_kzalloc(&vdev->dev, sizeof(*vpmem),
> > + GFP_KERNEL);
> > + if (!vpmem) {
> > + err = -ENOMEM;
> > + goto out_err;
> > + }
> > +
> > + vpmem->vdev = vdev;
> > + err = init_vq(vpmem);
> > + if (err)
> > + goto out_err;
> > +
> > + virtio_cread(vpmem->vdev, struct virtio_pmem_config,
> > + start, &vpmem->start);
> > + virtio_cread(vpmem->vdev, struct virtio_pmem_config,
> > + size, &vpmem->size);
> > +
> > + res.start = vpmem->start;
> > + res.end = vpmem->start + vpmem->size-1;
> > + vpmem->nd_desc.provider_name = "virtio-pmem";
> > + vpmem->nd_desc.module = THIS_MODULE;
> > +
> > + vpmem->nvdimm_bus = nvdimm_bus = nvdimm_bus_register(&vdev->dev,
> > + &vpmem->nd_desc);
> > + if (!nvdimm_bus)
> > + goto out_vq;
> > +
> > + dev_set_drvdata(&vdev->dev, nvdimm_bus);
> > +
> > + ndr_desc.res = &res;
> > + ndr_desc.numa_node = nid;
> > + ndr_desc.flush = virtio_pmem_flush;
> > + set_bit(ND_REGION_PAGEMAP, &ndr_desc.flags);
> > + set_bit(ND_REGION_ASYNC, &ndr_desc.flags);
> > + nd_region = nvdimm_pmem_region_create(nvdimm_bus, &ndr_desc);
> > + nd_region->provider_data = dev_to_virtio
> > + (nd_region->dev.parent->parent);
> > +
> > + if (!nd_region)
> > + goto out_nd;
> > +
> > + return 0;
> > +out_nd:
> > + err = -ENXIO;
> > + nvdimm_bus_unregister(nvdimm_bus);
> > +out_vq:
> > + vdev->config->del_vqs(vdev);
> > +out_err:
> > + dev_err(&vdev->dev, "failed to register virtio pmem memory\n");
> > + return err;
> > +}
> > +
> > +static void virtio_pmem_remove(struct virtio_device *vdev)
> > +{
> > + struct virtio_pmem *vpmem = vdev->priv;
> > + struct nvdimm_bus *nvdimm_bus = dev_get_drvdata(&vdev->dev);
> > +
> > + nvdimm_bus_unregister(nvdimm_bus);
> > + vdev->config->del_vqs(vdev);
> > + vdev->config->reset(vdev);
> > + kfree(vpmem);
> > +}
> > +
> > +static struct virtio_driver virtio_pmem_driver = {
> > + .driver.name = KBUILD_MODNAME,
> > + .driver.owner = THIS_MODULE,
> > + .id_table = id_table,
> > + .probe = virtio_pmem_probe,
> > + .remove = virtio_pmem_remove,
> > +};
> > +
> > +module_virtio_driver(virtio_pmem_driver);
> > +MODULE_DEVICE_TABLE(virtio, id_table);
> > +MODULE_DESCRIPTION("Virtio pmem driver");
> > +MODULE_LICENSE("GPL");
> > diff --git a/include/linux/virtio_pmem.h b/include/linux/virtio_pmem.h
> > new file mode 100644
> > index 000000000000..224f9d934be6
> > --- /dev/null
> > +++ b/include/linux/virtio_pmem.h
> > @@ -0,0 +1,60 @@
> > +/* SPDX-License-Identifier: GPL-2.0 */
> > +/*
> > + * virtio_pmem.h: virtio pmem Driver
> > + *
> > + * Discovers persistent memory range information
> > + * from host and provides a virtio based flushing
> > + * interface.
> > + **/
> > +
> > +#ifndef _LINUX_VIRTIO_PMEM_H
> > +#define _LINUX_VIRTIO_PMEM_H
> > +
> > +#include <linux/virtio_ids.h>
> > +#include <linux/module.h>
> > +#include <linux/virtio_config.h>
> > +#include <uapi/linux/virtio_pmem.h>
> > +#include <linux/libnvdimm.h>
> > +#include <linux/spinlock.h>
> > +
> > +struct virtio_pmem_request {
> > + /* Host return status corresponding to flush request */
> > + int ret;
> > +
> > + /* command name*/
> > + char name[16];
> > +
> > + /* Wait queue to process deferred work after ack from host */
> > + wait_queue_head_t host_acked;
> > + bool done;
> > +
> > + /* Wait queue to process deferred work after virt queue buffer avail */
> > + wait_queue_head_t wq_buf;
> > + bool wq_buf_avail;
> > + struct list_head list;
> > +};
> > +
> > +struct virtio_pmem {
> > + struct virtio_device *vdev;
> > +
> > + /* Virtio pmem request queue */
> > + struct virtqueue *req_vq;
> > +
> > + /* nvdimm bus registers virtio pmem device */
> > + struct nvdimm_bus *nvdimm_bus;
> > + struct nvdimm_bus_descriptor nd_desc;
> > +
> > + /* List to store deferred work if virtqueue is full */
> > + struct list_head req_list;
> > +
> > + /* Synchronize virtqueue data */
> > + spinlock_t pmem_lock;
> > +
> > + /* Memory region information */
> > + uint64_t start;
> > + uint64_t size;
> > +};
> > +
> > +void host_ack(struct virtqueue *vq);
> > +int virtio_pmem_flush(struct nd_region *nd_region);
> > +#endif
> > diff --git a/include/uapi/linux/virtio_ids.h
> > b/include/uapi/linux/virtio_ids.h
> > index 6d5c3b2d4f4d..346389565ac1 100644
> > --- a/include/uapi/linux/virtio_ids.h
> > +++ b/include/uapi/linux/virtio_ids.h
> > @@ -43,5 +43,6 @@
> > #define VIRTIO_ID_INPUT 18 /* virtio input */
> > #define VIRTIO_ID_VSOCK 19 /* virtio vsock transport */
> > #define VIRTIO_ID_CRYPTO 20 /* virtio crypto */
> > +#define VIRTIO_ID_PMEM 25 /* virtio pmem */
> >
> > #endif /* _LINUX_VIRTIO_IDS_H */
>
> Didn't Paolo point out someone is using 25 for audio?
Sorry! I did not notice this.
>
> Please, reserve an ID with the Virtio TC before using it.
I thought I requested[1] ID 25.
[1] https://github.com/oasis-tcs/virtio-spec/issues/38
[2] https://lists.oasis-open.org/archives/virtio-dev/201805/threads.html
In that case I will send request for next available ID i.e 26?
Thanks,
Pankaj
>
> > diff --git a/include/uapi/linux/virtio_pmem.h
> > b/include/uapi/linux/virtio_pmem.h
> > new file mode 100644
> > index 000000000000..fa3f7d52717a
> > --- /dev/null
> > +++ b/include/uapi/linux/virtio_pmem.h
> > @@ -0,0 +1,10 @@
> > +/* SPDX-License-Identifier: GPL-2.0 */
> > +
> > +#ifndef _UAPI_LINUX_VIRTIO_PMEM_H
> > +#define _UAPI_LINUX_VIRTIO_PMEM_H
> > +
> > +struct virtio_pmem_config {
> > + __le64 start;
> > + __le64 size;
> > +};
> > +#endif
> > --
> > 2.20.1
>
>
^ permalink raw reply
* Re: [Qemu-devel] [PATCH v5 2/5] virtio-pmem: Add virtio pmem driver
From: Pankaj Gupta @ 2019-04-10 14:03 UTC (permalink / raw)
To: Michael S. Tsirkin
Cc: jack, kvm, david, qemu-devel, virtualization, adilger kernel,
zwisler, aarcange, dave jiang, linux-nvdimm, vishal l verma,
willy, hch, linux-acpi, jmoyer, linux-ext4, lenb, kilobyte, riel,
yuval shaia, stefanha, imammedo, dan j williams, lcapitulino,
nilal, tytso, xiaoguangrong eric, cohuck, rjw, linux-kernel,
linux-xfs, linux-fsdevel, pbonzini, darrick wong <darric>
In-Reply-To: <20190410091216-mutt-send-email-mst@kernel.org>
>
> On Wed, Apr 10, 2019 at 09:38:22AM +0530, Pankaj Gupta wrote:
> > This patch adds virtio-pmem driver for KVM guest.
> >
> > Guest reads the persistent memory range information from
> > Qemu over VIRTIO and registers it on nvdimm_bus. It also
> > creates a nd_region object with the persistent memory
> > range information so that existing 'nvdimm/pmem' driver
> > can reserve this into system memory map. This way
> > 'virtio-pmem' driver uses existing functionality of pmem
> > driver to register persistent memory compatible for DAX
> > capable filesystems.
> >
> > This also provides function to perform guest flush over
> > VIRTIO from 'pmem' driver when userspace performs flush
> > on DAX memory range.
> >
> > Signed-off-by: Pankaj Gupta <pagupta@redhat.com>
> > ---
> > drivers/nvdimm/virtio_pmem.c | 88 ++++++++++++++++++++++
> > drivers/virtio/Kconfig | 10 +++
> > drivers/virtio/Makefile | 1 +
> > drivers/virtio/pmem.c | 124 +++++++++++++++++++++++++++++++
> > include/linux/virtio_pmem.h | 60 +++++++++++++++
> > include/uapi/linux/virtio_ids.h | 1 +
> > include/uapi/linux/virtio_pmem.h | 10 +++
> > 7 files changed, 294 insertions(+)
> > create mode 100644 drivers/nvdimm/virtio_pmem.c
> > create mode 100644 drivers/virtio/pmem.c
> > create mode 100644 include/linux/virtio_pmem.h
> > create mode 100644 include/uapi/linux/virtio_pmem.h
> >
> > diff --git a/drivers/nvdimm/virtio_pmem.c b/drivers/nvdimm/virtio_pmem.c
> > new file mode 100644
> > index 000000000000..01044cc2f3a3
> > --- /dev/null
> > +++ b/drivers/nvdimm/virtio_pmem.c
> > @@ -0,0 +1,88 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + * virtio_pmem.c: Virtio pmem Driver
> > + *
> > + * Discovers persistent memory range information
> > + * from host and provides a virtio based flushing
> > + * interface.
> > + */
> > +#include <linux/virtio_pmem.h>
> > +#include "nd.h"
> > +
> > + /* The interrupt handler */
> > +void host_ack(struct virtqueue *vq)
> > +{
> > + unsigned int len;
> > + unsigned long flags;
> > + struct virtio_pmem_request *req, *req_buf;
> > + struct virtio_pmem *vpmem = vq->vdev->priv;
> > +
> > + spin_lock_irqsave(&vpmem->pmem_lock, flags);
> > + while ((req = virtqueue_get_buf(vq, &len)) != NULL) {
> > + req->done = true;
> > + wake_up(&req->host_acked);
> > +
> > + if (!list_empty(&vpmem->req_list)) {
> > + req_buf = list_first_entry(&vpmem->req_list,
> > + struct virtio_pmem_request, list);
> > + list_del(&vpmem->req_list);
> > + req_buf->wq_buf_avail = true;
> > + wake_up(&req_buf->wq_buf);
> > + }
> > + }
> > + spin_unlock_irqrestore(&vpmem->pmem_lock, flags);
> > +}
> > +EXPORT_SYMBOL_GPL(host_ack);
> > +
> > + /* The request submission function */
> > +int virtio_pmem_flush(struct nd_region *nd_region)
> > +{
> > + int err;
> > + unsigned long flags;
> > + struct scatterlist *sgs[2], sg, ret;
> > + struct virtio_device *vdev = nd_region->provider_data;
> > + struct virtio_pmem *vpmem = vdev->priv;
> > + struct virtio_pmem_request *req;
> > +
> > + might_sleep();
> > + req = kmalloc(sizeof(*req), GFP_KERNEL);
> > + if (!req)
> > + return -ENOMEM;
> > +
> > + req->done = req->wq_buf_avail = false;
> > + strcpy(req->name, "FLUSH");
> > + init_waitqueue_head(&req->host_acked);
> > + init_waitqueue_head(&req->wq_buf);
> > + sg_init_one(&sg, req->name, strlen(req->name));
> > + sgs[0] = &sg;
> > + sg_init_one(&ret, &req->ret, sizeof(req->ret));
> > + sgs[1] = &ret;
> > +
> > + spin_lock_irqsave(&vpmem->pmem_lock, flags);
> > + err = virtqueue_add_sgs(vpmem->req_vq, sgs, 1, 1, req, GFP_ATOMIC);
> > + if (err) {
> > + dev_err(&vdev->dev, "failed to send command to virtio pmem device\n");
> > +
> > + list_add_tail(&vpmem->req_list, &req->list);
> > + spin_unlock_irqrestore(&vpmem->pmem_lock, flags);
> > +
> > + /* When host has read buffer, this completes via host_ack */
> > + wait_event(req->wq_buf, req->wq_buf_avail);
> > + spin_lock_irqsave(&vpmem->pmem_lock, flags);
> > + }
> > + err = virtqueue_kick(vpmem->req_vq);
> > + spin_unlock_irqrestore(&vpmem->pmem_lock, flags);
> > +
> > + if (!err) {
> > + err = -EIO;
> > + goto ret;
> > + }
> > + /* When host has read buffer, this completes via host_ack */
> > + wait_event(req->host_acked, req->done);
> > + err = req->ret;
> > +ret:
> > + kfree(req);
> > + return err;
> > +};
> > +EXPORT_SYMBOL_GPL(virtio_pmem_flush);
> > +MODULE_LICENSE("GPL");
> > diff --git a/drivers/virtio/Kconfig b/drivers/virtio/Kconfig
> > index 35897649c24f..9f634a2ed638 100644
> > --- a/drivers/virtio/Kconfig
> > +++ b/drivers/virtio/Kconfig
> > @@ -42,6 +42,16 @@ config VIRTIO_PCI_LEGACY
> >
> > If unsure, say Y.
> >
> > +config VIRTIO_PMEM
> > + tristate "Support for virtio pmem driver"
> > + depends on VIRTIO
> > + depends on LIBNVDIMM
> > + help
> > + This driver provides support for virtio based flushing interface
> > + for persistent memory range.
> > +
> > + If unsure, say M.
> > +
> > config VIRTIO_BALLOON
> > tristate "Virtio balloon driver"
> > depends on VIRTIO
> > diff --git a/drivers/virtio/Makefile b/drivers/virtio/Makefile
> > index 3a2b5c5dcf46..143ce91eabe9 100644
> > --- a/drivers/virtio/Makefile
> > +++ b/drivers/virtio/Makefile
> > @@ -6,3 +6,4 @@ virtio_pci-y := virtio_pci_modern.o virtio_pci_common.o
> > virtio_pci-$(CONFIG_VIRTIO_PCI_LEGACY) += virtio_pci_legacy.o
> > obj-$(CONFIG_VIRTIO_BALLOON) += virtio_balloon.o
> > obj-$(CONFIG_VIRTIO_INPUT) += virtio_input.o
> > +obj-$(CONFIG_VIRTIO_PMEM) += pmem.o ../nvdimm/virtio_pmem.o
> > diff --git a/drivers/virtio/pmem.c b/drivers/virtio/pmem.c
> > new file mode 100644
> > index 000000000000..cc9de9589d56
> > --- /dev/null
> > +++ b/drivers/virtio/pmem.c
> > @@ -0,0 +1,124 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + * virtio_pmem.c: Virtio pmem Driver
> > + *
> > + * Discovers persistent memory range information
> > + * from host and registers the virtual pmem device
> > + * with libnvdimm core.
> > + */
> > +#include <linux/virtio_pmem.h>
> > +#include <../../drivers/nvdimm/nd.h>
> > +
> > +static struct virtio_device_id id_table[] = {
> > + { VIRTIO_ID_PMEM, VIRTIO_DEV_ANY_ID },
> > + { 0 },
> > +};
> > +
> > + /* Initialize virt queue */
> > +static int init_vq(struct virtio_pmem *vpmem)
> > +{
> > + struct virtqueue *vq;
> > +
> > + /* single vq */
> > + vpmem->req_vq = vq = virtio_find_single_vq(vpmem->vdev,
> > + host_ack, "flush_queue");
> > + if (IS_ERR(vq))
> > + return PTR_ERR(vq);
> > +
> > + spin_lock_init(&vpmem->pmem_lock);
> > + INIT_LIST_HEAD(&vpmem->req_list);
> > +
> > + return 0;
> > +};
> > +
> > +static int virtio_pmem_probe(struct virtio_device *vdev)
> > +{
> > + int err = 0;
> > + struct resource res;
> > + struct virtio_pmem *vpmem;
> > + struct nvdimm_bus *nvdimm_bus;
> > + struct nd_region_desc ndr_desc = {};
> > + int nid = dev_to_node(&vdev->dev);
> > + struct nd_region *nd_region;
> > +
> > + if (!vdev->config->get) {
> > + dev_err(&vdev->dev, "%s failure: config disabled\n",
> > + __func__);
> > + return -EINVAL;
> > + }
> > +
> > + vdev->priv = vpmem = devm_kzalloc(&vdev->dev, sizeof(*vpmem),
> > + GFP_KERNEL);
> > + if (!vpmem) {
> > + err = -ENOMEM;
> > + goto out_err;
> > + }
> > +
> > + vpmem->vdev = vdev;
> > + err = init_vq(vpmem);
> > + if (err)
> > + goto out_err;
> > +
> > + virtio_cread(vpmem->vdev, struct virtio_pmem_config,
> > + start, &vpmem->start);
> > + virtio_cread(vpmem->vdev, struct virtio_pmem_config,
> > + size, &vpmem->size);
> > +
> > + res.start = vpmem->start;
> > + res.end = vpmem->start + vpmem->size-1;
> > + vpmem->nd_desc.provider_name = "virtio-pmem";
> > + vpmem->nd_desc.module = THIS_MODULE;
> > +
> > + vpmem->nvdimm_bus = nvdimm_bus = nvdimm_bus_register(&vdev->dev,
> > + &vpmem->nd_desc);
> > + if (!nvdimm_bus)
> > + goto out_vq;
> > +
> > + dev_set_drvdata(&vdev->dev, nvdimm_bus);
> > +
> > + ndr_desc.res = &res;
> > + ndr_desc.numa_node = nid;
> > + ndr_desc.flush = virtio_pmem_flush;
> > + set_bit(ND_REGION_PAGEMAP, &ndr_desc.flags);
> > + set_bit(ND_REGION_ASYNC, &ndr_desc.flags);
> > + nd_region = nvdimm_pmem_region_create(nvdimm_bus, &ndr_desc);
> > + nd_region->provider_data = dev_to_virtio
> > + (nd_region->dev.parent->parent);
> > +
> > + if (!nd_region)
> > + goto out_nd;
> > +
> > + return 0;
> > +out_nd:
> > + err = -ENXIO;
> > + nvdimm_bus_unregister(nvdimm_bus);
> > +out_vq:
> > + vdev->config->del_vqs(vdev);
> > +out_err:
> > + dev_err(&vdev->dev, "failed to register virtio pmem memory\n");
> > + return err;
> > +}
> > +
> > +static void virtio_pmem_remove(struct virtio_device *vdev)
> > +{
> > + struct virtio_pmem *vpmem = vdev->priv;
> > + struct nvdimm_bus *nvdimm_bus = dev_get_drvdata(&vdev->dev);
> > +
> > + nvdimm_bus_unregister(nvdimm_bus);
> > + vdev->config->del_vqs(vdev);
> > + vdev->config->reset(vdev);
> > + kfree(vpmem);
> > +}
> > +
> > +static struct virtio_driver virtio_pmem_driver = {
> > + .driver.name = KBUILD_MODNAME,
> > + .driver.owner = THIS_MODULE,
> > + .id_table = id_table,
> > + .probe = virtio_pmem_probe,
> > + .remove = virtio_pmem_remove,
> > +};
> > +
> > +module_virtio_driver(virtio_pmem_driver);
> > +MODULE_DEVICE_TABLE(virtio, id_table);
> > +MODULE_DESCRIPTION("Virtio pmem driver");
> > +MODULE_LICENSE("GPL");
> > diff --git a/include/linux/virtio_pmem.h b/include/linux/virtio_pmem.h
> > new file mode 100644
> > index 000000000000..224f9d934be6
> > --- /dev/null
> > +++ b/include/linux/virtio_pmem.h
> > @@ -0,0 +1,60 @@
> > +/* SPDX-License-Identifier: GPL-2.0 */
> > +/*
> > + * virtio_pmem.h: virtio pmem Driver
> > + *
> > + * Discovers persistent memory range information
> > + * from host and provides a virtio based flushing
> > + * interface.
> > + **/
> > +
> > +#ifndef _LINUX_VIRTIO_PMEM_H
> > +#define _LINUX_VIRTIO_PMEM_H
> > +
> > +#include <linux/virtio_ids.h>
> > +#include <linux/module.h>
> > +#include <linux/virtio_config.h>
> > +#include <uapi/linux/virtio_pmem.h>
> > +#include <linux/libnvdimm.h>
> > +#include <linux/spinlock.h>
> > +
> > +struct virtio_pmem_request {
> > + /* Host return status corresponding to flush request */
> > + int ret;
> > +
> > + /* command name*/
> > + char name[16];
> > +
> > + /* Wait queue to process deferred work after ack from host */
> > + wait_queue_head_t host_acked;
> > + bool done;
> > +
> > + /* Wait queue to process deferred work after virt queue buffer avail */
> > + wait_queue_head_t wq_buf;
> > + bool wq_buf_avail;
> > + struct list_head list;
> > +};
> > +
> > +struct virtio_pmem {
> > + struct virtio_device *vdev;
> > +
> > + /* Virtio pmem request queue */
> > + struct virtqueue *req_vq;
> > +
> > + /* nvdimm bus registers virtio pmem device */
> > + struct nvdimm_bus *nvdimm_bus;
> > + struct nvdimm_bus_descriptor nd_desc;
> > +
> > + /* List to store deferred work if virtqueue is full */
> > + struct list_head req_list;
> > +
> > + /* Synchronize virtqueue data */
> > + spinlock_t pmem_lock;
> > +
> > + /* Memory region information */
> > + uint64_t start;
> > + uint64_t size;
> > +};
> > +
> > +void host_ack(struct virtqueue *vq);
> > +int virtio_pmem_flush(struct nd_region *nd_region);
> > +#endif
> > diff --git a/include/uapi/linux/virtio_ids.h
> > b/include/uapi/linux/virtio_ids.h
> > index 6d5c3b2d4f4d..346389565ac1 100644
> > --- a/include/uapi/linux/virtio_ids.h
> > +++ b/include/uapi/linux/virtio_ids.h
> > @@ -43,5 +43,6 @@
> > #define VIRTIO_ID_INPUT 18 /* virtio input */
> > #define VIRTIO_ID_VSOCK 19 /* virtio vsock transport */
> > #define VIRTIO_ID_CRYPTO 20 /* virtio crypto */
> > +#define VIRTIO_ID_PMEM 25 /* virtio pmem */
> >
> > #endif /* _LINUX_VIRTIO_IDS_H */
>
> Didn't Paolo point out someone is using 25 for audio?
Sorry! I did not notice this.
>
> Please, reserve an ID with the Virtio TC before using it.
I thought I requested[1] ID 25.
[1] https://github.com/oasis-tcs/virtio-spec/issues/38
[2] https://lists.oasis-open.org/archives/virtio-dev/201805/threads.html
In that case I will send request for next available ID i.e 26?
Thanks,
Pankaj
>
> > diff --git a/include/uapi/linux/virtio_pmem.h
> > b/include/uapi/linux/virtio_pmem.h
> > new file mode 100644
> > index 000000000000..fa3f7d52717a
> > --- /dev/null
> > +++ b/include/uapi/linux/virtio_pmem.h
> > @@ -0,0 +1,10 @@
> > +/* SPDX-License-Identifier: GPL-2.0 */
> > +
> > +#ifndef _UAPI_LINUX_VIRTIO_PMEM_H
> > +#define _UAPI_LINUX_VIRTIO_PMEM_H
> > +
> > +struct virtio_pmem_config {
> > + __le64 start;
> > + __le64 size;
> > +};
> > +#endif
> > --
> > 2.20.1
>
>
^ permalink raw reply
* Re: [Qemu-devel] [PATCH v5 2/5] virtio-pmem: Add virtio pmem driver
From: Pankaj Gupta @ 2019-04-10 14:03 UTC (permalink / raw)
To: Michael S. Tsirkin
Cc: jack, kvm, david, jasowang, david, qemu-devel, virtualization,
adilger kernel, zwisler, aarcange, linux-nvdimm, willy, hch,
linux-acpi, linux-ext4, lenb, kilobyte, riel, yuval shaia,
stefanha, imammedo, lcapitulino, kwolf, nilal, tytso,
xiaoguangrong eric, cohuck, rjw, linux-kernel, linux-xfs,
linux-fsdevel, pbonzini, darrick wong
In-Reply-To: <20190410091216-mutt-send-email-mst@kernel.org>
>
> On Wed, Apr 10, 2019 at 09:38:22AM +0530, Pankaj Gupta wrote:
> > This patch adds virtio-pmem driver for KVM guest.
> >
> > Guest reads the persistent memory range information from
> > Qemu over VIRTIO and registers it on nvdimm_bus. It also
> > creates a nd_region object with the persistent memory
> > range information so that existing 'nvdimm/pmem' driver
> > can reserve this into system memory map. This way
> > 'virtio-pmem' driver uses existing functionality of pmem
> > driver to register persistent memory compatible for DAX
> > capable filesystems.
> >
> > This also provides function to perform guest flush over
> > VIRTIO from 'pmem' driver when userspace performs flush
> > on DAX memory range.
> >
> > Signed-off-by: Pankaj Gupta <pagupta@redhat.com>
> > ---
> > drivers/nvdimm/virtio_pmem.c | 88 ++++++++++++++++++++++
> > drivers/virtio/Kconfig | 10 +++
> > drivers/virtio/Makefile | 1 +
> > drivers/virtio/pmem.c | 124 +++++++++++++++++++++++++++++++
> > include/linux/virtio_pmem.h | 60 +++++++++++++++
> > include/uapi/linux/virtio_ids.h | 1 +
> > include/uapi/linux/virtio_pmem.h | 10 +++
> > 7 files changed, 294 insertions(+)
> > create mode 100644 drivers/nvdimm/virtio_pmem.c
> > create mode 100644 drivers/virtio/pmem.c
> > create mode 100644 include/linux/virtio_pmem.h
> > create mode 100644 include/uapi/linux/virtio_pmem.h
> >
> > diff --git a/drivers/nvdimm/virtio_pmem.c b/drivers/nvdimm/virtio_pmem.c
> > new file mode 100644
> > index 000000000000..01044cc2f3a3
> > --- /dev/null
> > +++ b/drivers/nvdimm/virtio_pmem.c
> > @@ -0,0 +1,88 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + * virtio_pmem.c: Virtio pmem Driver
> > + *
> > + * Discovers persistent memory range information
> > + * from host and provides a virtio based flushing
> > + * interface.
> > + */
> > +#include <linux/virtio_pmem.h>
> > +#include "nd.h"
> > +
> > + /* The interrupt handler */
> > +void host_ack(struct virtqueue *vq)
> > +{
> > + unsigned int len;
> > + unsigned long flags;
> > + struct virtio_pmem_request *req, *req_buf;
> > + struct virtio_pmem *vpmem = vq->vdev->priv;
> > +
> > + spin_lock_irqsave(&vpmem->pmem_lock, flags);
> > + while ((req = virtqueue_get_buf(vq, &len)) != NULL) {
> > + req->done = true;
> > + wake_up(&req->host_acked);
> > +
> > + if (!list_empty(&vpmem->req_list)) {
> > + req_buf = list_first_entry(&vpmem->req_list,
> > + struct virtio_pmem_request, list);
> > + list_del(&vpmem->req_list);
> > + req_buf->wq_buf_avail = true;
> > + wake_up(&req_buf->wq_buf);
> > + }
> > + }
> > + spin_unlock_irqrestore(&vpmem->pmem_lock, flags);
> > +}
> > +EXPORT_SYMBOL_GPL(host_ack);
> > +
> > + /* The request submission function */
> > +int virtio_pmem_flush(struct nd_region *nd_region)
> > +{
> > + int err;
> > + unsigned long flags;
> > + struct scatterlist *sgs[2], sg, ret;
> > + struct virtio_device *vdev = nd_region->provider_data;
> > + struct virtio_pmem *vpmem = vdev->priv;
> > + struct virtio_pmem_request *req;
> > +
> > + might_sleep();
> > + req = kmalloc(sizeof(*req), GFP_KERNEL);
> > + if (!req)
> > + return -ENOMEM;
> > +
> > + req->done = req->wq_buf_avail = false;
> > + strcpy(req->name, "FLUSH");
> > + init_waitqueue_head(&req->host_acked);
> > + init_waitqueue_head(&req->wq_buf);
> > + sg_init_one(&sg, req->name, strlen(req->name));
> > + sgs[0] = &sg;
> > + sg_init_one(&ret, &req->ret, sizeof(req->ret));
> > + sgs[1] = &ret;
> > +
> > + spin_lock_irqsave(&vpmem->pmem_lock, flags);
> > + err = virtqueue_add_sgs(vpmem->req_vq, sgs, 1, 1, req, GFP_ATOMIC);
> > + if (err) {
> > + dev_err(&vdev->dev, "failed to send command to virtio pmem device\n");
> > +
> > + list_add_tail(&vpmem->req_list, &req->list);
> > + spin_unlock_irqrestore(&vpmem->pmem_lock, flags);
> > +
> > + /* When host has read buffer, this completes via host_ack */
> > + wait_event(req->wq_buf, req->wq_buf_avail);
> > + spin_lock_irqsave(&vpmem->pmem_lock, flags);
> > + }
> > + err = virtqueue_kick(vpmem->req_vq);
> > + spin_unlock_irqrestore(&vpmem->pmem_lock, flags);
> > +
> > + if (!err) {
> > + err = -EIO;
> > + goto ret;
> > + }
> > + /* When host has read buffer, this completes via host_ack */
> > + wait_event(req->host_acked, req->done);
> > + err = req->ret;
> > +ret:
> > + kfree(req);
> > + return err;
> > +};
> > +EXPORT_SYMBOL_GPL(virtio_pmem_flush);
> > +MODULE_LICENSE("GPL");
> > diff --git a/drivers/virtio/Kconfig b/drivers/virtio/Kconfig
> > index 35897649c24f..9f634a2ed638 100644
> > --- a/drivers/virtio/Kconfig
> > +++ b/drivers/virtio/Kconfig
> > @@ -42,6 +42,16 @@ config VIRTIO_PCI_LEGACY
> >
> > If unsure, say Y.
> >
> > +config VIRTIO_PMEM
> > + tristate "Support for virtio pmem driver"
> > + depends on VIRTIO
> > + depends on LIBNVDIMM
> > + help
> > + This driver provides support for virtio based flushing interface
> > + for persistent memory range.
> > +
> > + If unsure, say M.
> > +
> > config VIRTIO_BALLOON
> > tristate "Virtio balloon driver"
> > depends on VIRTIO
> > diff --git a/drivers/virtio/Makefile b/drivers/virtio/Makefile
> > index 3a2b5c5dcf46..143ce91eabe9 100644
> > --- a/drivers/virtio/Makefile
> > +++ b/drivers/virtio/Makefile
> > @@ -6,3 +6,4 @@ virtio_pci-y := virtio_pci_modern.o virtio_pci_common.o
> > virtio_pci-$(CONFIG_VIRTIO_PCI_LEGACY) += virtio_pci_legacy.o
> > obj-$(CONFIG_VIRTIO_BALLOON) += virtio_balloon.o
> > obj-$(CONFIG_VIRTIO_INPUT) += virtio_input.o
> > +obj-$(CONFIG_VIRTIO_PMEM) += pmem.o ../nvdimm/virtio_pmem.o
> > diff --git a/drivers/virtio/pmem.c b/drivers/virtio/pmem.c
> > new file mode 100644
> > index 000000000000..cc9de9589d56
> > --- /dev/null
> > +++ b/drivers/virtio/pmem.c
> > @@ -0,0 +1,124 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + * virtio_pmem.c: Virtio pmem Driver
> > + *
> > + * Discovers persistent memory range information
> > + * from host and registers the virtual pmem device
> > + * with libnvdimm core.
> > + */
> > +#include <linux/virtio_pmem.h>
> > +#include <../../drivers/nvdimm/nd.h>
> > +
> > +static struct virtio_device_id id_table[] = {
> > + { VIRTIO_ID_PMEM, VIRTIO_DEV_ANY_ID },
> > + { 0 },
> > +};
> > +
> > + /* Initialize virt queue */
> > +static int init_vq(struct virtio_pmem *vpmem)
> > +{
> > + struct virtqueue *vq;
> > +
> > + /* single vq */
> > + vpmem->req_vq = vq = virtio_find_single_vq(vpmem->vdev,
> > + host_ack, "flush_queue");
> > + if (IS_ERR(vq))
> > + return PTR_ERR(vq);
> > +
> > + spin_lock_init(&vpmem->pmem_lock);
> > + INIT_LIST_HEAD(&vpmem->req_list);
> > +
> > + return 0;
> > +};
> > +
> > +static int virtio_pmem_probe(struct virtio_device *vdev)
> > +{
> > + int err = 0;
> > + struct resource res;
> > + struct virtio_pmem *vpmem;
> > + struct nvdimm_bus *nvdimm_bus;
> > + struct nd_region_desc ndr_desc = {};
> > + int nid = dev_to_node(&vdev->dev);
> > + struct nd_region *nd_region;
> > +
> > + if (!vdev->config->get) {
> > + dev_err(&vdev->dev, "%s failure: config disabled\n",
> > + __func__);
> > + return -EINVAL;
> > + }
> > +
> > + vdev->priv = vpmem = devm_kzalloc(&vdev->dev, sizeof(*vpmem),
> > + GFP_KERNEL);
> > + if (!vpmem) {
> > + err = -ENOMEM;
> > + goto out_err;
> > + }
> > +
> > + vpmem->vdev = vdev;
> > + err = init_vq(vpmem);
> > + if (err)
> > + goto out_err;
> > +
> > + virtio_cread(vpmem->vdev, struct virtio_pmem_config,
> > + start, &vpmem->start);
> > + virtio_cread(vpmem->vdev, struct virtio_pmem_config,
> > + size, &vpmem->size);
> > +
> > + res.start = vpmem->start;
> > + res.end = vpmem->start + vpmem->size-1;
> > + vpmem->nd_desc.provider_name = "virtio-pmem";
> > + vpmem->nd_desc.module = THIS_MODULE;
> > +
> > + vpmem->nvdimm_bus = nvdimm_bus = nvdimm_bus_register(&vdev->dev,
> > + &vpmem->nd_desc);
> > + if (!nvdimm_bus)
> > + goto out_vq;
> > +
> > + dev_set_drvdata(&vdev->dev, nvdimm_bus);
> > +
> > + ndr_desc.res = &res;
> > + ndr_desc.numa_node = nid;
> > + ndr_desc.flush = virtio_pmem_flush;
> > + set_bit(ND_REGION_PAGEMAP, &ndr_desc.flags);
> > + set_bit(ND_REGION_ASYNC, &ndr_desc.flags);
> > + nd_region = nvdimm_pmem_region_create(nvdimm_bus, &ndr_desc);
> > + nd_region->provider_data = dev_to_virtio
> > + (nd_region->dev.parent->parent);
> > +
> > + if (!nd_region)
> > + goto out_nd;
> > +
> > + return 0;
> > +out_nd:
> > + err = -ENXIO;
> > + nvdimm_bus_unregister(nvdimm_bus);
> > +out_vq:
> > + vdev->config->del_vqs(vdev);
> > +out_err:
> > + dev_err(&vdev->dev, "failed to register virtio pmem memory\n");
> > + return err;
> > +}
> > +
> > +static void virtio_pmem_remove(struct virtio_device *vdev)
> > +{
> > + struct virtio_pmem *vpmem = vdev->priv;
> > + struct nvdimm_bus *nvdimm_bus = dev_get_drvdata(&vdev->dev);
> > +
> > + nvdimm_bus_unregister(nvdimm_bus);
> > + vdev->config->del_vqs(vdev);
> > + vdev->config->reset(vdev);
> > + kfree(vpmem);
> > +}
> > +
> > +static struct virtio_driver virtio_pmem_driver = {
> > + .driver.name = KBUILD_MODNAME,
> > + .driver.owner = THIS_MODULE,
> > + .id_table = id_table,
> > + .probe = virtio_pmem_probe,
> > + .remove = virtio_pmem_remove,
> > +};
> > +
> > +module_virtio_driver(virtio_pmem_driver);
> > +MODULE_DEVICE_TABLE(virtio, id_table);
> > +MODULE_DESCRIPTION("Virtio pmem driver");
> > +MODULE_LICENSE("GPL");
> > diff --git a/include/linux/virtio_pmem.h b/include/linux/virtio_pmem.h
> > new file mode 100644
> > index 000000000000..224f9d934be6
> > --- /dev/null
> > +++ b/include/linux/virtio_pmem.h
> > @@ -0,0 +1,60 @@
> > +/* SPDX-License-Identifier: GPL-2.0 */
> > +/*
> > + * virtio_pmem.h: virtio pmem Driver
> > + *
> > + * Discovers persistent memory range information
> > + * from host and provides a virtio based flushing
> > + * interface.
> > + **/
> > +
> > +#ifndef _LINUX_VIRTIO_PMEM_H
> > +#define _LINUX_VIRTIO_PMEM_H
> > +
> > +#include <linux/virtio_ids.h>
> > +#include <linux/module.h>
> > +#include <linux/virtio_config.h>
> > +#include <uapi/linux/virtio_pmem.h>
> > +#include <linux/libnvdimm.h>
> > +#include <linux/spinlock.h>
> > +
> > +struct virtio_pmem_request {
> > + /* Host return status corresponding to flush request */
> > + int ret;
> > +
> > + /* command name*/
> > + char name[16];
> > +
> > + /* Wait queue to process deferred work after ack from host */
> > + wait_queue_head_t host_acked;
> > + bool done;
> > +
> > + /* Wait queue to process deferred work after virt queue buffer avail */
> > + wait_queue_head_t wq_buf;
> > + bool wq_buf_avail;
> > + struct list_head list;
> > +};
> > +
> > +struct virtio_pmem {
> > + struct virtio_device *vdev;
> > +
> > + /* Virtio pmem request queue */
> > + struct virtqueue *req_vq;
> > +
> > + /* nvdimm bus registers virtio pmem device */
> > + struct nvdimm_bus *nvdimm_bus;
> > + struct nvdimm_bus_descriptor nd_desc;
> > +
> > + /* List to store deferred work if virtqueue is full */
> > + struct list_head req_list;
> > +
> > + /* Synchronize virtqueue data */
> > + spinlock_t pmem_lock;
> > +
> > + /* Memory region information */
> > + uint64_t start;
> > + uint64_t size;
> > +};
> > +
> > +void host_ack(struct virtqueue *vq);
> > +int virtio_pmem_flush(struct nd_region *nd_region);
> > +#endif
> > diff --git a/include/uapi/linux/virtio_ids.h
> > b/include/uapi/linux/virtio_ids.h
> > index 6d5c3b2d4f4d..346389565ac1 100644
> > --- a/include/uapi/linux/virtio_ids.h
> > +++ b/include/uapi/linux/virtio_ids.h
> > @@ -43,5 +43,6 @@
> > #define VIRTIO_ID_INPUT 18 /* virtio input */
> > #define VIRTIO_ID_VSOCK 19 /* virtio vsock transport */
> > #define VIRTIO_ID_CRYPTO 20 /* virtio crypto */
> > +#define VIRTIO_ID_PMEM 25 /* virtio pmem */
> >
> > #endif /* _LINUX_VIRTIO_IDS_H */
>
> Didn't Paolo point out someone is using 25 for audio?
Sorry! I did not notice this.
>
> Please, reserve an ID with the Virtio TC before using it.
I thought I requested[1] ID 25.
[1] https://github.com/oasis-tcs/virtio-spec/issues/38
[2] https://lists.oasis-open.org/archives/virtio-dev/201805/threads.html
In that case I will send request for next available ID i.e 26?
Thanks,
Pankaj
>
> > diff --git a/include/uapi/linux/virtio_pmem.h
> > b/include/uapi/linux/virtio_pmem.h
> > new file mode 100644
> > index 000000000000..fa3f7d52717a
> > --- /dev/null
> > +++ b/include/uapi/linux/virtio_pmem.h
> > @@ -0,0 +1,10 @@
> > +/* SPDX-License-Identifier: GPL-2.0 */
> > +
> > +#ifndef _UAPI_LINUX_VIRTIO_PMEM_H
> > +#define _UAPI_LINUX_VIRTIO_PMEM_H
> > +
> > +struct virtio_pmem_config {
> > + __le64 start;
> > + __le64 size;
> > +};
> > +#endif
> > --
> > 2.20.1
>
>
_______________________________________________
Linux-nvdimm mailing list
Linux-nvdimm@lists.01.org
https://lists.01.org/mailman/listinfo/linux-nvdimm
^ permalink raw reply
* Re: [Qemu-devel] [PATCH v5 2/5] virtio-pmem: Add virtio pmem driver
From: Pankaj Gupta @ 2019-04-10 14:03 UTC (permalink / raw)
To: Michael S. Tsirkin
Cc: cohuck, jack, kvm, david, jasowang, david, qemu-devel,
virtualization, adilger kernel, zwisler, aarcange, dave jiang,
linux-nvdimm, vishal l verma, willy, hch, linux-acpi, jmoyer,
linux-ext4, lenb, kilobyte, riel, yuval shaia, stefanha, pbonzini,
dan j williams, lcapitulino, kwolf, nilal, tytso,
xiaoguangrong eric, darrick wong, rjw, linux-kernel, linux-xfs,
linux-fsdevel, imammedo
In-Reply-To: <20190410091216-mutt-send-email-mst@kernel.org>
>
> On Wed, Apr 10, 2019 at 09:38:22AM +0530, Pankaj Gupta wrote:
> > This patch adds virtio-pmem driver for KVM guest.
> >
> > Guest reads the persistent memory range information from
> > Qemu over VIRTIO and registers it on nvdimm_bus. It also
> > creates a nd_region object with the persistent memory
> > range information so that existing 'nvdimm/pmem' driver
> > can reserve this into system memory map. This way
> > 'virtio-pmem' driver uses existing functionality of pmem
> > driver to register persistent memory compatible for DAX
> > capable filesystems.
> >
> > This also provides function to perform guest flush over
> > VIRTIO from 'pmem' driver when userspace performs flush
> > on DAX memory range.
> >
> > Signed-off-by: Pankaj Gupta <pagupta@redhat.com>
> > ---
> > drivers/nvdimm/virtio_pmem.c | 88 ++++++++++++++++++++++
> > drivers/virtio/Kconfig | 10 +++
> > drivers/virtio/Makefile | 1 +
> > drivers/virtio/pmem.c | 124 +++++++++++++++++++++++++++++++
> > include/linux/virtio_pmem.h | 60 +++++++++++++++
> > include/uapi/linux/virtio_ids.h | 1 +
> > include/uapi/linux/virtio_pmem.h | 10 +++
> > 7 files changed, 294 insertions(+)
> > create mode 100644 drivers/nvdimm/virtio_pmem.c
> > create mode 100644 drivers/virtio/pmem.c
> > create mode 100644 include/linux/virtio_pmem.h
> > create mode 100644 include/uapi/linux/virtio_pmem.h
> >
> > diff --git a/drivers/nvdimm/virtio_pmem.c b/drivers/nvdimm/virtio_pmem.c
> > new file mode 100644
> > index 000000000000..01044cc2f3a3
> > --- /dev/null
> > +++ b/drivers/nvdimm/virtio_pmem.c
> > @@ -0,0 +1,88 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + * virtio_pmem.c: Virtio pmem Driver
> > + *
> > + * Discovers persistent memory range information
> > + * from host and provides a virtio based flushing
> > + * interface.
> > + */
> > +#include <linux/virtio_pmem.h>
> > +#include "nd.h"
> > +
> > + /* The interrupt handler */
> > +void host_ack(struct virtqueue *vq)
> > +{
> > + unsigned int len;
> > + unsigned long flags;
> > + struct virtio_pmem_request *req, *req_buf;
> > + struct virtio_pmem *vpmem = vq->vdev->priv;
> > +
> > + spin_lock_irqsave(&vpmem->pmem_lock, flags);
> > + while ((req = virtqueue_get_buf(vq, &len)) != NULL) {
> > + req->done = true;
> > + wake_up(&req->host_acked);
> > +
> > + if (!list_empty(&vpmem->req_list)) {
> > + req_buf = list_first_entry(&vpmem->req_list,
> > + struct virtio_pmem_request, list);
> > + list_del(&vpmem->req_list);
> > + req_buf->wq_buf_avail = true;
> > + wake_up(&req_buf->wq_buf);
> > + }
> > + }
> > + spin_unlock_irqrestore(&vpmem->pmem_lock, flags);
> > +}
> > +EXPORT_SYMBOL_GPL(host_ack);
> > +
> > + /* The request submission function */
> > +int virtio_pmem_flush(struct nd_region *nd_region)
> > +{
> > + int err;
> > + unsigned long flags;
> > + struct scatterlist *sgs[2], sg, ret;
> > + struct virtio_device *vdev = nd_region->provider_data;
> > + struct virtio_pmem *vpmem = vdev->priv;
> > + struct virtio_pmem_request *req;
> > +
> > + might_sleep();
> > + req = kmalloc(sizeof(*req), GFP_KERNEL);
> > + if (!req)
> > + return -ENOMEM;
> > +
> > + req->done = req->wq_buf_avail = false;
> > + strcpy(req->name, "FLUSH");
> > + init_waitqueue_head(&req->host_acked);
> > + init_waitqueue_head(&req->wq_buf);
> > + sg_init_one(&sg, req->name, strlen(req->name));
> > + sgs[0] = &sg;
> > + sg_init_one(&ret, &req->ret, sizeof(req->ret));
> > + sgs[1] = &ret;
> > +
> > + spin_lock_irqsave(&vpmem->pmem_lock, flags);
> > + err = virtqueue_add_sgs(vpmem->req_vq, sgs, 1, 1, req, GFP_ATOMIC);
> > + if (err) {
> > + dev_err(&vdev->dev, "failed to send command to virtio pmem device\n");
> > +
> > + list_add_tail(&vpmem->req_list, &req->list);
> > + spin_unlock_irqrestore(&vpmem->pmem_lock, flags);
> > +
> > + /* When host has read buffer, this completes via host_ack */
> > + wait_event(req->wq_buf, req->wq_buf_avail);
> > + spin_lock_irqsave(&vpmem->pmem_lock, flags);
> > + }
> > + err = virtqueue_kick(vpmem->req_vq);
> > + spin_unlock_irqrestore(&vpmem->pmem_lock, flags);
> > +
> > + if (!err) {
> > + err = -EIO;
> > + goto ret;
> > + }
> > + /* When host has read buffer, this completes via host_ack */
> > + wait_event(req->host_acked, req->done);
> > + err = req->ret;
> > +ret:
> > + kfree(req);
> > + return err;
> > +};
> > +EXPORT_SYMBOL_GPL(virtio_pmem_flush);
> > +MODULE_LICENSE("GPL");
> > diff --git a/drivers/virtio/Kconfig b/drivers/virtio/Kconfig
> > index 35897649c24f..9f634a2ed638 100644
> > --- a/drivers/virtio/Kconfig
> > +++ b/drivers/virtio/Kconfig
> > @@ -42,6 +42,16 @@ config VIRTIO_PCI_LEGACY
> >
> > If unsure, say Y.
> >
> > +config VIRTIO_PMEM
> > + tristate "Support for virtio pmem driver"
> > + depends on VIRTIO
> > + depends on LIBNVDIMM
> > + help
> > + This driver provides support for virtio based flushing interface
> > + for persistent memory range.
> > +
> > + If unsure, say M.
> > +
> > config VIRTIO_BALLOON
> > tristate "Virtio balloon driver"
> > depends on VIRTIO
> > diff --git a/drivers/virtio/Makefile b/drivers/virtio/Makefile
> > index 3a2b5c5dcf46..143ce91eabe9 100644
> > --- a/drivers/virtio/Makefile
> > +++ b/drivers/virtio/Makefile
> > @@ -6,3 +6,4 @@ virtio_pci-y := virtio_pci_modern.o virtio_pci_common.o
> > virtio_pci-$(CONFIG_VIRTIO_PCI_LEGACY) += virtio_pci_legacy.o
> > obj-$(CONFIG_VIRTIO_BALLOON) += virtio_balloon.o
> > obj-$(CONFIG_VIRTIO_INPUT) += virtio_input.o
> > +obj-$(CONFIG_VIRTIO_PMEM) += pmem.o ../nvdimm/virtio_pmem.o
> > diff --git a/drivers/virtio/pmem.c b/drivers/virtio/pmem.c
> > new file mode 100644
> > index 000000000000..cc9de9589d56
> > --- /dev/null
> > +++ b/drivers/virtio/pmem.c
> > @@ -0,0 +1,124 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + * virtio_pmem.c: Virtio pmem Driver
> > + *
> > + * Discovers persistent memory range information
> > + * from host and registers the virtual pmem device
> > + * with libnvdimm core.
> > + */
> > +#include <linux/virtio_pmem.h>
> > +#include <../../drivers/nvdimm/nd.h>
> > +
> > +static struct virtio_device_id id_table[] = {
> > + { VIRTIO_ID_PMEM, VIRTIO_DEV_ANY_ID },
> > + { 0 },
> > +};
> > +
> > + /* Initialize virt queue */
> > +static int init_vq(struct virtio_pmem *vpmem)
> > +{
> > + struct virtqueue *vq;
> > +
> > + /* single vq */
> > + vpmem->req_vq = vq = virtio_find_single_vq(vpmem->vdev,
> > + host_ack, "flush_queue");
> > + if (IS_ERR(vq))
> > + return PTR_ERR(vq);
> > +
> > + spin_lock_init(&vpmem->pmem_lock);
> > + INIT_LIST_HEAD(&vpmem->req_list);
> > +
> > + return 0;
> > +};
> > +
> > +static int virtio_pmem_probe(struct virtio_device *vdev)
> > +{
> > + int err = 0;
> > + struct resource res;
> > + struct virtio_pmem *vpmem;
> > + struct nvdimm_bus *nvdimm_bus;
> > + struct nd_region_desc ndr_desc = {};
> > + int nid = dev_to_node(&vdev->dev);
> > + struct nd_region *nd_region;
> > +
> > + if (!vdev->config->get) {
> > + dev_err(&vdev->dev, "%s failure: config disabled\n",
> > + __func__);
> > + return -EINVAL;
> > + }
> > +
> > + vdev->priv = vpmem = devm_kzalloc(&vdev->dev, sizeof(*vpmem),
> > + GFP_KERNEL);
> > + if (!vpmem) {
> > + err = -ENOMEM;
> > + goto out_err;
> > + }
> > +
> > + vpmem->vdev = vdev;
> > + err = init_vq(vpmem);
> > + if (err)
> > + goto out_err;
> > +
> > + virtio_cread(vpmem->vdev, struct virtio_pmem_config,
> > + start, &vpmem->start);
> > + virtio_cread(vpmem->vdev, struct virtio_pmem_config,
> > + size, &vpmem->size);
> > +
> > + res.start = vpmem->start;
> > + res.end = vpmem->start + vpmem->size-1;
> > + vpmem->nd_desc.provider_name = "virtio-pmem";
> > + vpmem->nd_desc.module = THIS_MODULE;
> > +
> > + vpmem->nvdimm_bus = nvdimm_bus = nvdimm_bus_register(&vdev->dev,
> > + &vpmem->nd_desc);
> > + if (!nvdimm_bus)
> > + goto out_vq;
> > +
> > + dev_set_drvdata(&vdev->dev, nvdimm_bus);
> > +
> > + ndr_desc.res = &res;
> > + ndr_desc.numa_node = nid;
> > + ndr_desc.flush = virtio_pmem_flush;
> > + set_bit(ND_REGION_PAGEMAP, &ndr_desc.flags);
> > + set_bit(ND_REGION_ASYNC, &ndr_desc.flags);
> > + nd_region = nvdimm_pmem_region_create(nvdimm_bus, &ndr_desc);
> > + nd_region->provider_data = dev_to_virtio
> > + (nd_region->dev.parent->parent);
> > +
> > + if (!nd_region)
> > + goto out_nd;
> > +
> > + return 0;
> > +out_nd:
> > + err = -ENXIO;
> > + nvdimm_bus_unregister(nvdimm_bus);
> > +out_vq:
> > + vdev->config->del_vqs(vdev);
> > +out_err:
> > + dev_err(&vdev->dev, "failed to register virtio pmem memory\n");
> > + return err;
> > +}
> > +
> > +static void virtio_pmem_remove(struct virtio_device *vdev)
> > +{
> > + struct virtio_pmem *vpmem = vdev->priv;
> > + struct nvdimm_bus *nvdimm_bus = dev_get_drvdata(&vdev->dev);
> > +
> > + nvdimm_bus_unregister(nvdimm_bus);
> > + vdev->config->del_vqs(vdev);
> > + vdev->config->reset(vdev);
> > + kfree(vpmem);
> > +}
> > +
> > +static struct virtio_driver virtio_pmem_driver = {
> > + .driver.name = KBUILD_MODNAME,
> > + .driver.owner = THIS_MODULE,
> > + .id_table = id_table,
> > + .probe = virtio_pmem_probe,
> > + .remove = virtio_pmem_remove,
> > +};
> > +
> > +module_virtio_driver(virtio_pmem_driver);
> > +MODULE_DEVICE_TABLE(virtio, id_table);
> > +MODULE_DESCRIPTION("Virtio pmem driver");
> > +MODULE_LICENSE("GPL");
> > diff --git a/include/linux/virtio_pmem.h b/include/linux/virtio_pmem.h
> > new file mode 100644
> > index 000000000000..224f9d934be6
> > --- /dev/null
> > +++ b/include/linux/virtio_pmem.h
> > @@ -0,0 +1,60 @@
> > +/* SPDX-License-Identifier: GPL-2.0 */
> > +/*
> > + * virtio_pmem.h: virtio pmem Driver
> > + *
> > + * Discovers persistent memory range information
> > + * from host and provides a virtio based flushing
> > + * interface.
> > + **/
> > +
> > +#ifndef _LINUX_VIRTIO_PMEM_H
> > +#define _LINUX_VIRTIO_PMEM_H
> > +
> > +#include <linux/virtio_ids.h>
> > +#include <linux/module.h>
> > +#include <linux/virtio_config.h>
> > +#include <uapi/linux/virtio_pmem.h>
> > +#include <linux/libnvdimm.h>
> > +#include <linux/spinlock.h>
> > +
> > +struct virtio_pmem_request {
> > + /* Host return status corresponding to flush request */
> > + int ret;
> > +
> > + /* command name*/
> > + char name[16];
> > +
> > + /* Wait queue to process deferred work after ack from host */
> > + wait_queue_head_t host_acked;
> > + bool done;
> > +
> > + /* Wait queue to process deferred work after virt queue buffer avail */
> > + wait_queue_head_t wq_buf;
> > + bool wq_buf_avail;
> > + struct list_head list;
> > +};
> > +
> > +struct virtio_pmem {
> > + struct virtio_device *vdev;
> > +
> > + /* Virtio pmem request queue */
> > + struct virtqueue *req_vq;
> > +
> > + /* nvdimm bus registers virtio pmem device */
> > + struct nvdimm_bus *nvdimm_bus;
> > + struct nvdimm_bus_descriptor nd_desc;
> > +
> > + /* List to store deferred work if virtqueue is full */
> > + struct list_head req_list;
> > +
> > + /* Synchronize virtqueue data */
> > + spinlock_t pmem_lock;
> > +
> > + /* Memory region information */
> > + uint64_t start;
> > + uint64_t size;
> > +};
> > +
> > +void host_ack(struct virtqueue *vq);
> > +int virtio_pmem_flush(struct nd_region *nd_region);
> > +#endif
> > diff --git a/include/uapi/linux/virtio_ids.h
> > b/include/uapi/linux/virtio_ids.h
> > index 6d5c3b2d4f4d..346389565ac1 100644
> > --- a/include/uapi/linux/virtio_ids.h
> > +++ b/include/uapi/linux/virtio_ids.h
> > @@ -43,5 +43,6 @@
> > #define VIRTIO_ID_INPUT 18 /* virtio input */
> > #define VIRTIO_ID_VSOCK 19 /* virtio vsock transport */
> > #define VIRTIO_ID_CRYPTO 20 /* virtio crypto */
> > +#define VIRTIO_ID_PMEM 25 /* virtio pmem */
> >
> > #endif /* _LINUX_VIRTIO_IDS_H */
>
> Didn't Paolo point out someone is using 25 for audio?
Sorry! I did not notice this.
>
> Please, reserve an ID with the Virtio TC before using it.
I thought I requested[1] ID 25.
[1] https://github.com/oasis-tcs/virtio-spec/issues/38
[2] https://lists.oasis-open.org/archives/virtio-dev/201805/threads.html
In that case I will send request for next available ID i.e 26?
Thanks,
Pankaj
>
> > diff --git a/include/uapi/linux/virtio_pmem.h
> > b/include/uapi/linux/virtio_pmem.h
> > new file mode 100644
> > index 000000000000..fa3f7d52717a
> > --- /dev/null
> > +++ b/include/uapi/linux/virtio_pmem.h
> > @@ -0,0 +1,10 @@
> > +/* SPDX-License-Identifier: GPL-2.0 */
> > +
> > +#ifndef _UAPI_LINUX_VIRTIO_PMEM_H
> > +#define _UAPI_LINUX_VIRTIO_PMEM_H
> > +
> > +struct virtio_pmem_config {
> > + __le64 start;
> > + __le64 size;
> > +};
> > +#endif
> > --
> > 2.20.1
>
>
^ permalink raw reply
* Re: [Qemu-devel] [PATCH for-4.1] q35: acpi: do not create dummy MCFG table
From: Wei Yang @ 2019-04-10 14:01 UTC (permalink / raw)
To: Igor Mammedov; +Cc: ehabkost, mst, Wei Yang, qemu-devel
In-Reply-To: <20190410110833.4db9721f@redhat.com>
On Wed, Apr 10, 2019 at 11:08:33AM +0200, Igor Mammedov wrote:
>On Wed, 10 Apr 2019 09:12:31 +0800
>Wei Yang <richardw.yang@linux.intel.com> wrote:
>
>> On Tue, Apr 09, 2019 at 05:00:37PM +0200, Igor Mammedov wrote:
>> >Dummy table (with signature "QEMU") creation came from original SeaBIOS
>> >codebase. And QEMU would have to keep it around if there were Q35 machine
>> >that depended on keeping ACPI tables blob constant size. Luckily there
>> >were no versioned Q35 machine types before commit:
>> > (since 2.3) a1666142db acpi-build: make ROMs RAM blocks resizeable
>> >which obsoleted need to keep ACPI tables blob the same size on source/destination.
>> >
>>
>> I am not sure getting the "versioned Q35" correctly. Seems originally there is
>> q35-1.4?
>>
>> commit bf3caa3dc17552b323cec6831301a22cfc98ecd5
>> Author: Paolo Bonzini <pbonzini@redhat.com>
>> Date: Fri Feb 8 14:06:15 2013 +0100
>>
>> pc: add compatibility machine types for 1.4
>>
>> Adds both pc-i440fx-1.4 and pc-q35-1.4.
>
>current upstream has only pc-q35-2.4 as earliest versioned Q35
>machine type (try to run: qemu-system-x86_64 -M help)
Yes, I see those old type are removed. This means we don't want to support
those old types, right? Because those old types can't be migrated to latest
upstream qemu.
--
Wei Yang
Help you, Help me
^ permalink raw reply
* Re: [PATCH v5 05/13] media: tvp5150: add input source selection of_graph support
From: Marco Felsch @ 2019-04-10 14:04 UTC (permalink / raw)
To: Jacopo Mondi
Cc: mchehab, sakari.ailus, hans.verkuil, jacopo+renesas, robh+dt,
p.zabel, javierm, laurent.pinchart, linux-media, devicetree,
kernel
In-Reply-To: <20190405144542.rinp3jrczlxo3lwf@uno.localdomain>
Hi Jacopo,
On 19-04-05 16:45, Jacopo Mondi wrote:
> Hi Marco,
>
> On Fri, Apr 05, 2019 at 08:03:09AM +0200, Marco Felsch wrote:
> > This patch adds the of_graph support to describe the tvp connections.
> > Physical the TVP5150 has three ports: AIP1A, AIP1B and YOUT. As result
> > of discussion [1],[2] the device-tree maps these ports 1:1. The svideo
> > connector must be conneted to port@0/endpoint@1, look at the Documentation
> > for more information. Since the TVP5150 is a converter the device-tree
> > must contain at least 1-input and 1-output port. The mc-connectors and
> > mc-links are only created if the device-tree contains the corresponding
> > connector nodes. If more than one connector is available the
> > media_entity_operations.link_setup() callback ensures that only one
> > connector is active.
> >
> > [1] https://www.spinics.net/lists/linux-media/msg138545.html
> > [2] https://www.spinics.net/lists/linux-media/msg138546.html
> >
> > Signed-off-by: Marco Felsch <m.felsch@pengutronix.de>
> > ---
> > Changelog:
> >
> > [1] https://patchwork.kernel.org/cover/10794703/
> > [2] https://patchwork.kernel.org/cover/10786553/
> >
> > v5:
> > - Fixing build deps:
> > - tvp5150_mc_init: fix CONFIG_MEDIA_CONTROLLER deps
> > - struct tvp5150: drop CONFIG_MEDIA_CONTROLLER conditional property
> > includes. This leads into to complex deps for futher development.
> > - tvp5150_dt_cleanup: enable function only if CONFIG_OF is enabled
> > - tvp5150_parse_dt: enable function only if CONFIG_OF is enabled
> > - tvp5150_probe: call tvp5150_dt_cleanup only if CONFIG_OF is enabled
> >
> > - Simplify link_setup routine:
> > - use generic connector parsing since both series [1,2] are squashed into
> > one
> > - struct tvp5150: drop pads_state and modify_second_link property
> > due to link_setup() rework.
> > - tvp5150_link_setup: add more comments
> > - tvp5150_link_setup: simply the link setup routine a lot. Edit the 2nd
> > link directly within the driver instead of a recursive media-framework
> > call (__media_entity_setup_link). This improves the readability and
> > shrinks the driver code.
> > - tvp5150_link_setup: disable all active links in case user switches
> > connectors without disable it first.
> > - tvp5150_registered: simplify default link enable path due to link_setup()
> > rework.
> >
> > - General cleanups
> > - tvp5150_parse_dt: drop unecessary test
> > - tvp5150_parse_dt: add err message due to misconfiguration
> > - tvp5150_parse_dt: make use of V4L2_MBUS_UNKNOWN definition
> > - s/dev_dbg/dev_dbg_lvl
> >
>
> Great, this looks much nicer!
>
> > v4:
> > - rebase on top of media_tree/master, fix merge conflict due to commit
> > 60359a28d592 ("media: v4l: fwnode: Initialise the V4L2 fwnode endpoints
> > to zero")
> >
> > v3:
> > - probe(): s/err/err_free_v4l2_ctrls
> > - drop MC dependency for tvp5150_pads
> >
> > v2:
> > - adapt commit message
> > - unify ifdef switches
> > - rename tvp5150_valid_input -> tvp5150_of_valid_input, to be more precise
> > - mc: use 2-input and 1-output pad
> > - mc: link svideo connector to both input pads
> > - mc: enable/disable svideo links in one go
> > - mc: change link_setup() behaviour, switch the input src don't require a
> > explicite disable before.
> > - mc: rename 'local' media_pad param to tvp5150_pad to avoid confusion
> > - mc: enable link to the first available connector and set the
> > corresponding tvp5150 input src per default during registered()
> > - mc/of: factor out oftree connector allocation
> > - of: drop svideo dt port
> > - of: move svideo connector to port@0/endpoint@1
> > - of: require at least 1-in and 1-out endpoint
> >
> > drivers/media/i2c/tvp5150.c | 408 ++++++++++++++++++++++++++++++++----
> > 1 file changed, 368 insertions(+), 40 deletions(-)
> >
> > diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c
> > index 89da921c8886..91504fddb551 100644
> > --- a/drivers/media/i2c/tvp5150.c
> > +++ b/drivers/media/i2c/tvp5150.c
> > @@ -44,16 +44,29 @@ MODULE_PARM_DESC(debug, "Debug level (0-2)");
> > #define dprintk0(__dev, __arg...) dev_dbg_lvl(__dev, 0, 0, __arg)
> >
> > enum tvp5150_pads {
> > - TVP5150_PAD_IF_INPUT,
> > + TVP5150_PAD_AIP1A = TVP5150_COMPOSITE0,
> > + TVP5150_PAD_AIP1B,
> > TVP5150_PAD_VID_OUT,
> > TVP5150_NUM_PADS
> > };
> >
> > +struct tvp5150_connector {
> > + struct v4l2_fwnode_connector base;
> > + struct media_entity ent;
> > + struct media_pad pad;
> > +};
> > +
> > struct tvp5150 {
> > struct v4l2_subdev sd;
> > -#ifdef CONFIG_MEDIA_CONTROLLER
> > + /* additional additional endpoint for the svideo connector */
>
> s/additional additional/additional/
Damn, fixed it.
> > + struct device_node *endpoints[TVP5150_NUM_PADS + 1];
> > + unsigned int endpoints_num;
> > +
> > + /* media-ctl properties */
> > struct media_pad pads[TVP5150_NUM_PADS];
> > -#endif
> > + struct tvp5150_connector *connectors;
> > + int connectors_num;
> > +
> > struct v4l2_ctrl_handler hdl;
> > struct v4l2_rect rect;
> > struct regmap *regmap;
> > @@ -1167,6 +1180,129 @@ static int tvp5150_enum_frame_size(struct v4l2_subdev *sd,
> > return 0;
> > }
> >
> > +/****************************************************************************
> > + * Media entity ops
> > + ****************************************************************************/
> > +#if defined(CONFIG_MEDIA_CONTROLLER)
> > +static int tvp5150_set_link(struct media_pad *connector_pad,
> > + struct media_pad *tvp5150_pad, u32 flags)
> > +{
> > + struct media_link *link;
> > +
> > + link = media_entity_find_link(connector_pad, tvp5150_pad);
> > + if (!link)
> > + return -EINVAL;
> > +
> > + link->flags = flags;
> > + link->reverse->flags = link->flags;
> > +
> > + return 0;
> > +}
> > +
> > +static int tvp5150_disable_all_input_links(struct tvp5150 *decoder)
> > +{
> > + struct media_pad *connector_pad;
> > + int i, err;
>
> i can be unsigned here
Okay
> > +
> > + for (i = 0; i < TVP5150_NUM_PADS - 1; i++) {
> > + connector_pad = media_entity_remote_pad(&decoder->pads[i]);
> > + if (!connector_pad)
> > + continue;
> > +
> > + err = tvp5150_set_link(connector_pad, &decoder->pads[i], 0);
> > + if (err)
> > + return err;
> > + }
> > +
> > + return 0;
> > +}
> > +
> > +static int tvp5150_s_routing(struct v4l2_subdev *sd, u32 input, u32 output,
> > + u32 config);
> > +
> > +static int tvp5150_link_setup(struct media_entity *entity,
> > + const struct media_pad *tvp5150_pad,
> > + const struct media_pad *remote, u32 flags)
> > +{
> > + struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity);
> > + struct tvp5150 *decoder = to_tvp5150(sd);
> > + struct media_pad *other_tvp5150_pad =
> > + &decoder->pads[tvp5150_pad->index ^ 1];
> > + bool is_svideo = false;
> > + int i, err;
>
> i can be unsigned
Okay
> > +
> > + /*
> > + * The TVP5150 state is determined by the enabled sink pad link(s).
> > + * Enabling or disabling the source pad link has no effect.
> > + */
> > + if (tvp5150_pad->flags & MEDIA_PAD_FL_SOURCE)
> > + return 0;
> > +
> > + /* Check if the svideo connector should be enabled */
> > + for (i = 0; i < decoder->connectors_num; i++) {
> > + if (remote->entity == &decoder->connectors[i].ent) {
> > + is_svideo =
> > + decoder->connectors[i].base.type == V4L2_CON_SVIDEO;
> > + break;
> > + }
> > + }
> > +
> > + dev_dbg_lvl(sd->dev, 1, debug, "link setup '%s':%d->'%s':%d[%d]",
> > + remote->entity->name, remote->index,
> > + tvp5150_pad->entity->name, tvp5150_pad->index,
> > + flags & MEDIA_LNK_FL_ENABLED);
> > + if (is_svideo)
> > + dev_dbg_lvl(sd->dev, 1, debug,
> > + "link setup '%s':%d->'%s':%d[%d]",
> > + remote->entity->name, remote->index,
> > + other_tvp5150_pad->entity->name,
> > + other_tvp5150_pad->index,
> > + flags & MEDIA_LNK_FL_ENABLED);
> > +
> > + /*
> > + * The TVP5150 has a internal mux which allows the following setup:
>
> an internal
Yes
> > + *
> > + * comp-connector1 --\
> > + * |---> AIP1A
> > + * /
> > + * svideo-connector -|
> > + * \
> > + * |---> AIP1B
> > + * comp-connector2 --/
> > + *
> > + * We can't rely on user space that the current connector gets disabled
> > + * first before enabling the new connector. Disable all active
> > + * connector links to be on the safe side.
> > + */
> > + err = tvp5150_disable_all_input_links(decoder);
> > + if (err)
> > + return err;
>
> Not sure here... I think you should refuse, say, to enable
> comp-connector2->AIP1B if S_VIDEO is enabled on AIP1A, or maybe that's not
> possible, as you have a single linke to AIP1B... Another example: you
> should refuse to enable comp-connector1->AIP1A if
> svideo-connector->AIP1A is enabled. These are two distinct links, so
> this should be possible. Am I wrong?
I tought the diagram and prose makes it cleaner, damn.. Thanks for
asking maybe I should think about rewording it..
In short, the svideo needs both links (AIP1A, AIP1B) enabled so there is
no AIP1A or AIP1B case since both are on. In a previouse version of this
series I added the refusing mechanism but Mauro had some concerns about
that. Since the media-api don't cover that he said the dynamic switching
should be the way to go since it is easier for the user space.
So the current solution is that there can be one link enabled (comp1 or
comp2) or two links (svideo). To handle these cases and avoid much
complexity I disable all active links first since it isn't forbidden by
the media-api.
> > +
> > + tvp5150_s_routing(sd, is_svideo ? TVP5150_SVIDEO : tvp5150_pad->index,
> > + flags & MEDIA_LNK_FL_ENABLED ? TVP5150_NORMAL :
> > + TVP5150_BLACK_SCREEN, 0);
> > +
> > + if (flags & MEDIA_LNK_FL_ENABLED) {
> > + /*
> > + * S-Video connector is conneted to both ports AIP1A and AIP1B.
> > + * Both links must be enabled in one-shot regardless which link
> > + * the user requests.
> > + */
> > + if (is_svideo) {
> > + err = tvp5150_set_link((struct media_pad *) remote,
> > + other_tvp5150_pad, flags);
> > + if (err)
> > + return err;
> > + }
> > + }
>
> This is much much nicer than v4! Great job!
>
> > +
> > + return 0;
> > +}
> > +
> > +static const struct media_entity_operations tvp5150_sd_media_ops = {
> > + .link_setup = tvp5150_link_setup,
> > +};
> > +#endif
> > /****************************************************************************
> > I2C Command
> > ****************************************************************************/
> > @@ -1314,6 +1450,65 @@ static int tvp5150_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
> > return 0;
> > }
> >
> > +static int tvp5150_registered(struct v4l2_subdev *sd)
> > +{
> > +#if defined(CONFIG_MEDIA_CONTROLLER)
>
> I wonder if it wouldn't make more sense to select MEDIA_CONTROLLER...
> How do you configure the device without MC, since I haven't seen support for
> platform data?
@Mauro
Can you say something about the non MC case?
I know that the em28xx device is using this driver and if I get it right
the em28xx calls the s_routing callback to set the specific input
source.
So in that case the MC mustn't available/enabled.
Luckily the em28xx can use most of the tvp5150 default config values.
>
> > + struct tvp5150 *decoder = to_tvp5150(sd);
> > + unsigned int i;
> > + int ret;
> > +
> > + /*
> > + * Setup connector pads and links. Enable the link to the first
> > + * available connector per default.
> > + */
> > + for (i = 0; i < decoder->connectors_num; i++) {
> > + struct media_entity *con = &decoder->connectors[i].ent;
> > + struct media_pad *pad = &decoder->connectors[i].pad;
> > + unsigned int port = decoder->connectors[i].base.remote_port;
> > + bool is_svideo =
> > + decoder->connectors[i].base.type == V4L2_CON_SVIDEO;
> > + int flags = i ? 0 : MEDIA_LNK_FL_ENABLED;
> > +
> > + pad->flags = MEDIA_PAD_FL_SOURCE;
> > + ret = media_entity_pads_init(con, 1, pad);
> > + if (ret < 0)
> > + return ret;
> > +
> > + ret = media_device_register_entity(sd->v4l2_dev->mdev, con);
> > + if (ret < 0)
> > + return ret;
> > +
> > + ret = media_create_pad_link(con, 0, &sd->entity, port, flags);
> > + if (ret < 0) {
> > + media_device_unregister_entity(con);
> > + return ret;
> > + }
> > +
> > + if (is_svideo) {
> > + /* svideo links to both aip1a and aip1b */
> > + ret = media_create_pad_link(con, 0, &sd->entity,
> > + port + 1, flags);
> > + if (ret < 0) {
> > + media_device_unregister_entity(con);
> > + return ret;
> > + }
> > + }
> > +
> > + /* enable default input */
> > + if (flags == MEDIA_LNK_FL_ENABLED) {
> > + decoder->input =
> > + is_svideo ? TVP5150_SVIDEO :
> > + port == 0 ? TVP5150_COMPOSITE0 :
> > + TVP5150_COMPOSITE1;
> > +
> > + tvp5150_selmux(sd);
> > + }
> > + }
> > +#endif
> > + return 0;
> > +}
> > +
> > +
> > /* ----------------------------------------------------------------------- */
> >
> > static const struct v4l2_ctrl_ops tvp5150_ctrl_ops = {
> > @@ -1367,6 +1562,10 @@ static const struct v4l2_subdev_ops tvp5150_ops = {
> > .pad = &tvp5150_pad_ops,
> > };
> >
> > +static const struct v4l2_subdev_internal_ops tvp5150_internal_ops = {
> > + .registered = tvp5150_registered,
> > +};
> > +
> > /****************************************************************************
> > I2C Client & Driver
> > ****************************************************************************/
> > @@ -1515,38 +1714,171 @@ static int tvp5150_init(struct i2c_client *c)
> > return 0;
> > }
> >
> > -static int tvp5150_parse_dt(struct tvp5150 *decoder, struct device_node *np)
> > +#if defined(CONFIG_MEDIA_CONTROLLER)
> > +static int tvp5150_add_of_connectors(struct tvp5150 *decoder)
> > {
> > - struct v4l2_fwnode_endpoint bus_cfg = { .bus_type = 0 };
> > - struct device_node *ep;
> > - unsigned int flags;
> > - int ret = 0;
> > + struct device *dev = decoder->sd.dev;
> > + struct tvp5150_connector *connectors;
> > + unsigned int connectors_num = decoder->connectors_num;
> > + int i, ret;
> > +
> > + /* Allocate and initialize all available input connectors */
> > + connectors = devm_kcalloc(dev, connectors_num, sizeof(*connectors),
> > + GFP_KERNEL);
> > + if (!connectors)
> > + return -ENOMEM;
> >
> > - ep = of_graph_get_next_endpoint(np, NULL);
> > - if (!ep)
> > - return -EINVAL;
> > + for (i = 0; i < connectors_num; i++) {
> > + struct v4l2_fwnode_connector *c = &connectors[i].base;
> >
> > - ret = v4l2_fwnode_endpoint_parse(of_fwnode_handle(ep), &bus_cfg);
> > - if (ret)
> > - goto err;
> > + ret = v4l2_fwnode_parse_connector(
> > + of_fwnode_handle(decoder->endpoints[i]), c);
> > +
> > + connectors[i].ent.flags = MEDIA_ENT_FL_CONNECTOR;
> > + connectors[i].ent.function = c->type == V4L2_CON_SVIDEO ?
> > + MEDIA_ENT_F_CONN_SVIDEO : MEDIA_ENT_F_CONN_COMPOSITE;
> > + connectors[i].ent.name = c->label;
>
> This is a bit of a duplication of what you're doing at parse_dt time,
> where you parse_connector() already. I guess you do this in two steps
> because you need to count connectors first, as you allocate their
> descriptor structure dynamically.
>
> Have you considered allocating them statically (it's up to 4
> connectors, not a big waste) and populate them at parse_dt time? (you
> could re-alloc too, but let's not consider that for now).
>
> Bonus point, if you parse_dt() then CONFIG_OF is enabled, and you can
> save the
> if (IS_ENABLED(CONFIG_OF))
> ret = tvp5150_add_of_connectors(decoder);
>
> you now have in tvp5150_mc_init()
Good point and your're right I parse it twice a time. I tought about
your suggestion but then I also tought about the case where it can be
get more complicated. Imagine you have 5 composite connectors: two
connected to AIP1A and 3 connected to AIP1B. Still the same behaviour,
only one link at the time can be enbaled. In that case you can't use
the static allocation. Anyway it isn't supported by the driver right now
but it is easier to add the support if we alloc them dynamic.
My idea between splitting was to have a correct abstraction.
Parsing/validation is done by parse_dt, the tvp5150_add_of_connectors()
relies on that result since it didn't check it again. Of course
v4l2_fwnode_parse_connector() gets parsed twice but this is done during
probe.
But your're right with that
> if (IS_ENABLED(CONFIG_OF))
> ret = tvp5150_add_of_connectors(decoder);
and your last review note. That check isn't correct since it can be the
case where CONFIG_OF and CONFIG_MEDIA_CONTROLLER is enabled but the
device using the driver isn't OF-capable (e.g. em28xx usb-device). So
the check must be:
if (decoder->connectors_num)
ret = tvp5150_add_of_connectors(decoder);
This ensures that tvp5150_add_of_connectors() gets called only for
OF-capable devices.
>
> > + }
> > +
> > + decoder->connectors = connectors;
> >
> > - flags = bus_cfg.bus.parallel.flags;
> > + return 0;
> > +}
> > +#endif
> >
> > - if (bus_cfg.bus_type == V4L2_MBUS_PARALLEL &&
> > - !(flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH &&
> > - flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH &&
> > - flags & V4L2_MBUS_FIELD_EVEN_LOW)) {
> > +static int tvp5150_mc_init(struct v4l2_subdev *sd)
> > +{
> > +#if defined(CONFIG_MEDIA_CONTROLLER)
> > + struct tvp5150 *decoder = to_tvp5150(sd);
> > + unsigned int i;
> > + int ret;
> > +
> > + sd->entity.ops = &tvp5150_sd_media_ops;
> > + sd->entity.function = MEDIA_ENT_F_ATV_DECODER;
> > +
> > + /* Initialize all TVP5150 pads */
> > + for (i = 0; i < TVP5150_NUM_PADS; i++) {
> > + if (i < TVP5150_NUM_PADS - 1) {
> > + decoder->pads[i].flags = MEDIA_PAD_FL_SINK;
> > + decoder->pads[i].sig_type = PAD_SIGNAL_ANALOG;
> > + } else {
> > + decoder->pads[i].flags = MEDIA_PAD_FL_SOURCE;
> > + decoder->pads[i].sig_type = PAD_SIGNAL_DV;
> > + }
> > + }
> > + ret = media_entity_pads_init(&sd->entity, TVP5150_NUM_PADS,
> > + decoder->pads);
> > + if (ret < 0)
> > + goto out;
> > +
> > + if (IS_ENABLED(CONFIG_OF))
> > + ret = tvp5150_add_of_connectors(decoder);
> > +out:
> > + return ret;
> > +#else
> > + return 0;
> > +#endif
>
> This would really read better as:
Good point, I will change that or should I rather change the
tvp5150_mc_init() call during the probe to
tvp5150_probe()
{
...
if(IS_ENABLED(CONFIG_MEDIA_CONTROLLER)
tvp5150_mc_init()
...
}
> #if defined(CONFIG_MEDIA_CONTROLLER)
> static int tvp5150_mc_init(struct v4l2_subdev *sd)
> {
> ...
>
> }
> static int tvp5150_mc_init(struct v4l2_subdev *sd)
> {
> ....
> }
> #else /* defined(CONFIG_MEDIA_CONTROLLER) */
> static int tvp5150_mc_init(struct v4l2_subdev *sd)
> {
> return 0;
> }
> static int tvp5150_mc_init(struct v4l2_subdev *sd)
> {
> return 0;
> }
> #endif /* defined(CONFIG_MEDIA_CONTROLLER) */
>
> > +}
> > +
> > +#if defined(CONFIG_OF)
>
> Do you need this? I tried compiling with OF support disabled and this
> #if guard removed and all went fine. After all, all calls to parse_dt
> and dt_cleanup are already guarded by an IS_ENABLED(CONFIG_OF)
My goal was to reduce the code size in case OF isn't enabled since the
call don't depend only on the CONFIG_OF this function won't be threw
away in case CONFIG_OF is disabled if I got it right.
if (IS_ENABLED(CONFIG_OF) && np)
But you're right I can remove it to reducing the ifdef switches.
> > +static int tvp5150_parse_dt(struct tvp5150 *decoder, struct device_node *np)
> > +{
> > + struct device *dev = decoder->sd.dev;
> > + struct v4l2_fwnode_endpoint bus_cfg = { .bus_type = V4L2_MBUS_UNKNOWN };
> > + struct v4l2_fwnode_connector c;
>
> Could you declare this inside the for loop?
Of course.
> > + struct device_node *ep_np;
> > + unsigned int flags;
Moved flags inside the for loop too.
> > + int ret, i = 0, in = 0;
>
> i and in could be unsigned
okay
> > + bool found = false;
> > +
> > + /* at least 1 output and 1 input */
> > + decoder->endpoints_num = of_graph_get_endpoint_count(np);
> > + if (decoder->endpoints_num < 2 || decoder->endpoints_num > 4) {
> > + dev_err(dev, "At least 1 input and 1 output must be connected to the device.\n");
> > ret = -EINVAL;
> > goto err;
> > }
> >
> > - decoder->mbus_type = bus_cfg.bus_type;
> > + for_each_endpoint_of_node(np, ep_np) {
> > + struct of_endpoint ep;
> > +
> > + of_graph_parse_endpoint(ep_np, &ep);
> > + switch (ep.port) {
> > + /* fall through */
>
> Move this below the case please
Yes.
> > + case TVP5150_PAD_AIP1A:
> > + case TVP5150_PAD_AIP1B:
> > + ret = v4l2_fwnode_parse_connector(
> > + of_fwnode_handle(ep_np), &c);
> > + if (c.type != V4L2_CON_COMPOSITE &&
> > + c.type != V4L2_CON_SVIDEO) {
> > + dev_err(dev,
> > + "Invalid endpoint %d on port %d\n",
> > + c.remote_id, c.remote_port);
> > + ret = -EINVAL;
> > + goto err;
> > + }
> > + in++;
> > + break;
> > + case TVP5150_PAD_VID_OUT:
> > + ret = v4l2_fwnode_endpoint_parse(of_fwnode_handle(ep_np),
> > + &bus_cfg);
> > + if (ret)
> > + goto err;
> > +
> > + flags = bus_cfg.bus.parallel.flags;
> > +
> > + if (bus_cfg.bus_type == V4L2_MBUS_PARALLEL &&
> > + !(flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH &&
> > + flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH &&
> > + flags & V4L2_MBUS_FIELD_EVEN_LOW)) {
> > + ret = -EINVAL;
> > + goto err;
> > + }
> > +
> > + decoder->mbus_type = bus_cfg.bus_type;
> > + break;
> > + default:
> > + dev_err(dev, "Invalid port %d for endpoint %pOF\n",
> > + ep.port, ep.local_node);
> > + ret = -EINVAL;
> > + goto err;
> > + }
> > +
> > + of_node_get(ep_np);
> > + decoder->endpoints[i] = ep_np;
> > + i++;
> >
> > + found = true;
> > + }
> > +
> > + decoder->connectors_num = in;
> > + return found ? 0 : -ENODEV;
> > err:
> > - of_node_put(ep);
> > return ret;
> > }
> >
> > +static void tvp5150_dt_cleanup(struct tvp5150 *decoder)
> > +{
> > + unsigned int i;
> > +
> > + for (i = 0; i < TVP5150_NUM_PADS; i++)
> > + of_node_put(decoder->endpoints[i]);
> > +}
> > +
> > +#else /* !defined(CONFIG_OF) */
> > +
> > +static inline int
> > +tvp5150_parse_dt(struct tvp5150 *decoder, struct device_node *np)
> > +{
> > + return 0;
> > +}
> > +
> > +static inline void tvp5150_dt_cleanup(struct tvp5150 *decoder)
> > +{
> > +
> > +}
> > +#endif
> > +
> > static const char * const tvp5150_test_patterns[2] = {
> > "Disabled",
> > "Black screen"
> > @@ -1585,7 +1917,7 @@ static int tvp5150_probe(struct i2c_client *c,
> > res = tvp5150_parse_dt(core, np);
> > if (res) {
> > dev_err(sd->dev, "DT parsing error: %d\n", res);
> > - return res;
> > + goto err_cleanup_dt;
> > }
> > } else {
> > /* Default to BT.656 embedded sync */
> > @@ -1593,25 +1925,16 @@ static int tvp5150_probe(struct i2c_client *c,
> > }
> >
> > v4l2_i2c_subdev_init(sd, c, &tvp5150_ops);
> > + sd->internal_ops = &tvp5150_internal_ops;
> > sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
> >
> > -#if defined(CONFIG_MEDIA_CONTROLLER)
> > - core->pads[TVP5150_PAD_IF_INPUT].flags = MEDIA_PAD_FL_SINK;
> > - core->pads[TVP5150_PAD_IF_INPUT].sig_type = PAD_SIGNAL_ANALOG;
> > - core->pads[TVP5150_PAD_VID_OUT].flags = MEDIA_PAD_FL_SOURCE;
> > - core->pads[TVP5150_PAD_VID_OUT].sig_type = PAD_SIGNAL_DV;
> > -
> > - sd->entity.function = MEDIA_ENT_F_ATV_DECODER;
> > -
> > - res = media_entity_pads_init(&sd->entity, TVP5150_NUM_PADS, core->pads);
> > - if (res < 0)
> > - return res;
> > -
> > -#endif
> > + res = tvp5150_mc_init(sd);
> > + if (res)
> > + goto err_cleanup_dt;
> >
> > res = tvp5150_detect_version(core);
> > if (res < 0)
> > - return res;
> > + goto err_cleanup_dt;
> >
> > core->norm = V4L2_STD_ALL; /* Default is autodetect */
> > core->detected_norm = V4L2_STD_UNKNOWN;
> > @@ -1637,7 +1960,7 @@ static int tvp5150_probe(struct i2c_client *c,
> > sd->ctrl_handler = &core->hdl;
> > if (core->hdl.error) {
> > res = core->hdl.error;
> > - goto err;
> > + goto err_free_v4l2_ctrls;
> > }
> >
> > tvp5150_set_default(tvp5150_read_std(sd), &core->rect);
> > @@ -1649,19 +1972,24 @@ static int tvp5150_probe(struct i2c_client *c,
> > tvp5150_isr, IRQF_TRIGGER_HIGH |
> > IRQF_ONESHOT, "tvp5150", core);
> > if (res)
> > - goto err;
> > + goto err_free_v4l2_ctrls;
> > }
> >
> > res = v4l2_async_register_subdev(sd);
> > if (res < 0)
> > - goto err;
> > + goto err_free_v4l2_ctrls;
> >
> > if (debug > 1)
> > tvp5150_log_status(sd);
> > +
> > return 0;
> >
> > -err:
> > +err_free_v4l2_ctrls:
> > v4l2_ctrl_handler_free(&core->hdl);
> > +err_cleanup_dt:
> > + if (IS_ENABLED(CONFIG_OF) && np)
>
> is there any case where CONFIG_OF is enabled and dev->of_node might be
> NULL ? How did the driver probed in first place if that was the case.
I think that can be the case if you have an embedded device (of-support)
where a tvp5150 is connected directly and an attached em28xx usb device.
>
> I made to the end of this big patch :p quite a nice one!
Thanks for your feedback =)
> Thanks
> j
>
Regards,
Marco
> > + tvp5150_dt_cleanup(core);
> > +
> > return res;
> > }
> >
> > --
> > 2.20.1
> >
--
Pengutronix e.K. | |
Industrial Linux Solutions | http://www.pengutronix.de/ |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
^ permalink raw reply
* Re: [ath6kl:ath11k-bringup 66/93] drivers/net/wireless/ath/ath11k/core.c:722:2-8: preceding lock on line 718 (fwd)
From: Kalle Valo @ 2019-04-10 14:04 UTC (permalink / raw)
To: Julia Lawall; +Cc: Pradeep Kumar Chitrapu, ath11k, kbuild-all
In-Reply-To: <alpine.DEB.2.21.1904100817290.2799@hadrien>
(moving the thread from ath10k to ath11k list, full copy below)
Julia Lawall <julia.lawall@lip6.fr> writes:
> An unlock seems to be missing on line 722.
>
> julia
>
> ---------- Forwarded message ----------
> Date: Wed, 10 Apr 2019 13:54:47 +0800
> From: kbuild test robot <lkp@intel.com>
> To: kbuild@01.org
> Cc: Julia Lawall <julia.lawall@lip6.fr>
> Subject: [ath6kl:ath11k-bringup 66/93]
> drivers/net/wireless/ath/ath11k/core.c:722:2-8: preceding lock on line 718
>
> CC: kbuild-all@01.org
> CC: ath10k@lists.infradead.org
> TO: Pradeep Kumar Chitrapu <pradeepc@codeaurora.org>
> CC: Kalle Valo <kvalo@codeaurora.org>
>
> tree: https://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git ath11k-bringup
> head: 9bcbbf4cedb7a1f30cb547cf87dc480d7f8a5e87
> commit: 3a7b4838b6f6f234239f263ef3dc02e612a083ad [66/93] ath11k: Add
> support for subsystem recovery
> :::::: branch date: 15 hours ago
> :::::: commit date: 8 days ago
>
>>> drivers/net/wireless/ath/ath11k/core.c:722:2-8: preceding lock on line 718
>
> #
> https://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git/commit/?id=3a7b4838b6f6f234239f263ef3dc02e612a083ad
> git remote add ath6kl https://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git
> git remote update ath6kl
> git checkout 3a7b4838b6f6f234239f263ef3dc02e612a083ad
> vim +722 drivers/net/wireless/ath/ath11k/core.c
>
> 3a7b4838 Pradeep Kumar Chitrapu 2019-03-21 682
> 3a7b4838 Pradeep Kumar Chitrapu 2019-03-21 683 static void
> ath11k_core_restart(struct work_struct *work)
> 3a7b4838 Pradeep Kumar Chitrapu 2019-03-21 684 {
> 3a7b4838 Pradeep Kumar Chitrapu 2019-03-21 685 struct ath11k_base *sc
> = container_of(work, struct ath11k_base, restart_work);
> 3a7b4838 Pradeep Kumar Chitrapu 2019-03-21 686 struct ath11k *ar;
> 3a7b4838 Pradeep Kumar Chitrapu 2019-03-21 687 struct ath11k_pdev *pdev;
> 3a7b4838 Pradeep Kumar Chitrapu 2019-03-21 688 int i, ret = 0;
> 3a7b4838 Pradeep Kumar Chitrapu 2019-03-21 689
> 3a7b4838 Pradeep Kumar Chitrapu 2019-03-21 690 spin_lock_bh(&sc->data_lock);
> 3a7b4838 Pradeep Kumar Chitrapu 2019-03-21 691 sc->stats.fw_crash_counter++;
> 3a7b4838 Pradeep Kumar Chitrapu 2019-03-21 692
> spin_unlock_bh(&sc->data_lock);
> 3a7b4838 Pradeep Kumar Chitrapu 2019-03-21 693
> 3a7b4838 Pradeep Kumar Chitrapu 2019-03-21 694 for (i = 0; i <
> sc->num_radios; i++) {
> 3a7b4838 Pradeep Kumar Chitrapu 2019-03-21 695 pdev = &sc->pdevs[i];
> 3a7b4838 Pradeep Kumar Chitrapu 2019-03-21 696 ar = pdev->ar;
> 3a7b4838 Pradeep Kumar Chitrapu 2019-03-21 697 if (!ar || ar->state ==
> ATH11K_STATE_OFF)
> 3a7b4838 Pradeep Kumar Chitrapu 2019-03-21 698 continue;
> 3a7b4838 Pradeep Kumar Chitrapu 2019-03-21 699
> 3a7b4838 Pradeep Kumar Chitrapu 2019-03-21 700
> ieee80211_stop_queues(ar->hw);
> 3a7b4838 Pradeep Kumar Chitrapu 2019-03-21 701 ath11k_drain_tx(ar);
> 3a7b4838 Pradeep Kumar Chitrapu 2019-03-21 702
> complete(&ar->scan.started);
> 3a7b4838 Pradeep Kumar Chitrapu 2019-03-21 703
> complete(&ar->scan.completed);
> 3a7b4838 Pradeep Kumar Chitrapu 2019-03-21 704
> complete(&ar->peer_assoc_done);
> 3a7b4838 Pradeep Kumar Chitrapu 2019-03-21 705
> complete(&ar->install_key_done);
> 3a7b4838 Pradeep Kumar Chitrapu 2019-03-21 706
> complete(&ar->vdev_setup_done);
> 3a7b4838 Pradeep Kumar Chitrapu 2019-03-21 707
> complete(&ar->bss_survey_done);
> 3a7b4838 Pradeep Kumar Chitrapu 2019-03-21 708
> 3a7b4838 Pradeep Kumar Chitrapu 2019-03-21 709
> wake_up(&ar->dp.tx_empty_waitq);
> 3a7b4838 Pradeep Kumar Chitrapu 2019-03-21 710
> idr_for_each(&ar->txmgmt_idr,
> 3a7b4838 Pradeep Kumar Chitrapu 2019-03-21 711
> ath11k_mac_tx_mgmt_pending_free, ar);
> 3a7b4838 Pradeep Kumar Chitrapu 2019-03-21 712
> idr_destroy(&ar->txmgmt_idr);
> 3a7b4838 Pradeep Kumar Chitrapu 2019-03-21 713 }
> 3a7b4838 Pradeep Kumar Chitrapu 2019-03-21 714
> 3a7b4838 Pradeep Kumar Chitrapu 2019-03-21 715
> wake_up(&sc->wmi_sc.tx_credits_wq);
> 3a7b4838 Pradeep Kumar Chitrapu 2019-03-21 716 wake_up(&sc->peer_mapping_wq);
> 3a7b4838 Pradeep Kumar Chitrapu 2019-03-21 717
> 3a7b4838 Pradeep Kumar Chitrapu 2019-03-21 @718 mutex_lock(&sc->core_lock);
> 3a7b4838 Pradeep Kumar Chitrapu 2019-03-21 719 ret =
> ath11k_core_reconfigure_on_crash(sc);
> 3a7b4838 Pradeep Kumar Chitrapu 2019-03-21 720 if (ret) {
> 3a7b4838 Pradeep Kumar Chitrapu 2019-03-21 721 ath11k_err(sc, "failed
> to reconfigure driver on crash recovery\n");
> 3a7b4838 Pradeep Kumar Chitrapu 2019-03-21 @722 return;
> 3a7b4838 Pradeep Kumar Chitrapu 2019-03-21 723 }
> 3a7b4838 Pradeep Kumar Chitrapu 2019-03-21 724 mutex_unlock(&sc->core_lock);
> 3a7b4838 Pradeep Kumar Chitrapu 2019-03-21 725
> 3a7b4838 Pradeep Kumar Chitrapu 2019-03-21 726 for (i = 0; i <
> sc->num_radios; i++) {
> 3a7b4838 Pradeep Kumar Chitrapu 2019-03-21 727 pdev = &sc->pdevs[i];
> 3a7b4838 Pradeep Kumar Chitrapu 2019-03-21 728 ar = pdev->ar;
> 3a7b4838 Pradeep Kumar Chitrapu 2019-03-21 729 if (!ar || ar->state ==
> ATH11K_STATE_OFF)
> 3a7b4838 Pradeep Kumar Chitrapu 2019-03-21 730 continue;
> 3a7b4838 Pradeep Kumar Chitrapu 2019-03-21 731
> 3a7b4838 Pradeep Kumar Chitrapu 2019-03-21 732
> mutex_lock(&ar->conf_mutex);
> 3a7b4838 Pradeep Kumar Chitrapu 2019-03-21 733
> 3a7b4838 Pradeep Kumar Chitrapu 2019-03-21 734 switch (ar->state) {
> 3a7b4838 Pradeep Kumar Chitrapu 2019-03-21 735 case ATH11K_STATE_ON:
> 3a7b4838 Pradeep Kumar Chitrapu 2019-03-21 736 ar->state =
> ATH11K_STATE_RESTARTING;
> 3a7b4838 Pradeep Kumar Chitrapu 2019-03-21 737 ath11k_core_halt(ar);
> 3a7b4838 Pradeep Kumar Chitrapu 2019-03-21 738
> ieee80211_restart_hw(ar->hw);
> 3a7b4838 Pradeep Kumar Chitrapu 2019-03-21 739 break;
> 3a7b4838 Pradeep Kumar Chitrapu 2019-03-21 740 case ATH11K_STATE_OFF:
> 3a7b4838 Pradeep Kumar Chitrapu 2019-03-21 741 ath11k_warn(sc, "cannot
> restart radio %d "
> 3a7b4838 Pradeep Kumar Chitrapu 2019-03-21 742 "that hasn't been
> started\n", i);
> 3a7b4838 Pradeep Kumar Chitrapu 2019-03-21 743 break;
> 3a7b4838 Pradeep Kumar Chitrapu 2019-03-21 744 case
> ATH11K_STATE_RESTARTING:
> 3a7b4838 Pradeep Kumar Chitrapu 2019-03-21 745 break;
> 3a7b4838 Pradeep Kumar Chitrapu 2019-03-21 746 case
> ATH11K_STATE_RESTARTED:
> 3a7b4838 Pradeep Kumar Chitrapu 2019-03-21 747 ar->state =
> ATH11K_STATE_WEDGED;
> 3a7b4838 Pradeep Kumar Chitrapu 2019-03-21 748 case
> ATH11K_STATE_WEDGED:
> 3a7b4838 Pradeep Kumar Chitrapu 2019-03-21 749 ath11k_warn(sc,
> 3a7b4838 Pradeep Kumar Chitrapu 2019-03-21 750 "device is wedged, will
> not restart radio %d\n", i);
> 3a7b4838 Pradeep Kumar Chitrapu 2019-03-21 751 break;
> 3a7b4838 Pradeep Kumar Chitrapu 2019-03-21 752 }
> 3a7b4838 Pradeep Kumar Chitrapu 2019-03-21 753
> mutex_unlock(&ar->conf_mutex);
> 3a7b4838 Pradeep Kumar Chitrapu 2019-03-21 754 }
> 3a7b4838 Pradeep Kumar Chitrapu 2019-03-21 755
> complete(&sc->driver_recovery);
> 3a7b4838 Pradeep Kumar Chitrapu 2019-03-21 756 }
> 3a7b4838 Pradeep Kumar Chitrapu 2019-03-21 757
>
> ---
> 0-DAY kernel test infrastructure Open Source Technology Center
> https://lists.01.org/pipermail/kbuild-all Intel Corporation
--
Kalle Valo
_______________________________________________
ath11k mailing list
ath11k@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/ath11k
^ permalink raw reply
* Re: [Qemu-devel] [PATCH v5 2/5] virtio-pmem: Add virtio pmem driver
From: Pankaj Gupta @ 2019-04-10 14:03 UTC (permalink / raw)
To: Michael S. Tsirkin
Cc: jack, kvm, david, jasowang, david, qemu-devel, virtualization,
adilger kernel, zwisler, aarcange, dave jiang, linux-nvdimm,
vishal l verma, willy, hch, linux-acpi, jmoyer, linux-ext4, lenb,
kilobyte, riel, yuval shaia, stefanha, imammedo, dan j williams,
lcapitulino, kwolf, nilal, tytso, xiaoguangrong eric, cohuck, rjw,
linux-kernel, linux-xfs, linux-fsdevel, pbonzini, darrick wong
In-Reply-To: <20190410091216-mutt-send-email-mst@kernel.org>
>
> On Wed, Apr 10, 2019 at 09:38:22AM +0530, Pankaj Gupta wrote:
> > This patch adds virtio-pmem driver for KVM guest.
> >
> > Guest reads the persistent memory range information from
> > Qemu over VIRTIO and registers it on nvdimm_bus. It also
> > creates a nd_region object with the persistent memory
> > range information so that existing 'nvdimm/pmem' driver
> > can reserve this into system memory map. This way
> > 'virtio-pmem' driver uses existing functionality of pmem
> > driver to register persistent memory compatible for DAX
> > capable filesystems.
> >
> > This also provides function to perform guest flush over
> > VIRTIO from 'pmem' driver when userspace performs flush
> > on DAX memory range.
> >
> > Signed-off-by: Pankaj Gupta <pagupta@redhat.com>
> > ---
> > drivers/nvdimm/virtio_pmem.c | 88 ++++++++++++++++++++++
> > drivers/virtio/Kconfig | 10 +++
> > drivers/virtio/Makefile | 1 +
> > drivers/virtio/pmem.c | 124 +++++++++++++++++++++++++++++++
> > include/linux/virtio_pmem.h | 60 +++++++++++++++
> > include/uapi/linux/virtio_ids.h | 1 +
> > include/uapi/linux/virtio_pmem.h | 10 +++
> > 7 files changed, 294 insertions(+)
> > create mode 100644 drivers/nvdimm/virtio_pmem.c
> > create mode 100644 drivers/virtio/pmem.c
> > create mode 100644 include/linux/virtio_pmem.h
> > create mode 100644 include/uapi/linux/virtio_pmem.h
> >
> > diff --git a/drivers/nvdimm/virtio_pmem.c b/drivers/nvdimm/virtio_pmem.c
> > new file mode 100644
> > index 000000000000..01044cc2f3a3
> > --- /dev/null
> > +++ b/drivers/nvdimm/virtio_pmem.c
> > @@ -0,0 +1,88 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + * virtio_pmem.c: Virtio pmem Driver
> > + *
> > + * Discovers persistent memory range information
> > + * from host and provides a virtio based flushing
> > + * interface.
> > + */
> > +#include <linux/virtio_pmem.h>
> > +#include "nd.h"
> > +
> > + /* The interrupt handler */
> > +void host_ack(struct virtqueue *vq)
> > +{
> > + unsigned int len;
> > + unsigned long flags;
> > + struct virtio_pmem_request *req, *req_buf;
> > + struct virtio_pmem *vpmem = vq->vdev->priv;
> > +
> > + spin_lock_irqsave(&vpmem->pmem_lock, flags);
> > + while ((req = virtqueue_get_buf(vq, &len)) != NULL) {
> > + req->done = true;
> > + wake_up(&req->host_acked);
> > +
> > + if (!list_empty(&vpmem->req_list)) {
> > + req_buf = list_first_entry(&vpmem->req_list,
> > + struct virtio_pmem_request, list);
> > + list_del(&vpmem->req_list);
> > + req_buf->wq_buf_avail = true;
> > + wake_up(&req_buf->wq_buf);
> > + }
> > + }
> > + spin_unlock_irqrestore(&vpmem->pmem_lock, flags);
> > +}
> > +EXPORT_SYMBOL_GPL(host_ack);
> > +
> > + /* The request submission function */
> > +int virtio_pmem_flush(struct nd_region *nd_region)
> > +{
> > + int err;
> > + unsigned long flags;
> > + struct scatterlist *sgs[2], sg, ret;
> > + struct virtio_device *vdev = nd_region->provider_data;
> > + struct virtio_pmem *vpmem = vdev->priv;
> > + struct virtio_pmem_request *req;
> > +
> > + might_sleep();
> > + req = kmalloc(sizeof(*req), GFP_KERNEL);
> > + if (!req)
> > + return -ENOMEM;
> > +
> > + req->done = req->wq_buf_avail = false;
> > + strcpy(req->name, "FLUSH");
> > + init_waitqueue_head(&req->host_acked);
> > + init_waitqueue_head(&req->wq_buf);
> > + sg_init_one(&sg, req->name, strlen(req->name));
> > + sgs[0] = &sg;
> > + sg_init_one(&ret, &req->ret, sizeof(req->ret));
> > + sgs[1] = &ret;
> > +
> > + spin_lock_irqsave(&vpmem->pmem_lock, flags);
> > + err = virtqueue_add_sgs(vpmem->req_vq, sgs, 1, 1, req, GFP_ATOMIC);
> > + if (err) {
> > + dev_err(&vdev->dev, "failed to send command to virtio pmem device\n");
> > +
> > + list_add_tail(&vpmem->req_list, &req->list);
> > + spin_unlock_irqrestore(&vpmem->pmem_lock, flags);
> > +
> > + /* When host has read buffer, this completes via host_ack */
> > + wait_event(req->wq_buf, req->wq_buf_avail);
> > + spin_lock_irqsave(&vpmem->pmem_lock, flags);
> > + }
> > + err = virtqueue_kick(vpmem->req_vq);
> > + spin_unlock_irqrestore(&vpmem->pmem_lock, flags);
> > +
> > + if (!err) {
> > + err = -EIO;
> > + goto ret;
> > + }
> > + /* When host has read buffer, this completes via host_ack */
> > + wait_event(req->host_acked, req->done);
> > + err = req->ret;
> > +ret:
> > + kfree(req);
> > + return err;
> > +};
> > +EXPORT_SYMBOL_GPL(virtio_pmem_flush);
> > +MODULE_LICENSE("GPL");
> > diff --git a/drivers/virtio/Kconfig b/drivers/virtio/Kconfig
> > index 35897649c24f..9f634a2ed638 100644
> > --- a/drivers/virtio/Kconfig
> > +++ b/drivers/virtio/Kconfig
> > @@ -42,6 +42,16 @@ config VIRTIO_PCI_LEGACY
> >
> > If unsure, say Y.
> >
> > +config VIRTIO_PMEM
> > + tristate "Support for virtio pmem driver"
> > + depends on VIRTIO
> > + depends on LIBNVDIMM
> > + help
> > + This driver provides support for virtio based flushing interface
> > + for persistent memory range.
> > +
> > + If unsure, say M.
> > +
> > config VIRTIO_BALLOON
> > tristate "Virtio balloon driver"
> > depends on VIRTIO
> > diff --git a/drivers/virtio/Makefile b/drivers/virtio/Makefile
> > index 3a2b5c5dcf46..143ce91eabe9 100644
> > --- a/drivers/virtio/Makefile
> > +++ b/drivers/virtio/Makefile
> > @@ -6,3 +6,4 @@ virtio_pci-y := virtio_pci_modern.o virtio_pci_common.o
> > virtio_pci-$(CONFIG_VIRTIO_PCI_LEGACY) += virtio_pci_legacy.o
> > obj-$(CONFIG_VIRTIO_BALLOON) += virtio_balloon.o
> > obj-$(CONFIG_VIRTIO_INPUT) += virtio_input.o
> > +obj-$(CONFIG_VIRTIO_PMEM) += pmem.o ../nvdimm/virtio_pmem.o
> > diff --git a/drivers/virtio/pmem.c b/drivers/virtio/pmem.c
> > new file mode 100644
> > index 000000000000..cc9de9589d56
> > --- /dev/null
> > +++ b/drivers/virtio/pmem.c
> > @@ -0,0 +1,124 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + * virtio_pmem.c: Virtio pmem Driver
> > + *
> > + * Discovers persistent memory range information
> > + * from host and registers the virtual pmem device
> > + * with libnvdimm core.
> > + */
> > +#include <linux/virtio_pmem.h>
> > +#include <../../drivers/nvdimm/nd.h>
> > +
> > +static struct virtio_device_id id_table[] = {
> > + { VIRTIO_ID_PMEM, VIRTIO_DEV_ANY_ID },
> > + { 0 },
> > +};
> > +
> > + /* Initialize virt queue */
> > +static int init_vq(struct virtio_pmem *vpmem)
> > +{
> > + struct virtqueue *vq;
> > +
> > + /* single vq */
> > + vpmem->req_vq = vq = virtio_find_single_vq(vpmem->vdev,
> > + host_ack, "flush_queue");
> > + if (IS_ERR(vq))
> > + return PTR_ERR(vq);
> > +
> > + spin_lock_init(&vpmem->pmem_lock);
> > + INIT_LIST_HEAD(&vpmem->req_list);
> > +
> > + return 0;
> > +};
> > +
> > +static int virtio_pmem_probe(struct virtio_device *vdev)
> > +{
> > + int err = 0;
> > + struct resource res;
> > + struct virtio_pmem *vpmem;
> > + struct nvdimm_bus *nvdimm_bus;
> > + struct nd_region_desc ndr_desc = {};
> > + int nid = dev_to_node(&vdev->dev);
> > + struct nd_region *nd_region;
> > +
> > + if (!vdev->config->get) {
> > + dev_err(&vdev->dev, "%s failure: config disabled\n",
> > + __func__);
> > + return -EINVAL;
> > + }
> > +
> > + vdev->priv = vpmem = devm_kzalloc(&vdev->dev, sizeof(*vpmem),
> > + GFP_KERNEL);
> > + if (!vpmem) {
> > + err = -ENOMEM;
> > + goto out_err;
> > + }
> > +
> > + vpmem->vdev = vdev;
> > + err = init_vq(vpmem);
> > + if (err)
> > + goto out_err;
> > +
> > + virtio_cread(vpmem->vdev, struct virtio_pmem_config,
> > + start, &vpmem->start);
> > + virtio_cread(vpmem->vdev, struct virtio_pmem_config,
> > + size, &vpmem->size);
> > +
> > + res.start = vpmem->start;
> > + res.end = vpmem->start + vpmem->size-1;
> > + vpmem->nd_desc.provider_name = "virtio-pmem";
> > + vpmem->nd_desc.module = THIS_MODULE;
> > +
> > + vpmem->nvdimm_bus = nvdimm_bus = nvdimm_bus_register(&vdev->dev,
> > + &vpmem->nd_desc);
> > + if (!nvdimm_bus)
> > + goto out_vq;
> > +
> > + dev_set_drvdata(&vdev->dev, nvdimm_bus);
> > +
> > + ndr_desc.res = &res;
> > + ndr_desc.numa_node = nid;
> > + ndr_desc.flush = virtio_pmem_flush;
> > + set_bit(ND_REGION_PAGEMAP, &ndr_desc.flags);
> > + set_bit(ND_REGION_ASYNC, &ndr_desc.flags);
> > + nd_region = nvdimm_pmem_region_create(nvdimm_bus, &ndr_desc);
> > + nd_region->provider_data = dev_to_virtio
> > + (nd_region->dev.parent->parent);
> > +
> > + if (!nd_region)
> > + goto out_nd;
> > +
> > + return 0;
> > +out_nd:
> > + err = -ENXIO;
> > + nvdimm_bus_unregister(nvdimm_bus);
> > +out_vq:
> > + vdev->config->del_vqs(vdev);
> > +out_err:
> > + dev_err(&vdev->dev, "failed to register virtio pmem memory\n");
> > + return err;
> > +}
> > +
> > +static void virtio_pmem_remove(struct virtio_device *vdev)
> > +{
> > + struct virtio_pmem *vpmem = vdev->priv;
> > + struct nvdimm_bus *nvdimm_bus = dev_get_drvdata(&vdev->dev);
> > +
> > + nvdimm_bus_unregister(nvdimm_bus);
> > + vdev->config->del_vqs(vdev);
> > + vdev->config->reset(vdev);
> > + kfree(vpmem);
> > +}
> > +
> > +static struct virtio_driver virtio_pmem_driver = {
> > + .driver.name = KBUILD_MODNAME,
> > + .driver.owner = THIS_MODULE,
> > + .id_table = id_table,
> > + .probe = virtio_pmem_probe,
> > + .remove = virtio_pmem_remove,
> > +};
> > +
> > +module_virtio_driver(virtio_pmem_driver);
> > +MODULE_DEVICE_TABLE(virtio, id_table);
> > +MODULE_DESCRIPTION("Virtio pmem driver");
> > +MODULE_LICENSE("GPL");
> > diff --git a/include/linux/virtio_pmem.h b/include/linux/virtio_pmem.h
> > new file mode 100644
> > index 000000000000..224f9d934be6
> > --- /dev/null
> > +++ b/include/linux/virtio_pmem.h
> > @@ -0,0 +1,60 @@
> > +/* SPDX-License-Identifier: GPL-2.0 */
> > +/*
> > + * virtio_pmem.h: virtio pmem Driver
> > + *
> > + * Discovers persistent memory range information
> > + * from host and provides a virtio based flushing
> > + * interface.
> > + **/
> > +
> > +#ifndef _LINUX_VIRTIO_PMEM_H
> > +#define _LINUX_VIRTIO_PMEM_H
> > +
> > +#include <linux/virtio_ids.h>
> > +#include <linux/module.h>
> > +#include <linux/virtio_config.h>
> > +#include <uapi/linux/virtio_pmem.h>
> > +#include <linux/libnvdimm.h>
> > +#include <linux/spinlock.h>
> > +
> > +struct virtio_pmem_request {
> > + /* Host return status corresponding to flush request */
> > + int ret;
> > +
> > + /* command name*/
> > + char name[16];
> > +
> > + /* Wait queue to process deferred work after ack from host */
> > + wait_queue_head_t host_acked;
> > + bool done;
> > +
> > + /* Wait queue to process deferred work after virt queue buffer avail */
> > + wait_queue_head_t wq_buf;
> > + bool wq_buf_avail;
> > + struct list_head list;
> > +};
> > +
> > +struct virtio_pmem {
> > + struct virtio_device *vdev;
> > +
> > + /* Virtio pmem request queue */
> > + struct virtqueue *req_vq;
> > +
> > + /* nvdimm bus registers virtio pmem device */
> > + struct nvdimm_bus *nvdimm_bus;
> > + struct nvdimm_bus_descriptor nd_desc;
> > +
> > + /* List to store deferred work if virtqueue is full */
> > + struct list_head req_list;
> > +
> > + /* Synchronize virtqueue data */
> > + spinlock_t pmem_lock;
> > +
> > + /* Memory region information */
> > + uint64_t start;
> > + uint64_t size;
> > +};
> > +
> > +void host_ack(struct virtqueue *vq);
> > +int virtio_pmem_flush(struct nd_region *nd_region);
> > +#endif
> > diff --git a/include/uapi/linux/virtio_ids.h
> > b/include/uapi/linux/virtio_ids.h
> > index 6d5c3b2d4f4d..346389565ac1 100644
> > --- a/include/uapi/linux/virtio_ids.h
> > +++ b/include/uapi/linux/virtio_ids.h
> > @@ -43,5 +43,6 @@
> > #define VIRTIO_ID_INPUT 18 /* virtio input */
> > #define VIRTIO_ID_VSOCK 19 /* virtio vsock transport */
> > #define VIRTIO_ID_CRYPTO 20 /* virtio crypto */
> > +#define VIRTIO_ID_PMEM 25 /* virtio pmem */
> >
> > #endif /* _LINUX_VIRTIO_IDS_H */
>
> Didn't Paolo point out someone is using 25 for audio?
Sorry! I did not notice this.
>
> Please, reserve an ID with the Virtio TC before using it.
I thought I requested[1] ID 25.
[1] https://github.com/oasis-tcs/virtio-spec/issues/38
[2] https://lists.oasis-open.org/archives/virtio-dev/201805/threads.html
In that case I will send request for next available ID i.e 26?
Thanks,
Pankaj
>
> > diff --git a/include/uapi/linux/virtio_pmem.h
> > b/include/uapi/linux/virtio_pmem.h
> > new file mode 100644
> > index 000000000000..fa3f7d52717a
> > --- /dev/null
> > +++ b/include/uapi/linux/virtio_pmem.h
> > @@ -0,0 +1,10 @@
> > +/* SPDX-License-Identifier: GPL-2.0 */
> > +
> > +#ifndef _UAPI_LINUX_VIRTIO_PMEM_H
> > +#define _UAPI_LINUX_VIRTIO_PMEM_H
> > +
> > +struct virtio_pmem_config {
> > + __le64 start;
> > + __le64 size;
> > +};
> > +#endif
> > --
> > 2.20.1
>
>
^ permalink raw reply
* [PATCH -next] memory: tegra: Make terga20_mc_reset_ops static
From: Yue Haibing @ 2019-04-10 14:04 UTC (permalink / raw)
To: thierry.reding, jonathanh, digetx, jroedel
Cc: linux-kernel, linux-tegra, YueHaibing
From: YueHaibing <yuehaibing@huawei.com>
Fix sparse warning:
drivers/memory/tegra/tegra20.c:277:33: warning:
symbol 'terga20_mc_reset_ops' was not declared. Should it be static?
Reported-by: Hulk Robot <hulkci@huawei.com>
Signed-off-by: YueHaibing <yuehaibing@huawei.com>
---
drivers/memory/tegra/tegra20.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/memory/tegra/tegra20.c b/drivers/memory/tegra/tegra20.c
index 7119e53..b786aec 100644
--- a/drivers/memory/tegra/tegra20.c
+++ b/drivers/memory/tegra/tegra20.c
@@ -274,7 +274,7 @@ static int terga20_mc_unblock_dma(struct tegra_mc *mc,
return 0;
}
-const struct tegra_mc_reset_ops terga20_mc_reset_ops = {
+static const struct tegra_mc_reset_ops terga20_mc_reset_ops = {
.hotreset_assert = terga20_mc_hotreset_assert,
.hotreset_deassert = terga20_mc_hotreset_deassert,
.block_dma = terga20_mc_block_dma,
--
2.7.4
^ permalink raw reply related
* Re: [Qemu-devel] [PATCH RESEND v2 2/2] cpus: move hvf_cpu_synchronize* calls to cpu_synchronize* functions
From: Roman Bolshakov @ 2019-04-10 14:02 UTC (permalink / raw)
To: Sukrit Bhatnagar; +Cc: Paolo Bonzini, qemu-devel, Richard Henderson
In-Reply-To: <CAMzgYoMqE20=L+n+tjt8Nb10Tidxr0C6OumQ8vvQ423xJxnN=w@mail.gmail.com>
On Wed, Apr 10, 2019 at 05:35:23PM +0530, Sukrit Bhatnagar wrote:
> On Wed, 10 Apr 2019 at 17:20, Roman Bolshakov <r.bolshakov@yadro.com> wrote:
> >
> > On Sun, Apr 07, 2019 at 05:28:39PM +0530, Sukrit Bhatnagar wrote:
> > > Keep the calls made to synchronize cpu by all hypervisors in one place
> > > inside cpu_synchronize_* functions in include/sysemu/hw_accel.h
> > >
> >
> > The commit itself looks sane but qemu starts to hang during BIOS boot
> > after I've applied it if I run it with hvf accel.
>
> Hi Roman,
> Thanks for reviewing the patches.
> If this is happening, then I assume patches are not ready
> to be merged into qemu-stable.
> Do you have any idea why the problem is not detected
> during tests, but rather at runtime?
> I am not really sure if this patch (2/2) has anything to do with
> the problem but the previous patch (1/2) might.
>
I've applied, built and tested both sequentially. Applying and running
with patch 1/2 alone doesn't result in the behavior I mentioned. I also
tried to apply only the first hunk that moves hvf_cpu_synchronize_state
into cpu_synchronize_state and it also causes the issue with BIOS.
Honestly, I don't know if the tests run qemu with hvf accel. AFAIK
kvm-unit-tests can be used to test an accel itself.
Thanks,
Roman
^ permalink raw reply
* Re: [PATCH] dt-bindings: connector: Spelling mistake
From: Rob Herring @ 2019-04-10 14:05 UTC (permalink / raw)
To: Miquel Raynal; +Cc: Mark Rutland, devicetree
In-Reply-To: <20190401130900.6069-1-miquel.raynal@bootlin.com>
On Mon, Apr 01, 2019 at 03:09:00PM +0200, Miquel Raynal wrote:
> Cosmetic change multpile -> multiple.
>
> Fixes: 593aa2b405f9 ("dt-bindings: add bindings for USB physical connector")
> Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
> ---
> Documentation/devicetree/bindings/connector/usb-connector.txt | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
Applied.
Rob
^ permalink raw reply
* RE: [EXTERNAL] Re: [PATCH] media: omap_vout: potential buffer overflow in vidioc_dqbuf()
From: Scheurer, Amber @ 2019-04-10 14:05 UTC (permalink / raw)
To: Dan Carpenter, Hans Verkuil
Cc: Mauro Carvalho Chehab, Niklas Söderlund, Philipp Zabel,
Parrot, Benoit, linux-media@vger.kernel.org,
kernel-janitors@vger.kernel.org, Andrzej Hajda
In-Reply-To: <20190410111415.GB31633@kadam>
I think you might have the wrong Amber copied on this email.
Amber
-----Original Message-----
From: Dan Carpenter [mailto:dan.carpenter@oracle.com]
Sent: Wednesday, April 10, 2019 6:14 AM
To: Hans Verkuil
Cc: Mauro Carvalho Chehab; Scheurer, Amber; Niklas Söderlund; Philipp Zabel; Parrot, Benoit; linux-media@vger.kernel.org; kernel-janitors@vger.kernel.org; Andrzej Hajda
Subject: [EXTERNAL] Re: [PATCH] media: omap_vout: potential buffer overflow in vidioc_dqbuf()
On Wed, Apr 10, 2019 at 12:50:31PM +0200, Hans Verkuil wrote:
> On 4/9/19 1:29 PM, Dan Carpenter wrote:
> > diff --git a/drivers/media/platform/omap/omap_vout.c b/drivers/media/platform/omap/omap_vout.c
> > index 37f0d7146dfa..15e38990e85a 100644
> > --- a/drivers/media/platform/omap/omap_vout.c
> > +++ b/drivers/media/platform/omap/omap_vout.c
> > @@ -1527,8 +1527,6 @@ static int vidioc_dqbuf(struct file *file, void *fh, struct v4l2_buffer *b)
> > unsigned long size;
> > struct videobuf_buffer *vb;
> >
> > - vb = q->bufs[b->index];
> > -
> > if (!vout->streaming)
> > return -EINVAL;
> >
> > @@ -1539,6 +1537,8 @@ static int vidioc_dqbuf(struct file *file, void *fh, struct v4l2_buffer *b)
> > /* Call videobuf_dqbuf for blocking mode */
> > ret = videobuf_dqbuf(q, (struct v4l2_buffer *)b, 0);
>
> We need a:
>
> if (ret)
> return ret;
>
> here. Or alternatively, add 'if (!ret)' around the next five lines.
>
> b->index is only valid if the videobuf_dqbuf call returned 0.
>
Doh. Thanks.
regards,
dan carpenter
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.