License cleanup: add SPDX GPL-2.0 license identifier to files with no license
Many source files in the tree are missing licensing information, which
makes it harder for compliance tools to determine the correct license.
By default all files without license information are under the default
license of the kernel, which is GPL version 2.
Update the files which contain no license information with the 'GPL-2.0'
SPDX license identifier. The SPDX identifier is a legally binding
shorthand, which can be used instead of the full boiler plate text.
This patch is based on work done by Thomas Gleixner and Kate Stewart and
Philippe Ombredanne.
How this work was done:
Patches were generated and checked against linux-4.14-rc6 for a subset of
the use cases:
- file had no licensing information it it.
- file was a */uapi/* one with no licensing information in it,
- file was a */uapi/* one with existing licensing information,
Further patches will be generated in subsequent months to fix up cases
where non-standard license headers were used, and references to license
had to be inferred by heuristics based on keywords.
The analysis to determine which SPDX License Identifier to be applied to
a file was done in a spreadsheet of side by side results from of the
output of two independent scanners (ScanCode & Windriver) producing SPDX
tag:value files created by Philippe Ombredanne. Philippe prepared the
base worksheet, and did an initial spot review of a few 1000 files.
The 4.13 kernel was the starting point of the analysis with 60,537 files
assessed. Kate Stewart did a file by file comparison of the scanner
results in the spreadsheet to determine which SPDX license identifier(s)
to be applied to the file. She confirmed any determination that was not
immediately clear with lawyers working with the Linux Foundation.
Criteria used to select files for SPDX license identifier tagging was:
- Files considered eligible had to be source code files.
- Make and config files were included as candidates if they contained >5
lines of source
- File already had some variant of a license header in it (even if <5
lines).
All documentation files were explicitly excluded.
The following heuristics were used to determine which SPDX license
identifiers to apply.
- when both scanners couldn't find any license traces, file was
considered to have no license information in it, and the top level
COPYING file license applied.
For non */uapi/* files that summary was:
SPDX license identifier # files
---------------------------------------------------|-------
GPL-2.0 11139
and resulted in the first patch in this series.
If that file was a */uapi/* path one, it was "GPL-2.0 WITH
Linux-syscall-note" otherwise it was "GPL-2.0". Results of that was:
SPDX license identifier # files
---------------------------------------------------|-------
GPL-2.0 WITH Linux-syscall-note 930
and resulted in the second patch in this series.
- if a file had some form of licensing information in it, and was one
of the */uapi/* ones, it was denoted with the Linux-syscall-note if
any GPL family license was found in the file or had no licensing in
it (per prior point). Results summary:
SPDX license identifier # files
---------------------------------------------------|------
GPL-2.0 WITH Linux-syscall-note 270
GPL-2.0+ WITH Linux-syscall-note 169
((GPL-2.0 WITH Linux-syscall-note) OR BSD-2-Clause) 21
((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) 17
LGPL-2.1+ WITH Linux-syscall-note 15
GPL-1.0+ WITH Linux-syscall-note 14
((GPL-2.0+ WITH Linux-syscall-note) OR BSD-3-Clause) 5
LGPL-2.0+ WITH Linux-syscall-note 4
LGPL-2.1 WITH Linux-syscall-note 3
((GPL-2.0 WITH Linux-syscall-note) OR MIT) 3
((GPL-2.0 WITH Linux-syscall-note) AND MIT) 1
and that resulted in the third patch in this series.
- when the two scanners agreed on the detected license(s), that became
the concluded license(s).
- when there was disagreement between the two scanners (one detected a
license but the other didn't, or they both detected different
licenses) a manual inspection of the file occurred.
- In most cases a manual inspection of the information in the file
resulted in a clear resolution of the license that should apply (and
which scanner probably needed to revisit its heuristics).
- When it was not immediately clear, the license identifier was
confirmed with lawyers working with the Linux Foundation.
- If there was any question as to the appropriate license identifier,
the file was flagged for further research and to be revisited later
in time.
In total, over 70 hours of logged manual review was done on the
spreadsheet to determine the SPDX license identifiers to apply to the
source files by Kate, Philippe, Thomas and, in some cases, confirmation
by lawyers working with the Linux Foundation.
Kate also obtained a third independent scan of the 4.13 code base from
FOSSology, and compared selected files where the other two scanners
disagreed against that SPDX file, to see if there was new insights. The
Windriver scanner is based on an older version of FOSSology in part, so
they are related.
Thomas did random spot checks in about 500 files from the spreadsheets
for the uapi headers and agreed with SPDX license identifier in the
files he inspected. For the non-uapi files Thomas did random spot checks
in about 15000 files.
In initial set of patches against 4.14-rc6, 3 files were found to have
copy/paste license identifier errors, and have been fixed to reflect the
correct identifier.
Additionally Philippe spent 10 hours this week doing a detailed manual
inspection and review of the 12,461 patched files from the initial patch
version early this week with:
- a full scancode scan run, collecting the matched texts, detected
license ids and scores
- reviewing anything where there was a license detected (about 500+
files) to ensure that the applied SPDX license was correct
- reviewing anything where there was no detection but the patch license
was not GPL-2.0 WITH Linux-syscall-note to ensure that the applied
SPDX license was correct
This produced a worksheet with 20 files needing minor correction. This
worksheet was then exported into 3 different .csv files for the
different types of files to be modified.
These .csv files were then reviewed by Greg. Thomas wrote a script to
parse the csv files and add the proper SPDX tag to the file, in the
format that the file expected. This script was further refined by Greg
based on the output to detect more types of files automatically and to
distinguish between header and source .c files (which need different
comment types.) Finally Greg ran the script using the .csv files to
generate the patches.
Reviewed-by: Kate Stewart <kstewart@linuxfoundation.org>
Reviewed-by: Philippe Ombredanne <pombredanne@nexb.com>
Reviewed-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2017-11-01 22:07:57 +08:00
|
|
|
// SPDX-License-Identifier: GPL-2.0
|
2005-04-17 06:20:36 +08:00
|
|
|
/*
|
2018-03-10 06:36:33 +08:00
|
|
|
* Support routines for initializing a PCI subsystem
|
2005-04-17 06:20:36 +08:00
|
|
|
*
|
|
|
|
* Extruded from code written by
|
|
|
|
* Dave Rusling (david.rusling@reo.mts.dec.com)
|
|
|
|
* David Mosberger (davidm@cs.arizona.edu)
|
|
|
|
* David Miller (davem@redhat.com)
|
|
|
|
*
|
2018-03-10 06:36:33 +08:00
|
|
|
* Fixed for multiple PCI buses, 1999 Andrea Arcangeli <andrea@suse.de>
|
|
|
|
*
|
2005-04-17 06:20:36 +08:00
|
|
|
* Nov 2000, Ivan Kokshaysky <ink@jurassic.park.msu.ru>
|
|
|
|
* Resource sorting
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <linux/kernel.h>
|
2011-05-27 21:37:25 +08:00
|
|
|
#include <linux/export.h>
|
2005-04-17 06:20:36 +08:00
|
|
|
#include <linux/pci.h>
|
|
|
|
#include <linux/errno.h>
|
|
|
|
#include <linux/ioport.h>
|
|
|
|
#include <linux/cache.h>
|
|
|
|
#include <linux/slab.h>
|
|
|
|
#include "pci.h"
|
|
|
|
|
2016-11-28 23:15:52 +08:00
|
|
|
static void pci_std_update_resource(struct pci_dev *dev, int resno)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
|
|
|
struct pci_bus_region region;
|
2012-07-10 09:49:37 +08:00
|
|
|
bool disable;
|
|
|
|
u16 cmd;
|
2005-04-17 06:20:36 +08:00
|
|
|
u32 new, check, mask;
|
|
|
|
int reg;
|
2008-11-22 02:38:52 +08:00
|
|
|
struct resource *res = dev->resource + resno;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2016-11-29 01:19:27 +08:00
|
|
|
/* Per SR-IOV spec 3.4.1.11, VF BARs are RO zero */
|
|
|
|
if (dev->is_virtfn)
|
2015-07-29 16:52:58 +08:00
|
|
|
return;
|
|
|
|
|
2006-12-20 05:12:08 +08:00
|
|
|
/*
|
|
|
|
* Ignore resources for unimplemented BARs and unused resource slots
|
|
|
|
* for 64 bit BARs.
|
|
|
|
*/
|
2005-08-07 17:49:59 +08:00
|
|
|
if (!res->flags)
|
|
|
|
return;
|
|
|
|
|
2014-02-27 02:25:59 +08:00
|
|
|
if (res->flags & IORESOURCE_UNSET)
|
|
|
|
return;
|
|
|
|
|
2006-12-20 05:12:08 +08:00
|
|
|
/*
|
|
|
|
* Ignore non-moveable resources. This might be legacy resources for
|
|
|
|
* which no functional BAR register exists or another important
|
2008-06-14 00:52:11 +08:00
|
|
|
* system resource we shouldn't move around.
|
2006-12-20 05:12:08 +08:00
|
|
|
*/
|
|
|
|
if (res->flags & IORESOURCE_PCI_FIXED)
|
|
|
|
return;
|
|
|
|
|
PCI: Convert pcibios_resource_to_bus() to take a pci_bus, not a pci_dev
These interfaces:
pcibios_resource_to_bus(struct pci_dev *dev, *bus_region, *resource)
pcibios_bus_to_resource(struct pci_dev *dev, *resource, *bus_region)
took a pci_dev, but they really depend only on the pci_bus. And we want to
use them in resource allocation paths where we have the bus but not a
device, so this patch converts them to take the pci_bus instead of the
pci_dev:
pcibios_resource_to_bus(struct pci_bus *bus, *bus_region, *resource)
pcibios_bus_to_resource(struct pci_bus *bus, *resource, *bus_region)
In fact, with standard PCI-PCI bridges, they only depend on the host
bridge, because that's the only place address translation occurs, but
we aren't going that far yet.
[bhelgaas: changelog]
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
2013-12-10 14:54:40 +08:00
|
|
|
pcibios_resource_to_bus(dev->bus, ®ion, res);
|
2016-11-29 22:14:47 +08:00
|
|
|
new = region.start;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2016-11-29 22:14:47 +08:00
|
|
|
if (res->flags & IORESOURCE_IO) {
|
2005-04-17 06:20:36 +08:00
|
|
|
mask = (u32)PCI_BASE_ADDRESS_IO_MASK;
|
2016-11-29 22:14:47 +08:00
|
|
|
new |= res->flags & ~PCI_BASE_ADDRESS_IO_MASK;
|
|
|
|
} else if (resno == PCI_ROM_RESOURCE) {
|
2017-04-15 04:38:02 +08:00
|
|
|
mask = PCI_ROM_ADDRESS_MASK;
|
2016-11-29 22:14:47 +08:00
|
|
|
} else {
|
2005-04-17 06:20:36 +08:00
|
|
|
mask = (u32)PCI_BASE_ADDRESS_MEM_MASK;
|
2016-11-29 22:14:47 +08:00
|
|
|
new |= res->flags & ~PCI_BASE_ADDRESS_MEM_MASK;
|
|
|
|
}
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2016-11-29 06:51:19 +08:00
|
|
|
if (resno < PCI_ROM_RESOURCE) {
|
|
|
|
reg = PCI_BASE_ADDRESS_0 + 4 * resno;
|
|
|
|
} else if (resno == PCI_ROM_RESOURCE) {
|
2016-11-29 06:17:41 +08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Apparently some Matrox devices have ROM BARs that read
|
|
|
|
* as zero when disabled, so don't update ROM BARs unless
|
2020-07-01 01:41:39 +08:00
|
|
|
* they're enabled. See
|
|
|
|
* https://lore.kernel.org/r/43147B3D.1030309@vc.cvut.cz/
|
PCI: Work around Intel I210 ROM BAR overlap defect
Per PCIe r5, sec 7.5.1.2.4, a device must not claim accesses to its
Expansion ROM unless both the Memory Space Enable and the Expansion ROM
Enable bit are set. But apparently some Intel I210 NICs don't work
correctly if the ROM BAR overlaps another BAR, even if the Expansion ROM is
disabled.
Michael reported that on a Kontron SMARC-sAL28 ARM64 system with U-Boot
v2021.01-rc3, the ROM BAR overlaps BAR 3, and networking doesn't work at
all:
BAR 0: 0x40000000 (32-bit, non-prefetchable) [size=1M]
BAR 3: 0x40200000 (32-bit, non-prefetchable) [size=16K]
ROM: 0x40200000 (disabled) [size=1M]
NETDEV WATCHDOG: enP2p1s0 (igb): transmit queue 0 timed out
Hardware name: Kontron SMARC-sAL28 (Single PHY) on SMARC Eval 2.0 carrier (DT)
igb 0002:01:00.0 enP2p1s0: Reset adapter
Previously, pci_std_update_resource() wrote the assigned ROM address to the
BAR only when the ROM was enabled. This meant that the I210 ROM BAR could
be left with an address assigned by firmware, which might overlap with
other BARs.
Quirk these I210 devices so pci_std_update_resource() always writes the
assigned address to the ROM BAR, whether or not the ROM is enabled.
Link: https://lore.kernel.org/r/20211223163754.GA1267351@bhelgaas
Link: https://lore.kernel.org/r/20201230185317.30915-1-michael@walle.cc
Link: https://bugzilla.kernel.org/show_bug.cgi?id=211105
Reported-by: Michael Walle <michael@walle.cc>
Tested-by: Michael Walle <michael@walle.cc>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
2021-12-22 00:45:07 +08:00
|
|
|
* But we must update ROM BAR for buggy devices where even a
|
|
|
|
* disabled ROM can conflict with other BARs.
|
2016-11-29 06:17:41 +08:00
|
|
|
*/
|
PCI: Work around Intel I210 ROM BAR overlap defect
Per PCIe r5, sec 7.5.1.2.4, a device must not claim accesses to its
Expansion ROM unless both the Memory Space Enable and the Expansion ROM
Enable bit are set. But apparently some Intel I210 NICs don't work
correctly if the ROM BAR overlaps another BAR, even if the Expansion ROM is
disabled.
Michael reported that on a Kontron SMARC-sAL28 ARM64 system with U-Boot
v2021.01-rc3, the ROM BAR overlaps BAR 3, and networking doesn't work at
all:
BAR 0: 0x40000000 (32-bit, non-prefetchable) [size=1M]
BAR 3: 0x40200000 (32-bit, non-prefetchable) [size=16K]
ROM: 0x40200000 (disabled) [size=1M]
NETDEV WATCHDOG: enP2p1s0 (igb): transmit queue 0 timed out
Hardware name: Kontron SMARC-sAL28 (Single PHY) on SMARC Eval 2.0 carrier (DT)
igb 0002:01:00.0 enP2p1s0: Reset adapter
Previously, pci_std_update_resource() wrote the assigned ROM address to the
BAR only when the ROM was enabled. This meant that the I210 ROM BAR could
be left with an address assigned by firmware, which might overlap with
other BARs.
Quirk these I210 devices so pci_std_update_resource() always writes the
assigned address to the ROM BAR, whether or not the ROM is enabled.
Link: https://lore.kernel.org/r/20211223163754.GA1267351@bhelgaas
Link: https://lore.kernel.org/r/20201230185317.30915-1-michael@walle.cc
Link: https://bugzilla.kernel.org/show_bug.cgi?id=211105
Reported-by: Michael Walle <michael@walle.cc>
Tested-by: Michael Walle <michael@walle.cc>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
2021-12-22 00:45:07 +08:00
|
|
|
if (!(res->flags & IORESOURCE_ROM_ENABLE) &&
|
|
|
|
!dev->rom_bar_overlap)
|
2005-08-27 01:49:22 +08:00
|
|
|
return;
|
2016-11-29 06:51:19 +08:00
|
|
|
|
|
|
|
reg = dev->rom_base_reg;
|
PCI: Work around Intel I210 ROM BAR overlap defect
Per PCIe r5, sec 7.5.1.2.4, a device must not claim accesses to its
Expansion ROM unless both the Memory Space Enable and the Expansion ROM
Enable bit are set. But apparently some Intel I210 NICs don't work
correctly if the ROM BAR overlaps another BAR, even if the Expansion ROM is
disabled.
Michael reported that on a Kontron SMARC-sAL28 ARM64 system with U-Boot
v2021.01-rc3, the ROM BAR overlaps BAR 3, and networking doesn't work at
all:
BAR 0: 0x40000000 (32-bit, non-prefetchable) [size=1M]
BAR 3: 0x40200000 (32-bit, non-prefetchable) [size=16K]
ROM: 0x40200000 (disabled) [size=1M]
NETDEV WATCHDOG: enP2p1s0 (igb): transmit queue 0 timed out
Hardware name: Kontron SMARC-sAL28 (Single PHY) on SMARC Eval 2.0 carrier (DT)
igb 0002:01:00.0 enP2p1s0: Reset adapter
Previously, pci_std_update_resource() wrote the assigned ROM address to the
BAR only when the ROM was enabled. This meant that the I210 ROM BAR could
be left with an address assigned by firmware, which might overlap with
other BARs.
Quirk these I210 devices so pci_std_update_resource() always writes the
assigned address to the ROM BAR, whether or not the ROM is enabled.
Link: https://lore.kernel.org/r/20211223163754.GA1267351@bhelgaas
Link: https://lore.kernel.org/r/20201230185317.30915-1-michael@walle.cc
Link: https://bugzilla.kernel.org/show_bug.cgi?id=211105
Reported-by: Michael Walle <michael@walle.cc>
Tested-by: Michael Walle <michael@walle.cc>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
2021-12-22 00:45:07 +08:00
|
|
|
if (res->flags & IORESOURCE_ROM_ENABLE)
|
|
|
|
new |= PCI_ROM_ADDRESS_ENABLE;
|
2016-11-29 06:51:19 +08:00
|
|
|
} else
|
|
|
|
return;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2012-07-10 09:49:37 +08:00
|
|
|
/*
|
|
|
|
* We can't update a 64-bit BAR atomically, so when possible,
|
|
|
|
* disable decoding so that a half-updated BAR won't conflict
|
|
|
|
* with another device.
|
|
|
|
*/
|
|
|
|
disable = (res->flags & IORESOURCE_MEM_64) && !dev->mmio_always_on;
|
|
|
|
if (disable) {
|
|
|
|
pci_read_config_word(dev, PCI_COMMAND, &cmd);
|
|
|
|
pci_write_config_word(dev, PCI_COMMAND,
|
|
|
|
cmd & ~PCI_COMMAND_MEMORY);
|
|
|
|
}
|
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
pci_write_config_dword(dev, reg, new);
|
|
|
|
pci_read_config_dword(dev, reg, &check);
|
|
|
|
|
|
|
|
if ((new ^ check) & mask) {
|
2018-01-19 02:55:24 +08:00
|
|
|
pci_err(dev, "BAR %d: error updating (%#08x != %#08x)\n",
|
2008-06-14 00:52:11 +08:00
|
|
|
resno, new, check);
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
2011-06-15 03:04:35 +08:00
|
|
|
if (res->flags & IORESOURCE_MEM_64) {
|
2005-08-07 17:49:59 +08:00
|
|
|
new = region.start >> 16 >> 16;
|
2005-04-17 06:20:36 +08:00
|
|
|
pci_write_config_dword(dev, reg + 4, new);
|
|
|
|
pci_read_config_dword(dev, reg + 4, &check);
|
|
|
|
if (check != new) {
|
2018-01-19 02:55:24 +08:00
|
|
|
pci_err(dev, "BAR %d: error updating (high %#08x != %#08x)\n",
|
2014-04-19 08:13:50 +08:00
|
|
|
resno, new, check);
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
}
|
2012-07-10 09:49:37 +08:00
|
|
|
|
|
|
|
if (disable)
|
|
|
|
pci_write_config_word(dev, PCI_COMMAND, cmd);
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
2016-11-28 23:15:52 +08:00
|
|
|
void pci_update_resource(struct pci_dev *dev, int resno)
|
|
|
|
{
|
|
|
|
if (resno <= PCI_ROM_RESOURCE)
|
|
|
|
pci_std_update_resource(dev, resno);
|
|
|
|
#ifdef CONFIG_PCI_IOV
|
|
|
|
else if (resno >= PCI_IOV_RESOURCES && resno <= PCI_IOV_RESOURCE_END)
|
|
|
|
pci_iov_update_resource(dev, resno);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2007-03-27 13:53:30 +08:00
|
|
|
int pci_claim_resource(struct pci_dev *dev, int resource)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
|
|
|
struct resource *res = &dev->resource[resource];
|
2010-03-12 08:01:19 +08:00
|
|
|
struct resource *root, *conflict;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2014-02-27 02:25:59 +08:00
|
|
|
if (res->flags & IORESOURCE_UNSET) {
|
2018-01-19 02:55:24 +08:00
|
|
|
pci_info(dev, "can't claim BAR %d %pR: no address assigned\n",
|
2014-02-27 02:25:59 +08:00
|
|
|
resource, res);
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
2016-11-09 04:25:24 +08:00
|
|
|
/*
|
|
|
|
* If we have a shadow copy in RAM, the PCI device doesn't respond
|
|
|
|
* to the shadow range, so we don't need to claim it, and upstream
|
|
|
|
* bridges don't need to route the range to the device.
|
|
|
|
*/
|
|
|
|
if (res->flags & IORESOURCE_ROM_SHADOW)
|
|
|
|
return 0;
|
|
|
|
|
2009-06-18 04:33:33 +08:00
|
|
|
root = pci_find_parent_resource(dev, res);
|
2009-11-05 01:32:57 +08:00
|
|
|
if (!root) {
|
2018-01-19 02:55:24 +08:00
|
|
|
pci_info(dev, "can't claim BAR %d %pR: no compatible bridge window\n",
|
2014-02-27 02:25:59 +08:00
|
|
|
resource, res);
|
2015-03-13 01:30:06 +08:00
|
|
|
res->flags |= IORESOURCE_UNSET;
|
2009-11-05 01:32:57 +08:00
|
|
|
return -EINVAL;
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
2010-03-12 08:01:19 +08:00
|
|
|
conflict = request_resource_conflict(root, res);
|
|
|
|
if (conflict) {
|
2018-01-19 02:55:24 +08:00
|
|
|
pci_info(dev, "can't claim BAR %d %pR: address conflict with %s %pR\n",
|
2014-02-27 02:25:59 +08:00
|
|
|
resource, res, conflict->name, conflict);
|
2015-03-13 01:30:06 +08:00
|
|
|
res->flags |= IORESOURCE_UNSET;
|
2010-03-12 08:01:19 +08:00
|
|
|
return -EBUSY;
|
|
|
|
}
|
2009-11-05 01:32:57 +08:00
|
|
|
|
2010-03-12 08:01:19 +08:00
|
|
|
return 0;
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
2009-07-01 12:45:44 +08:00
|
|
|
EXPORT_SYMBOL(pci_claim_resource);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2009-03-16 16:13:39 +08:00
|
|
|
void pci_disable_bridge_window(struct pci_dev *dev)
|
|
|
|
{
|
|
|
|
/* MMIO Base/Limit */
|
|
|
|
pci_write_config_dword(dev, PCI_MEMORY_BASE, 0x0000fff0);
|
|
|
|
|
|
|
|
/* Prefetchable MMIO Base/Limit */
|
|
|
|
pci_write_config_dword(dev, PCI_PREF_LIMIT_UPPER32, 0);
|
|
|
|
pci_write_config_dword(dev, PCI_PREF_MEMORY_BASE, 0x0000fff0);
|
|
|
|
pci_write_config_dword(dev, PCI_PREF_BASE_UPPER32, 0xffffffff);
|
|
|
|
}
|
2011-07-26 04:08:39 +08:00
|
|
|
|
2011-11-22 02:54:19 +08:00
|
|
|
/*
|
|
|
|
* Generic function that returns a value indicating that the device's
|
|
|
|
* original BIOS BAR address was not saved and so is not available for
|
|
|
|
* reinstatement.
|
|
|
|
*
|
|
|
|
* Can be over-ridden by architecture specific code that implements
|
|
|
|
* reinstatement functionality rather than leaving it disabled when
|
|
|
|
* normal allocation attempts fail.
|
|
|
|
*/
|
|
|
|
resource_size_t __weak pcibios_retrieve_fw_addr(struct pci_dev *dev, int idx)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2013-11-15 02:28:18 +08:00
|
|
|
static int pci_revert_fw_address(struct resource *res, struct pci_dev *dev,
|
2011-07-26 04:08:39 +08:00
|
|
|
int resno, resource_size_t size)
|
|
|
|
{
|
|
|
|
struct resource *root, *conflict;
|
2011-11-22 02:54:19 +08:00
|
|
|
resource_size_t fw_addr, start, end;
|
PCI: fall back to original BIOS BAR addresses
If we fail to assign resources to a PCI BAR, this patch makes us try the
original address from BIOS rather than leaving it disabled.
Linux tries to make sure all PCI device BARs are inside the upstream
PCI host bridge or P2P bridge apertures, reassigning BARs if necessary.
Windows does similar reassignment.
Before this patch, if we could not move a BAR into an aperture, we left
the resource unassigned, i.e., at address zero. Windows leaves such BARs
at the original BIOS addresses, and this patch makes Linux do the same.
This is a bit ugly because we disable the resource long before we try to
reassign it, so we have to keep track of the BIOS BAR address somewhere.
For lack of a better place, I put it in the struct pci_dev.
I think it would be cleaner to attempt the assignment immediately when the
claim fails, so we could easily remember the original address. But we
currently claim motherboard resources in the middle, after attempting to
claim PCI resources and before assigning new PCI resources, and changing
that is a fairly big job.
Addresses https://bugzilla.kernel.org/show_bug.cgi?id=16263
Reported-by: Andrew <nitr0@seti.kr.ua>
Tested-by: Andrew <nitr0@seti.kr.ua>
Signed-off-by: Bjorn Helgaas <bjorn.helgaas@hp.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
2010-07-15 23:41:42 +08:00
|
|
|
|
2011-11-22 02:54:19 +08:00
|
|
|
fw_addr = pcibios_retrieve_fw_addr(dev, resno);
|
|
|
|
if (!fw_addr)
|
2014-07-09 06:00:42 +08:00
|
|
|
return -ENOMEM;
|
2011-11-22 02:54:19 +08:00
|
|
|
|
2011-07-26 04:08:39 +08:00
|
|
|
start = res->start;
|
|
|
|
end = res->end;
|
2011-11-22 02:54:19 +08:00
|
|
|
res->start = fw_addr;
|
2011-07-26 04:08:39 +08:00
|
|
|
res->end = res->start + size - 1;
|
2015-09-22 07:26:45 +08:00
|
|
|
res->flags &= ~IORESOURCE_UNSET;
|
2011-11-22 02:54:07 +08:00
|
|
|
|
|
|
|
root = pci_find_parent_resource(dev, res);
|
|
|
|
if (!root) {
|
PCI: Sanitise firmware BAR assignments behind a PCI-PCI bridge
When pci_assign_resource() is unable to assign resources to a BAR, it uses
pci_revert_fw_address() to fall back to a firmware assignment (if any).
Previously pci_revert_fw_address() assumed all addresses could reach the
device, but this is not true if the device is below a bridge that only
forwards addresses within its windows.
This problem was observed on a Tyan Tomcat IV S1564D system where the BIOS
did not assign valid addresses to several bridges and USB devices:
pci 0000:00:11.0: PCI-to-PCIe bridge to [bus 01-ff]
pci 0000:00:11.0: bridge window [io 0xe000-0xefff]
pci 0000:01:00.0: PCIe Upstream Port to [bus 02-ff]
pci 0000:01:00.0: bridge window [io 0x0000-0x0fff] # unreachable
pci 0000:02:02.0: PCIe Downstream Port to [bus 05-ff]
pci 0000:02:02.0: bridge window [io 0x0000-0x0fff] # unreachable
pci 0000:05:00.0: PCIe-to-PCI bridge to [bus 06-ff]
pci 0000:05:00.0: bridge window [io 0x0000-0x0fff] # unreachable
pci 0000:06:08.0: USB UHCI 1.1
pci 0000:06:08.0: BAR 4: [io 0xfce0-0xfcff] # unreachable
pci 0000:06:08.1: USB UHCI 1.1
pci 0000:06:08.1: BAR 4: [io 0xfce0-0xfcff] # unreachable
pci 0000:06:08.0: can't claim BAR 4 [io 0xfce0-0xfcff]: no compatible bridge window
pci 0000:06:08.1: can't claim BAR 4 [io 0xfce0-0xfcff]: no compatible bridge window
During the first pass of assigning unassigned resources, there was not
enough I/O space available, so we couldn't assign the 06:08.0 BAR and
reverted to the firmware assignment (still unreachable). Reverting the
06:08.1 assignment failed because it conflicted with 06:08.0:
pci 0000:00:11.0: bridge window [io 0xe000-0xefff]
pci 0000:01:00.0: no space for bridge window [io size 0x2000]
pci 0000:02:02.0: no space for bridge window [io size 0x1000]
pci 0000:05:00.0: no space for bridge window [io size 0x1000]
pci 0000:06:08.0: BAR 4: no space for [io size 0x0020]
pci 0000:06:08.0: BAR 4: trying firmware assignment [io 0xfce0-0xfcff]
pci 0000:06:08.1: BAR 4: no space for [io size 0x0020]
pci 0000:06:08.1: BAR 4: trying firmware assignment [io 0xfce0-0xfcff]
pci 0000:06:08.1: BAR 4: [io 0xfce0-0xfcff] conflicts with 0000:06:08.0 [io 0xfce0-0xfcff]
A subsequent pass assigned valid bridge windows and a valid 06:08.1 BAR,
but left the 06:08.0 BAR alone, so the UHCI device was still unusable:
pci 0000:00:11.0: bridge window [io 0xe000-0xefff] released
pci 0000:00:11.0: bridge window [io 0x1000-0x2fff] # reassigned
pci 0000:01:00.0: bridge window [io 0x1000-0x2fff] # reassigned
pci 0000:02:02.0: bridge window [io 0x2000-0x2fff] # reassigned
pci 0000:05:00.0: bridge window [io 0x2000-0x2fff] # reassigned
pci 0000:06:08.0: BAR 4: assigned [io 0xfce0-0xfcff] # left alone
pci 0000:06:08.1: BAR 4: assigned [io 0x2000-0x201f]
...
uhci_hcd 0000:06:08.0: host system error, PCI problems?
uhci_hcd 0000:06:08.0: host controller process error, something bad happened!
uhci_hcd 0000:06:08.0: host controller halted, very bad!
uhci_hcd 0000:06:08.0: HCRESET not completed yet!
uhci_hcd 0000:06:08.0: HC died; cleaning up
If the address assigned by firmware is not reachable because it's not
within upstream bridge windows, fail instead of assigning the unusable
address from firmware.
[bhelgaas: commit log, use pci_upstream_bridge()]
Link: https://bugzilla.kernel.org/show_bug.cgi?id=16263
Link: https://lore.kernel.org/r/alpine.DEB.2.21.2203012338460.46819@angie.orcam.me.uk
Link: https://lore.kernel.org/r/alpine.DEB.2.21.2209211921250.29493@angie.orcam.me.uk
Fixes: 58c84eda0756 ("PCI: fall back to original BIOS BAR addresses")
Signed-off-by: Maciej W. Rozycki <macro@orcam.me.uk>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Cc: stable@vger.kernel.org # v2.6.35+
2022-09-22 03:49:16 +08:00
|
|
|
/*
|
|
|
|
* If dev is behind a bridge, accesses will only reach it
|
|
|
|
* if res is inside the relevant bridge window.
|
|
|
|
*/
|
|
|
|
if (pci_upstream_bridge(dev))
|
|
|
|
return -ENXIO;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* On the root bus, assume the host bridge will forward
|
|
|
|
* everything.
|
|
|
|
*/
|
2011-11-22 02:54:07 +08:00
|
|
|
if (res->flags & IORESOURCE_IO)
|
|
|
|
root = &ioport_resource;
|
|
|
|
else
|
|
|
|
root = &iomem_resource;
|
|
|
|
}
|
|
|
|
|
2018-01-19 02:55:24 +08:00
|
|
|
pci_info(dev, "BAR %d: trying firmware assignment %pR\n",
|
2011-07-26 04:08:39 +08:00
|
|
|
resno, res);
|
|
|
|
conflict = request_resource_conflict(root, res);
|
|
|
|
if (conflict) {
|
2018-01-19 02:55:24 +08:00
|
|
|
pci_info(dev, "BAR %d: %pR conflicts with %s %pR\n",
|
2014-07-09 06:00:42 +08:00
|
|
|
resno, res, conflict->name, conflict);
|
2011-07-26 04:08:39 +08:00
|
|
|
res->start = start;
|
|
|
|
res->end = end;
|
2015-09-22 07:26:45 +08:00
|
|
|
res->flags |= IORESOURCE_UNSET;
|
2014-07-09 06:00:42 +08:00
|
|
|
return -EBUSY;
|
2011-07-26 04:08:39 +08:00
|
|
|
}
|
2014-07-09 06:00:42 +08:00
|
|
|
return 0;
|
2011-07-26 04:08:39 +08:00
|
|
|
}
|
|
|
|
|
2017-08-03 03:44:50 +08:00
|
|
|
/*
|
|
|
|
* We don't have to worry about legacy ISA devices, so nothing to do here.
|
|
|
|
* This is marked as __weak because multiple architectures define it; it should
|
|
|
|
* eventually go away.
|
|
|
|
*/
|
|
|
|
resource_size_t __weak pcibios_align_resource(void *data,
|
|
|
|
const struct resource *res,
|
|
|
|
resource_size_t size,
|
|
|
|
resource_size_t align)
|
|
|
|
{
|
|
|
|
return res->start;
|
|
|
|
}
|
|
|
|
|
2012-07-12 07:05:43 +08:00
|
|
|
static int __pci_assign_resource(struct pci_bus *bus, struct pci_dev *dev,
|
|
|
|
int resno, resource_size_t size, resource_size_t align)
|
|
|
|
{
|
|
|
|
struct resource *res = dev->resource + resno;
|
|
|
|
resource_size_t min;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
min = (res->flags & IORESOURCE_IO) ? PCIBIOS_MIN_IO : PCIBIOS_MIN_MEM;
|
|
|
|
|
2014-05-20 08:32:18 +08:00
|
|
|
/*
|
|
|
|
* First, try exact prefetching match. Even if a 64-bit
|
|
|
|
* prefetchable bridge window is below 4GB, we can't put a 32-bit
|
|
|
|
* prefetchable resource in it because pbus_size_mem() assumes a
|
|
|
|
* 64-bit window will contain no 32-bit resources. If we assign
|
|
|
|
* things differently than they were sized, not everything will fit.
|
|
|
|
*/
|
2012-07-12 07:05:43 +08:00
|
|
|
ret = pci_bus_alloc_resource(bus, res, size, align, min,
|
PCI: Restrict 64-bit prefetchable bridge windows to 64-bit resources
This patch changes the way we handle 64-bit prefetchable bridge windows to
make it more likely that we can assign space to all devices.
Previously we put all prefetchable resources in the prefetchable bridge
window. If any of those resources was 32-bit only, we restricted the
window to be below 4GB.
After this patch, we only put 64-bit prefetchable resources in a 64-bit
prefetchable window. We put all 32-bit prefetchable resources in the
non-prefetchable window, even if there are no 64-bit prefetchable
resources.
With the previous approach, if there was a 32-bit prefetchable resource
behind a bridge, we forced the bridge's prefetchable window below 4GB,
which meant that even if there was plenty of space above 4GB available, we
couldn't use it, and assignment of large 64-bit resources could fail, as
in the bugzilla below.
The new strategy is:
1) If the prefetchable window is 64 bits wide, we put only 64-bit
prefetchable resources in it. Any 32-bit prefetchable resources go in
the non-prefetchable window.
2) If the prefetchable window is 32 bits wide, we put both 32- and 64-bit
prefetchable resources in it.
3) If there is no prefetchable window, all MMIO resources go in the
non-prefetchable window.
This reduces performance for 32-bit prefetchable resources below a bridge
with a 64-bit prefetchable window. We previously assigned prefetchable
space, but now we'll assign non-prefetchable space. This is the case even
if there are no 64-bit prefetchable resources, or if they would all fit
below 4GB. In those cases, the old strategy would work and would have
better performance.
[bhelgaas: write changelog, add bugzilla link, fold in mem64_mask removal]
Link: https://bugzilla.kernel.org/show_bug.cgi?id=74151
Tested-by: Guo Chao <yan@linux.vnet.ibm.com>
Tested-by: Wei Yang <weiyang@linux.vnet.ibm.com>
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
2014-05-20 07:01:55 +08:00
|
|
|
IORESOURCE_PREFETCH | IORESOURCE_MEM_64,
|
2012-07-12 07:05:43 +08:00
|
|
|
pcibios_align_resource, dev);
|
2014-05-20 08:39:07 +08:00
|
|
|
if (ret == 0)
|
|
|
|
return 0;
|
2012-07-12 07:05:43 +08:00
|
|
|
|
2014-05-20 08:32:18 +08:00
|
|
|
/*
|
|
|
|
* If the prefetchable window is only 32 bits wide, we can put
|
|
|
|
* 64-bit prefetchable resources in it.
|
|
|
|
*/
|
2014-05-20 08:39:07 +08:00
|
|
|
if ((res->flags & (IORESOURCE_PREFETCH | IORESOURCE_MEM_64)) ==
|
PCI: Restrict 64-bit prefetchable bridge windows to 64-bit resources
This patch changes the way we handle 64-bit prefetchable bridge windows to
make it more likely that we can assign space to all devices.
Previously we put all prefetchable resources in the prefetchable bridge
window. If any of those resources was 32-bit only, we restricted the
window to be below 4GB.
After this patch, we only put 64-bit prefetchable resources in a 64-bit
prefetchable window. We put all 32-bit prefetchable resources in the
non-prefetchable window, even if there are no 64-bit prefetchable
resources.
With the previous approach, if there was a 32-bit prefetchable resource
behind a bridge, we forced the bridge's prefetchable window below 4GB,
which meant that even if there was plenty of space above 4GB available, we
couldn't use it, and assignment of large 64-bit resources could fail, as
in the bugzilla below.
The new strategy is:
1) If the prefetchable window is 64 bits wide, we put only 64-bit
prefetchable resources in it. Any 32-bit prefetchable resources go in
the non-prefetchable window.
2) If the prefetchable window is 32 bits wide, we put both 32- and 64-bit
prefetchable resources in it.
3) If there is no prefetchable window, all MMIO resources go in the
non-prefetchable window.
This reduces performance for 32-bit prefetchable resources below a bridge
with a 64-bit prefetchable window. We previously assigned prefetchable
space, but now we'll assign non-prefetchable space. This is the case even
if there are no 64-bit prefetchable resources, or if they would all fit
below 4GB. In those cases, the old strategy would work and would have
better performance.
[bhelgaas: write changelog, add bugzilla link, fold in mem64_mask removal]
Link: https://bugzilla.kernel.org/show_bug.cgi?id=74151
Tested-by: Guo Chao <yan@linux.vnet.ibm.com>
Tested-by: Wei Yang <weiyang@linux.vnet.ibm.com>
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
2014-05-20 07:01:55 +08:00
|
|
|
(IORESOURCE_PREFETCH | IORESOURCE_MEM_64)) {
|
|
|
|
ret = pci_bus_alloc_resource(bus, res, size, align, min,
|
|
|
|
IORESOURCE_PREFETCH,
|
2012-07-12 07:05:43 +08:00
|
|
|
pcibios_align_resource, dev);
|
2014-05-20 08:39:07 +08:00
|
|
|
if (ret == 0)
|
|
|
|
return 0;
|
2012-07-12 07:05:43 +08:00
|
|
|
}
|
PCI: Restrict 64-bit prefetchable bridge windows to 64-bit resources
This patch changes the way we handle 64-bit prefetchable bridge windows to
make it more likely that we can assign space to all devices.
Previously we put all prefetchable resources in the prefetchable bridge
window. If any of those resources was 32-bit only, we restricted the
window to be below 4GB.
After this patch, we only put 64-bit prefetchable resources in a 64-bit
prefetchable window. We put all 32-bit prefetchable resources in the
non-prefetchable window, even if there are no 64-bit prefetchable
resources.
With the previous approach, if there was a 32-bit prefetchable resource
behind a bridge, we forced the bridge's prefetchable window below 4GB,
which meant that even if there was plenty of space above 4GB available, we
couldn't use it, and assignment of large 64-bit resources could fail, as
in the bugzilla below.
The new strategy is:
1) If the prefetchable window is 64 bits wide, we put only 64-bit
prefetchable resources in it. Any 32-bit prefetchable resources go in
the non-prefetchable window.
2) If the prefetchable window is 32 bits wide, we put both 32- and 64-bit
prefetchable resources in it.
3) If there is no prefetchable window, all MMIO resources go in the
non-prefetchable window.
This reduces performance for 32-bit prefetchable resources below a bridge
with a 64-bit prefetchable window. We previously assigned prefetchable
space, but now we'll assign non-prefetchable space. This is the case even
if there are no 64-bit prefetchable resources, or if they would all fit
below 4GB. In those cases, the old strategy would work and would have
better performance.
[bhelgaas: write changelog, add bugzilla link, fold in mem64_mask removal]
Link: https://bugzilla.kernel.org/show_bug.cgi?id=74151
Tested-by: Guo Chao <yan@linux.vnet.ibm.com>
Tested-by: Wei Yang <weiyang@linux.vnet.ibm.com>
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
2014-05-20 07:01:55 +08:00
|
|
|
|
2014-05-20 08:32:18 +08:00
|
|
|
/*
|
|
|
|
* If we didn't find a better match, we can put any memory resource
|
|
|
|
* in a non-prefetchable window. If this resource is 32 bits and
|
|
|
|
* non-prefetchable, the first call already tried the only possibility
|
|
|
|
* so we don't need to try again.
|
|
|
|
*/
|
|
|
|
if (res->flags & (IORESOURCE_PREFETCH | IORESOURCE_MEM_64))
|
2012-07-12 07:05:43 +08:00
|
|
|
ret = pci_bus_alloc_resource(bus, res, size, align, min, 0,
|
|
|
|
pcibios_align_resource, dev);
|
2014-05-20 08:32:18 +08:00
|
|
|
|
2012-07-12 07:05:43 +08:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2012-06-21 03:56:00 +08:00
|
|
|
static int _pci_assign_resource(struct pci_dev *dev, int resno,
|
|
|
|
resource_size_t size, resource_size_t min_align)
|
2011-07-26 04:08:39 +08:00
|
|
|
{
|
|
|
|
struct pci_bus *bus;
|
|
|
|
int ret;
|
PCI: fall back to original BIOS BAR addresses
If we fail to assign resources to a PCI BAR, this patch makes us try the
original address from BIOS rather than leaving it disabled.
Linux tries to make sure all PCI device BARs are inside the upstream
PCI host bridge or P2P bridge apertures, reassigning BARs if necessary.
Windows does similar reassignment.
Before this patch, if we could not move a BAR into an aperture, we left
the resource unassigned, i.e., at address zero. Windows leaves such BARs
at the original BIOS addresses, and this patch makes Linux do the same.
This is a bit ugly because we disable the resource long before we try to
reassign it, so we have to keep track of the BIOS BAR address somewhere.
For lack of a better place, I put it in the struct pci_dev.
I think it would be cleaner to attempt the assignment immediately when the
claim fails, so we could easily remember the original address. But we
currently claim motherboard resources in the middle, after attempting to
claim PCI resources and before assigning new PCI resources, and changing
that is a fairly big job.
Addresses https://bugzilla.kernel.org/show_bug.cgi?id=16263
Reported-by: Andrew <nitr0@seti.kr.ua>
Tested-by: Andrew <nitr0@seti.kr.ua>
Signed-off-by: Bjorn Helgaas <bjorn.helgaas@hp.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
2010-07-15 23:41:42 +08:00
|
|
|
|
2011-07-26 04:08:39 +08:00
|
|
|
bus = dev->bus;
|
|
|
|
while ((ret = __pci_assign_resource(bus, dev, resno, size, min_align))) {
|
|
|
|
if (!bus->parent || !bus->self->transparent)
|
|
|
|
break;
|
|
|
|
bus = bus->parent;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2009-04-24 11:49:25 +08:00
|
|
|
int pci_assign_resource(struct pci_dev *dev, int resno)
|
|
|
|
{
|
|
|
|
struct resource *res = dev->resource + resno;
|
2011-07-26 04:08:39 +08:00
|
|
|
resource_size_t align, size;
|
2009-04-24 11:49:25 +08:00
|
|
|
int ret;
|
|
|
|
|
2016-03-02 00:58:04 +08:00
|
|
|
if (res->flags & IORESOURCE_PCI_FIXED)
|
|
|
|
return 0;
|
|
|
|
|
2014-02-27 02:25:58 +08:00
|
|
|
res->flags |= IORESOURCE_UNSET;
|
2009-08-29 04:00:06 +08:00
|
|
|
align = pci_resource_alignment(dev, res);
|
2009-04-24 11:49:25 +08:00
|
|
|
if (!align) {
|
2018-01-19 02:55:24 +08:00
|
|
|
pci_info(dev, "BAR %d: can't assign %pR (bogus alignment)\n",
|
2014-04-19 08:13:50 +08:00
|
|
|
resno, res);
|
2009-04-24 11:49:25 +08:00
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
2011-07-26 04:08:39 +08:00
|
|
|
size = resource_size(res);
|
|
|
|
ret = _pci_assign_resource(dev, resno, size, align);
|
2009-04-24 11:49:25 +08:00
|
|
|
|
2011-07-26 04:08:39 +08:00
|
|
|
/*
|
|
|
|
* If we failed to assign anything, let's try the address
|
|
|
|
* where firmware left it. That at least has a chance of
|
|
|
|
* working, which is better than just leaving it disabled.
|
|
|
|
*/
|
2014-07-09 06:04:22 +08:00
|
|
|
if (ret < 0) {
|
2018-01-19 02:55:24 +08:00
|
|
|
pci_info(dev, "BAR %d: no space for %pR\n", resno, res);
|
2011-07-26 04:08:39 +08:00
|
|
|
ret = pci_revert_fw_address(res, dev, resno, size);
|
2014-07-09 06:04:22 +08:00
|
|
|
}
|
2009-04-24 11:49:25 +08:00
|
|
|
|
2014-07-09 06:04:22 +08:00
|
|
|
if (ret < 0) {
|
2018-01-19 02:55:24 +08:00
|
|
|
pci_info(dev, "BAR %d: failed to assign %pR\n", resno, res);
|
2014-07-05 05:58:15 +08:00
|
|
|
return ret;
|
2014-07-09 06:04:22 +08:00
|
|
|
}
|
2014-07-05 05:58:15 +08:00
|
|
|
|
|
|
|
res->flags &= ~IORESOURCE_UNSET;
|
|
|
|
res->flags &= ~IORESOURCE_STARTALIGN;
|
2018-01-19 02:55:24 +08:00
|
|
|
pci_info(dev, "BAR %d: assigned %pR\n", resno, res);
|
2014-07-05 05:58:15 +08:00
|
|
|
if (resno < PCI_BRIDGE_RESOURCES)
|
|
|
|
pci_update_resource(dev, resno);
|
|
|
|
|
|
|
|
return 0;
|
2009-04-24 11:49:25 +08:00
|
|
|
}
|
2014-04-26 04:32:25 +08:00
|
|
|
EXPORT_SYMBOL(pci_assign_resource);
|
2009-04-24 11:49:25 +08:00
|
|
|
|
2012-07-12 07:05:43 +08:00
|
|
|
int pci_reassign_resource(struct pci_dev *dev, int resno, resource_size_t addsize,
|
|
|
|
resource_size_t min_align)
|
|
|
|
{
|
|
|
|
struct resource *res = dev->resource + resno;
|
2014-07-04 08:30:29 +08:00
|
|
|
unsigned long flags;
|
2012-07-12 07:05:43 +08:00
|
|
|
resource_size_t new_size;
|
|
|
|
int ret;
|
|
|
|
|
2016-03-02 00:58:04 +08:00
|
|
|
if (res->flags & IORESOURCE_PCI_FIXED)
|
|
|
|
return 0;
|
|
|
|
|
2014-07-04 08:30:29 +08:00
|
|
|
flags = res->flags;
|
2014-02-27 02:25:58 +08:00
|
|
|
res->flags |= IORESOURCE_UNSET;
|
2012-07-12 07:05:43 +08:00
|
|
|
if (!res->parent) {
|
2018-01-19 02:55:24 +08:00
|
|
|
pci_info(dev, "BAR %d: can't reassign an unassigned resource %pR\n",
|
2014-04-19 08:13:50 +08:00
|
|
|
resno, res);
|
2012-07-12 07:05:43 +08:00
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* already aligned with min_align */
|
|
|
|
new_size = resource_size(res) + addsize;
|
|
|
|
ret = _pci_assign_resource(dev, resno, new_size, min_align);
|
2014-07-05 05:58:15 +08:00
|
|
|
if (ret) {
|
2014-07-04 08:30:29 +08:00
|
|
|
res->flags = flags;
|
2018-01-19 02:55:24 +08:00
|
|
|
pci_info(dev, "BAR %d: %pR (failed to expand by %#llx)\n",
|
2014-07-04 08:30:29 +08:00
|
|
|
resno, res, (unsigned long long) addsize);
|
2014-07-05 05:58:15 +08:00
|
|
|
return ret;
|
2012-07-12 07:05:43 +08:00
|
|
|
}
|
2014-07-04 08:30:29 +08:00
|
|
|
|
2014-07-05 05:58:15 +08:00
|
|
|
res->flags &= ~IORESOURCE_UNSET;
|
|
|
|
res->flags &= ~IORESOURCE_STARTALIGN;
|
2018-01-19 02:55:24 +08:00
|
|
|
pci_info(dev, "BAR %d: reassigned %pR (expanded by %#llx)\n",
|
2014-07-09 06:04:22 +08:00
|
|
|
resno, res, (unsigned long long) addsize);
|
2014-07-05 05:58:15 +08:00
|
|
|
if (resno < PCI_BRIDGE_RESOURCES)
|
|
|
|
pci_update_resource(dev, resno);
|
|
|
|
|
|
|
|
return 0;
|
2012-07-12 07:05:43 +08:00
|
|
|
}
|
|
|
|
|
2017-10-25 03:40:26 +08:00
|
|
|
void pci_release_resource(struct pci_dev *dev, int resno)
|
|
|
|
{
|
|
|
|
struct resource *res = dev->resource + resno;
|
|
|
|
|
2018-01-19 02:55:24 +08:00
|
|
|
pci_info(dev, "BAR %d: releasing %pR\n", resno, res);
|
2018-02-27 04:51:13 +08:00
|
|
|
|
|
|
|
if (!res->parent)
|
|
|
|
return;
|
|
|
|
|
2017-10-25 03:40:26 +08:00
|
|
|
release_resource(res);
|
|
|
|
res->end = resource_size(res) - 1;
|
|
|
|
res->start = 0;
|
|
|
|
res->flags |= IORESOURCE_UNSET;
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(pci_release_resource);
|
|
|
|
|
|
|
|
int pci_resize_resource(struct pci_dev *dev, int resno, int size)
|
|
|
|
{
|
|
|
|
struct resource *res = dev->resource + resno;
|
2021-01-09 17:53:53 +08:00
|
|
|
struct pci_host_bridge *host;
|
2017-10-25 03:40:26 +08:00
|
|
|
int old, ret;
|
|
|
|
u32 sizes;
|
|
|
|
u16 cmd;
|
|
|
|
|
2021-01-09 17:53:53 +08:00
|
|
|
/* Check if we must preserve the firmware's resource assignment */
|
|
|
|
host = pci_find_host_bridge(dev->bus);
|
|
|
|
if (host->preserve_config)
|
|
|
|
return -ENOTSUPP;
|
|
|
|
|
2017-10-25 03:40:26 +08:00
|
|
|
/* Make sure the resource isn't assigned before resizing it. */
|
|
|
|
if (!(res->flags & IORESOURCE_UNSET))
|
|
|
|
return -EBUSY;
|
|
|
|
|
|
|
|
pci_read_config_word(dev, PCI_COMMAND, &cmd);
|
|
|
|
if (cmd & PCI_COMMAND_MEMORY)
|
|
|
|
return -EBUSY;
|
|
|
|
|
|
|
|
sizes = pci_rebar_get_possible_sizes(dev, resno);
|
|
|
|
if (!sizes)
|
|
|
|
return -ENOTSUPP;
|
|
|
|
|
|
|
|
if (!(sizes & BIT(size)))
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
old = pci_rebar_get_current_size(dev, resno);
|
|
|
|
if (old < 0)
|
|
|
|
return old;
|
|
|
|
|
|
|
|
ret = pci_rebar_set_size(dev, resno, size);
|
|
|
|
if (ret)
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
res->end = res->start + pci_rebar_size_to_bytes(size) - 1;
|
|
|
|
|
|
|
|
/* Check if the new config works by trying to assign everything. */
|
2020-04-22 00:22:56 +08:00
|
|
|
if (dev->bus->self) {
|
|
|
|
ret = pci_reassign_bridge_resources(dev->bus->self, res->flags);
|
|
|
|
if (ret)
|
|
|
|
goto error_resize;
|
|
|
|
}
|
2017-10-25 03:40:26 +08:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
error_resize:
|
|
|
|
pci_rebar_set_size(dev, resno, old);
|
|
|
|
res->end = res->start + pci_rebar_size_to_bytes(old) - 1;
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(pci_resize_resource);
|
|
|
|
|
2008-03-05 02:56:47 +08:00
|
|
|
int pci_enable_resources(struct pci_dev *dev, int mask)
|
|
|
|
{
|
|
|
|
u16 cmd, old_cmd;
|
|
|
|
int i;
|
|
|
|
struct resource *r;
|
|
|
|
|
|
|
|
pci_read_config_word(dev, PCI_COMMAND, &cmd);
|
|
|
|
old_cmd = cmd;
|
|
|
|
|
|
|
|
for (i = 0; i < PCI_NUM_RESOURCES; i++) {
|
|
|
|
if (!(mask & (1 << i)))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
r = &dev->resource[i];
|
|
|
|
|
|
|
|
if (!(r->flags & (IORESOURCE_IO | IORESOURCE_MEM)))
|
|
|
|
continue;
|
|
|
|
if ((i == PCI_ROM_RESOURCE) &&
|
|
|
|
(!(r->flags & IORESOURCE_ROM_ENABLE)))
|
|
|
|
continue;
|
|
|
|
|
2014-02-27 02:26:00 +08:00
|
|
|
if (r->flags & IORESOURCE_UNSET) {
|
2018-01-19 02:55:24 +08:00
|
|
|
pci_err(dev, "can't enable device: BAR %d %pR not assigned\n",
|
2014-02-27 02:26:00 +08:00
|
|
|
i, r);
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
2008-03-05 02:56:47 +08:00
|
|
|
if (!r->parent) {
|
2018-01-19 02:55:24 +08:00
|
|
|
pci_err(dev, "can't enable device: BAR %d %pR not claimed\n",
|
2014-02-27 02:26:00 +08:00
|
|
|
i, r);
|
2008-03-05 02:56:47 +08:00
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (r->flags & IORESOURCE_IO)
|
|
|
|
cmd |= PCI_COMMAND_IO;
|
|
|
|
if (r->flags & IORESOURCE_MEM)
|
|
|
|
cmd |= PCI_COMMAND_MEMORY;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (cmd != old_cmd) {
|
2018-01-19 02:55:24 +08:00
|
|
|
pci_info(dev, "enabling device (%04x -> %04x)\n", old_cmd, cmd);
|
2008-03-05 02:56:47 +08:00
|
|
|
pci_write_config_word(dev, PCI_COMMAND, cmd);
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|