From: Sasha Levin Date: Thu, 19 Aug 2021 00:54:22 +0000 (-0400) Subject: Fixes for 5.10 X-Git-Tag: v5.13.13~40 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=94e19281317ea5894173579ec4ae9bf4a5201bec;p=thirdparty%2Fkernel%2Fstable-queue.git Fixes for 5.10 Signed-off-by: Sasha Levin --- 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 index 00000000000..6aa97140395 --- /dev/null +++ b/queue-5.10/kvm-x86-factor-out-x86-instruction-emulation-with-de.patch @@ -0,0 +1,124 @@ +From 3bd1f94b8bf98369fbe00e8a1bfcc3ce35b6ccff Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 26 Jan 2021 03:18:28 -0500 +Subject: KVM: x86: Factor out x86 instruction emulation with decoding + +From: Wei Huang + +[ 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 +Signed-off-by: Bandan Das +Signed-off-by: Wei Huang +Message-Id: <20210126081831.570253-2-wei.huang2@amd.com> +Signed-off-by: Paolo Bonzini +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..3c008ab5eac --- /dev/null +++ b/queue-5.10/kvm-x86-fix-warning-caused-by-stale-emulation-contex.patch @@ -0,0 +1,77 @@ +From c20eeb98dcc16a54442d453f764591275ac750d4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 27 May 2021 17:01:36 -0700 +Subject: KVM: X86: Fix warning caused by stale emulation context + +From: Wanpeng Li + +[ 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 +Reviewed-by: Sean Christopherson +Message-Id: <1622160097-37633-1-git-send-email-wanpengli@tencent.com> +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..b0dec6dfaba --- /dev/null +++ b/queue-5.10/media-drivers-media-usb-fix-memory-leak-in-zr364xx_p.patch @@ -0,0 +1,80 @@ +From aede96a2fd1274b2a5c6d6e0fa21d317f3ccc1c0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 1 Mar 2021 21:38:26 +0100 +Subject: media: drivers/media/usb: fix memory leak in zr364xx_probe + +From: Pavel Skripkin + +[ 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 +Signed-off-by: Hans Verkuil +Signed-off-by: Mauro Carvalho Chehab +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..e8cf091e1a5 --- /dev/null +++ b/queue-5.10/media-zr364xx-fix-memory-leaks-in-probe.patch @@ -0,0 +1,186 @@ +From 3463701e1a5cf2ceacc112cb12990f5fecee7be5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 21 Jan 2021 07:44:00 +0100 +Subject: media: zr364xx: fix memory leaks in probe() + +From: Dan Carpenter + +[ 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 +Signed-off-by: Hans Verkuil +Signed-off-by: Mauro Carvalho Chehab +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..125ed070b06 --- /dev/null +++ b/queue-5.10/media-zr364xx-propagate-errors-from-zr364xx_start_re.patch @@ -0,0 +1,92 @@ +From 52c65020c801237090a2ad5f69084277e723bff3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 6 Oct 2020 19:21:22 +0200 +Subject: media: zr364xx: propagate errors from zr364xx_start_readpipe() + +From: Evgeny Novikov + +[ 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 +Signed-off-by: Hans Verkuil +Signed-off-by: Mauro Carvalho Chehab +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..f4e6c0020c2 --- /dev/null +++ b/queue-5.10/mm-cma-change-cma-mutex-to-irq-safe-spinlock.patch @@ -0,0 +1,197 @@ +From 25e9036a041c6d3c258c02e970b67fa62c10bdad Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 4 May 2021 18:34:44 -0700 +Subject: mm/cma: change cma mutex to irq safe spinlock + +From: Mike Kravetz + +[ 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 +Acked-by: Michal Hocko +Reviewed-by: David Hildenbrand +Acked-by: Roman Gushchin +Cc: Shakeel Butt +Cc: Oscar Salvador +Cc: Muchun Song +Cc: David Rientjes +Cc: Miaohe Lin +Cc: Peter Zijlstra +Cc: Matthew Wilcox +Cc: HORIGUCHI NAOYA +Cc: "Aneesh Kumar K . V" +Cc: Waiman Long +Cc: Peter Xu +Cc: Mina Almasry +Cc: Hillf Danton +Cc: Joonsoo Kim +Cc: Barry Song +Cc: Will Deacon +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Sasha Levin +--- + 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 + #include + #include +-#include + #include + #include + #include +@@ -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 + diff --git a/queue-5.10/series b/queue-5.10/series index 051fef1b72f..ccd4b6df7db 100644 --- a/queue-5.10/series +++ b/queue-5.10/series @@ -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 index 00000000000..d096d14687f --- /dev/null +++ b/queue-5.10/usb-core-avoid-warnings-for-0-length-descriptor-requ.patch @@ -0,0 +1,52 @@ +From 8119cc0d0c5575ee9b06ff0c53dcb610e1d212da Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 7 Jun 2021 11:23:07 -0400 +Subject: USB: core: Avoid WARNings for 0-length descriptor requests + +From: Alan Stern + +[ 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 +Reported-and-tested-by: syzbot+7dbcd9ff34dc4ed45240@syzkaller.appspotmail.com +Reviewed-by: Johan Hovold +Signed-off-by: Alan Stern +Link: https://lore.kernel.org/r/20210607152307.GD1768031@rowland.harvard.edu +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..25645f1184d --- /dev/null +++ b/queue-5.10/usb-core-fix-incorrect-pipe-calculation-in-do_proc_c.patch @@ -0,0 +1,50 @@ +From c32e4b595f27626445595120180eb94fe8f0e120 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 12 Jul 2021 14:54:36 -0400 +Subject: USB: core: Fix incorrect pipe calculation in do_proc_control() + +From: Alan Stern + +[ 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 +Link: https://lore.kernel.org/r/20210712185436.GB326369@rowland.harvard.edu +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..90f747acbe4 --- /dev/null +++ b/queue-5.10/vdpa-define-vdpa-mgmt-device-ops-and-a-netlink-inter.patch @@ -0,0 +1,417 @@ +From ae78f42e582eb3e9c067f1dfee9cba5738c484c0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 5 Jan 2021 12:32:00 +0200 +Subject: vdpa: Define vdpa mgmt device, ops and a netlink interface + +From: Parav Pandit + +[ 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 +Reviewed-by: Eli Cohen +Reviewed-by: Jason Wang +Link: https://lore.kernel.org/r/20210105103203.82508-4-parav@nvidia.com +Signed-off-by: Michael S. Tsirkin + +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 +Reported-by: syzbot +Cc: Parav Pandit +Cc: Eli Cohen +Cc: Jason Wang +Cc: Michael S. Tsirkin +Link: https://lore.kernel.org/r/20210210134911.4119555-1-eric.dumazet@gmail.com +Signed-off-by: Michael S. Tsirkin +Signed-off-by: Sasha Levin +--- + 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 + #include + #include ++#include ++#include ++#include + ++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 index 00000000000..7a6db02e31d --- /dev/null +++ b/queue-5.10/vdpa-extend-routine-to-accept-vdpa-device-name.patch @@ -0,0 +1,183 @@ +From afa16171dec6abe830dfeb803c9cc18f28fe802c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 5 Jan 2021 12:31:59 +0200 +Subject: vdpa: Extend routine to accept vdpa device name + +From: Parav Pandit + +[ 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 +Reviewed-by: Eli Cohen +Acked-by: Jason Wang +Link: https://lore.kernel.org/r/20210105103203.82508-3-parav@nvidia.com +Signed-off-by: Michael S. Tsirkin +Signed-off-by: Sasha Levin +--- + 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 + #include + ++/* 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 +