Received: by 2002:ac0:a5a7:0:0:0:0:0 with SMTP id m36-v6csp34838imm; Fri, 13 Jul 2018 16:33:25 -0700 (PDT) X-Google-Smtp-Source: AAOMgpfVKTQg+jNTkdw2cyLUoGaSv2ssTNXpljA9CwfSOoiApE2ei2qs3r478bv+LqJ0aF9ythVL X-Received: by 2002:a63:614d:: with SMTP id v74-v6mr7722472pgb.328.1531524805812; Fri, 13 Jul 2018 16:33:25 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1531524805; cv=none; d=google.com; s=arc-20160816; b=hEGammijCUqhT0OWfQta16y6do6D6+9pURTiofhIc+cDi6y1nmmTcyt8FEY0wboQOu DvavB1yHRHeJ0h8ByAmiR5F2i1LJaX/AIR1s3CQxLn/PuI2Hi+MkRPNOj8oIndz+VU1P mf00G40HBUAgjIzBWrjzNvc2b3v08+UBOZt+475k8XVNuys5oQTmAs4+Ct7/+TLY3jN4 zVg9d/seD9FhAyUjYvae96TtG8T/vUHyX+Vv0crXcGMIiSdZMcxVYHycBTiqwyUYjQJf uGNms0msprkS4hnHsv1A3qjslflupiz95fC4N8MG+DqcC10o9+JZGz0D2ZMdBjMKMIs6 01JQ== 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=fhbEhsXkucYFWLMqhZ1jEGfXOjjiplkSdSJylHf6y5I=; b=n4vr0A0rnylyZ/rUi9H87XFVKUbTlFxq3otBY3XIWMS8teoOThLPwvrDH0GXB9PvmY A9TEUO0PEb9k6E/m+el9rEXW4mQQEYIdRBAOl2koA1BBI/0yw+FDbb4Yh8JwQ/f8/BsS H2kPPh2ME4L6w2h9aTiilIjS+iauoWEb7gkEk4eMr0fTUj84nJ189YVLxPeZ6OitLPmb ajWYe8tO+dO9QdxNOx4MMZDj1fF6XSiZGBF3p6JIi2H72e1FHq96hEnrtbdyHZCkoG8W g3NABXxHd7EtgjUeGk/NdAMwPfz4v6C2IarxX7ZMSlHt4EH3jfSQDNLAXnzG2YITCi27 tPJg== 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 g184-v6si26449069pfc.115.2018.07.13.16.33.11; Fri, 13 Jul 2018 16:33:25 -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 S1731973AbeGMXtC (ORCPT + 99 others); Fri, 13 Jul 2018 19:49:02 -0400 Received: from ale.deltatee.com ([207.54.116.67]:48372 "EHLO ale.deltatee.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1731589AbeGMXtB (ORCPT ); Fri, 13 Jul 2018 19:49:01 -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 1fe7Xm-000245-1V; Fri, 13 Jul 2018 17:32:13 -0600 Received: from gunthorp by cgy1-donard.priv.deltatee.com with local (Exim 4.89) (envelope-from ) id 1fe7Xd-00055l-Nw; Fri, 13 Jul 2018 17:32:01 -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: Fri, 13 Jul 2018 17:31:55 -0600 Message-Id: <20180713233158.19528-2-logang@deltatee.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20180713233158.19528-1-logang@deltatee.com> References: <20180713233158.19528-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=-6.9 required=5.0 tests=ALL_TRUSTED,BAYES_00 autolearn=ham autolearn_force=no version=3.4.1 Subject: [PATCH v6 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 efc7aa7a0670..e783bcefadac 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