Commit 18e88bec authored by Bjorn Helgaas's avatar Bjorn Helgaas

Merge branches 'pci/enumeration', 'pci/hotplug', 'pci/misc', 'pci/numa' and...

Merge branches 'pci/enumeration', 'pci/hotplug', 'pci/misc', 'pci/numa' 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()
...@@ -281,3 +281,16 @@ Description: ...@@ -281,3 +281,16 @@ Description:
opt-out of driver binding using a driver_override name such as opt-out of driver binding using a driver_override name such as
"none". Only a single driver may be specified in the override, "none". Only a single driver may be specified in the override,
there is no support for parsing delimiters. 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.
...@@ -376,10 +376,7 @@ int __init ibmphp_rsrc_init (void) ...@@ -376,10 +376,7 @@ int __init ibmphp_rsrc_init (void)
if (rc) if (rc)
return rc; return rc;
} }
rc = once_over (); /* This is to align ranges (so no -1) */ return once_over (); /* This is to align ranges (so no -1) */
if (rc)
return rc;
return 0;
} }
/******************************************************************************** /********************************************************************************
......
...@@ -479,20 +479,16 @@ void pci_iov_release(struct pci_dev *dev) ...@@ -479,20 +479,16 @@ void pci_iov_release(struct pci_dev *dev)
* pci_iov_resource_bar - get position of the SR-IOV BAR * pci_iov_resource_bar - get position of the SR-IOV BAR
* @dev: the PCI device * @dev: the PCI device
* @resno: the resource number * @resno: the resource number
* @type: the BAR type to be filled in
* *
* Returns position of the BAR encapsulated in the SR-IOV capability. * Returns position of the BAR encapsulated in the SR-IOV capability.
*/ */
int pci_iov_resource_bar(struct pci_dev *dev, int resno, int pci_iov_resource_bar(struct pci_dev *dev, int resno)
enum pci_bar_type *type)
{ {
if (resno < PCI_IOV_RESOURCES || resno > PCI_IOV_RESOURCE_END) if (resno < PCI_IOV_RESOURCES || resno > PCI_IOV_RESOURCE_END)
return 0; return 0;
BUG_ON(!dev->is_physfn); BUG_ON(!dev->is_physfn);
*type = pci_bar_unknown;
return dev->sriov->pos + PCI_SRIOV_BAR + return dev->sriov->pos + PCI_SRIOV_BAR +
4 * (resno - PCI_IOV_RESOURCES); 4 * (resno - PCI_IOV_RESOURCES);
} }
...@@ -510,13 +506,12 @@ int pci_iov_resource_bar(struct pci_dev *dev, int resno, ...@@ -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) resource_size_t pci_sriov_resource_alignment(struct pci_dev *dev, int resno)
{ {
struct resource tmp; struct resource tmp;
enum pci_bar_type type; int reg = pci_iov_resource_bar(dev, resno);
int reg = pci_iov_resource_bar(dev, resno, &type);
if (!reg) if (!reg)
return 0; return 0;
__pci_read_base(dev, type, &tmp, reg); __pci_read_base(dev, pci_bar_unknown, &tmp, reg);
return resource_alignment(&tmp); return resource_alignment(&tmp);
} }
......
...@@ -322,7 +322,6 @@ static void pci_acpi_wake_dev(struct work_struct *work) ...@@ -322,7 +322,6 @@ static void pci_acpi_wake_dev(struct work_struct *work)
pci_wakeup_event(pci_dev); pci_wakeup_event(pci_dev);
pm_runtime_resume(&pci_dev->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);
} }
......
...@@ -221,12 +221,37 @@ static ssize_t enabled_show(struct device *dev, struct device_attribute *attr, ...@@ -221,12 +221,37 @@ static ssize_t enabled_show(struct device *dev, struct device_attribute *attr,
static DEVICE_ATTR_RW(enabled); static DEVICE_ATTR_RW(enabled);
#ifdef CONFIG_NUMA #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, static ssize_t numa_node_show(struct device *dev, struct device_attribute *attr,
char *buf) char *buf)
{ {
return sprintf(buf, "%d\n", dev->numa_node); return sprintf(buf, "%d\n", dev->numa_node);
} }
static DEVICE_ATTR_RO(numa_node); static DEVICE_ATTR_RW(numa_node);
#endif #endif
static ssize_t dma_mask_bits_show(struct device *dev, static ssize_t dma_mask_bits_show(struct device *dev,
......
...@@ -1012,11 +1012,7 @@ int pci_save_state(struct pci_dev *dev) ...@@ -1012,11 +1012,7 @@ int pci_save_state(struct pci_dev *dev)
if (i != 0) if (i != 0)
return i; return i;
i = pci_save_vc_state(dev); return pci_save_vc_state(dev);
if (i != 0)
return i;
return 0;
} }
EXPORT_SYMBOL(pci_save_state); EXPORT_SYMBOL(pci_save_state);
...@@ -3144,12 +3140,10 @@ static int pcie_flr(struct pci_dev *dev, int probe) ...@@ -3144,12 +3140,10 @@ static int pcie_flr(struct pci_dev *dev, int probe)
return 0; return 0;
if (!pci_wait_for_pending_transaction(dev)) 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); pcie_capability_set_word(dev, PCI_EXP_DEVCTL, PCI_EXP_DEVCTL_BCR_FLR);
msleep(100); msleep(100);
return 0; return 0;
} }
...@@ -3174,16 +3168,12 @@ static int pci_af_flr(struct pci_dev *dev, int probe) ...@@ -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 * is used, so we use the conrol offset rather than status and shift
* the test bit to match. * 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)) PCI_AF_STATUS_TP << 8))
goto clear; dev_err(&dev->dev, "timed out waiting for pending transaction; performing AF function level reset anyway\n");
dev_err(&dev->dev, "transaction is not cleared; proceeding with reset anyway\n");
clear:
pci_write_config_byte(dev, pos + PCI_AF_CTRL, PCI_AF_CTRL_FLR); pci_write_config_byte(dev, pos + PCI_AF_CTRL, PCI_AF_CTRL_FLR);
msleep(100); msleep(100);
return 0; return 0;
} }
...@@ -4180,7 +4170,8 @@ int pci_resource_bar(struct pci_dev *dev, int resno, enum pci_bar_type *type) ...@@ -4180,7 +4170,8 @@ int pci_resource_bar(struct pci_dev *dev, int resno, enum pci_bar_type *type)
return dev->rom_base_reg; return dev->rom_base_reg;
} else if (resno < PCI_BRIDGE_RESOURCES) { } else if (resno < PCI_BRIDGE_RESOURCES) {
/* device specific resource */ /* device specific resource */
reg = pci_iov_resource_bar(dev, resno, type); *type = pci_bar_unknown;
reg = pci_iov_resource_bar(dev, resno);
if (reg) if (reg)
return reg; return reg;
} }
......
...@@ -251,8 +251,7 @@ static inline void pci_restore_ats_state(struct pci_dev *dev) ...@@ -251,8 +251,7 @@ static inline void pci_restore_ats_state(struct pci_dev *dev)
#ifdef CONFIG_PCI_IOV #ifdef CONFIG_PCI_IOV
int pci_iov_init(struct pci_dev *dev); int pci_iov_init(struct pci_dev *dev);
void pci_iov_release(struct pci_dev *dev); void pci_iov_release(struct pci_dev *dev);
int pci_iov_resource_bar(struct pci_dev *dev, int resno, int pci_iov_resource_bar(struct pci_dev *dev, int resno);
enum pci_bar_type *type);
resource_size_t pci_sriov_resource_alignment(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); void pci_restore_iov_state(struct pci_dev *dev);
int pci_iov_bus_range(struct pci_bus *bus); int pci_iov_bus_range(struct pci_bus *bus);
...@@ -266,8 +265,7 @@ static inline void pci_iov_release(struct pci_dev *dev) ...@@ -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, static inline int pci_iov_resource_bar(struct pci_dev *dev, int resno)
enum pci_bar_type *type)
{ {
return 0; return 0;
} }
......
...@@ -87,7 +87,6 @@ static void release_pcibus_dev(struct device *dev) ...@@ -87,7 +87,6 @@ static void release_pcibus_dev(struct device *dev)
{ {
struct pci_bus *pci_bus = to_pci_bus(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_bus_remove_resources(pci_bus);
pci_release_bus_of_node(pci_bus); pci_release_bus_of_node(pci_bus);
...@@ -175,7 +174,6 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type, ...@@ -175,7 +174,6 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
u64 l64, sz64, mask64; u64 l64, sz64, mask64;
u16 orig_cmd; u16 orig_cmd;
struct pci_bus_region region, inverted_region; 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; mask = type ? PCI_ROM_ADDRESS_MASK : ~0;
...@@ -201,8 +199,8 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type, ...@@ -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 * memory BAR or a ROM, bit 0 must be clear; if it's an io BAR, bit
* 1 must be clear. * 1 must be clear.
*/ */
if (!sz || sz == 0xffffffff) if (sz == 0xffffffff)
goto fail; sz = 0;
/* /*
* I don't know how l can have all bits set. Copied from old code. * I don't know how l can have all bits set. Copied from old code.
...@@ -215,23 +213,22 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type, ...@@ -215,23 +213,22 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
res->flags = decode_bar(dev, l); res->flags = decode_bar(dev, l);
res->flags |= IORESOURCE_SIZEALIGN; res->flags |= IORESOURCE_SIZEALIGN;
if (res->flags & IORESOURCE_IO) { if (res->flags & IORESOURCE_IO) {
l &= PCI_BASE_ADDRESS_IO_MASK; l64 = l & PCI_BASE_ADDRESS_IO_MASK;
mask = PCI_BASE_ADDRESS_IO_MASK & (u32) IO_SPACE_LIMIT; sz64 = sz & PCI_BASE_ADDRESS_IO_MASK;
mask64 = PCI_BASE_ADDRESS_IO_MASK & (u32)IO_SPACE_LIMIT;
} else { } else {
l &= PCI_BASE_ADDRESS_MEM_MASK; l64 = l & PCI_BASE_ADDRESS_MEM_MASK;
mask = (u32)PCI_BASE_ADDRESS_MEM_MASK; sz64 = sz & PCI_BASE_ADDRESS_MEM_MASK;
mask64 = (u32)PCI_BASE_ADDRESS_MEM_MASK;
} }
} else { } else {
res->flags |= (l & IORESOURCE_ROM_ENABLE); res->flags |= (l & IORESOURCE_ROM_ENABLE);
l &= PCI_ROM_ADDRESS_MASK; l64 = l & PCI_ROM_ADDRESS_MASK;
mask = (u32)PCI_ROM_ADDRESS_MASK; sz64 = sz & PCI_ROM_ADDRESS_MASK;
mask64 = (u32)PCI_ROM_ADDRESS_MASK;
} }
if (res->flags & IORESOURCE_MEM_64) { if (res->flags & IORESOURCE_MEM_64) {
l64 = l;
sz64 = sz;
mask64 = mask | (u64)~0 << 32;
pci_read_config_dword(dev, pos + 4, &l); pci_read_config_dword(dev, pos + 4, &l);
pci_write_config_dword(dev, pos + 4, ~0); pci_write_config_dword(dev, pos + 4, ~0);
pci_read_config_dword(dev, pos + 4, &sz); pci_read_config_dword(dev, pos + 4, &sz);
...@@ -239,18 +236,30 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type, ...@@ -239,18 +236,30 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
l64 |= ((u64)l << 32); l64 |= ((u64)l << 32);
sz64 |= ((u64)sz << 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) if (!sz64)
goto fail; 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) && if ((sizeof(dma_addr_t) < 8 || sizeof(resource_size_t) < 8) &&
sz64 > 0x100000000ULL) { sz64 > 0x100000000ULL) {
res->flags |= IORESOURCE_UNSET | IORESOURCE_DISABLED; res->flags |= IORESOURCE_UNSET | IORESOURCE_DISABLED;
res->start = 0; res->start = 0;
res->end = 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; goto out;
} }
...@@ -259,22 +268,15 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type, ...@@ -259,22 +268,15 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
res->flags |= IORESOURCE_UNSET; res->flags |= IORESOURCE_UNSET;
res->start = 0; res->start = 0;
res->end = sz64; 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; 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_bus_to_resource(dev->bus, res, &region);
pcibios_resource_to_bus(dev->bus, &inverted_region, res); pcibios_resource_to_bus(dev->bus, &inverted_region, res);
...@@ -293,7 +295,8 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type, ...@@ -293,7 +295,8 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
res->flags |= IORESOURCE_UNSET; res->flags |= IORESOURCE_UNSET;
res->start = 0; res->start = 0;
res->end = region.end - region.start; 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; goto out;
...@@ -302,19 +305,6 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type, ...@@ -302,19 +305,6 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
fail: fail:
res->flags = 0; res->flags = 0;
out: 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) if (res->flags)
dev_printk(KERN_DEBUG, &dev->dev, "reg 0x%x: %pR\n", pos, res); dev_printk(KERN_DEBUG, &dev->dev, "reg 0x%x: %pR\n", pos, res);
......
...@@ -271,7 +271,6 @@ static struct pci_dev *pci_get_dev_by_id(const struct pci_device_id *id, ...@@ -271,7 +271,6 @@ static struct pci_dev *pci_get_dev_by_id(const struct pci_device_id *id,
match_pci_dev_by_id); match_pci_dev_by_id);
if (dev) if (dev)
pdev = to_pci_dev(dev); pdev = to_pci_dev(dev);
if (from)
pci_dev_put(from); pci_dev_put(from);
return pdev; return pdev;
} }
......
...@@ -596,7 +596,6 @@ static pci_ers_result_t pcifront_common_process(int cmd, ...@@ -596,7 +596,6 @@ static pci_ers_result_t pcifront_common_process(int cmd,
pcidev = pci_get_bus_and_slot(bus, devfn); pcidev = pci_get_bus_and_slot(bus, devfn);
if (!pcidev || !pcidev->driver) { if (!pcidev || !pcidev->driver) {
dev_err(&pdev->xdev->dev, "device or AER driver is NULL\n"); dev_err(&pdev->xdev->dev, "device or AER driver is NULL\n");
if (pcidev)
pci_dev_put(pcidev); pci_dev_put(pcidev);
return result; return result;
} }
...@@ -866,6 +865,11 @@ static int pcifront_try_connect(struct pcifront_device *pdev) ...@@ -866,6 +865,11 @@ static int pcifront_try_connect(struct pcifront_device *pdev)
xenbus_dev_error(pdev->xdev, err, xenbus_dev_error(pdev->xdev, err,
"No PCI Roots found, trying 0000:00"); "No PCI Roots found, trying 0000:00");
err = pcifront_scan_root(pdev, 0, 0); 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; num_roots = 0;
} else if (err != 1) { } else if (err != 1) {
if (err == 0) if (err == 0)
...@@ -947,6 +951,11 @@ static int pcifront_attach_devices(struct pcifront_device *pdev) ...@@ -947,6 +951,11 @@ static int pcifront_attach_devices(struct pcifront_device *pdev)
xenbus_dev_error(pdev->xdev, err, xenbus_dev_error(pdev->xdev, err,
"No PCI Roots found, trying 0000:00"); "No PCI Roots found, trying 0000:00");
err = pcifront_rescan_root(pdev, 0, 0); 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; num_roots = 0;
} else if (err != 1) { } else if (err != 1) {
if (err == 0) if (err == 0)
......
...@@ -109,7 +109,6 @@ struct hotplug_slot { ...@@ -109,7 +109,6 @@ struct hotplug_slot {
struct list_head slot_list; struct list_head slot_list;
struct pci_slot *pci_slot; 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) static inline const char *hotplug_slot_name(const struct hotplug_slot *slot)
{ {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment