Skip to content

Commit

Permalink
Merge branches 'pci/enumeration', 'pci/hotplug', 'pci/misc', 'pci/num…
Browse files Browse the repository at this point in the history
…a' and 'pci/virtualization' into next

* pci/enumeration:
  PCI: Remove fixed parameter in pci_iov_resource_bar()
  PCI: Add informational printk for invalid BARs
  PCI: Shrink decoding-disabled window while sizing BARs
  PCI: Restore detection of read-only BARs

* pci/hotplug:
  PCI: Remove unused and broken to_hotplug_slot()

* pci/misc:
  PCI: Make FLR and AF FLR reset warning messages different
  PCI: Simplify if-return sequences
  PCI: Delete unnecessary NULL pointer checks

* pci/numa:
  PCI: Allow numa_node override via sysfs

* pci/virtualization:
  xen/pcifront: Process failure for pcifront_(re)scan_root()
  • Loading branch information
Bjorn Helgaas committed Nov 19, 2014
6 parents 35437e3 + 26ff46c + a4acded + bb383e2 + 63692df + 23cf1d0 commit 18e88be
Show file tree
Hide file tree
Showing 11 changed files with 99 additions and 84 deletions.
13 changes: 13 additions & 0 deletions Documentation/ABI/testing/sysfs-bus-pci
Original file line number Diff line number Diff line change
Expand Up @@ -281,3 +281,16 @@ Description:
opt-out of driver binding using a driver_override name such as
"none". Only a single driver may be specified in the override,
there is no support for parsing delimiters.

What: /sys/bus/pci/devices/.../numa_node
Date: Oct 2014
Contact: Prarit Bhargava <prarit@redhat.com>
Description:
This file contains the NUMA node to which the PCI device is
attached, or -1 if the node is unknown. The initial value
comes from an ACPI _PXM method or a similar firmware
source. If that is missing or incorrect, this file can be
written to override the node. In that case, please report
a firmware bug to the system vendor. Writing to this file
taints the kernel with TAINT_FIRMWARE_WORKAROUND, which
reduces the supportability of your system.
5 changes: 1 addition & 4 deletions drivers/pci/hotplug/ibmphp_res.c
Original file line number Diff line number Diff line change
Expand Up @@ -376,10 +376,7 @@ int __init ibmphp_rsrc_init (void)
if (rc)
return rc;
}
rc = once_over (); /* This is to align ranges (so no -1) */
if (rc)
return rc;
return 0;
return once_over (); /* This is to align ranges (so no -1) */
}

/********************************************************************************
Expand Down
11 changes: 3 additions & 8 deletions drivers/pci/iov.c
Original file line number Diff line number Diff line change
Expand Up @@ -479,20 +479,16 @@ void pci_iov_release(struct pci_dev *dev)
* pci_iov_resource_bar - get position of the SR-IOV BAR
* @dev: the PCI device
* @resno: the resource number
* @type: the BAR type to be filled in
*
* Returns position of the BAR encapsulated in the SR-IOV capability.
*/
int pci_iov_resource_bar(struct pci_dev *dev, int resno,
enum pci_bar_type *type)
int pci_iov_resource_bar(struct pci_dev *dev, int resno)
{
if (resno < PCI_IOV_RESOURCES || resno > PCI_IOV_RESOURCE_END)
return 0;

BUG_ON(!dev->is_physfn);

*type = pci_bar_unknown;

return dev->sriov->pos + PCI_SRIOV_BAR +
4 * (resno - PCI_IOV_RESOURCES);
}
Expand All @@ -510,13 +506,12 @@ int pci_iov_resource_bar(struct pci_dev *dev, int resno,
resource_size_t pci_sriov_resource_alignment(struct pci_dev *dev, int resno)
{
struct resource tmp;
enum pci_bar_type type;
int reg = pci_iov_resource_bar(dev, resno, &type);
int reg = pci_iov_resource_bar(dev, resno);

if (!reg)
return 0;

__pci_read_base(dev, type, &tmp, reg);
__pci_read_base(dev, pci_bar_unknown, &tmp, reg);
return resource_alignment(&tmp);
}

Expand Down
3 changes: 1 addition & 2 deletions drivers/pci/pci-acpi.c
Original file line number Diff line number Diff line change
Expand Up @@ -322,8 +322,7 @@ static void pci_acpi_wake_dev(struct work_struct *work)
pci_wakeup_event(pci_dev);
pm_runtime_resume(&pci_dev->dev);

if (pci_dev->subordinate)
pci_pme_wakeup_bus(pci_dev->subordinate);
pci_pme_wakeup_bus(pci_dev->subordinate);
}

/**
Expand Down
27 changes: 26 additions & 1 deletion drivers/pci/pci-sysfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -221,12 +221,37 @@ static ssize_t enabled_show(struct device *dev, struct device_attribute *attr,
static DEVICE_ATTR_RW(enabled);

#ifdef CONFIG_NUMA
static ssize_t numa_node_store(struct device *dev,
struct device_attribute *attr, const char *buf,
size_t count)
{
struct pci_dev *pdev = to_pci_dev(dev);
int node, ret;

if (!capable(CAP_SYS_ADMIN))
return -EPERM;

ret = kstrtoint(buf, 0, &node);
if (ret)
return ret;

if (!node_online(node))
return -EINVAL;

add_taint(TAINT_FIRMWARE_WORKAROUND, LOCKDEP_STILL_OK);
dev_alert(&pdev->dev, FW_BUG "Overriding NUMA node to %d. Contact your vendor for updates.",
node);

dev->numa_node = node;
return count;
}

static ssize_t numa_node_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
return sprintf(buf, "%d\n", dev->numa_node);
}
static DEVICE_ATTR_RO(numa_node);
static DEVICE_ATTR_RW(numa_node);
#endif

static ssize_t dma_mask_bits_show(struct device *dev,
Expand Down
21 changes: 6 additions & 15 deletions drivers/pci/pci.c
Original file line number Diff line number Diff line change
Expand Up @@ -1012,11 +1012,7 @@ int pci_save_state(struct pci_dev *dev)
if (i != 0)
return i;

i = pci_save_vc_state(dev);
if (i != 0)
return i;

return 0;
return pci_save_vc_state(dev);
}
EXPORT_SYMBOL(pci_save_state);

Expand Down Expand Up @@ -3144,12 +3140,10 @@ static int pcie_flr(struct pci_dev *dev, int probe)
return 0;

if (!pci_wait_for_pending_transaction(dev))
dev_err(&dev->dev, "transaction is not cleared; proceeding with reset anyway\n");
dev_err(&dev->dev, "timed out waiting for pending transaction; performing function level reset anyway\n");

pcie_capability_set_word(dev, PCI_EXP_DEVCTL, PCI_EXP_DEVCTL_BCR_FLR);

msleep(100);

return 0;
}

Expand All @@ -3174,16 +3168,12 @@ static int pci_af_flr(struct pci_dev *dev, int probe)
* is used, so we use the conrol offset rather than status and shift
* the test bit to match.
*/
if (pci_wait_for_pending(dev, pos + PCI_AF_CTRL,
if (!pci_wait_for_pending(dev, pos + PCI_AF_CTRL,
PCI_AF_STATUS_TP << 8))
goto clear;

dev_err(&dev->dev, "transaction is not cleared; proceeding with reset anyway\n");
dev_err(&dev->dev, "timed out waiting for pending transaction; performing AF function level reset anyway\n");

clear:
pci_write_config_byte(dev, pos + PCI_AF_CTRL, PCI_AF_CTRL_FLR);
msleep(100);

return 0;
}

Expand Down Expand Up @@ -4180,7 +4170,8 @@ int pci_resource_bar(struct pci_dev *dev, int resno, enum pci_bar_type *type)
return dev->rom_base_reg;
} else if (resno < PCI_BRIDGE_RESOURCES) {
/* device specific resource */
reg = pci_iov_resource_bar(dev, resno, type);
*type = pci_bar_unknown;
reg = pci_iov_resource_bar(dev, resno);
if (reg)
return reg;
}
Expand Down
6 changes: 2 additions & 4 deletions drivers/pci/pci.h
Original file line number Diff line number Diff line change
Expand Up @@ -251,8 +251,7 @@ static inline void pci_restore_ats_state(struct pci_dev *dev)
#ifdef CONFIG_PCI_IOV
int pci_iov_init(struct pci_dev *dev);
void pci_iov_release(struct pci_dev *dev);
int pci_iov_resource_bar(struct pci_dev *dev, int resno,
enum pci_bar_type *type);
int pci_iov_resource_bar(struct pci_dev *dev, int resno);
resource_size_t pci_sriov_resource_alignment(struct pci_dev *dev, int resno);
void pci_restore_iov_state(struct pci_dev *dev);
int pci_iov_bus_range(struct pci_bus *bus);
Expand All @@ -266,8 +265,7 @@ static inline void pci_iov_release(struct pci_dev *dev)

{
}
static inline int pci_iov_resource_bar(struct pci_dev *dev, int resno,
enum pci_bar_type *type)
static inline int pci_iov_resource_bar(struct pci_dev *dev, int resno)
{
return 0;
}
Expand Down
80 changes: 35 additions & 45 deletions drivers/pci/probe.c
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,7 @@ static void release_pcibus_dev(struct device *dev)
{
struct pci_bus *pci_bus = to_pci_bus(dev);

if (pci_bus->bridge)
put_device(pci_bus->bridge);
put_device(pci_bus->bridge);
pci_bus_remove_resources(pci_bus);
pci_release_bus_of_node(pci_bus);
kfree(pci_bus);
Expand Down Expand Up @@ -175,7 +174,6 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
u64 l64, sz64, mask64;
u16 orig_cmd;
struct pci_bus_region region, inverted_region;
bool bar_too_big = false, bar_too_high = false, bar_invalid = false;

mask = type ? PCI_ROM_ADDRESS_MASK : ~0;

Expand All @@ -201,8 +199,8 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
* memory BAR or a ROM, bit 0 must be clear; if it's an io BAR, bit
* 1 must be clear.
*/
if (!sz || sz == 0xffffffff)
goto fail;
if (sz == 0xffffffff)
sz = 0;

/*
* I don't know how l can have all bits set. Copied from old code.
Expand All @@ -215,42 +213,53 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
res->flags = decode_bar(dev, l);
res->flags |= IORESOURCE_SIZEALIGN;
if (res->flags & IORESOURCE_IO) {
l &= PCI_BASE_ADDRESS_IO_MASK;
mask = PCI_BASE_ADDRESS_IO_MASK & (u32) IO_SPACE_LIMIT;
l64 = l & PCI_BASE_ADDRESS_IO_MASK;
sz64 = sz & PCI_BASE_ADDRESS_IO_MASK;
mask64 = PCI_BASE_ADDRESS_IO_MASK & (u32)IO_SPACE_LIMIT;
} else {
l &= PCI_BASE_ADDRESS_MEM_MASK;
mask = (u32)PCI_BASE_ADDRESS_MEM_MASK;
l64 = l & PCI_BASE_ADDRESS_MEM_MASK;
sz64 = sz & PCI_BASE_ADDRESS_MEM_MASK;
mask64 = (u32)PCI_BASE_ADDRESS_MEM_MASK;
}
} else {
res->flags |= (l & IORESOURCE_ROM_ENABLE);
l &= PCI_ROM_ADDRESS_MASK;
mask = (u32)PCI_ROM_ADDRESS_MASK;
l64 = l & PCI_ROM_ADDRESS_MASK;
sz64 = sz & PCI_ROM_ADDRESS_MASK;
mask64 = (u32)PCI_ROM_ADDRESS_MASK;
}

if (res->flags & IORESOURCE_MEM_64) {
l64 = l;
sz64 = sz;
mask64 = mask | (u64)~0 << 32;

pci_read_config_dword(dev, pos + 4, &l);
pci_write_config_dword(dev, pos + 4, ~0);
pci_read_config_dword(dev, pos + 4, &sz);
pci_write_config_dword(dev, pos + 4, l);

l64 |= ((u64)l << 32);
sz64 |= ((u64)sz << 32);
mask64 |= ((u64)~0 << 32);
}

sz64 = pci_size(l64, sz64, mask64);
if (!dev->mmio_always_on && (orig_cmd & PCI_COMMAND_DECODE_ENABLE))
pci_write_config_word(dev, PCI_COMMAND, orig_cmd);

if (!sz64)
goto fail;
if (!sz64)
goto fail;

sz64 = pci_size(l64, sz64, mask64);
if (!sz64) {
dev_info(&dev->dev, FW_BUG "reg 0x%x: invalid BAR (can't size)\n",
pos);
goto fail;
}

if (res->flags & IORESOURCE_MEM_64) {
if ((sizeof(dma_addr_t) < 8 || sizeof(resource_size_t) < 8) &&
sz64 > 0x100000000ULL) {
res->flags |= IORESOURCE_UNSET | IORESOURCE_DISABLED;
res->start = 0;
res->end = 0;
bar_too_big = true;
dev_err(&dev->dev, "reg 0x%x: can't handle BAR larger than 4GB (size %#010llx)\n",
pos, (unsigned long long)sz64);
goto out;
}

Expand All @@ -259,22 +268,15 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
res->flags |= IORESOURCE_UNSET;
res->start = 0;
res->end = sz64;
bar_too_high = true;
dev_info(&dev->dev, "reg 0x%x: can't handle BAR above 4GB (bus address %#010llx)\n",
pos, (unsigned long long)l64);
goto out;
} else {
region.start = l64;
region.end = l64 + sz64;
}
} else {
sz = pci_size(l, sz, mask);

if (!sz)
goto fail;

region.start = l;
region.end = l + sz;
}

region.start = l64;
region.end = l64 + sz64;

pcibios_bus_to_resource(dev->bus, res, &region);
pcibios_resource_to_bus(dev->bus, &inverted_region, res);

Expand All @@ -293,7 +295,8 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
res->flags |= IORESOURCE_UNSET;
res->start = 0;
res->end = region.end - region.start;
bar_invalid = true;
dev_info(&dev->dev, "reg 0x%x: initial BAR value %#010llx invalid\n",
pos, (unsigned long long)region.start);
}

goto out;
Expand All @@ -302,19 +305,6 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
fail:
res->flags = 0;
out:
if (!dev->mmio_always_on &&
(orig_cmd & PCI_COMMAND_DECODE_ENABLE))
pci_write_config_word(dev, PCI_COMMAND, orig_cmd);

if (bar_too_big)
dev_err(&dev->dev, "reg 0x%x: can't handle BAR larger than 4GB (size %#010llx)\n",
pos, (unsigned long long) sz64);
if (bar_too_high)
dev_info(&dev->dev, "reg 0x%x: can't handle BAR above 4G (bus address %#010llx)\n",
pos, (unsigned long long) l64);
if (bar_invalid)
dev_info(&dev->dev, "reg 0x%x: initial BAR value %#010llx invalid\n",
pos, (unsigned long long) region.start);
if (res->flags)
dev_printk(KERN_DEBUG, &dev->dev, "reg 0x%x: %pR\n", pos, res);

Expand Down
3 changes: 1 addition & 2 deletions drivers/pci/search.c
Original file line number Diff line number Diff line change
Expand Up @@ -271,8 +271,7 @@ static struct pci_dev *pci_get_dev_by_id(const struct pci_device_id *id,
match_pci_dev_by_id);
if (dev)
pdev = to_pci_dev(dev);
if (from)
pci_dev_put(from);
pci_dev_put(from);
return pdev;
}

Expand Down
13 changes: 11 additions & 2 deletions drivers/pci/xen-pcifront.c
Original file line number Diff line number Diff line change
Expand Up @@ -596,8 +596,7 @@ static pci_ers_result_t pcifront_common_process(int cmd,
pcidev = pci_get_bus_and_slot(bus, devfn);
if (!pcidev || !pcidev->driver) {
dev_err(&pdev->xdev->dev, "device or AER driver is NULL\n");
if (pcidev)
pci_dev_put(pcidev);
pci_dev_put(pcidev);
return result;
}
pdrv = pcidev->driver;
Expand Down Expand Up @@ -866,6 +865,11 @@ static int pcifront_try_connect(struct pcifront_device *pdev)
xenbus_dev_error(pdev->xdev, err,
"No PCI Roots found, trying 0000:00");
err = pcifront_scan_root(pdev, 0, 0);
if (err) {
xenbus_dev_fatal(pdev->xdev, err,
"Error scanning PCI root 0000:00");
goto out;
}
num_roots = 0;
} else if (err != 1) {
if (err == 0)
Expand Down Expand Up @@ -947,6 +951,11 @@ static int pcifront_attach_devices(struct pcifront_device *pdev)
xenbus_dev_error(pdev->xdev, err,
"No PCI Roots found, trying 0000:00");
err = pcifront_rescan_root(pdev, 0, 0);
if (err) {
xenbus_dev_fatal(pdev->xdev, err,
"Error scanning PCI root 0000:00");
goto out;
}
num_roots = 0;
} else if (err != 1) {
if (err == 0)
Expand Down
1 change: 0 additions & 1 deletion include/linux/pci_hotplug.h
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,6 @@ struct hotplug_slot {
struct list_head slot_list;
struct pci_slot *pci_slot;
};
#define to_hotplug_slot(n) container_of(n, struct hotplug_slot, kobj)

static inline const char *hotplug_slot_name(const struct hotplug_slot *slot)
{
Expand Down

0 comments on commit 18e88be

Please sign in to comment.