Skip to content

Commit

Permalink
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel…
Browse files Browse the repository at this point in the history
…/git/jbarnes/pci-2.6

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jbarnes/pci-2.6:
  PCI: Fix IRQ swizzling for ARI-enabled devices
  ia64/PCI: adjust section annotation for pcibios_setup()
  x86/PCI: get root CRS before scanning children
  x86/PCI: fix boundary checking when using root CRS
  PCI MSI: Fix restoration of MSI/MSI-X mask states in suspend/resume
  PCI MSI: Unmask MSI if setup failed
  PCI MSI: shorten PCI_MSIX_ENTRY_* symbol names
  PCI: make pci_name() take const argument
  PCI: More PATA quirks for not entering D3
  PCI: fix kernel-doc warnings
  PCI: check if bus has a proper bridge device before triggering SBR
  PCI: remove pci_dac_dma_... APIs on mn10300
  PCI ECRC: Remove unnecessary semicolons
  PCI MSI: Return if alloc_msi_entry for MSI-X failed
  • Loading branch information
torvalds committed Jul 6, 2009
2 parents f560902 + 46b952a commit dc53fff
Show file tree
Hide file tree
Showing 12 changed files with 104 additions and 73 deletions.
2 changes: 1 addition & 1 deletion arch/ia64/pci/pci.c
Original file line number Diff line number Diff line change
Expand Up @@ -537,7 +537,7 @@ pcibios_align_resource (void *data, struct resource *res,
/*
* PCI BIOS setup, always defaults to SAL interface
*/
char * __devinit
char * __init
pcibios_setup (char *str)
{
return str;
Expand Down
4 changes: 0 additions & 4 deletions arch/mn10300/include/asm/pci.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,10 +70,6 @@ struct pci_dev;
*/
#define PCI_DMA_BUS_IS_PHYS (1)


/* This is always fine. */
#define pci_dac_dma_supported(pci_dev, mask) (0)

/* Return the index of the PCI controller for device. */
static inline int pci_controller_num(struct pci_dev *dev)
{
Expand Down
59 changes: 24 additions & 35 deletions arch/x86/pci/acpi.c
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,10 @@ setup_resource(struct acpi_resource *acpi_res, void *data)
unsigned long flags;
struct resource *root;
int max_root_bus_resources = PCI_BUS_NUM_RESOURCES;
u64 start, end;

if (bus_has_transparent_bridge(info->bus))
max_root_bus_resources -= 3;

status = resource_to_addr(acpi_res, &addr);
if (!ACPI_SUCCESS(status))
Expand All @@ -84,25 +88,24 @@ setup_resource(struct acpi_resource *acpi_res, void *data)
} else
return AE_OK;

res = &info->res[info->res_num];
res->name = info->name;
res->flags = flags;
res->start = addr.minimum + addr.translation_offset;
res->end = res->start + addr.address_length - 1;
res->child = NULL;

if (bus_has_transparent_bridge(info->bus))
max_root_bus_resources -= 3;
start = addr.minimum + addr.translation_offset;
end = start + addr.address_length - 1;
if (info->res_num >= max_root_bus_resources) {
printk(KERN_WARNING "PCI: Failed to allocate 0x%lx-0x%lx "
"from %s for %s due to _CRS returning more than "
"%d resource descriptors\n", (unsigned long) res->start,
(unsigned long) res->end, root->name, info->name,
"%d resource descriptors\n", (unsigned long) start,
(unsigned long) end, root->name, info->name,
max_root_bus_resources);
info->res_num++;
return AE_OK;
}

res = &info->res[info->res_num];
res->name = info->name;
res->flags = flags;
res->start = start;
res->end = end;
res->child = NULL;

if (insert_resource(root, res)) {
printk(KERN_ERR "PCI: Failed to allocate 0x%lx-0x%lx "
"from %s for %s\n", (unsigned long) res->start,
Expand All @@ -114,23 +117,6 @@ setup_resource(struct acpi_resource *acpi_res, void *data)
return AE_OK;
}

static void
adjust_transparent_bridge_resources(struct pci_bus *bus)
{
struct pci_dev *dev;

list_for_each_entry(dev, &bus->devices, bus_list) {
int i;
u16 class = dev->class >> 8;

if (class == PCI_CLASS_BRIDGE_PCI && dev->transparent) {
for(i = 3; i < PCI_BUS_NUM_RESOURCES; i++)
dev->subordinate->resource[i] =
dev->bus->resource[i - 3];
}
}
}

static void
get_current_resources(struct acpi_device *device, int busnum,
int domain, struct pci_bus *bus)
Expand Down Expand Up @@ -158,8 +144,6 @@ get_current_resources(struct acpi_device *device, int busnum,
info.res_num = 0;
acpi_walk_resources(device->handle, METHOD_NAME__CRS, setup_resource,
&info);
if (info.res_num)
adjust_transparent_bridge_resources(bus);

return;

Expand Down Expand Up @@ -222,8 +206,15 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_device *device, int do
*/
memcpy(bus->sysdata, sd, sizeof(*sd));
kfree(sd);
} else
bus = pci_scan_bus_parented(NULL, busnum, &pci_root_ops, sd);
} else {
bus = pci_create_bus(NULL, busnum, &pci_root_ops, sd);
if (bus) {
if (pci_probe & PCI_USE__CRS)
get_current_resources(device, busnum, domain,
bus);
bus->subordinate = pci_scan_child_bus(bus);
}
}

if (!bus)
kfree(sd);
Expand All @@ -238,8 +229,6 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_device *device, int do
#endif
}

if (bus && (pci_probe & PCI_USE__CRS))
get_current_resources(device, busnum, domain, bus);
return bus;
}

Expand Down
8 changes: 6 additions & 2 deletions arch/x86/pci/amd_bus.c
Original file line number Diff line number Diff line change
Expand Up @@ -100,8 +100,9 @@ void x86_pci_root_bus_res_quirks(struct pci_bus *b)
int j;
struct pci_root_info *info;

/* don't go for it if _CRS is used */
if (pci_probe & PCI_USE__CRS)
/* don't go for it if _CRS is used already */
if (b->resource[0] != &ioport_resource ||
b->resource[1] != &iomem_resource)
return;

/* if only one root bus, don't need to anything */
Expand All @@ -116,6 +117,9 @@ void x86_pci_root_bus_res_quirks(struct pci_bus *b)
if (i == pci_root_num)
return;

printk(KERN_DEBUG "PCI: peer root bus %02x res updated from pci conf\n",
b->number);

info = &pci_root_info[i];
for (j = 0; j < info->res_num; j++) {
struct resource *res;
Expand Down
2 changes: 2 additions & 0 deletions drivers/pci/hotplug/pci_hotplug_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -555,6 +555,8 @@ static struct hotplug_slot *get_slot_from_name (const char *name)
* @slot: pointer to the &struct hotplug_slot to register
* @devnr: device number
* @name: name registered with kobject core
* @owner: caller module owner
* @mod_name: caller module name
*
* Registers a hotplug slot with the pci hotplug subsystem, which will allow
* userspace interaction to the slot.
Expand Down
64 changes: 45 additions & 19 deletions drivers/pci/msi.c
Original file line number Diff line number Diff line change
Expand Up @@ -127,17 +127,23 @@ static inline __attribute_const__ u32 msi_enabled_mask(u16 control)
* reliably as devices without an INTx disable bit will then generate a
* level IRQ which will never be cleared.
*/
static void msi_mask_irq(struct msi_desc *desc, u32 mask, u32 flag)
static u32 __msi_mask_irq(struct msi_desc *desc, u32 mask, u32 flag)
{
u32 mask_bits = desc->masked;

if (!desc->msi_attrib.maskbit)
return;
return 0;

mask_bits &= ~mask;
mask_bits |= flag;
pci_write_config_dword(desc->dev, desc->mask_pos, mask_bits);
desc->masked = mask_bits;

return mask_bits;
}

static void msi_mask_irq(struct msi_desc *desc, u32 mask, u32 flag)
{
desc->masked = __msi_mask_irq(desc, mask, flag);
}

/*
Expand All @@ -147,15 +153,21 @@ static void msi_mask_irq(struct msi_desc *desc, u32 mask, u32 flag)
* file. This saves a few milliseconds when initialising devices with lots
* of MSI-X interrupts.
*/
static void msix_mask_irq(struct msi_desc *desc, u32 flag)
static u32 __msix_mask_irq(struct msi_desc *desc, u32 flag)
{
u32 mask_bits = desc->masked;
unsigned offset = desc->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE +
PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET;
PCI_MSIX_ENTRY_VECTOR_CTRL;
mask_bits &= ~1;
mask_bits |= flag;
writel(mask_bits, desc->mask_base + offset);
desc->masked = mask_bits;

return mask_bits;
}

static void msix_mask_irq(struct msi_desc *desc, u32 flag)
{
desc->masked = __msix_mask_irq(desc, flag);
}

static void msi_set_mask_bit(unsigned irq, u32 flag)
Expand Down Expand Up @@ -188,9 +200,9 @@ void read_msi_msg_desc(struct irq_desc *desc, struct msi_msg *msg)
void __iomem *base = entry->mask_base +
entry->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE;

msg->address_lo = readl(base + PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET);
msg->address_hi = readl(base + PCI_MSIX_ENTRY_UPPER_ADDR_OFFSET);
msg->data = readl(base + PCI_MSIX_ENTRY_DATA_OFFSET);
msg->address_lo = readl(base + PCI_MSIX_ENTRY_LOWER_ADDR);
msg->address_hi = readl(base + PCI_MSIX_ENTRY_UPPER_ADDR);
msg->data = readl(base + PCI_MSIX_ENTRY_DATA);
} else {
struct pci_dev *dev = entry->dev;
int pos = entry->msi_attrib.pos;
Expand Down Expand Up @@ -225,11 +237,9 @@ void write_msi_msg_desc(struct irq_desc *desc, struct msi_msg *msg)
base = entry->mask_base +
entry->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE;

writel(msg->address_lo,
base + PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET);
writel(msg->address_hi,
base + PCI_MSIX_ENTRY_UPPER_ADDR_OFFSET);
writel(msg->data, base + PCI_MSIX_ENTRY_DATA_OFFSET);
writel(msg->address_lo, base + PCI_MSIX_ENTRY_LOWER_ADDR);
writel(msg->address_hi, base + PCI_MSIX_ENTRY_UPPER_ADDR);
writel(msg->data, base + PCI_MSIX_ENTRY_DATA);
} else {
struct pci_dev *dev = entry->dev;
int pos = entry->msi_attrib.pos;
Expand Down Expand Up @@ -385,6 +395,7 @@ static int msi_capability_init(struct pci_dev *dev, int nvec)
/* Configure MSI capability structure */
ret = arch_setup_msi_irqs(dev, nvec, PCI_CAP_ID_MSI);
if (ret) {
msi_mask_irq(entry, mask, ~mask);
msi_free_irqs(dev);
return ret;
}
Expand Down Expand Up @@ -439,8 +450,14 @@ static int msix_capability_init(struct pci_dev *dev,

for (i = 0; i < nvec; i++) {
entry = alloc_msi_entry(dev);
if (!entry)
break;
if (!entry) {
if (!i)
iounmap(base);
else
msi_free_irqs(dev);
/* No enough memory. Don't try again */
return -ENOMEM;
}

j = entries[i].entry;
entry->msi_attrib.is_msix = 1;
Expand Down Expand Up @@ -487,7 +504,7 @@ static int msix_capability_init(struct pci_dev *dev,
set_irq_msi(entry->irq, entry);
j = entries[i].entry;
entry->masked = readl(base + j * PCI_MSIX_ENTRY_SIZE +
PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET);
PCI_MSIX_ENTRY_VECTOR_CTRL);
msix_mask_irq(entry, 1);
i++;
}
Expand Down Expand Up @@ -611,9 +628,11 @@ void pci_msi_shutdown(struct pci_dev *dev)
pci_intx_for_msi(dev, 1);
dev->msi_enabled = 0;

/* Return the device with MSI unmasked as initial states */
pci_read_config_word(dev, pos + PCI_MSI_FLAGS, &ctrl);
mask = msi_capable_mask(ctrl);
msi_mask_irq(desc, mask, ~mask);
/* Keep cached state to be restored */
__msi_mask_irq(desc, mask, ~mask);

/* Restore dev->irq to its default pin-assertion irq */
dev->irq = desc->msi_attrib.default_irq;
Expand Down Expand Up @@ -653,7 +672,6 @@ static int msi_free_irqs(struct pci_dev* dev)

list_for_each_entry_safe(entry, tmp, &dev->msi_list, list) {
if (entry->msi_attrib.is_msix) {
msix_mask_irq(entry, 1);
if (list_is_last(&entry->list, &dev->msi_list))
iounmap(entry->mask_base);
}
Expand Down Expand Up @@ -741,9 +759,17 @@ static void msix_free_all_irqs(struct pci_dev *dev)

void pci_msix_shutdown(struct pci_dev* dev)
{
struct msi_desc *entry;

if (!pci_msi_enable || !dev || !dev->msix_enabled)
return;

/* Return the device with MSI-X masked as initial states */
list_for_each_entry(entry, &dev->msi_list, list) {
/* Keep cached states to be restored */
__msix_mask_irq(entry, 1);
}

msix_set_enable(dev, 0);
pci_intx_for_msi(dev, 1);
dev->msix_enabled = 0;
Expand Down
10 changes: 5 additions & 5 deletions drivers/pci/msi.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@
#ifndef MSI_H
#define MSI_H

#define PCI_MSIX_ENTRY_SIZE 16
#define PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET 0
#define PCI_MSIX_ENTRY_UPPER_ADDR_OFFSET 4
#define PCI_MSIX_ENTRY_DATA_OFFSET 8
#define PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET 12
#define PCI_MSIX_ENTRY_SIZE 16
#define PCI_MSIX_ENTRY_LOWER_ADDR 0
#define PCI_MSIX_ENTRY_UPPER_ADDR 4
#define PCI_MSIX_ENTRY_DATA 8
#define PCI_MSIX_ENTRY_VECTOR_CTRL 12

#define msi_control_reg(base) (base + PCI_MSI_FLAGS)
#define msi_lower_address_reg(base) (base + PCI_MSI_ADDRESS_LO)
Expand Down
15 changes: 12 additions & 3 deletions drivers/pci/pci.c
Original file line number Diff line number Diff line change
Expand Up @@ -1517,11 +1517,20 @@ void pci_enable_ari(struct pci_dev *dev)
*
* Perform INTx swizzling for a device behind one level of bridge. This is
* required by section 9.1 of the PCI-to-PCI bridge specification for devices
* behind bridges on add-in cards.
* behind bridges on add-in cards. For devices with ARI enabled, the slot
* number is always 0 (see the Implementation Note in section 2.2.8.1 of
* the PCI Express Base Specification, Revision 2.1)
*/
u8 pci_swizzle_interrupt_pin(struct pci_dev *dev, u8 pin)
{
return (((pin - 1) + PCI_SLOT(dev->devfn)) % 4) + 1;
int slot;

if (pci_ari_enabled(dev->bus))
slot = 0;
else
slot = PCI_SLOT(dev->devfn);

return (((pin - 1) + slot) % 4) + 1;
}

int
Expand Down Expand Up @@ -2171,7 +2180,7 @@ static int pci_parent_bus_reset(struct pci_dev *dev, int probe)
u16 ctrl;
struct pci_dev *pdev;

if (dev->subordinate)
if (pci_is_root_bus(dev->bus) || dev->subordinate || !dev->bus->self)
return -ENOTTY;

list_for_each_entry(pdev, &dev->bus->devices, bus_list)
Expand Down
2 changes: 1 addition & 1 deletion drivers/pci/pcie/aer/ecrc.c
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ void pcie_set_ecrc_checking(struct pci_dev *dev)
disable_ecrc_checking(dev);
break;
case ECRC_POLICY_ON:
enable_ecrc_checking(dev);;
enable_ecrc_checking(dev);
break;
default:
return;
Expand Down
5 changes: 5 additions & 0 deletions drivers/pci/quirks.c
Original file line number Diff line number Diff line change
Expand Up @@ -1058,6 +1058,11 @@ static void __devinit quirk_no_ata_d3(struct pci_dev *pdev)
}
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_SERVERWORKS, PCI_ANY_ID, quirk_no_ata_d3);
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_ATI, PCI_ANY_ID, quirk_no_ata_d3);
/* ALi loses some register settings that we cannot then restore */
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_AL, PCI_ANY_ID, quirk_no_ata_d3);
/* VIA comes back fine but we need to keep it alive or ACPI GTM failures
occur when mode detecting */
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_VIA, PCI_ANY_ID, quirk_no_ata_d3);

/* This was originally an Alpha specific thing, but it really fits here.
* The i82375 PCI/EISA bridge appears as non-classified. Fix that.
Expand Down
4 changes: 2 additions & 2 deletions drivers/pci/slot.c
Original file line number Diff line number Diff line change
Expand Up @@ -311,7 +311,7 @@ EXPORT_SYMBOL_GPL(pci_destroy_slot);
#include <linux/pci_hotplug.h>
/**
* pci_hp_create_link - create symbolic link to the hotplug driver module.
* @slot: struct pci_slot
* @pci_slot: struct pci_slot
*
* Helper function for pci_hotplug_core.c to create symbolic link to
* the hotplug driver module.
Expand All @@ -334,7 +334,7 @@ EXPORT_SYMBOL_GPL(pci_hp_create_module_link);

/**
* pci_hp_remove_link - remove symbolic link to the hotplug driver module.
* @slot: struct pci_slot
* @pci_slot: struct pci_slot
*
* Helper function for pci_hotplug_core.c to remove symbolic link to
* the hotplug driver module.
Expand Down
Loading

0 comments on commit dc53fff

Please sign in to comment.