mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2025-01-11 00:08:50 +00:00
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/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
This commit is contained in:
commit
dc53fffc10
@ -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;
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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))
|
||||
@ -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,
|
||||
@ -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)
|
||||
@ -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;
|
||||
|
||||
@ -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);
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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 */
|
||||
@ -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;
|
||||
|
@ -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.
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -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)
|
||||
@ -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;
|
||||
@ -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;
|
||||
@ -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;
|
||||
}
|
||||
@ -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;
|
||||
@ -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++;
|
||||
}
|
||||
@ -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;
|
||||
@ -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);
|
||||
}
|
||||
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
@ -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)
|
||||
|
@ -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;
|
||||
|
@ -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.
|
||||
|
@ -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.
|
||||
@ -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.
|
||||
|
@ -1145,7 +1145,7 @@ static inline void pci_set_drvdata(struct pci_dev *pdev, void *data)
|
||||
/* If you want to know what to call your pci_dev, ask this function.
|
||||
* Again, it's a wrapper around the generic device.
|
||||
*/
|
||||
static inline const char *pci_name(struct pci_dev *pdev)
|
||||
static inline const char *pci_name(const struct pci_dev *pdev)
|
||||
{
|
||||
return dev_name(&pdev->dev);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user