]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
Fixes for 5.10
authorSasha Levin <sashal@kernel.org>
Thu, 19 Aug 2021 00:54:22 +0000 (20:54 -0400)
committerSasha Levin <sashal@kernel.org>
Thu, 19 Aug 2021 00:54:22 +0000 (20:54 -0400)
Signed-off-by: Sasha Levin <sashal@kernel.org>
queue-5.10/kvm-x86-factor-out-x86-instruction-emulation-with-de.patch [new file with mode: 0644]
queue-5.10/kvm-x86-fix-warning-caused-by-stale-emulation-contex.patch [new file with mode: 0644]
queue-5.10/media-drivers-media-usb-fix-memory-leak-in-zr364xx_p.patch [new file with mode: 0644]
queue-5.10/media-zr364xx-fix-memory-leaks-in-probe.patch [new file with mode: 0644]
queue-5.10/media-zr364xx-propagate-errors-from-zr364xx_start_re.patch [new file with mode: 0644]
queue-5.10/mm-cma-change-cma-mutex-to-irq-safe-spinlock.patch [new file with mode: 0644]
queue-5.10/series
queue-5.10/usb-core-avoid-warnings-for-0-length-descriptor-requ.patch [new file with mode: 0644]
queue-5.10/usb-core-fix-incorrect-pipe-calculation-in-do_proc_c.patch [new file with mode: 0644]
queue-5.10/vdpa-define-vdpa-mgmt-device-ops-and-a-netlink-inter.patch [new file with mode: 0644]
queue-5.10/vdpa-extend-routine-to-accept-vdpa-device-name.patch [new file with mode: 0644]

diff --git a/queue-5.10/kvm-x86-factor-out-x86-instruction-emulation-with-de.patch b/queue-5.10/kvm-x86-factor-out-x86-instruction-emulation-with-de.patch
new file mode 100644 (file)
index 0000000..6aa9714
--- /dev/null
@@ -0,0 +1,124 @@
+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
+
diff --git a/queue-5.10/kvm-x86-fix-warning-caused-by-stale-emulation-contex.patch b/queue-5.10/kvm-x86-fix-warning-caused-by-stale-emulation-contex.patch
new file mode 100644 (file)
index 0000000..3c008ab
--- /dev/null
@@ -0,0 +1,77 @@
+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
+
diff --git a/queue-5.10/media-drivers-media-usb-fix-memory-leak-in-zr364xx_p.patch b/queue-5.10/media-drivers-media-usb-fix-memory-leak-in-zr364xx_p.patch
new file mode 100644 (file)
index 0000000..b0dec6d
--- /dev/null
@@ -0,0 +1,80 @@
+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
+
diff --git a/queue-5.10/media-zr364xx-fix-memory-leaks-in-probe.patch b/queue-5.10/media-zr364xx-fix-memory-leaks-in-probe.patch
new file mode 100644 (file)
index 0000000..e8cf091
--- /dev/null
@@ -0,0 +1,186 @@
+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
+
diff --git a/queue-5.10/media-zr364xx-propagate-errors-from-zr364xx_start_re.patch b/queue-5.10/media-zr364xx-propagate-errors-from-zr364xx_start_re.patch
new file mode 100644 (file)
index 0000000..125ed07
--- /dev/null
@@ -0,0 +1,92 @@
+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
+
diff --git a/queue-5.10/mm-cma-change-cma-mutex-to-irq-safe-spinlock.patch b/queue-5.10/mm-cma-change-cma-mutex-to-irq-safe-spinlock.patch
new file mode 100644 (file)
index 0000000..f4e6c00
--- /dev/null
@@ -0,0 +1,197 @@
+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
+
index 051fef1b72f0bff608e196948a33f373d01bc679..ccd4b6df7dba5ef8c191b9c8a3fffc93118caa60 100644 (file)
@@ -4,3 +4,13 @@ ath-export-ath_hw_keysetmac.patch
 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
diff --git a/queue-5.10/usb-core-avoid-warnings-for-0-length-descriptor-requ.patch b/queue-5.10/usb-core-avoid-warnings-for-0-length-descriptor-requ.patch
new file mode 100644 (file)
index 0000000..d096d14
--- /dev/null
@@ -0,0 +1,52 @@
+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
+
diff --git a/queue-5.10/usb-core-fix-incorrect-pipe-calculation-in-do_proc_c.patch b/queue-5.10/usb-core-fix-incorrect-pipe-calculation-in-do_proc_c.patch
new file mode 100644 (file)
index 0000000..25645f1
--- /dev/null
@@ -0,0 +1,50 @@
+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
+
diff --git a/queue-5.10/vdpa-define-vdpa-mgmt-device-ops-and-a-netlink-inter.patch b/queue-5.10/vdpa-define-vdpa-mgmt-device-ops-and-a-netlink-inter.patch
new file mode 100644 (file)
index 0000000..90f747a
--- /dev/null
@@ -0,0 +1,417 @@
+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
+
diff --git a/queue-5.10/vdpa-extend-routine-to-accept-vdpa-device-name.patch b/queue-5.10/vdpa-extend-routine-to-accept-vdpa-device-name.patch
new file mode 100644 (file)
index 0000000..7a6db02
--- /dev/null
@@ -0,0 +1,183 @@
+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
+