mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-29 03:01:39 -04:00
Merge branch 'linux-next' of git://git.kernel.org/pub/scm/linux/kernel/git/jbarnes/pci-2.6
* 'linux-next' of git://git.kernel.org/pub/scm/linux/kernel/git/jbarnes/pci-2.6: (27 commits) x86: allocate space within a region top-down x86: update iomem_resource end based on CPU physical address capabilities x86/PCI: allocate space from the end of a region, not the beginning PCI: allocate bus resources from the top down resources: support allocating space within a region from the top down resources: handle overflow when aligning start of available area resources: ensure callback doesn't allocate outside available space resources: factor out resource_clip() to simplify find_resource() resources: add a default alignf to simplify find_resource() x86/PCI: MMCONFIG: fix region end calculation PCI: Add support for polling PME state on suspended legacy PCI devices PCI: Export some PCI PM functionality PCI: fix message typo PCI: log vendor/device ID always PCI: update Intel chipset names and defines PCI: use new ccflags variable in Makefile PCI: add PCI_MSIX_TABLE/PBA defines PCI: add PCI vendor id for STmicroelectronics x86/PCI: irq and pci_ids patch for Intel Patsburg DeviceIDs PCI: OLPC: Only enable PCI configuration type override on XO-1 ...
This commit is contained in:
commit
e9f29c9a56
27 changed files with 395 additions and 70 deletions
|
|
@ -65,6 +65,4 @@ obj-$(CONFIG_PCI_SYSCALL) += syscall.o
|
|||
|
||||
obj-$(CONFIG_PCI_STUB) += pci-stub.o
|
||||
|
||||
ifeq ($(CONFIG_PCI_DEBUG),y)
|
||||
EXTRA_CFLAGS += -DDEBUG
|
||||
endif
|
||||
ccflags-$(CONFIG_PCI_DEBUG) := -DDEBUG
|
||||
|
|
|
|||
|
|
@ -64,6 +64,49 @@ void pci_bus_remove_resources(struct pci_bus *bus)
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Find the highest-address bus resource below the cursor "res". If the
|
||||
* cursor is NULL, return the highest resource.
|
||||
*/
|
||||
static struct resource *pci_bus_find_resource_prev(struct pci_bus *bus,
|
||||
unsigned int type,
|
||||
struct resource *res)
|
||||
{
|
||||
struct resource *r, *prev = NULL;
|
||||
int i;
|
||||
|
||||
pci_bus_for_each_resource(bus, r, i) {
|
||||
if (!r)
|
||||
continue;
|
||||
|
||||
if ((r->flags & IORESOURCE_TYPE_BITS) != type)
|
||||
continue;
|
||||
|
||||
/* If this resource is at or past the cursor, skip it */
|
||||
if (res) {
|
||||
if (r == res)
|
||||
continue;
|
||||
if (r->end > res->end)
|
||||
continue;
|
||||
if (r->end == res->end && r->start > res->start)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!prev)
|
||||
prev = r;
|
||||
|
||||
/*
|
||||
* A small resource is higher than a large one that ends at
|
||||
* the same address.
|
||||
*/
|
||||
if (r->end > prev->end ||
|
||||
(r->end == prev->end && r->start > prev->start))
|
||||
prev = r;
|
||||
}
|
||||
|
||||
return prev;
|
||||
}
|
||||
|
||||
/**
|
||||
* pci_bus_alloc_resource - allocate a resource from a parent bus
|
||||
* @bus: PCI bus
|
||||
|
|
@ -89,9 +132,10 @@ pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res,
|
|||
resource_size_t),
|
||||
void *alignf_data)
|
||||
{
|
||||
int i, ret = -ENOMEM;
|
||||
int ret = -ENOMEM;
|
||||
struct resource *r;
|
||||
resource_size_t max = -1;
|
||||
unsigned int type = res->flags & IORESOURCE_TYPE_BITS;
|
||||
|
||||
type_mask |= IORESOURCE_IO | IORESOURCE_MEM;
|
||||
|
||||
|
|
@ -99,10 +143,9 @@ pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res,
|
|||
if (!(res->flags & IORESOURCE_MEM_64))
|
||||
max = PCIBIOS_MAX_MEM_32;
|
||||
|
||||
pci_bus_for_each_resource(bus, r, i) {
|
||||
if (!r)
|
||||
continue;
|
||||
|
||||
/* Look for space at highest addresses first */
|
||||
r = pci_bus_find_resource_prev(bus, type, NULL);
|
||||
for ( ; r; r = pci_bus_find_resource_prev(bus, type, r)) {
|
||||
/* type_mask must match */
|
||||
if ((res->flags ^ r->flags) & type_mask)
|
||||
continue;
|
||||
|
|
|
|||
|
|
@ -133,8 +133,8 @@ void __init ibmphp_hpc_initvars (void)
|
|||
debug ("%s - Entry\n", __func__);
|
||||
|
||||
mutex_init(&sem_hpcaccess);
|
||||
init_MUTEX (&semOperations);
|
||||
init_MUTEX_LOCKED (&sem_exit);
|
||||
sema_init(&semOperations, 1);
|
||||
sema_init(&sem_exit, 0);
|
||||
to_debug = 0;
|
||||
|
||||
debug ("%s - Exit\n", __func__);
|
||||
|
|
|
|||
|
|
@ -22,8 +22,8 @@
|
|||
#define is_64bit_address(control) (!!(control & PCI_MSI_FLAGS_64BIT))
|
||||
#define is_mask_bit_support(control) (!!(control & PCI_MSI_FLAGS_MASKBIT))
|
||||
|
||||
#define msix_table_offset_reg(base) (base + 0x04)
|
||||
#define msix_pba_offset_reg(base) (base + 0x08)
|
||||
#define msix_table_offset_reg(base) (base + PCI_MSIX_TABLE)
|
||||
#define msix_pba_offset_reg(base) (base + PCI_MSIX_PBA)
|
||||
#define msix_table_size(control) ((control & PCI_MSIX_FLAGS_QSIZE)+1)
|
||||
#define multi_msix_capable(control) msix_table_size((control))
|
||||
|
||||
|
|
|
|||
|
|
@ -38,6 +38,19 @@ EXPORT_SYMBOL(pci_pci_problems);
|
|||
|
||||
unsigned int pci_pm_d3_delay;
|
||||
|
||||
static void pci_pme_list_scan(struct work_struct *work);
|
||||
|
||||
static LIST_HEAD(pci_pme_list);
|
||||
static DEFINE_MUTEX(pci_pme_list_mutex);
|
||||
static DECLARE_DELAYED_WORK(pci_pme_work, pci_pme_list_scan);
|
||||
|
||||
struct pci_pme_device {
|
||||
struct list_head list;
|
||||
struct pci_dev *dev;
|
||||
};
|
||||
|
||||
#define PME_TIMEOUT 1000 /* How long between PME checks */
|
||||
|
||||
static void pci_dev_d3_sleep(struct pci_dev *dev)
|
||||
{
|
||||
unsigned int delay = dev->d3_delay;
|
||||
|
|
@ -1331,6 +1344,32 @@ bool pci_pme_capable(struct pci_dev *dev, pci_power_t state)
|
|||
return !!(dev->pme_support & (1 << state));
|
||||
}
|
||||
|
||||
static void pci_pme_list_scan(struct work_struct *work)
|
||||
{
|
||||
struct pci_pme_device *pme_dev;
|
||||
|
||||
mutex_lock(&pci_pme_list_mutex);
|
||||
if (!list_empty(&pci_pme_list)) {
|
||||
list_for_each_entry(pme_dev, &pci_pme_list, list)
|
||||
pci_pme_wakeup(pme_dev->dev, NULL);
|
||||
schedule_delayed_work(&pci_pme_work, msecs_to_jiffies(PME_TIMEOUT));
|
||||
}
|
||||
mutex_unlock(&pci_pme_list_mutex);
|
||||
}
|
||||
|
||||
/**
|
||||
* pci_external_pme - is a device an external PCI PME source?
|
||||
* @dev: PCI device to check
|
||||
*
|
||||
*/
|
||||
|
||||
static bool pci_external_pme(struct pci_dev *dev)
|
||||
{
|
||||
if (pci_is_pcie(dev) || dev->bus->number == 0)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* pci_pme_active - enable or disable PCI device's PME# function
|
||||
* @dev: PCI device to handle.
|
||||
|
|
@ -1354,6 +1393,44 @@ void pci_pme_active(struct pci_dev *dev, bool enable)
|
|||
|
||||
pci_write_config_word(dev, dev->pm_cap + PCI_PM_CTRL, pmcsr);
|
||||
|
||||
/* PCI (as opposed to PCIe) PME requires that the device have
|
||||
its PME# line hooked up correctly. Not all hardware vendors
|
||||
do this, so the PME never gets delivered and the device
|
||||
remains asleep. The easiest way around this is to
|
||||
periodically walk the list of suspended devices and check
|
||||
whether any have their PME flag set. The assumption is that
|
||||
we'll wake up often enough anyway that this won't be a huge
|
||||
hit, and the power savings from the devices will still be a
|
||||
win. */
|
||||
|
||||
if (pci_external_pme(dev)) {
|
||||
struct pci_pme_device *pme_dev;
|
||||
if (enable) {
|
||||
pme_dev = kmalloc(sizeof(struct pci_pme_device),
|
||||
GFP_KERNEL);
|
||||
if (!pme_dev)
|
||||
goto out;
|
||||
pme_dev->dev = dev;
|
||||
mutex_lock(&pci_pme_list_mutex);
|
||||
list_add(&pme_dev->list, &pci_pme_list);
|
||||
if (list_is_singular(&pci_pme_list))
|
||||
schedule_delayed_work(&pci_pme_work,
|
||||
msecs_to_jiffies(PME_TIMEOUT));
|
||||
mutex_unlock(&pci_pme_list_mutex);
|
||||
} else {
|
||||
mutex_lock(&pci_pme_list_mutex);
|
||||
list_for_each_entry(pme_dev, &pci_pme_list, list) {
|
||||
if (pme_dev->dev == dev) {
|
||||
list_del(&pme_dev->list);
|
||||
kfree(pme_dev);
|
||||
break;
|
||||
}
|
||||
}
|
||||
mutex_unlock(&pci_pme_list_mutex);
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
dev_printk(KERN_DEBUG, &dev->dev, "PME# %s\n",
|
||||
enable ? "enabled" : "disabled");
|
||||
}
|
||||
|
|
@ -2689,7 +2766,7 @@ int pcie_get_readrq(struct pci_dev *dev)
|
|||
|
||||
ret = pci_read_config_word(dev, cap + PCI_EXP_DEVCTL, &ctl);
|
||||
if (!ret)
|
||||
ret = 128 << ((ctl & PCI_EXP_DEVCTL_READRQ) >> 12);
|
||||
ret = 128 << ((ctl & PCI_EXP_DEVCTL_READRQ) >> 12);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -63,11 +63,8 @@ struct pci_platform_pm_ops {
|
|||
extern int pci_set_platform_pm(struct pci_platform_pm_ops *ops);
|
||||
extern void pci_update_current_state(struct pci_dev *dev, pci_power_t state);
|
||||
extern void pci_disable_enabled_device(struct pci_dev *dev);
|
||||
extern bool pci_check_pme_status(struct pci_dev *dev);
|
||||
extern int pci_finish_runtime_suspend(struct pci_dev *dev);
|
||||
extern void pci_wakeup_event(struct pci_dev *dev);
|
||||
extern int __pci_pme_wakeup(struct pci_dev *dev, void *ign);
|
||||
extern void pci_pme_wakeup_bus(struct pci_bus *bus);
|
||||
extern void pci_pm_init(struct pci_dev *dev);
|
||||
extern void platform_pci_wakeup_init(struct pci_dev *dev);
|
||||
extern void pci_allocate_cap_save_buffers(struct pci_dev *dev);
|
||||
|
|
|
|||
|
|
@ -416,7 +416,7 @@ static void aer_error_resume(struct pci_dev *dev)
|
|||
*/
|
||||
static int __init aer_service_init(void)
|
||||
{
|
||||
if (!pci_aer_available())
|
||||
if (!pci_aer_available() || aer_acpi_firmware_first())
|
||||
return -ENXIO;
|
||||
return pcie_port_service_register(&aerdriver);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -132,6 +132,7 @@ static inline int aer_osc_setup(struct pcie_device *pciedev)
|
|||
|
||||
#ifdef CONFIG_ACPI_APEI
|
||||
extern int pcie_aer_get_firmware_first(struct pci_dev *pci_dev);
|
||||
extern bool aer_acpi_firmware_first(void);
|
||||
#else
|
||||
static inline int pcie_aer_get_firmware_first(struct pci_dev *pci_dev)
|
||||
{
|
||||
|
|
@ -139,6 +140,8 @@ static inline int pcie_aer_get_firmware_first(struct pci_dev *pci_dev)
|
|||
return pci_dev->__aer_firmware_first;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline bool aer_acpi_firmware_first(void) { return false; }
|
||||
#endif
|
||||
|
||||
static inline void pcie_aer_force_firmware_first(struct pci_dev *pci_dev,
|
||||
|
|
|
|||
|
|
@ -93,4 +93,38 @@ int pcie_aer_get_firmware_first(struct pci_dev *dev)
|
|||
aer_set_firmware_first(dev);
|
||||
return dev->__aer_firmware_first;
|
||||
}
|
||||
|
||||
static bool aer_firmware_first;
|
||||
|
||||
static int aer_hest_parse_aff(struct acpi_hest_header *hest_hdr, void *data)
|
||||
{
|
||||
struct acpi_hest_aer_common *p;
|
||||
|
||||
if (aer_firmware_first)
|
||||
return 0;
|
||||
|
||||
switch (hest_hdr->type) {
|
||||
case ACPI_HEST_TYPE_AER_ROOT_PORT:
|
||||
case ACPI_HEST_TYPE_AER_ENDPOINT:
|
||||
case ACPI_HEST_TYPE_AER_BRIDGE:
|
||||
p = (struct acpi_hest_aer_common *)(hest_hdr + 1);
|
||||
aer_firmware_first = !!(p->flags & ACPI_HEST_FIRMWARE_FIRST);
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* aer_acpi_firmware_first - Check if APEI should control AER.
|
||||
*/
|
||||
bool aer_acpi_firmware_first(void)
|
||||
{
|
||||
static bool parsed = false;
|
||||
|
||||
if (!parsed) {
|
||||
apei_hest_parse(aer_hest_parse_aff, NULL);
|
||||
parsed = true;
|
||||
}
|
||||
return aer_firmware_first;
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -754,7 +754,7 @@ void aer_isr(struct work_struct *work)
|
|||
{
|
||||
struct aer_rpc *rpc = container_of(work, struct aer_rpc, dpc_handler);
|
||||
struct pcie_device *p_device = rpc->rpd;
|
||||
struct aer_err_source e_src;
|
||||
struct aer_err_source uninitialized_var(e_src);
|
||||
|
||||
mutex_lock(&rpc->rpc_mutex);
|
||||
while (get_e_source(rpc, &e_src))
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ int pcie_port_acpi_setup(struct pci_dev *port, int *srv_mask)
|
|||
| OSC_PCI_EXPRESS_PME_CONTROL;
|
||||
|
||||
if (pci_aer_available()) {
|
||||
if (pcie_aer_get_firmware_first(port))
|
||||
if (aer_acpi_firmware_first())
|
||||
dev_dbg(&port->dev, "PCIe errors handled by BIOS.\n");
|
||||
else
|
||||
flags |= OSC_PCI_EXPRESS_AER_CONTROL;
|
||||
|
|
|
|||
|
|
@ -961,8 +961,8 @@ int pci_setup_device(struct pci_dev *dev)
|
|||
dev->class = class;
|
||||
class >>= 8;
|
||||
|
||||
dev_dbg(&dev->dev, "found [%04x:%04x] class %06x header type %02x\n",
|
||||
dev->vendor, dev->device, class, dev->hdr_type);
|
||||
dev_printk(KERN_DEBUG, &dev->dev, "[%04x:%04x] type %d class %#08x\n",
|
||||
dev->vendor, dev->device, dev->hdr_type, class);
|
||||
|
||||
/* need to have dev->class ready */
|
||||
dev->cfg_size = pci_cfg_space_size(dev);
|
||||
|
|
|
|||
|
|
@ -303,6 +303,7 @@ static const struct file_operations proc_bus_pci_operations = {
|
|||
.read = proc_bus_pci_read,
|
||||
.write = proc_bus_pci_write,
|
||||
.unlocked_ioctl = proc_bus_pci_ioctl,
|
||||
.compat_ioctl = proc_bus_pci_ioctl,
|
||||
#ifdef HAVE_PCI_MMAP
|
||||
.open = proc_bus_pci_open,
|
||||
.release = proc_bus_pci_release,
|
||||
|
|
|
|||
|
|
@ -2297,6 +2297,37 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_NVIDIA,
|
|||
PCI_DEVICE_ID_NVIDIA_NVENET_15,
|
||||
nvenet_msi_disable);
|
||||
|
||||
/*
|
||||
* Some versions of the MCP55 bridge from nvidia have a legacy irq routing
|
||||
* config register. This register controls the routing of legacy interrupts
|
||||
* from devices that route through the MCP55. If this register is misprogramed
|
||||
* interrupts are only sent to the bsp, unlike conventional systems where the
|
||||
* irq is broadxast to all online cpus. Not having this register set
|
||||
* properly prevents kdump from booting up properly, so lets make sure that
|
||||
* we have it set correctly.
|
||||
* Note this is an undocumented register.
|
||||
*/
|
||||
static void __devinit nvbridge_check_legacy_irq_routing(struct pci_dev *dev)
|
||||
{
|
||||
u32 cfg;
|
||||
|
||||
pci_read_config_dword(dev, 0x74, &cfg);
|
||||
|
||||
if (cfg & ((1 << 2) | (1 << 15))) {
|
||||
printk(KERN_INFO "Rewriting irq routing register on MCP55\n");
|
||||
cfg &= ~((1 << 2) | (1 << 15));
|
||||
pci_write_config_dword(dev, 0x74, cfg);
|
||||
}
|
||||
}
|
||||
|
||||
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_NVIDIA,
|
||||
PCI_DEVICE_ID_NVIDIA_MCP55_BRIDGE_V0,
|
||||
nvbridge_check_legacy_irq_routing);
|
||||
|
||||
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_NVIDIA,
|
||||
PCI_DEVICE_ID_NVIDIA_MCP55_BRIDGE_V4,
|
||||
nvbridge_check_legacy_irq_routing);
|
||||
|
||||
static int __devinit ht_check_msi_mapping(struct pci_dev *dev)
|
||||
{
|
||||
int pos, ttl = 48;
|
||||
|
|
|
|||
|
|
@ -85,7 +85,7 @@ void pci_update_resource(struct pci_dev *dev, int resno)
|
|||
}
|
||||
}
|
||||
res->flags &= ~IORESOURCE_UNSET;
|
||||
dev_info(&dev->dev, "BAR %d: set to %pR (PCI address [%#llx-%#llx]\n",
|
||||
dev_info(&dev->dev, "BAR %d: set to %pR (PCI address [%#llx-%#llx])\n",
|
||||
resno, res, (unsigned long long)region.start,
|
||||
(unsigned long long)region.end);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue