Received: by 2002:ac0:a5a7:0:0:0:0:0 with SMTP id m36-v6csp3775162imm; Tue, 17 Jul 2018 10:03:23 -0700 (PDT) X-Google-Smtp-Source: AAOMgpeTfhNaBEaAm9s+Y8UfKVuhl7blgvAUBzMnNv8jQRebMBLVMulJazmEZV3G4RA/nw741U8s X-Received: by 2002:a63:5e45:: with SMTP id s66-v6mr2353024pgb.151.1531847003094; Tue, 17 Jul 2018 10:03:23 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1531847003; cv=none; d=google.com; s=arc-20160816; b=bzYIRPEW2HF+7VFk+hOjbQp2afg0XkaDXJqLLKnXHaiWYkcZO+Ya1ncKNMvelVYklR So82KkIj2k2Lytg7guiLbu+k4zJNMP+cIvinCQC+tB4FFVTV7HCeDaea+M19LeP5yss6 hFos1qR1/CWPmzcw/DzM8h76lZUw/o/sxt4FwPSd6C5ZyV3bJTSpx3AWj/wCezV1scJD B3PpkTvMy1+FOE8yZRkTYxmuLh2c1XwF+Ko5iqrJQW06R9UiF4sVxsGe9YjRJ3Zz91AG 8b9n8Wepmcq+KE32dfdoVJhNL7xNBREfa2mX5oR5ZwfkHL+VhHC7JHxr3pBzBnejEl03 vM2w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:subject:content-transfer-encoding :mime-version:references:in-reply-to:message-id:date:cc:to:from :arc-authentication-results; bh=UOpGDyqMQIL4MG4X3hQuTYvhtBNZ3pFNGgwaNM5NaQw=; b=xLNVDjqKN4nxJfMK3El5r6bjDPRwb2RPAHE9mOK19ODYfu2ntJ6uOoLPnTpQTOh71X gBRcZAk4UoK/0Kgy0ldYqh+si1JQBqUJG0LXTQLXGFi/cDRO31/yhf6S0nlhygDu8dVS niIZ/3OrSzJOEFwRDXhX1QEuZj5wT3414m5T7LRp1+GVCcuVfMB3cYpWgO7g35aVLFxo SYg8u7FYZ6yLcGvdiKY7j+ZDj0xPjZviqUBFUKW0slLNfXVU1CsKITdCPyMlMRD5nqun NNXDRaet1sZg2s5JLVCxVLSOCQP294ISArgxrhuQEe6yoFtY4jJ8yCQSdlJm0KdcB5+b A0FA== 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 Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id f12-v6si1197443pgo.203.2018.07.17.10.03.07; Tue, 17 Jul 2018 10:03:23 -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 Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730203AbeGQRf6 (ORCPT + 99 others); Tue, 17 Jul 2018 13:35:58 -0400 Received: from ale.deltatee.com ([207.54.116.67]:44606 "EHLO ale.deltatee.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729689AbeGQRf5 (ORCPT ); Tue, 17 Jul 2018 13:35:57 -0400 Received: from cgy1-donard.priv.deltatee.com ([172.16.1.31]) by ale.deltatee.com with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.89) (envelope-from ) id 1ffTMh-0006bw-TT; Tue, 17 Jul 2018 11:02:23 -0600 Received: from gunthorp by cgy1-donard.priv.deltatee.com with local (Exim 4.89) (envelope-from ) id 1ffTMT-0007wF-P3; Tue, 17 Jul 2018 11:02:05 -0600 From: Logan Gunthorpe To: linux-kernel@vger.kernel.org, linux-pci@vger.kernel.org, linux-doc@vger.kernel.org Cc: Stephen Bates , Christoph Hellwig , Bjorn Helgaas , Jonathan Corbet , Ingo Molnar , Thomas Gleixner , "Paul E. McKenney" , Marc Zyngier , Kai-Heng Feng , Frederic Weisbecker , Dan Williams , =?UTF-8?q?J=C3=A9r=C3=B4me=20Glisse?= , Benjamin Herrenschmidt , Alex Williamson , =?UTF-8?q?Christian=20K=C3=B6nig?= , Matthew Wilcox , Logan Gunthorpe Date: Tue, 17 Jul 2018 11:02:01 -0600 Message-Id: <20180717170204.30470-2-logang@deltatee.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20180717170204.30470-1-logang@deltatee.com> References: <20180717170204.30470-1-logang@deltatee.com> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-SA-Exim-Connect-IP: 172.16.1.31 X-SA-Exim-Rcpt-To: linux-kernel@vger.kernel.org, linux-pci@vger.kernel.org, linux-doc@vger.kernel.org, sbates@raithlin.com, hch@lst.de, bhelgaas@google.com, corbet@lwn.net, tglx@linutronix.de, paulmck@linux.vnet.ibm.com, marc.zyngier@arm.com, kai.heng.feng@canonical.com, mingo@kernel.org, frederic@kernel.org, dan.j.williams@intel.com, benh@kernel.crashing.org, jglisse@redhat.com, alex.williamson@redhat.com, christian.koenig@amd.com, willy@infradead.org, logang@deltatee.com X-SA-Exim-Mail-From: gunthorp@deltatee.com X-Spam-Checker-Version: SpamAssassin 3.4.1 (2015-04-28) on ale.deltatee.com X-Spam-Level: X-Spam-Status: No, score=-8.9 required=5.0 tests=ALL_TRUSTED,BAYES_00, GREYLIST_ISWHITE autolearn=ham autolearn_force=no version=3.4.1 Subject: [PATCH v7 1/4] PCI: Make specifying PCI devices in kernel parameters reusable X-SA-Exim-Version: 4.2.1 (built Tue, 02 Aug 2016 21:08:31 +0000) X-SA-Exim-Scanned: Yes (on ale.deltatee.com) Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Separate out the code to match a PCI device with a string (typically originating from a kernel parameter) from the pci_specified_resource_alignment() function into its own helper function. While we are at it, this change fixes the kernel style of the function (fixing a number of long lines and extra parentheses). Additionally, make the analogous change to the kernel parameter documentation: Separating the description of how to specify a PCI device into it's own section at the head of the pci= parameter. This patch should have no functional alterations. Signed-off-by: Logan Gunthorpe Reviewed-by: Stephen Bates Acked-by: Christian König Reviewed-by: Alex Williamson --- Documentation/admin-guide/kernel-parameters.txt | 28 ++++- drivers/pci/pci.c | 157 ++++++++++++++++-------- 2 files changed, 126 insertions(+), 59 deletions(-) diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt index 533ff5c68970..5cc215870ee1 100644 --- a/Documentation/admin-guide/kernel-parameters.txt +++ b/Documentation/admin-guide/kernel-parameters.txt @@ -2994,7 +2994,26 @@ See header of drivers/block/paride/pcd.c. See also Documentation/blockdev/paride.txt. - pci=option[,option...] [PCI] various PCI subsystem options: + pci=option[,option...] [PCI] various PCI subsystem options. + + Some options herein operate on a specific device + or a set of devices (). These are + specified in one of the following formats: + + [:]:. + pci::[::] + + Note: the first format specifies a PCI + bus/slot/function address which may change + if new hardware is inserted, if motherboard + firmware changes, or due to changes caused + by other kernel parameters. If the + domain is left unspecified, it is + taken to be zero. The second format + selects devices using IDs from the + configuration space which may match multiple + devices in the system. + earlydump [X86] dump PCI config space before the kernel changes anything off [X86] don't probe for the PCI bus @@ -3123,11 +3142,10 @@ window. The default value is 64 megabytes. resource_alignment= Format: - [@][:]:.[; ...] - [@]pci::\ - [::][; ...] + [@][; ...] Specifies alignment and device to reassign - aligned memory resources. + aligned memory resources. How to + specify the device is described above. If is not specified, PAGE_SIZE is used as alignment. PCI-PCI bridge can be specified, if resource diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 97acba712e4e..6127155d4170 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -191,6 +191,92 @@ void __iomem *pci_ioremap_wc_bar(struct pci_dev *pdev, int bar) EXPORT_SYMBOL_GPL(pci_ioremap_wc_bar); #endif +/** + * pci_dev_str_match - test if a string matches a device + * @dev: the PCI device to test + * @p: string to match the device against + * @endptr: pointer to the string after the match + * + * Test if a string (typically from a kernel parameter) matches a specified + * PCI device. The string may be of one of the following formats: + * + * [:]:. + * pci::[::] + * + * The first format specifies a PCI bus/slot/function address which + * may change if new hardware is inserted, if motherboard firmware changes, + * or due to changes caused in kernel parameters. If the domain is + * left unspecified, it is taken to be 0. + * + * The second format matches devices using IDs in the configuration + * space which may match multiple devices in the system. A value of 0 + * for any field will match all devices. (Note: this differs from + * in-kernel code that uses PCI_ANY_ID which is ~0; this is for + * legacy reasons and convenience so users don't have to specify + * FFFFFFFFs on the command line.) + * + * Returns 1 if the string matches the device, 0 if it does not and + * a negative error code if the string cannot be parsed. + */ +static int pci_dev_str_match(struct pci_dev *dev, const char *p, + const char **endptr) +{ + int ret; + int seg, bus, slot, func, count; + unsigned short vendor, device, subsystem_vendor, subsystem_device; + + if (strncmp(p, "pci:", 4) == 0) { + /* PCI vendor/device (subvendor/subdevice) ids are specified */ + p += 4; + ret = sscanf(p, "%hx:%hx:%hx:%hx%n", &vendor, &device, + &subsystem_vendor, &subsystem_device, &count); + if (ret != 4) { + ret = sscanf(p, "%hx:%hx%n", &vendor, &device, &count); + if (ret != 2) + return -EINVAL; + + subsystem_vendor = 0; + subsystem_device = 0; + } + + p += count; + + if ((!vendor || vendor == dev->vendor) && + (!device || device == dev->device) && + (!subsystem_vendor || + subsystem_vendor == dev->subsystem_vendor) && + (!subsystem_device || + subsystem_device == dev->subsystem_device)) + goto found; + + } else { + /* PCI Bus,Slot,Function ids are specified */ + ret = sscanf(p, "%x:%x:%x.%x%n", &seg, &bus, &slot, + &func, &count); + if (ret != 4) { + seg = 0; + ret = sscanf(p, "%x:%x.%x%n", &bus, &slot, + &func, &count); + if (ret != 3) + return -EINVAL; + } + + p += count; + + if (seg == pci_domain_nr(dev->bus) && + bus == dev->bus->number && + slot == PCI_SLOT(dev->devfn) && + func == PCI_FUNC(dev->devfn)) + goto found; + } + + *endptr = p; + return 0; + +found: + *endptr = p; + return 1; +} static int __pci_find_next_cap_ttl(struct pci_bus *bus, unsigned int devfn, u8 pos, int cap, int *ttl) @@ -5454,10 +5540,10 @@ static DEFINE_SPINLOCK(resource_alignment_lock); static resource_size_t pci_specified_resource_alignment(struct pci_dev *dev, bool *resize) { - int seg, bus, slot, func, align_order, count; - unsigned short vendor, device, subsystem_vendor, subsystem_device; + int align_order, count; resource_size_t align = pcibios_default_alignment(); - char *p; + const char *p; + int ret; spin_lock(&resource_alignment_lock); p = resource_alignment_param; @@ -5477,58 +5563,21 @@ static resource_size_t pci_specified_resource_alignment(struct pci_dev *dev, } else { align_order = -1; } - if (strncmp(p, "pci:", 4) == 0) { - /* PCI vendor/device (subvendor/subdevice) ids are specified */ - p += 4; - if (sscanf(p, "%hx:%hx:%hx:%hx%n", - &vendor, &device, &subsystem_vendor, &subsystem_device, &count) != 4) { - if (sscanf(p, "%hx:%hx%n", &vendor, &device, &count) != 2) { - printk(KERN_ERR "PCI: Can't parse resource_alignment parameter: pci:%s\n", - p); - break; - } - subsystem_vendor = subsystem_device = 0; - } - p += count; - if ((!vendor || (vendor == dev->vendor)) && - (!device || (device == dev->device)) && - (!subsystem_vendor || (subsystem_vendor == dev->subsystem_vendor)) && - (!subsystem_device || (subsystem_device == dev->subsystem_device))) { - *resize = true; - if (align_order == -1) - align = PAGE_SIZE; - else - align = 1 << align_order; - /* Found */ - break; - } - } - else { - if (sscanf(p, "%x:%x:%x.%x%n", - &seg, &bus, &slot, &func, &count) != 4) { - seg = 0; - if (sscanf(p, "%x:%x.%x%n", - &bus, &slot, &func, &count) != 3) { - /* Invalid format */ - printk(KERN_ERR "PCI: Can't parse resource_alignment parameter: %s\n", - p); - break; - } - } - p += count; - if (seg == pci_domain_nr(dev->bus) && - bus == dev->bus->number && - slot == PCI_SLOT(dev->devfn) && - func == PCI_FUNC(dev->devfn)) { - *resize = true; - if (align_order == -1) - align = PAGE_SIZE; - else - align = 1 << align_order; - /* Found */ - break; - } + + ret = pci_dev_str_match(dev, p, &p); + if (ret == 1) { + *resize = true; + if (align_order == -1) + align = PAGE_SIZE; + else + align = 1 << align_order; + break; + } else if (ret < 0) { + pr_err("PCI: Can't parse resource_alignment parameter: %s\n", + p); + break; } + if (*p != ';' && *p != ',') { /* End of param or invalid format */ break; -- 2.11.0