--- /dev/null
+From 3bd1f94b8bf98369fbe00e8a1bfcc3ce35b6ccff Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 Jan 2021 03:18:28 -0500
+Subject: KVM: x86: Factor out x86 instruction emulation with decoding
+
+From: Wei Huang <wei.huang2@amd.com>
+
+[ Upstream commit 4aa2691dcbd38ce1c461188799d863398dd2865d ]
+
+Move the instruction decode part out of x86_emulate_instruction() for it
+to be used in other places. Also kvm_clear_exception_queue() is moved
+inside the if-statement as it doesn't apply when KVM are coming back from
+userspace.
+
+Co-developed-by: Bandan Das <bsd@redhat.com>
+Signed-off-by: Bandan Das <bsd@redhat.com>
+Signed-off-by: Wei Huang <wei.huang2@amd.com>
+Message-Id: <20210126081831.570253-2-wei.huang2@amd.com>
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/kvm/x86.c | 62 +++++++++++++++++++++++++++++-----------------
+ arch/x86/kvm/x86.h | 2 ++
+ 2 files changed, 41 insertions(+), 23 deletions(-)
+
+diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
+index 6ab42cdcb8a4..d5e25bf51f47 100644
+--- a/arch/x86/kvm/x86.c
++++ b/arch/x86/kvm/x86.c
+@@ -7338,6 +7338,42 @@ static bool is_vmware_backdoor_opcode(struct x86_emulate_ctxt *ctxt)
+ return false;
+ }
+
++/*
++ * Decode to be emulated instruction. Return EMULATION_OK if success.
++ */
++int x86_decode_emulated_instruction(struct kvm_vcpu *vcpu, int emulation_type,
++ void *insn, int insn_len)
++{
++ int r = EMULATION_OK;
++ struct x86_emulate_ctxt *ctxt = vcpu->arch.emulate_ctxt;
++
++ init_emulate_ctxt(vcpu);
++
++ /*
++ * We will reenter on the same instruction since we do not set
++ * complete_userspace_io. This does not handle watchpoints yet,
++ * those would be handled in the emulate_ops.
++ */
++ if (!(emulation_type & EMULTYPE_SKIP) &&
++ kvm_vcpu_check_breakpoint(vcpu, &r))
++ return r;
++
++ ctxt->interruptibility = 0;
++ ctxt->have_exception = false;
++ ctxt->exception.vector = -1;
++ ctxt->perm_ok = false;
++
++ ctxt->ud = emulation_type & EMULTYPE_TRAP_UD;
++
++ r = x86_decode_insn(ctxt, insn, insn_len);
++
++ trace_kvm_emulate_insn_start(vcpu);
++ ++vcpu->stat.insn_emulation;
++
++ return r;
++}
++EXPORT_SYMBOL_GPL(x86_decode_emulated_instruction);
++
+ int x86_emulate_instruction(struct kvm_vcpu *vcpu, gpa_t cr2_or_gpa,
+ int emulation_type, void *insn, int insn_len)
+ {
+@@ -7357,32 +7393,12 @@ int x86_emulate_instruction(struct kvm_vcpu *vcpu, gpa_t cr2_or_gpa,
+ */
+ write_fault_to_spt = vcpu->arch.write_fault_to_shadow_pgtable;
+ vcpu->arch.write_fault_to_shadow_pgtable = false;
+- kvm_clear_exception_queue(vcpu);
+
+ if (!(emulation_type & EMULTYPE_NO_DECODE)) {
+- init_emulate_ctxt(vcpu);
+-
+- /*
+- * We will reenter on the same instruction since
+- * we do not set complete_userspace_io. This does not
+- * handle watchpoints yet, those would be handled in
+- * the emulate_ops.
+- */
+- if (!(emulation_type & EMULTYPE_SKIP) &&
+- kvm_vcpu_check_breakpoint(vcpu, &r))
+- return r;
+-
+- ctxt->interruptibility = 0;
+- ctxt->have_exception = false;
+- ctxt->exception.vector = -1;
+- ctxt->perm_ok = false;
+-
+- ctxt->ud = emulation_type & EMULTYPE_TRAP_UD;
+-
+- r = x86_decode_insn(ctxt, insn, insn_len);
++ kvm_clear_exception_queue(vcpu);
+
+- trace_kvm_emulate_insn_start(vcpu);
+- ++vcpu->stat.insn_emulation;
++ r = x86_decode_emulated_instruction(vcpu, emulation_type,
++ insn, insn_len);
+ if (r != EMULATION_OK) {
+ if ((emulation_type & EMULTYPE_TRAP_UD) ||
+ (emulation_type & EMULTYPE_TRAP_UD_FORCED)) {
+diff --git a/arch/x86/kvm/x86.h b/arch/x86/kvm/x86.h
+index 2249a7d7ca27..2bff44f1efec 100644
+--- a/arch/x86/kvm/x86.h
++++ b/arch/x86/kvm/x86.h
+@@ -272,6 +272,8 @@ bool kvm_mtrr_check_gfn_range_consistency(struct kvm_vcpu *vcpu, gfn_t gfn,
+ int page_num);
+ bool kvm_vector_hashing_enabled(void);
+ void kvm_fixup_and_inject_pf_error(struct kvm_vcpu *vcpu, gva_t gva, u16 error_code);
++int x86_decode_emulated_instruction(struct kvm_vcpu *vcpu, int emulation_type,
++ void *insn, int insn_len);
+ int x86_emulate_instruction(struct kvm_vcpu *vcpu, gpa_t cr2_or_gpa,
+ int emulation_type, void *insn, int insn_len);
+ fastpath_t handle_fastpath_set_msr_irqoff(struct kvm_vcpu *vcpu);
+--
+2.30.2
+
--- /dev/null
+From c20eeb98dcc16a54442d453f764591275ac750d4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 27 May 2021 17:01:36 -0700
+Subject: KVM: X86: Fix warning caused by stale emulation context
+
+From: Wanpeng Li <wanpengli@tencent.com>
+
+[ Upstream commit da6393cdd8aaa354b3a2437cd73ebb34cac958e3 ]
+
+Reported by syzkaller:
+
+ WARNING: CPU: 7 PID: 10526 at linux/arch/x86/kvm//x86.c:7621 x86_emulate_instruction+0x41b/0x510 [kvm]
+ RIP: 0010:x86_emulate_instruction+0x41b/0x510 [kvm]
+ Call Trace:
+ kvm_mmu_page_fault+0x126/0x8f0 [kvm]
+ vmx_handle_exit+0x11e/0x680 [kvm_intel]
+ vcpu_enter_guest+0xd95/0x1b40 [kvm]
+ kvm_arch_vcpu_ioctl_run+0x377/0x6a0 [kvm]
+ kvm_vcpu_ioctl+0x389/0x630 [kvm]
+ __x64_sys_ioctl+0x8e/0xd0
+ do_syscall_64+0x3c/0xb0
+ entry_SYSCALL_64_after_hwframe+0x44/0xae
+
+Commit 4a1e10d5b5d8 ("KVM: x86: handle hardware breakpoints during emulation())
+adds hardware breakpoints check before emulation the instruction and parts of
+emulation context initialization, actually we don't have the EMULTYPE_NO_DECODE flag
+here and the emulation context will not be reused. Commit c8848cee74ff ("KVM: x86:
+set ctxt->have_exception in x86_decode_insn()) triggers the warning because it
+catches the stale emulation context has #UD, however, it is not during instruction
+decoding which should result in EMULATION_FAILED. This patch fixes it by moving
+the second part emulation context initialization into init_emulate_ctxt() and
+before hardware breakpoints check. The ctxt->ud will be dropped by a follow-up
+patch.
+
+syzkaller source: https://syzkaller.appspot.com/x/repro.c?x=134683fdd00000
+
+Reported-by: syzbot+71271244f206d17f6441@syzkaller.appspotmail.com
+Fixes: 4a1e10d5b5d8 (KVM: x86: handle hardware breakpoints during emulation)
+Signed-off-by: Wanpeng Li <wanpengli@tencent.com>
+Reviewed-by: Sean Christopherson <seanjc@google.com>
+Message-Id: <1622160097-37633-1-git-send-email-wanpengli@tencent.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/kvm/x86.c | 10 +++++-----
+ 1 file changed, 5 insertions(+), 5 deletions(-)
+
+diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
+index d5e25bf51f47..812585986bb8 100644
+--- a/arch/x86/kvm/x86.c
++++ b/arch/x86/kvm/x86.c
+@@ -7023,6 +7023,11 @@ static void init_emulate_ctxt(struct kvm_vcpu *vcpu)
+ BUILD_BUG_ON(HF_SMM_MASK != X86EMUL_SMM_MASK);
+ BUILD_BUG_ON(HF_SMM_INSIDE_NMI_MASK != X86EMUL_SMM_INSIDE_NMI_MASK);
+
++ ctxt->interruptibility = 0;
++ ctxt->have_exception = false;
++ ctxt->exception.vector = -1;
++ ctxt->perm_ok = false;
++
+ init_decode_cache(ctxt);
+ vcpu->arch.emulate_regs_need_sync_from_vcpu = false;
+ }
+@@ -7358,11 +7363,6 @@ int x86_decode_emulated_instruction(struct kvm_vcpu *vcpu, int emulation_type,
+ kvm_vcpu_check_breakpoint(vcpu, &r))
+ return r;
+
+- ctxt->interruptibility = 0;
+- ctxt->have_exception = false;
+- ctxt->exception.vector = -1;
+- ctxt->perm_ok = false;
+-
+ ctxt->ud = emulation_type & EMULTYPE_TRAP_UD;
+
+ r = x86_decode_insn(ctxt, insn, insn_len);
+--
+2.30.2
+
--- /dev/null
+From aede96a2fd1274b2a5c6d6e0fa21d317f3ccc1c0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 1 Mar 2021 21:38:26 +0100
+Subject: media: drivers/media/usb: fix memory leak in zr364xx_probe
+
+From: Pavel Skripkin <paskripkin@gmail.com>
+
+[ Upstream commit 9c39be40c0155c43343f53e3a439290c0fec5542 ]
+
+syzbot reported memory leak in zr364xx_probe()[1].
+The problem was in invalid error handling order.
+All error conditions rigth after v4l2_ctrl_handler_init()
+must call v4l2_ctrl_handler_free().
+
+Reported-by: syzbot+efe9aefc31ae1e6f7675@syzkaller.appspotmail.com
+Signed-off-by: Pavel Skripkin <paskripkin@gmail.com>
+Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
+Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/media/usb/zr364xx/zr364xx.c | 13 ++++++-------
+ 1 file changed, 6 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/media/usb/zr364xx/zr364xx.c b/drivers/media/usb/zr364xx/zr364xx.c
+index 8636acf2dad0..08b86b22e5e8 100644
+--- a/drivers/media/usb/zr364xx/zr364xx.c
++++ b/drivers/media/usb/zr364xx/zr364xx.c
+@@ -1433,7 +1433,7 @@ static int zr364xx_probe(struct usb_interface *intf,
+ if (hdl->error) {
+ err = hdl->error;
+ dev_err(&udev->dev, "couldn't register control\n");
+- goto unregister;
++ goto free_hdlr_and_unreg_dev;
+ }
+ /* save the init method used by this camera */
+ cam->method = id->driver_info;
+@@ -1506,7 +1506,7 @@ static int zr364xx_probe(struct usb_interface *intf,
+ if (!cam->read_endpoint) {
+ err = -ENOMEM;
+ dev_err(&intf->dev, "Could not find bulk-in endpoint\n");
+- goto unregister;
++ goto free_hdlr_and_unreg_dev;
+ }
+
+ /* v4l */
+@@ -1518,7 +1518,7 @@ static int zr364xx_probe(struct usb_interface *intf,
+ /* load zr364xx board specific */
+ err = zr364xx_board_init(cam);
+ if (err)
+- goto unregister;
++ goto free_hdlr_and_unreg_dev;
+ err = v4l2_ctrl_handler_setup(hdl);
+ if (err)
+ goto board_uninit;
+@@ -1536,7 +1536,7 @@ static int zr364xx_probe(struct usb_interface *intf,
+ err = video_register_device(&cam->vdev, VFL_TYPE_VIDEO, -1);
+ if (err) {
+ dev_err(&udev->dev, "video_register_device failed\n");
+- goto free_handler;
++ goto board_uninit;
+ }
+ cam->v4l2_dev.release = zr364xx_release;
+
+@@ -1544,11 +1544,10 @@ static int zr364xx_probe(struct usb_interface *intf,
+ video_device_node_name(&cam->vdev));
+ return 0;
+
+-free_handler:
+- v4l2_ctrl_handler_free(hdl);
+ board_uninit:
+ zr364xx_board_uninit(cam);
+-unregister:
++free_hdlr_and_unreg_dev:
++ v4l2_ctrl_handler_free(hdl);
+ v4l2_device_unregister(&cam->v4l2_dev);
+ free_cam:
+ kfree(cam);
+--
+2.30.2
+
--- /dev/null
+From 3463701e1a5cf2ceacc112cb12990f5fecee7be5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 21 Jan 2021 07:44:00 +0100
+Subject: media: zr364xx: fix memory leaks in probe()
+
+From: Dan Carpenter <dan.carpenter@oracle.com>
+
+[ Upstream commit ea354b6ddd6f09be29424f41fa75a3e637fea234 ]
+
+Syzbot discovered that the probe error handling doesn't clean up the
+resources allocated in zr364xx_board_init(). There are several
+related bugs in this code so I have re-written the error handling.
+
+1) Introduce a new function zr364xx_board_uninit() which cleans up
+ the resources in zr364xx_board_init().
+2) In zr364xx_board_init() if the call to zr364xx_start_readpipe()
+ fails then release the "cam->buffer.frame[i].lpvbits" memory
+ before returning. This way every function either allocates
+ everything successfully or it cleans up after itself.
+3) Re-write the probe function so that each failure path goto frees
+ the most recent allocation. That way we don't free anything
+ before it has been allocated and we can also verify that
+ everything is freed.
+4) Originally, in the probe function the "cam->v4l2_dev.release"
+ pointer was set to "zr364xx_release" near the start but I moved
+ that assignment to the end, after everything had succeeded. The
+ release function was never actually called during the probe cleanup
+ process, but with this change I wanted to make it clear that we
+ don't want to call zr364xx_release() until everything is
+ allocated successfully.
+
+Next I re-wrote the zr364xx_release() function. Ideally this would
+have been a simple matter of copy and pasting the cleanup code from
+probe and adding an additional call to video_unregister_device(). But
+there are a couple quirks to note.
+
+1) The probe function does not call videobuf_mmap_free() and I don't
+ know where the videobuf_mmap is allocated. I left the code as-is to
+ avoid introducing a bug in code I don't understand.
+2) The zr364xx_board_uninit() has a call to zr364xx_stop_readpipe()
+ which is a change from the original behavior with regards to
+ unloading the driver. Calling zr364xx_stop_readpipe() on a stopped
+ pipe is not a problem so this is safe and is potentially a bugfix.
+
+Reported-by: syzbot+b4d54814b339b5c6bbd4@syzkaller.appspotmail.com
+Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
+Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
+Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/media/usb/zr364xx/zr364xx.c | 49 ++++++++++++++++++-----------
+ 1 file changed, 31 insertions(+), 18 deletions(-)
+
+diff --git a/drivers/media/usb/zr364xx/zr364xx.c b/drivers/media/usb/zr364xx/zr364xx.c
+index 5c8997d7de23..8636acf2dad0 100644
+--- a/drivers/media/usb/zr364xx/zr364xx.c
++++ b/drivers/media/usb/zr364xx/zr364xx.c
+@@ -1184,15 +1184,11 @@ static int zr364xx_open(struct file *file)
+ return err;
+ }
+
+-static void zr364xx_release(struct v4l2_device *v4l2_dev)
++static void zr364xx_board_uninit(struct zr364xx_camera *cam)
+ {
+- struct zr364xx_camera *cam =
+- container_of(v4l2_dev, struct zr364xx_camera, v4l2_dev);
+ unsigned long i;
+
+- v4l2_device_unregister(&cam->v4l2_dev);
+-
+- videobuf_mmap_free(&cam->vb_vidq);
++ zr364xx_stop_readpipe(cam);
+
+ /* release sys buffers */
+ for (i = 0; i < FRAMES; i++) {
+@@ -1203,9 +1199,19 @@ static void zr364xx_release(struct v4l2_device *v4l2_dev)
+ cam->buffer.frame[i].lpvbits = NULL;
+ }
+
+- v4l2_ctrl_handler_free(&cam->ctrl_handler);
+ /* release transfer buffer */
+ kfree(cam->pipe->transfer_buffer);
++}
++
++static void zr364xx_release(struct v4l2_device *v4l2_dev)
++{
++ struct zr364xx_camera *cam =
++ container_of(v4l2_dev, struct zr364xx_camera, v4l2_dev);
++
++ videobuf_mmap_free(&cam->vb_vidq);
++ v4l2_ctrl_handler_free(&cam->ctrl_handler);
++ zr364xx_board_uninit(cam);
++ v4l2_device_unregister(&cam->v4l2_dev);
+ kfree(cam);
+ }
+
+@@ -1379,11 +1385,14 @@ static int zr364xx_board_init(struct zr364xx_camera *cam)
+ /* start read pipe */
+ err = zr364xx_start_readpipe(cam);
+ if (err)
+- goto err_free;
++ goto err_free_frames;
+
+ DBG(": board initialized\n");
+ return 0;
+
++err_free_frames:
++ for (i = 0; i < FRAMES; i++)
++ vfree(cam->buffer.frame[i].lpvbits);
+ err_free:
+ kfree(cam->pipe->transfer_buffer);
+ cam->pipe->transfer_buffer = NULL;
+@@ -1412,12 +1421,10 @@ static int zr364xx_probe(struct usb_interface *intf,
+ if (!cam)
+ return -ENOMEM;
+
+- cam->v4l2_dev.release = zr364xx_release;
+ err = v4l2_device_register(&intf->dev, &cam->v4l2_dev);
+ if (err < 0) {
+ dev_err(&udev->dev, "couldn't register v4l2_device\n");
+- kfree(cam);
+- return err;
++ goto free_cam;
+ }
+ hdl = &cam->ctrl_handler;
+ v4l2_ctrl_handler_init(hdl, 1);
+@@ -1426,7 +1433,7 @@ static int zr364xx_probe(struct usb_interface *intf,
+ if (hdl->error) {
+ err = hdl->error;
+ dev_err(&udev->dev, "couldn't register control\n");
+- goto fail;
++ goto unregister;
+ }
+ /* save the init method used by this camera */
+ cam->method = id->driver_info;
+@@ -1499,7 +1506,7 @@ static int zr364xx_probe(struct usb_interface *intf,
+ if (!cam->read_endpoint) {
+ err = -ENOMEM;
+ dev_err(&intf->dev, "Could not find bulk-in endpoint\n");
+- goto fail;
++ goto unregister;
+ }
+
+ /* v4l */
+@@ -1510,10 +1517,11 @@ static int zr364xx_probe(struct usb_interface *intf,
+
+ /* load zr364xx board specific */
+ err = zr364xx_board_init(cam);
+- if (!err)
+- err = v4l2_ctrl_handler_setup(hdl);
+ if (err)
+- goto fail;
++ goto unregister;
++ err = v4l2_ctrl_handler_setup(hdl);
++ if (err)
++ goto board_uninit;
+
+ spin_lock_init(&cam->slock);
+
+@@ -1528,16 +1536,21 @@ static int zr364xx_probe(struct usb_interface *intf,
+ err = video_register_device(&cam->vdev, VFL_TYPE_VIDEO, -1);
+ if (err) {
+ dev_err(&udev->dev, "video_register_device failed\n");
+- goto fail;
++ goto free_handler;
+ }
++ cam->v4l2_dev.release = zr364xx_release;
+
+ dev_info(&udev->dev, DRIVER_DESC " controlling device %s\n",
+ video_device_node_name(&cam->vdev));
+ return 0;
+
+-fail:
++free_handler:
+ v4l2_ctrl_handler_free(hdl);
++board_uninit:
++ zr364xx_board_uninit(cam);
++unregister:
+ v4l2_device_unregister(&cam->v4l2_dev);
++free_cam:
+ kfree(cam);
+ return err;
+ }
+--
+2.30.2
+
--- /dev/null
+From 52c65020c801237090a2ad5f69084277e723bff3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 6 Oct 2020 19:21:22 +0200
+Subject: media: zr364xx: propagate errors from zr364xx_start_readpipe()
+
+From: Evgeny Novikov <novikov@ispras.ru>
+
+[ Upstream commit af0321a5be3e5647441eb6b79355beaa592df97a ]
+
+zr364xx_start_readpipe() can fail but callers do not care about that.
+This can result in various negative consequences. The patch adds missed
+error handling.
+
+Found by Linux Driver Verification project (linuxtesting.org).
+
+Signed-off-by: Evgeny Novikov <novikov@ispras.ru>
+Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
+Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/media/usb/zr364xx/zr364xx.c | 31 ++++++++++++++++++++++-------
+ 1 file changed, 24 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/media/usb/zr364xx/zr364xx.c b/drivers/media/usb/zr364xx/zr364xx.c
+index 1b79053b2a05..5c8997d7de23 100644
+--- a/drivers/media/usb/zr364xx/zr364xx.c
++++ b/drivers/media/usb/zr364xx/zr364xx.c
+@@ -1328,6 +1328,7 @@ static int zr364xx_board_init(struct zr364xx_camera *cam)
+ {
+ struct zr364xx_pipeinfo *pipe = cam->pipe;
+ unsigned long i;
++ int err;
+
+ DBG("board init: %p\n", cam);
+ memset(pipe, 0, sizeof(*pipe));
+@@ -1360,9 +1361,8 @@ static int zr364xx_board_init(struct zr364xx_camera *cam)
+
+ if (i == 0) {
+ printk(KERN_INFO KBUILD_MODNAME ": out of memory. Aborting\n");
+- kfree(cam->pipe->transfer_buffer);
+- cam->pipe->transfer_buffer = NULL;
+- return -ENOMEM;
++ err = -ENOMEM;
++ goto err_free;
+ } else
+ cam->buffer.dwFrames = i;
+
+@@ -1377,9 +1377,17 @@ static int zr364xx_board_init(struct zr364xx_camera *cam)
+ /*** end create system buffers ***/
+
+ /* start read pipe */
+- zr364xx_start_readpipe(cam);
++ err = zr364xx_start_readpipe(cam);
++ if (err)
++ goto err_free;
++
+ DBG(": board initialized\n");
+ return 0;
++
++err_free:
++ kfree(cam->pipe->transfer_buffer);
++ cam->pipe->transfer_buffer = NULL;
++ return err;
+ }
+
+ static int zr364xx_probe(struct usb_interface *intf,
+@@ -1576,10 +1584,19 @@ static int zr364xx_resume(struct usb_interface *intf)
+ if (!cam->was_streaming)
+ return 0;
+
+- zr364xx_start_readpipe(cam);
++ res = zr364xx_start_readpipe(cam);
++ if (res)
++ return res;
++
+ res = zr364xx_prepare(cam);
+- if (!res)
+- zr364xx_start_acquire(cam);
++ if (res)
++ goto err_prepare;
++
++ zr364xx_start_acquire(cam);
++ return 0;
++
++err_prepare:
++ zr364xx_stop_readpipe(cam);
+ return res;
+ }
+ #endif
+--
+2.30.2
+
--- /dev/null
+From 25e9036a041c6d3c258c02e970b67fa62c10bdad Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 4 May 2021 18:34:44 -0700
+Subject: mm/cma: change cma mutex to irq safe spinlock
+
+From: Mike Kravetz <mike.kravetz@oracle.com>
+
+[ Upstream commit 0ef7dcac998fefc4767b7f10eb3b6df150c38a4e ]
+
+Patch series "make hugetlb put_page safe for all calling contexts", v5.
+
+This effort is the result a recent bug report [1]. Syzbot found a
+potential deadlock in the hugetlb put_page/free_huge_page_path. WARNING:
+SOFTIRQ-safe -> SOFTIRQ-unsafe lock order detected Since the
+free_huge_page_path already has code to 'hand off' page free requests to a
+workqueue, a suggestion was proposed to make the in_irq() detection
+accurate by always enabling PREEMPT_COUNT [2]. The outcome of that
+discussion was that the hugetlb put_page path (free_huge_page) path should
+be properly fixed and safe for all calling contexts.
+
+[1] https://lore.kernel.org/linux-mm/000000000000f1c03b05bc43aadc@google.com/
+[2] http://lkml.kernel.org/r/20210311021321.127500-1-mike.kravetz@oracle.com
+
+This patch (of 8):
+
+cma_release is currently a sleepable operatation because the bitmap
+manipulation is protected by cma->lock mutex. Hugetlb code which relies
+on cma_release for CMA backed (giga) hugetlb pages, however, needs to be
+irq safe.
+
+The lock doesn't protect any sleepable operation so it can be changed to a
+(irq aware) spin lock. The bitmap processing should be quite fast in
+typical case but if cma sizes grow to TB then we will likely need to
+replace the lock by a more optimized bitmap implementation.
+
+Link: https://lkml.kernel.org/r/20210409205254.242291-1-mike.kravetz@oracle.com
+Link: https://lkml.kernel.org/r/20210409205254.242291-2-mike.kravetz@oracle.com
+Signed-off-by: Mike Kravetz <mike.kravetz@oracle.com>
+Acked-by: Michal Hocko <mhocko@suse.com>
+Reviewed-by: David Hildenbrand <david@redhat.com>
+Acked-by: Roman Gushchin <guro@fb.com>
+Cc: Shakeel Butt <shakeelb@google.com>
+Cc: Oscar Salvador <osalvador@suse.de>
+Cc: Muchun Song <songmuchun@bytedance.com>
+Cc: David Rientjes <rientjes@google.com>
+Cc: Miaohe Lin <linmiaohe@huawei.com>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Cc: Matthew Wilcox <willy@infradead.org>
+Cc: HORIGUCHI NAOYA <naoya.horiguchi@nec.com>
+Cc: "Aneesh Kumar K . V" <aneesh.kumar@linux.ibm.com>
+Cc: Waiman Long <longman@redhat.com>
+Cc: Peter Xu <peterx@redhat.com>
+Cc: Mina Almasry <almasrymina@google.com>
+Cc: Hillf Danton <hdanton@sina.com>
+Cc: Joonsoo Kim <iamjoonsoo.kim@lge.com>
+Cc: Barry Song <song.bao.hua@hisilicon.com>
+Cc: Will Deacon <will@kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ mm/cma.c | 18 +++++++++---------
+ mm/cma.h | 2 +-
+ mm/cma_debug.c | 8 ++++----
+ 3 files changed, 14 insertions(+), 14 deletions(-)
+
+diff --git a/mm/cma.c b/mm/cma.c
+index 7f415d7cda9f..019e3aa2cc09 100644
+--- a/mm/cma.c
++++ b/mm/cma.c
+@@ -24,7 +24,6 @@
+ #include <linux/memblock.h>
+ #include <linux/err.h>
+ #include <linux/mm.h>
+-#include <linux/mutex.h>
+ #include <linux/sizes.h>
+ #include <linux/slab.h>
+ #include <linux/log2.h>
+@@ -84,13 +83,14 @@ static void cma_clear_bitmap(struct cma *cma, unsigned long pfn,
+ unsigned int count)
+ {
+ unsigned long bitmap_no, bitmap_count;
++ unsigned long flags;
+
+ bitmap_no = (pfn - cma->base_pfn) >> cma->order_per_bit;
+ bitmap_count = cma_bitmap_pages_to_bits(cma, count);
+
+- mutex_lock(&cma->lock);
++ spin_lock_irqsave(&cma->lock, flags);
+ bitmap_clear(cma->bitmap, bitmap_no, bitmap_count);
+- mutex_unlock(&cma->lock);
++ spin_unlock_irqrestore(&cma->lock, flags);
+ }
+
+ static void __init cma_activate_area(struct cma *cma)
+@@ -124,7 +124,7 @@ static void __init cma_activate_area(struct cma *cma)
+ init_cma_reserved_pageblock(pfn_to_page(base_pfn));
+ } while (--i);
+
+- mutex_init(&cma->lock);
++ spin_lock_init(&cma->lock);
+
+ #ifdef CONFIG_CMA_DEBUGFS
+ INIT_HLIST_HEAD(&cma->mem_head);
+@@ -377,7 +377,7 @@ static void cma_debug_show_areas(struct cma *cma)
+ unsigned long nr_part, nr_total = 0;
+ unsigned long nbits = cma_bitmap_maxno(cma);
+
+- mutex_lock(&cma->lock);
++ spin_lock_irq(&cma->lock);
+ pr_info("number of available pages: ");
+ for (;;) {
+ next_zero_bit = find_next_zero_bit(cma->bitmap, nbits, start);
+@@ -392,7 +392,7 @@ static void cma_debug_show_areas(struct cma *cma)
+ start = next_zero_bit + nr_zero;
+ }
+ pr_cont("=> %lu free of %lu total pages\n", nr_total, cma->count);
+- mutex_unlock(&cma->lock);
++ spin_unlock_irq(&cma->lock);
+ }
+ #else
+ static inline void cma_debug_show_areas(struct cma *cma) { }
+@@ -437,12 +437,12 @@ struct page *cma_alloc(struct cma *cma, size_t count, unsigned int align,
+ return NULL;
+
+ for (;;) {
+- mutex_lock(&cma->lock);
++ spin_lock_irq(&cma->lock);
+ bitmap_no = bitmap_find_next_zero_area_off(cma->bitmap,
+ bitmap_maxno, start, bitmap_count, mask,
+ offset);
+ if (bitmap_no >= bitmap_maxno) {
+- mutex_unlock(&cma->lock);
++ spin_unlock_irq(&cma->lock);
+ break;
+ }
+ bitmap_set(cma->bitmap, bitmap_no, bitmap_count);
+@@ -451,7 +451,7 @@ struct page *cma_alloc(struct cma *cma, size_t count, unsigned int align,
+ * our exclusive use. If the migration fails we will take the
+ * lock again and unmark it.
+ */
+- mutex_unlock(&cma->lock);
++ spin_unlock_irq(&cma->lock);
+
+ pfn = cma->base_pfn + (bitmap_no << cma->order_per_bit);
+ mutex_lock(&cma_mutex);
+diff --git a/mm/cma.h b/mm/cma.h
+index 42ae082cb067..c46c5050aaa9 100644
+--- a/mm/cma.h
++++ b/mm/cma.h
+@@ -9,7 +9,7 @@ struct cma {
+ unsigned long count;
+ unsigned long *bitmap;
+ unsigned int order_per_bit; /* Order of pages represented by one bit */
+- struct mutex lock;
++ spinlock_t lock;
+ #ifdef CONFIG_CMA_DEBUGFS
+ struct hlist_head mem_head;
+ spinlock_t mem_head_lock;
+diff --git a/mm/cma_debug.c b/mm/cma_debug.c
+index d5bf8aa34fdc..2e7704955f4f 100644
+--- a/mm/cma_debug.c
++++ b/mm/cma_debug.c
+@@ -36,10 +36,10 @@ static int cma_used_get(void *data, u64 *val)
+ struct cma *cma = data;
+ unsigned long used;
+
+- mutex_lock(&cma->lock);
++ spin_lock_irq(&cma->lock);
+ /* pages counter is smaller than sizeof(int) */
+ used = bitmap_weight(cma->bitmap, (int)cma_bitmap_maxno(cma));
+- mutex_unlock(&cma->lock);
++ spin_unlock_irq(&cma->lock);
+ *val = (u64)used << cma->order_per_bit;
+
+ return 0;
+@@ -53,7 +53,7 @@ static int cma_maxchunk_get(void *data, u64 *val)
+ unsigned long start, end = 0;
+ unsigned long bitmap_maxno = cma_bitmap_maxno(cma);
+
+- mutex_lock(&cma->lock);
++ spin_lock_irq(&cma->lock);
+ for (;;) {
+ start = find_next_zero_bit(cma->bitmap, bitmap_maxno, end);
+ if (start >= bitmap_maxno)
+@@ -61,7 +61,7 @@ static int cma_maxchunk_get(void *data, u64 *val)
+ end = find_next_bit(cma->bitmap, bitmap_maxno, start);
+ maxchunk = max(end - start, maxchunk);
+ }
+- mutex_unlock(&cma->lock);
++ spin_unlock_irq(&cma->lock);
+ *val = (u64)maxchunk << cma->order_per_bit;
+
+ return 0;
+--
+2.30.2
+
ath-modify-ath_key_delete-to-not-need-full-key-entry.patch
ath9k-postpone-key-cache-entry-deletion-for-txq-frames-reference-it.patch
mtd-cfi_cmdset_0002-fix-crash-when-erasing-writing-amd-cards.patch
+media-zr364xx-propagate-errors-from-zr364xx_start_re.patch
+media-zr364xx-fix-memory-leaks-in-probe.patch
+vdpa-extend-routine-to-accept-vdpa-device-name.patch
+vdpa-define-vdpa-mgmt-device-ops-and-a-netlink-inter.patch
+media-drivers-media-usb-fix-memory-leak-in-zr364xx_p.patch
+mm-cma-change-cma-mutex-to-irq-safe-spinlock.patch
+kvm-x86-factor-out-x86-instruction-emulation-with-de.patch
+kvm-x86-fix-warning-caused-by-stale-emulation-contex.patch
+usb-core-avoid-warnings-for-0-length-descriptor-requ.patch
+usb-core-fix-incorrect-pipe-calculation-in-do_proc_c.patch
--- /dev/null
+From 8119cc0d0c5575ee9b06ff0c53dcb610e1d212da Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 7 Jun 2021 11:23:07 -0400
+Subject: USB: core: Avoid WARNings for 0-length descriptor requests
+
+From: Alan Stern <stern@rowland.harvard.edu>
+
+[ Upstream commit 60dfe484cef45293e631b3a6e8995f1689818172 ]
+
+The USB core has utility routines to retrieve various types of
+descriptors. These routines will now provoke a WARN if they are asked
+to retrieve 0 bytes (USB "receive" requests must not have zero
+length), so avert this by checking the size argument at the start.
+
+CC: Johan Hovold <johan@kernel.org>
+Reported-and-tested-by: syzbot+7dbcd9ff34dc4ed45240@syzkaller.appspotmail.com
+Reviewed-by: Johan Hovold <johan@kernel.org>
+Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
+Link: https://lore.kernel.org/r/20210607152307.GD1768031@rowland.harvard.edu
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/usb/core/message.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
+index 19ebb542befc..dba2baca486e 100644
+--- a/drivers/usb/core/message.c
++++ b/drivers/usb/core/message.c
+@@ -785,6 +785,9 @@ int usb_get_descriptor(struct usb_device *dev, unsigned char type,
+ int i;
+ int result;
+
++ if (size <= 0) /* No point in asking for no data */
++ return -EINVAL;
++
+ memset(buf, 0, size); /* Make sure we parse really received data */
+
+ for (i = 0; i < 3; ++i) {
+@@ -833,6 +836,9 @@ static int usb_get_string(struct usb_device *dev, unsigned short langid,
+ int i;
+ int result;
+
++ if (size <= 0) /* No point in asking for no data */
++ return -EINVAL;
++
+ for (i = 0; i < 3; ++i) {
+ /* retry on length 0 or stall; some devices are flakey */
+ result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
+--
+2.30.2
+
--- /dev/null
+From c32e4b595f27626445595120180eb94fe8f0e120 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 12 Jul 2021 14:54:36 -0400
+Subject: USB: core: Fix incorrect pipe calculation in do_proc_control()
+
+From: Alan Stern <stern@rowland.harvard.edu>
+
+[ Upstream commit b0863f1927323110e3d0d69f6adb6a91018a9a3c ]
+
+When the user submits a control URB via usbfs, the user supplies the
+bRequestType value and the kernel uses it to compute the pipe value.
+However, do_proc_control() performs this computation incorrectly in
+the case where the bRequestType direction bit is set to USB_DIR_IN and
+the URB's transfer length is 0: The pipe's direction is also set to IN
+but it should be OUT, which is the direction the actual transfer will
+use regardless of bRequestType.
+
+Commit 5cc59c418fde ("USB: core: WARN if pipe direction != setup
+packet direction") added a check to compare the direction bit in the
+pipe value to a control URB's actual direction and to WARN if they are
+different. This can be triggered by the incorrect computation
+mentioned above, as found by syzbot.
+
+This patch fixes the computation, thus avoiding the WARNing.
+
+Reported-and-tested-by: syzbot+72af3105289dcb4c055b@syzkaller.appspotmail.com
+Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
+Link: https://lore.kernel.org/r/20210712185436.GB326369@rowland.harvard.edu
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/usb/core/devio.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
+index 2218941d35a3..73b60f013b20 100644
+--- a/drivers/usb/core/devio.c
++++ b/drivers/usb/core/devio.c
+@@ -1133,7 +1133,7 @@ static int do_proc_control(struct usb_dev_state *ps,
+ "wIndex=%04x wLength=%04x\n",
+ ctrl->bRequestType, ctrl->bRequest, ctrl->wValue,
+ ctrl->wIndex, ctrl->wLength);
+- if (ctrl->bRequestType & 0x80) {
++ if ((ctrl->bRequestType & USB_DIR_IN) && ctrl->wLength) {
+ pipe = usb_rcvctrlpipe(dev, 0);
+ snoop_urb(dev, NULL, pipe, ctrl->wLength, tmo, SUBMIT, NULL, 0);
+
+--
+2.30.2
+
--- /dev/null
+From ae78f42e582eb3e9c067f1dfee9cba5738c484c0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 5 Jan 2021 12:32:00 +0200
+Subject: vdpa: Define vdpa mgmt device, ops and a netlink interface
+
+From: Parav Pandit <parav@nvidia.com>
+
+[ Upstream commit 33b347503f014ebf76257327cbc7001c6b721956 ]
+
+To add one or more VDPA devices, define a management device which
+allows adding or removing vdpa device. A management device defines
+set of callbacks to manage vdpa devices.
+
+To begin with, it defines add and remove callbacks through which a user
+defined vdpa device can be added or removed.
+
+A unique management device is identified by its unique handle identified
+by management device name and optionally the bus name.
+
+Hence, introduce routine through which driver can register a
+management device and its callback operations for adding and remove
+a vdpa device.
+
+Introduce vdpa netlink socket family so that user can query management
+device and its attributes.
+
+Example of show vdpa management device which allows creating vdpa device of
+networking class (device id = 0x1) of virtio specification 1.1
+section 5.1.1.
+
+$ vdpa mgmtdev show
+vdpasim_net:
+ supported_classes:
+ net
+
+Example of showing vdpa management device in JSON format.
+
+$ vdpa mgmtdev show -jp
+{
+ "show": {
+ "vdpasim_net": {
+ "supported_classes": [ "net" ]
+ }
+ }
+}
+
+Signed-off-by: Parav Pandit <parav@nvidia.com>
+Reviewed-by: Eli Cohen <elic@nvidia.com>
+Reviewed-by: Jason Wang <jasowang@redhat.com>
+Link: https://lore.kernel.org/r/20210105103203.82508-4-parav@nvidia.com
+Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
+
+Including a bugfix:
+
+vpda: correctly size vdpa_nl_policy
+
+We need to ensure last entry of vdpa_nl_policy[]
+is zero, otherwise out-of-bounds access is hurting us.
+
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Reported-by: syzbot <syzkaller@googlegroups.com>
+Cc: Parav Pandit <parav@nvidia.com>
+Cc: Eli Cohen <elic@nvidia.com>
+Cc: Jason Wang <jasowang@redhat.com>
+Cc: Michael S. Tsirkin <mst@redhat.com>
+Link: https://lore.kernel.org/r/20210210134911.4119555-1-eric.dumazet@gmail.com
+Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/vdpa/Kconfig | 1 +
+ drivers/vdpa/vdpa.c | 213 +++++++++++++++++++++++++++++++++++++-
+ include/linux/vdpa.h | 31 ++++++
+ include/uapi/linux/vdpa.h | 31 ++++++
+ 4 files changed, 275 insertions(+), 1 deletion(-)
+ create mode 100644 include/uapi/linux/vdpa.h
+
+diff --git a/drivers/vdpa/Kconfig b/drivers/vdpa/Kconfig
+index 6caf539091e5..4be7be39be26 100644
+--- a/drivers/vdpa/Kconfig
++++ b/drivers/vdpa/Kconfig
+@@ -1,6 +1,7 @@
+ # SPDX-License-Identifier: GPL-2.0-only
+ menuconfig VDPA
+ tristate "vDPA drivers"
++ depends on NET
+ help
+ Enable this module to support vDPA device that uses a
+ datapath which complies with virtio specifications with
+diff --git a/drivers/vdpa/vdpa.c b/drivers/vdpa/vdpa.c
+index b3408cc8c63b..e96b81431e4f 100644
+--- a/drivers/vdpa/vdpa.c
++++ b/drivers/vdpa/vdpa.c
+@@ -11,11 +11,17 @@
+ #include <linux/idr.h>
+ #include <linux/slab.h>
+ #include <linux/vdpa.h>
++#include <uapi/linux/vdpa.h>
++#include <net/genetlink.h>
++#include <linux/mod_devicetable.h>
+
++static LIST_HEAD(mdev_head);
+ /* A global mutex that protects vdpa management device and device level operations. */
+ static DEFINE_MUTEX(vdpa_dev_mutex);
+ static DEFINE_IDA(vdpa_index_ida);
+
++static struct genl_family vdpa_nl_family;
++
+ static int vdpa_dev_probe(struct device *d)
+ {
+ struct vdpa_device *vdev = dev_to_vdpa(d);
+@@ -195,13 +201,218 @@ void vdpa_unregister_driver(struct vdpa_driver *drv)
+ }
+ EXPORT_SYMBOL_GPL(vdpa_unregister_driver);
+
++/**
++ * vdpa_mgmtdev_register - register a vdpa management device
++ *
++ * @mdev: Pointer to vdpa management device
++ * vdpa_mgmtdev_register() register a vdpa management device which supports
++ * vdpa device management.
++ */
++int vdpa_mgmtdev_register(struct vdpa_mgmt_dev *mdev)
++{
++ if (!mdev->device || !mdev->ops || !mdev->ops->dev_add || !mdev->ops->dev_del)
++ return -EINVAL;
++
++ INIT_LIST_HEAD(&mdev->list);
++ mutex_lock(&vdpa_dev_mutex);
++ list_add_tail(&mdev->list, &mdev_head);
++ mutex_unlock(&vdpa_dev_mutex);
++ return 0;
++}
++EXPORT_SYMBOL_GPL(vdpa_mgmtdev_register);
++
++void vdpa_mgmtdev_unregister(struct vdpa_mgmt_dev *mdev)
++{
++ mutex_lock(&vdpa_dev_mutex);
++ list_del(&mdev->list);
++ mutex_unlock(&vdpa_dev_mutex);
++}
++EXPORT_SYMBOL_GPL(vdpa_mgmtdev_unregister);
++
++static bool mgmtdev_handle_match(const struct vdpa_mgmt_dev *mdev,
++ const char *busname, const char *devname)
++{
++ /* Bus name is optional for simulated management device, so ignore the
++ * device with bus if bus attribute is provided.
++ */
++ if ((busname && !mdev->device->bus) || (!busname && mdev->device->bus))
++ return false;
++
++ if (!busname && strcmp(dev_name(mdev->device), devname) == 0)
++ return true;
++
++ if (busname && (strcmp(mdev->device->bus->name, busname) == 0) &&
++ (strcmp(dev_name(mdev->device), devname) == 0))
++ return true;
++
++ return false;
++}
++
++static struct vdpa_mgmt_dev *vdpa_mgmtdev_get_from_attr(struct nlattr **attrs)
++{
++ struct vdpa_mgmt_dev *mdev;
++ const char *busname = NULL;
++ const char *devname;
++
++ if (!attrs[VDPA_ATTR_MGMTDEV_DEV_NAME])
++ return ERR_PTR(-EINVAL);
++ devname = nla_data(attrs[VDPA_ATTR_MGMTDEV_DEV_NAME]);
++ if (attrs[VDPA_ATTR_MGMTDEV_BUS_NAME])
++ busname = nla_data(attrs[VDPA_ATTR_MGMTDEV_BUS_NAME]);
++
++ list_for_each_entry(mdev, &mdev_head, list) {
++ if (mgmtdev_handle_match(mdev, busname, devname))
++ return mdev;
++ }
++ return ERR_PTR(-ENODEV);
++}
++
++static int vdpa_nl_mgmtdev_handle_fill(struct sk_buff *msg, const struct vdpa_mgmt_dev *mdev)
++{
++ if (mdev->device->bus &&
++ nla_put_string(msg, VDPA_ATTR_MGMTDEV_BUS_NAME, mdev->device->bus->name))
++ return -EMSGSIZE;
++ if (nla_put_string(msg, VDPA_ATTR_MGMTDEV_DEV_NAME, dev_name(mdev->device)))
++ return -EMSGSIZE;
++ return 0;
++}
++
++static int vdpa_mgmtdev_fill(const struct vdpa_mgmt_dev *mdev, struct sk_buff *msg,
++ u32 portid, u32 seq, int flags)
++{
++ u64 supported_classes = 0;
++ void *hdr;
++ int i = 0;
++ int err;
++
++ hdr = genlmsg_put(msg, portid, seq, &vdpa_nl_family, flags, VDPA_CMD_MGMTDEV_NEW);
++ if (!hdr)
++ return -EMSGSIZE;
++ err = vdpa_nl_mgmtdev_handle_fill(msg, mdev);
++ if (err)
++ goto msg_err;
++
++ while (mdev->id_table[i].device) {
++ supported_classes |= BIT(mdev->id_table[i].device);
++ i++;
++ }
++
++ if (nla_put_u64_64bit(msg, VDPA_ATTR_MGMTDEV_SUPPORTED_CLASSES,
++ supported_classes, VDPA_ATTR_UNSPEC)) {
++ err = -EMSGSIZE;
++ goto msg_err;
++ }
++
++ genlmsg_end(msg, hdr);
++ return 0;
++
++msg_err:
++ genlmsg_cancel(msg, hdr);
++ return err;
++}
++
++static int vdpa_nl_cmd_mgmtdev_get_doit(struct sk_buff *skb, struct genl_info *info)
++{
++ struct vdpa_mgmt_dev *mdev;
++ struct sk_buff *msg;
++ int err;
++
++ msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
++ if (!msg)
++ return -ENOMEM;
++
++ mutex_lock(&vdpa_dev_mutex);
++ mdev = vdpa_mgmtdev_get_from_attr(info->attrs);
++ if (IS_ERR(mdev)) {
++ mutex_unlock(&vdpa_dev_mutex);
++ NL_SET_ERR_MSG_MOD(info->extack, "Fail to find the specified mgmt device");
++ err = PTR_ERR(mdev);
++ goto out;
++ }
++
++ err = vdpa_mgmtdev_fill(mdev, msg, info->snd_portid, info->snd_seq, 0);
++ mutex_unlock(&vdpa_dev_mutex);
++ if (err)
++ goto out;
++ err = genlmsg_reply(msg, info);
++ return err;
++
++out:
++ nlmsg_free(msg);
++ return err;
++}
++
++static int
++vdpa_nl_cmd_mgmtdev_get_dumpit(struct sk_buff *msg, struct netlink_callback *cb)
++{
++ struct vdpa_mgmt_dev *mdev;
++ int start = cb->args[0];
++ int idx = 0;
++ int err;
++
++ mutex_lock(&vdpa_dev_mutex);
++ list_for_each_entry(mdev, &mdev_head, list) {
++ if (idx < start) {
++ idx++;
++ continue;
++ }
++ err = vdpa_mgmtdev_fill(mdev, msg, NETLINK_CB(cb->skb).portid,
++ cb->nlh->nlmsg_seq, NLM_F_MULTI);
++ if (err)
++ goto out;
++ idx++;
++ }
++out:
++ mutex_unlock(&vdpa_dev_mutex);
++ cb->args[0] = idx;
++ return msg->len;
++}
++
++static const struct nla_policy vdpa_nl_policy[VDPA_ATTR_MAX + 1] = {
++ [VDPA_ATTR_MGMTDEV_BUS_NAME] = { .type = NLA_NUL_STRING },
++ [VDPA_ATTR_MGMTDEV_DEV_NAME] = { .type = NLA_STRING },
++};
++
++static const struct genl_ops vdpa_nl_ops[] = {
++ {
++ .cmd = VDPA_CMD_MGMTDEV_GET,
++ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
++ .doit = vdpa_nl_cmd_mgmtdev_get_doit,
++ .dumpit = vdpa_nl_cmd_mgmtdev_get_dumpit,
++ },
++};
++
++static struct genl_family vdpa_nl_family __ro_after_init = {
++ .name = VDPA_GENL_NAME,
++ .version = VDPA_GENL_VERSION,
++ .maxattr = VDPA_ATTR_MAX,
++ .policy = vdpa_nl_policy,
++ .netnsok = false,
++ .module = THIS_MODULE,
++ .ops = vdpa_nl_ops,
++ .n_ops = ARRAY_SIZE(vdpa_nl_ops),
++};
++
+ static int vdpa_init(void)
+ {
+- return bus_register(&vdpa_bus);
++ int err;
++
++ err = bus_register(&vdpa_bus);
++ if (err)
++ return err;
++ err = genl_register_family(&vdpa_nl_family);
++ if (err)
++ goto err;
++ return 0;
++
++err:
++ bus_unregister(&vdpa_bus);
++ return err;
+ }
+
+ static void __exit vdpa_exit(void)
+ {
++ genl_unregister_family(&vdpa_nl_family);
+ bus_unregister(&vdpa_bus);
+ ida_destroy(&vdpa_index_ida);
+ }
+diff --git a/include/linux/vdpa.h b/include/linux/vdpa.h
+index ac58462e8aed..d2f4e021ac79 100644
+--- a/include/linux/vdpa.h
++++ b/include/linux/vdpa.h
+@@ -35,6 +35,8 @@ struct vdpa_vq_state {
+ u16 avail_index;
+ };
+
++struct vdpa_mgmt_dev;
++
+ /**
+ * vDPA device - representation of a vDPA device
+ * @dev: underlying device
+@@ -334,4 +336,33 @@ static inline void vdpa_get_config(struct vdpa_device *vdev, unsigned offset,
+ ops->get_config(vdev, offset, buf, len);
+ }
+
++/**
++ * vdpa_mgmtdev_ops - vdpa device ops
++ * @dev_add: Add a vdpa device using alloc and register
++ * @mdev: parent device to use for device addition
++ * @name: name of the new vdpa device
++ * Driver need to add a new device using _vdpa_register_device()
++ * after fully initializing the vdpa device. Driver must return 0
++ * on success or appropriate error code.
++ * @dev_del: Remove a vdpa device using unregister
++ * @mdev: parent device to use for device removal
++ * @dev: vdpa device to remove
++ * Driver need to remove the specified device by calling
++ * _vdpa_unregister_device().
++ */
++struct vdpa_mgmtdev_ops {
++ int (*dev_add)(struct vdpa_mgmt_dev *mdev, const char *name);
++ void (*dev_del)(struct vdpa_mgmt_dev *mdev, struct vdpa_device *dev);
++};
++
++struct vdpa_mgmt_dev {
++ struct device *device;
++ const struct vdpa_mgmtdev_ops *ops;
++ const struct virtio_device_id *id_table; /* supported ids */
++ struct list_head list;
++};
++
++int vdpa_mgmtdev_register(struct vdpa_mgmt_dev *mdev);
++void vdpa_mgmtdev_unregister(struct vdpa_mgmt_dev *mdev);
++
+ #endif /* _LINUX_VDPA_H */
+diff --git a/include/uapi/linux/vdpa.h b/include/uapi/linux/vdpa.h
+new file mode 100644
+index 000000000000..d44d82e567b1
+--- /dev/null
++++ b/include/uapi/linux/vdpa.h
+@@ -0,0 +1,31 @@
++/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */
++/*
++ * vdpa device management interface
++ * Copyright (c) 2020 Mellanox Technologies Ltd. All rights reserved.
++ */
++
++#ifndef _UAPI_LINUX_VDPA_H_
++#define _UAPI_LINUX_VDPA_H_
++
++#define VDPA_GENL_NAME "vdpa"
++#define VDPA_GENL_VERSION 0x1
++
++enum vdpa_command {
++ VDPA_CMD_UNSPEC,
++ VDPA_CMD_MGMTDEV_NEW,
++ VDPA_CMD_MGMTDEV_GET, /* can dump */
++};
++
++enum vdpa_attr {
++ VDPA_ATTR_UNSPEC,
++
++ /* bus name (optional) + dev name together make the parent device handle */
++ VDPA_ATTR_MGMTDEV_BUS_NAME, /* string */
++ VDPA_ATTR_MGMTDEV_DEV_NAME, /* string */
++ VDPA_ATTR_MGMTDEV_SUPPORTED_CLASSES, /* u64 */
++
++ /* new attributes must be added above here */
++ VDPA_ATTR_MAX,
++};
++
++#endif
+--
+2.30.2
+
--- /dev/null
+From afa16171dec6abe830dfeb803c9cc18f28fe802c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 5 Jan 2021 12:31:59 +0200
+Subject: vdpa: Extend routine to accept vdpa device name
+
+From: Parav Pandit <parav@nvidia.com>
+
+[ Upstream commit fd70a406a344e084ac680c3f14e71d37d6023883 ]
+
+In a subsequent patch, when user initiated command creates a vdpa device,
+the user chooses the name of the vdpa device.
+To support it, extend the device allocation API to consider this name
+specified by the caller driver.
+
+Signed-off-by: Parav Pandit <parav@nvidia.com>
+Reviewed-by: Eli Cohen <elic@nvidia.com>
+Acked-by: Jason Wang <jasowang@redhat.com>
+Link: https://lore.kernel.org/r/20210105103203.82508-3-parav@nvidia.com
+Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/vdpa/ifcvf/ifcvf_main.c | 2 +-
+ drivers/vdpa/mlx5/net/mlx5_vnet.c | 2 +-
+ drivers/vdpa/vdpa.c | 36 +++++++++++++++++++++++++++----
+ drivers/vdpa/vdpa_sim/vdpa_sim.c | 2 +-
+ include/linux/vdpa.h | 7 +++---
+ 5 files changed, 38 insertions(+), 11 deletions(-)
+
+diff --git a/drivers/vdpa/ifcvf/ifcvf_main.c b/drivers/vdpa/ifcvf/ifcvf_main.c
+index 8b4028556cb6..23474af7da40 100644
+--- a/drivers/vdpa/ifcvf/ifcvf_main.c
++++ b/drivers/vdpa/ifcvf/ifcvf_main.c
+@@ -439,7 +439,7 @@ static int ifcvf_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+
+ adapter = vdpa_alloc_device(struct ifcvf_adapter, vdpa,
+ dev, &ifc_vdpa_ops,
+- IFCVF_MAX_QUEUE_PAIRS * 2);
++ IFCVF_MAX_QUEUE_PAIRS * 2, NULL);
+ if (adapter == NULL) {
+ IFCVF_ERR(pdev, "Failed to allocate vDPA structure");
+ return -ENOMEM;
+diff --git a/drivers/vdpa/mlx5/net/mlx5_vnet.c b/drivers/vdpa/mlx5/net/mlx5_vnet.c
+index fbdc9468818d..b15d8552832a 100644
+--- a/drivers/vdpa/mlx5/net/mlx5_vnet.c
++++ b/drivers/vdpa/mlx5/net/mlx5_vnet.c
+@@ -1982,7 +1982,7 @@ void *mlx5_vdpa_add_dev(struct mlx5_core_dev *mdev)
+ max_vqs = min_t(u32, max_vqs, MLX5_MAX_SUPPORTED_VQS);
+
+ ndev = vdpa_alloc_device(struct mlx5_vdpa_net, mvdev.vdev, mdev->device, &mlx5_vdpa_ops,
+- 2 * mlx5_vdpa_max_qps(max_vqs));
++ 2 * mlx5_vdpa_max_qps(max_vqs), NULL);
+ if (IS_ERR(ndev))
+ return ndev;
+
+diff --git a/drivers/vdpa/vdpa.c b/drivers/vdpa/vdpa.c
+index a69ffc991e13..b3408cc8c63b 100644
+--- a/drivers/vdpa/vdpa.c
++++ b/drivers/vdpa/vdpa.c
+@@ -12,6 +12,8 @@
+ #include <linux/slab.h>
+ #include <linux/vdpa.h>
+
++/* A global mutex that protects vdpa management device and device level operations. */
++static DEFINE_MUTEX(vdpa_dev_mutex);
+ static DEFINE_IDA(vdpa_index_ida);
+
+ static int vdpa_dev_probe(struct device *d)
+@@ -63,6 +65,7 @@ static void vdpa_release_dev(struct device *d)
+ * @config: the bus operations that is supported by this device
+ * @nvqs: number of virtqueues supported by this device
+ * @size: size of the parent structure that contains private data
++ * @name: name of the vdpa device; optional.
+ *
+ * Driver should use vdpa_alloc_device() wrapper macro instead of
+ * using this directly.
+@@ -72,8 +75,7 @@ static void vdpa_release_dev(struct device *d)
+ */
+ struct vdpa_device *__vdpa_alloc_device(struct device *parent,
+ const struct vdpa_config_ops *config,
+- int nvqs,
+- size_t size)
++ int nvqs, size_t size, const char *name)
+ {
+ struct vdpa_device *vdev;
+ int err = -EINVAL;
+@@ -101,7 +103,10 @@ struct vdpa_device *__vdpa_alloc_device(struct device *parent,
+ vdev->features_valid = false;
+ vdev->nvqs = nvqs;
+
+- err = dev_set_name(&vdev->dev, "vdpa%u", vdev->index);
++ if (name)
++ err = dev_set_name(&vdev->dev, "%s", name);
++ else
++ err = dev_set_name(&vdev->dev, "vdpa%u", vdev->index);
+ if (err)
+ goto err_name;
+
+@@ -118,6 +123,13 @@ struct vdpa_device *__vdpa_alloc_device(struct device *parent,
+ }
+ EXPORT_SYMBOL_GPL(__vdpa_alloc_device);
+
++static int vdpa_name_match(struct device *dev, const void *data)
++{
++ struct vdpa_device *vdev = container_of(dev, struct vdpa_device, dev);
++
++ return (strcmp(dev_name(&vdev->dev), data) == 0);
++}
++
+ /**
+ * vdpa_register_device - register a vDPA device
+ * Callers must have a succeed call of vdpa_alloc_device() before.
+@@ -127,7 +139,21 @@ EXPORT_SYMBOL_GPL(__vdpa_alloc_device);
+ */
+ int vdpa_register_device(struct vdpa_device *vdev)
+ {
+- return device_add(&vdev->dev);
++ struct device *dev;
++ int err;
++
++ mutex_lock(&vdpa_dev_mutex);
++ dev = bus_find_device(&vdpa_bus, NULL, dev_name(&vdev->dev), vdpa_name_match);
++ if (dev) {
++ put_device(dev);
++ err = -EEXIST;
++ goto name_err;
++ }
++
++ err = device_add(&vdev->dev);
++name_err:
++ mutex_unlock(&vdpa_dev_mutex);
++ return err;
+ }
+ EXPORT_SYMBOL_GPL(vdpa_register_device);
+
+@@ -137,7 +163,9 @@ EXPORT_SYMBOL_GPL(vdpa_register_device);
+ */
+ void vdpa_unregister_device(struct vdpa_device *vdev)
+ {
++ mutex_lock(&vdpa_dev_mutex);
+ device_unregister(&vdev->dev);
++ mutex_unlock(&vdpa_dev_mutex);
+ }
+ EXPORT_SYMBOL_GPL(vdpa_unregister_device);
+
+diff --git a/drivers/vdpa/vdpa_sim/vdpa_sim.c b/drivers/vdpa/vdpa_sim/vdpa_sim.c
+index f2ad450db547..df1f585e08dc 100644
+--- a/drivers/vdpa/vdpa_sim/vdpa_sim.c
++++ b/drivers/vdpa/vdpa_sim/vdpa_sim.c
+@@ -370,7 +370,7 @@ static struct vdpasim *vdpasim_create(struct vdpasim_dev_attr *dev_attr)
+ ops = &vdpasim_net_config_ops;
+
+ vdpasim = vdpa_alloc_device(struct vdpasim, vdpa, NULL, ops,
+- dev_attr->nvqs);
++ dev_attr->nvqs, NULL);
+ if (!vdpasim)
+ goto err_alloc;
+
+diff --git a/include/linux/vdpa.h b/include/linux/vdpa.h
+index 30bc7a7223bb..ac58462e8aed 100644
+--- a/include/linux/vdpa.h
++++ b/include/linux/vdpa.h
+@@ -244,15 +244,14 @@ struct vdpa_config_ops {
+
+ struct vdpa_device *__vdpa_alloc_device(struct device *parent,
+ const struct vdpa_config_ops *config,
+- int nvqs,
+- size_t size);
++ int nvqs, size_t size, const char *name);
+
+-#define vdpa_alloc_device(dev_struct, member, parent, config, nvqs) \
++#define vdpa_alloc_device(dev_struct, member, parent, config, nvqs, name) \
+ container_of(__vdpa_alloc_device( \
+ parent, config, nvqs, \
+ sizeof(dev_struct) + \
+ BUILD_BUG_ON_ZERO(offsetof( \
+- dev_struct, member))), \
++ dev_struct, member)), name), \
+ dev_struct, member)
+
+ int vdpa_register_device(struct vdpa_device *vdev);
+--
+2.30.2
+