Received: by 10.223.164.202 with SMTP id h10csp226918wrb; Wed, 8 Nov 2017 15:16:46 -0800 (PST) X-Google-Smtp-Source: ABhQp+RgG3mtYBuNSkhUQL5mPXkZzIHP2iUMvFNsEqyISIrio/roie6Wf0ja/3U8k+/cws7zZUSo X-Received: by 10.159.203.133 with SMTP id ay5mr1833581plb.361.1510183006813; Wed, 08 Nov 2017 15:16:46 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1510183006; cv=none; d=google.com; s=arc-20160816; b=hIAc3YKudl8bARpT7PAFTvO+MSkrLBqQxgJFOB8Yyv1BH81F76w15DfBQb+zkCzWNi 0U2l+Ew2YGG8QELsMbAiWvDpxxNUL98HVAaOQaY3WlMJnbuuLOW3OZFzsyhONN3tsg9l 0891rQbA3CVaM1PwIUV3ln1/ZiyMNS1T9lvFvh9fcW63/6Nq0fuj3RQG/kTJKjyV4NpW hbP1I4U9JoeLQJkqaZjTNj2zxlQqLCXL0PZkH7C4H76d62aCMIeMdPb94fB12KL4qNzL /nMA9+6cHCjd7V2Tt2uOdsGBGFQ3+vD2MRQFRXoq+XyW0cCEAyUAvXxMcfBamxanTZs5 xhEA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:message-id:date:subject:cc:to:from :arc-authentication-results; bh=NSbJnhEnBw23og4/HWYJJEBR6yWLpaiuoVCFfpfKJ/k=; b=LMTK7bb2n139bab1+KwnBTYqnz4kpSnJV0NF3pxezi6W476zQfEdzFrx2ABqm1jhnD VmiHu4TLkbHm7Hrf2y6QZSjnGVYMb27E8oA0B1/tpOFKihQVyDH9zWkZMzBEYlWlyw2R Rp6hjCdReslejzX/oLsCuJsDpPpkQqWQtOp+RZaBFRNzNrtDlNWe32AnQXbEEopvyMZv SCxU/xm/VtCSIfF372Me0T/2La2HrmOg/RZCtT+moj4KbddCgABja896itygFFulVIhe 90B12qHGIi80Q1rYsC+Q8xtG0SnYPyx7s8hIJLlBhR6jAkbV92DA6dFKzp8sHmxJCkL1 0AcQ== 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=oracle.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id d5si4823326pgq.280.2017.11.08.15.16.34; Wed, 08 Nov 2017 15:16:46 -0800 (PST) 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=oracle.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753063AbdKHXOl (ORCPT + 84 others); Wed, 8 Nov 2017 18:14:41 -0500 Received: from userp1040.oracle.com ([156.151.31.81]:22441 "EHLO userp1040.oracle.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752559AbdKHXOk (ORCPT ); Wed, 8 Nov 2017 18:14:40 -0500 Received: from userv0021.oracle.com (userv0021.oracle.com [156.151.31.71]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id vA8NDXVm010634 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Wed, 8 Nov 2017 23:13:33 GMT Received: from userv0121.oracle.com (userv0121.oracle.com [156.151.31.72]) by userv0021.oracle.com (8.14.4/8.14.4) with ESMTP id vA8NDXSW007715 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Wed, 8 Nov 2017 23:13:33 GMT Received: from abhmp0008.oracle.com (abhmp0008.oracle.com [141.146.116.14]) by userv0121.oracle.com (8.14.4/8.13.8) with ESMTP id vA8NDWPT005272; Wed, 8 Nov 2017 23:13:32 GMT Received: from ban25x6uut145.us.oracle.com (/10.153.73.145) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Wed, 08 Nov 2017 15:13:31 -0800 From: Govinda Tatti To: xen-devel@lists.xenproject.org, linux-kernel@vger.kernel.org, boris.ostrovsky@Oracle.COM, jgross@suse.com, roger.pau@citrix.com, JBeulich@suse.com Cc: konrad.wilk@Oracle.COM Subject: [PATCH V2] Xen/pciback: Implement PCI slot or bus reset with 'do_flr' SysFS attribute Date: Wed, 8 Nov 2017 18:06:54 -0500 Message-Id: <20171108230654.2981-1-Govinda.Tatti@Oracle.COM> X-Mailer: git-send-email 2.9.5 X-Source-IP: userv0021.oracle.com [156.151.31.71] Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org The life-cycle of a PCI device in Xen pciback is complex and is constrained by the generic PCI locking mechanism. - It starts with the device being bound to us, for which we do a function reset (done via SysFS so the PCI lock is held). - If the device is unbound from us, we also do a function reset (done via SysFS so the PCI lock is held). - If the device is un-assigned from a guest - we do a function reset (no PCI lock is held). All reset operations are done on the individual PCI function level (so bus:device:function). The reset for an individual PCI function means device must support FLR (PCIe or AF), PM reset on D3hot->D0 device specific reset, or a secondary bus reset for a singleton device on a bus but FLR does not have widespread support or it is not reliable in some cases. So, we need to provide an alternate mechanism to users to perform a slot or bus level reset. Currently, a slot or bus reset is not exposed in SysFS as there is no good way of exposing a bus topology there. This is due to the complexity - we MUST know that the different functions of a PCIe device are not in use by other drivers, or if they are in use (say one of them is assigned to a guest and the other is idle) - it is still OK to reset the slot (assuming both of them are owned by Xen pciback). This patch does that by doing a slot or bus reset (if slot not supported) if all of the functions of a PCIe device belong to Xen PCIback. Due to the complexity with the PCI lock we cannot do the reset when a device is bound ('echo $BDF > bind') or when unbound ('echo $BDF > unbind') as the pci_[slot|bus]_reset also takes the same lock resulting in a dead-lock. Putting the reset function in a work-queue or thread won't work either - as we have to do the reset function outside the 'unbind' context (it holds the PCI lock). But once you 'unbind' a device the device is no longer under the ownership of Xen pciback and the pci_set_drvdata has been reset, so we cannot use a thread for this. Instead of doing all this complex dance, we depend on the tool-stack doing the right thing. As such, we implement the 'do_flr' SysFS attribute which 'xl' uses when a device is detached or attached from/to a guest. It bypasses the need to worry about the PCI lock. To not inadvertently do a bus reset that would affect devices that are in use by other drivers (other than Xen pciback) prior to the reset, we check that all of the devices under the bridge are owned by Xen pciback. If they are not, we refrain from executing the bus (or slot) reset. Signed-off-by: Govinda Tatti Signed-off-by: Konrad Rzeszutek Wilk Reviewed-by: Boris Ostrovsky --- Documentation/ABI/testing/sysfs-driver-pciback | 12 +++ drivers/xen/xen-pciback/pci_stub.c | 119 +++++++++++++++++++++++++ 2 files changed, 131 insertions(+) diff --git a/Documentation/ABI/testing/sysfs-driver-pciback b/Documentation/ABI/testing/sysfs-driver-pciback index 6a733bf..ccf7dc0 100644 --- a/Documentation/ABI/testing/sysfs-driver-pciback +++ b/Documentation/ABI/testing/sysfs-driver-pciback @@ -11,3 +11,15 @@ Description: #echo 00:19.0-E0:2:FF > /sys/bus/pci/drivers/pciback/quirks will allow the guest to read and write to the configuration register 0x0E. + +What: /sys/bus/pci/drivers/pciback/do_flr +Date: Nov 2017 +KernelVersion: 4.15 +Contact: xen-devel@lists.xenproject.org +Description: + An option to perform a slot or bus reset when a PCI device + is owned by Xen PCI backend. Writing a string of DDDD:BB:DD.F + will cause the pciback driver to perform a slot or bus reset + if the device supports it. It also checks to make sure that + all of the devices under the bridge are owned by Xen PCI + backend. diff --git a/drivers/xen/xen-pciback/pci_stub.c b/drivers/xen/xen-pciback/pci_stub.c index 6331a95..e2677a6 100644 --- a/drivers/xen/xen-pciback/pci_stub.c +++ b/drivers/xen/xen-pciback/pci_stub.c @@ -244,6 +244,91 @@ struct pci_dev *pcistub_get_pci_dev(struct xen_pcibk_device *pdev, return found_dev; } +struct pcistub_args { + struct pci_dev *dev; + unsigned int dcount; +}; + +static int pcistub_search_dev(struct pci_dev *dev, void *data) +{ + struct pcistub_device *psdev; + struct pcistub_args *arg = data; + bool found_dev = false; + unsigned long flags; + + spin_lock_irqsave(&pcistub_devices_lock, flags); + + list_for_each_entry(psdev, &pcistub_devices, dev_list) { + if (psdev->dev == dev) { + found_dev = true; + arg->dcount++; + break; + } + } + + spin_unlock_irqrestore(&pcistub_devices_lock, flags); + + /* Device not owned by pcistub, someone owns it. Abort the walk */ + if (!found_dev) + arg->dev = dev; + + return found_dev ? 0 : 1; +} + +static int pcistub_reset_dev(struct pci_dev *dev) +{ + struct xen_pcibk_dev_data *dev_data; + bool slot = false, bus = false; + struct pcistub_args arg = {}; + + if (!dev) + return -EINVAL; + + dev_dbg(&dev->dev, "[%s]\n", __func__); + + if (!pci_probe_reset_slot(dev->slot)) + slot = true; + else if ((!pci_probe_reset_bus(dev->bus)) && + (!pci_is_root_bus(dev->bus))) + bus = true; + + if (!bus && !slot) + return -EOPNOTSUPP; + + /* + * Make sure all devices on this bus are owned by the + * PCI backend so that we can safely reset the whole bus. + */ + pci_walk_bus(dev->bus, pcistub_search_dev, &arg); + + /* All devices under the bus should be part of pcistub! */ + if (arg.dev) { + dev_err(&dev->dev, "%s device on bus 0x%x is not owned by pcistub\n", + pci_name(arg.dev), dev->bus->number); + + return -EBUSY; + } + + dev_dbg(&dev->dev, "pcistub owns %d devices on bus 0x%x\n", + arg.dcount, dev->bus->number); + + dev_data = pci_get_drvdata(dev); + if (!pci_load_saved_state(dev, dev_data->pci_saved_state)) + pci_restore_state(dev); + + /* This disables the device. */ + xen_pcibk_reset_device(dev); + + /* Cleanup up any emulated fields */ + xen_pcibk_config_reset_dev(dev); + + dev_dbg(&dev->dev, "resetting %s device using %s reset\n", + pci_name(dev), slot ? "slot" : "bus"); + + return slot ? pci_try_reset_slot(dev->slot) : + pci_try_reset_bus(dev->bus); +} + /* * Called when: * - XenBus state has been reconfigure (pci unplug). See xen_pcibk_remove_device @@ -1434,6 +1519,33 @@ static ssize_t permissive_show(struct device_driver *drv, char *buf) static DRIVER_ATTR(permissive, S_IRUSR | S_IWUSR, permissive_show, permissive_add); +static ssize_t pcistub_do_flr(struct device_driver *drv, const char *buf, + size_t count) +{ + struct pcistub_device *psdev; + int domain, bus, slot, func; + int err; + + err = str_to_slot(buf, &domain, &bus, &slot, &func); + if (err) + return err; + + psdev = pcistub_device_find(domain, bus, slot, func); + if (psdev) { + err = pcistub_reset_dev(psdev->dev); + pcistub_device_put(psdev); + } else { + err = -ENODEV; + } + + if (!err) + err = count; + + return err; +} + +static DRIVER_ATTR(do_flr, S_IWUSR, NULL, pcistub_do_flr); + static void pcistub_exit(void) { driver_remove_file(&xen_pcibk_pci_driver.driver, &driver_attr_new_slot); @@ -1447,6 +1559,8 @@ static void pcistub_exit(void) &driver_attr_irq_handlers); driver_remove_file(&xen_pcibk_pci_driver.driver, &driver_attr_irq_handler_state); + driver_remove_file(&xen_pcibk_pci_driver.driver, + &driver_attr_do_flr); pci_unregister_driver(&xen_pcibk_pci_driver); } @@ -1540,6 +1654,11 @@ static int __init pcistub_init(void) if (!err) err = driver_create_file(&xen_pcibk_pci_driver.driver, &driver_attr_irq_handler_state); + + if (!err) + err = driver_create_file(&xen_pcibk_pci_driver.driver, + &driver_attr_do_flr); + if (err) pcistub_exit(); -- 2.9.5 From 1585256666949132856@xxx Mon Nov 27 21:36:08 +0000 2017 X-GM-THRID: 1584676432362707323 X-Gmail-Labels: Inbox,Category Forums,HistoricalUnread