Received: by 2002:a25:8b12:0:0:0:0:0 with SMTP id i18csp3528188ybl; Mon, 12 Aug 2019 01:55:38 -0700 (PDT) X-Google-Smtp-Source: APXvYqyU7ZOVyfpHSjyuK8CYxl7KtfM9bn47i4ifY64zsgtfYkwxHB57hV+KQ3eyOztsF08nCTYj X-Received: by 2002:a63:221f:: with SMTP id i31mr29873729pgi.251.1565600138402; Mon, 12 Aug 2019 01:55:38 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1565600138; cv=none; d=google.com; s=arc-20160816; b=eJTH901ZLUejrz8o6knNqhG5+TNl2juicPHnwahyqg27BSjBtW8v7kirn6V9Ug/3bk UVftR7QVGpw31MGUoYDd9exgRzweRz3kmJoJMhTH+xd7UQBisP0jdeKGs0gCe0xucLKF XqGhkKywKD1oEZN2t5ecr17ynYKIvdyclhLNbWBaIcjDUJldFXZTg1MByX4KRsYXl6VZ nX16SjMB6944iUd114VTn3QfC0m2KTF0G4qtorGub3Y92ggykX6Ixv5mxcDC04+BMuur 1MD7MUhPD0owMfwCoijDewXaRvd5B30rPOTjNdz5zxTITbQCc/0EshclTa4/Dez+2rpA +ZBw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:references :in-reply-to:message-id:date:subject:cc:to:from; bh=ZTKxvgX0/FffU4K1/dDH8Nk6SEBE3n44eLpbjTrbeXE=; b=s4czNzegjdSfd+U8wVMSLLpI875gUWvun2YRmehfLie5XyKuOfjyk9v+oqxQFxe+MW YSxsZm0rHpLeMIm5WBrNGVj9taXWjqUZFsh8NxAhbZQoz+cDMXuuh4a6mEzoyXGn5+gi n/Bd4p+Uz9fDaVlOTeksfPUvSh+zXv+1+9pXp2+OGljpQuUFuXdbDgwGSUl7cNL5cMcS 6Egn6biqUS3aeSZfMC9U7aAYB7RF7SFuUgYJ+apJSMpwb8a3jGJkvVaOJIeD2DKY01aZ 9p5CSBT9Z1f70iPFiIKzeo+Hl4viV01aq5lor7fj5Z59UeSdLPlQYCZgwWw9q8zhYmey HUFg== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=alibaba.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id m15si63972636pff.267.2019.08.12.01.55.23; Mon, 12 Aug 2019 01:55:38 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=alibaba.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727279AbfHLIwp (ORCPT + 99 others); Mon, 12 Aug 2019 04:52:45 -0400 Received: from out30-132.freemail.mail.aliyun.com ([115.124.30.132]:34123 "EHLO out30-132.freemail.mail.aliyun.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726495AbfHLIwp (ORCPT ); Mon, 12 Aug 2019 04:52:45 -0400 X-Alimail-AntiSpam: AC=PASS;BC=-1|-1;BR=01201311R171e4;CH=green;DM=||false|;FP=0|-1|-1|-1|0|-1|-1|-1;HT=e01e07486;MF=luoben@linux.alibaba.com;NM=1;PH=DS;RN=7;SR=0;TI=SMTPD_---0TZFSTZI_1565599949; Received: from localhost(mailfrom:luoben@linux.alibaba.com fp:SMTPD_---0TZFSTZI_1565599949) by smtp.aliyun-inc.com(127.0.0.1); Mon, 12 Aug 2019 16:52:37 +0800 From: Ben Luo To: tglx@linutronix.de, alex.williamson@redhat.com, linux-kernel@vger.kernel.org Cc: tao.ma@linux.alibaba.com, gerry@linux.alibaba.com, nanhai.zou@linux.alibaba.com, linyunsheng@huawei.com Subject: [PATCH v2 3/3] vfio_pci: make use of update_irq_devid and optimize irq ops Date: Mon, 12 Aug 2019 16:52:06 +0800 Message-Id: X-Mailer: git-send-email 1.8.3.1 In-Reply-To: References: In-Reply-To: References: Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org When userspace (e.g. qemu) triggers a switch between KVM irqfd and userspace eventfd, only dev_id of irq action (i.e. the "trigger" in this patch's context) will be changed, but a free-then-request-irq action is taken in current code. And, irq affinity setting in VM will also trigger a free-then-request-irq action, which actully changes nothing, but only fires a producer re-registration to update irte in case that posted-interrupt is in use. This patch makes use of update_irq_devid() and optimize both cases above, which reduces the risk of losing interrupt and also cuts some overhead. Signed-off-by: Ben Luo Reviewed-by: Liu Jiang Reviewed-by: Zou Nanhai Reviewed-by: Yunsheng Lin --- drivers/vfio/pci/vfio_pci_intrs.c | 99 ++++++++++++++++++++++++--------------- 1 file changed, 61 insertions(+), 38 deletions(-) diff --git a/drivers/vfio/pci/vfio_pci_intrs.c b/drivers/vfio/pci/vfio_pci_intrs.c index 3fa3f72..541153d 100644 --- a/drivers/vfio/pci/vfio_pci_intrs.c +++ b/drivers/vfio/pci/vfio_pci_intrs.c @@ -284,70 +284,93 @@ static int vfio_msi_enable(struct vfio_pci_device *vdev, int nvec, bool msix) static int vfio_msi_set_vector_signal(struct vfio_pci_device *vdev, int vector, int fd, bool msix) { + struct eventfd_ctx *trigger = NULL; struct pci_dev *pdev = vdev->pdev; - struct eventfd_ctx *trigger; int irq, ret; if (vector < 0 || vector >= vdev->num_ctx) return -EINVAL; + if (fd >= 0) { + trigger = eventfd_ctx_fdget(fd); + if (IS_ERR(trigger)) + return PTR_ERR(trigger); + } + irq = pci_irq_vector(pdev, vector); if (vdev->ctx[vector].trigger) { - free_irq(irq, vdev->ctx[vector].trigger); - irq_bypass_unregister_producer(&vdev->ctx[vector].producer); - kfree(vdev->ctx[vector].name); - eventfd_ctx_put(vdev->ctx[vector].trigger); - vdev->ctx[vector].trigger = NULL; + if (vdev->ctx[vector].trigger == trigger) { + irq_bypass_unregister_producer(&vdev->ctx[vector].producer); + } else if (trigger) { + ret = update_irq_devid(irq, + vdev->ctx[vector].trigger, trigger); + if (unlikely(ret)) { + dev_info(&pdev->dev, + "update_irq_devid %d (token %p) fails: %d\n", + irq, vdev->ctx[vector].trigger, ret); + eventfd_ctx_put(trigger); + return ret; + } + irq_bypass_unregister_producer(&vdev->ctx[vector].producer); + eventfd_ctx_put(vdev->ctx[vector].trigger); + vdev->ctx[vector].producer.token = trigger; + vdev->ctx[vector].trigger = trigger; + } else { + free_irq(irq, vdev->ctx[vector].trigger); + irq_bypass_unregister_producer(&vdev->ctx[vector].producer); + kfree(vdev->ctx[vector].name); + eventfd_ctx_put(vdev->ctx[vector].trigger); + vdev->ctx[vector].trigger = NULL; + } } if (fd < 0) return 0; - vdev->ctx[vector].name = kasprintf(GFP_KERNEL, "vfio-msi%s[%d](%s)", - msix ? "x" : "", vector, - pci_name(pdev)); - if (!vdev->ctx[vector].name) - return -ENOMEM; + if (!vdev->ctx[vector].trigger) { + vdev->ctx[vector].name = kasprintf(GFP_KERNEL, "vfio-msi%s[%d](%s)", + msix ? "x" : "", vector, + pci_name(pdev)); + if (!vdev->ctx[vector].name) { + eventfd_ctx_put(trigger); + return -ENOMEM; + } - trigger = eventfd_ctx_fdget(fd); - if (IS_ERR(trigger)) { - kfree(vdev->ctx[vector].name); - return PTR_ERR(trigger); - } + /* + * The MSIx vector table resides in device memory which may be cleared + * via backdoor resets. We don't allow direct access to the vector + * table so even if a userspace driver attempts to save/restore around + * such a reset it would be unsuccessful. To avoid this, restore the + * cached value of the message prior to enabling. + */ + if (msix) { + struct msi_msg msg; - /* - * The MSIx vector table resides in device memory which may be cleared - * via backdoor resets. We don't allow direct access to the vector - * table so even if a userspace driver attempts to save/restore around - * such a reset it would be unsuccessful. To avoid this, restore the - * cached value of the message prior to enabling. - */ - if (msix) { - struct msi_msg msg; + get_cached_msi_msg(irq, &msg); + pci_write_msi_msg(irq, &msg); + } - get_cached_msi_msg(irq, &msg); - pci_write_msi_msg(irq, &msg); - } + ret = request_irq(irq, vfio_msihandler, 0, + vdev->ctx[vector].name, trigger); + if (ret) { + kfree(vdev->ctx[vector].name); + eventfd_ctx_put(trigger); + return ret; + } - ret = request_irq(irq, vfio_msihandler, 0, - vdev->ctx[vector].name, trigger); - if (ret) { - kfree(vdev->ctx[vector].name); - eventfd_ctx_put(trigger); - return ret; + vdev->ctx[vector].producer.token = trigger; + vdev->ctx[vector].producer.irq = irq; + vdev->ctx[vector].trigger = trigger; } - vdev->ctx[vector].producer.token = trigger; - vdev->ctx[vector].producer.irq = irq; + /* always update irte for posted mode */ ret = irq_bypass_register_producer(&vdev->ctx[vector].producer); if (unlikely(ret)) dev_info(&pdev->dev, "irq bypass producer (token %p) registration fails: %d\n", vdev->ctx[vector].producer.token, ret); - vdev->ctx[vector].trigger = trigger; - return 0; } -- 1.8.3.1