Skip to content

Commit

Permalink
Merge branch 'linux-next' of git://git.kernel.org/pub/scm/linux/kerne…
Browse files Browse the repository at this point in the history
…l/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
  ...
  • Loading branch information
torvalds committed Oct 28, 2010
2 parents 800416f + 1af3c2e commit e9f29c9
Show file tree
Hide file tree
Showing 27 changed files with 395 additions and 70 deletions.
5 changes: 5 additions & 0 deletions Documentation/kernel-parameters.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2175,6 +2175,11 @@ and is between 256 and 4096 characters. It is defined in the file
reset_devices [KNL] Force drivers to reset the underlying device
during initialization.

resource_alloc_from_bottom
Allocate new resources from the beginning of available
space, not the end. If you need to use this, please
report a bug.

resume= [SWSUSP]
Specify the partition device for software suspend

Expand Down
2 changes: 2 additions & 0 deletions arch/x86/kernel/setup.c
Original file line number Diff line number Diff line change
Expand Up @@ -769,6 +769,8 @@ void __init setup_arch(char **cmdline_p)

x86_init.oem.arch_setup();

resource_alloc_from_bottom = 0;
iomem_resource.end = (1ULL << boot_cpu_data.x86_phys_bits) - 1;
setup_memory_map();
parse_setup_data();
/* update the e820_saved too */
Expand Down
17 changes: 11 additions & 6 deletions arch/x86/pci/i386.c
Original file line number Diff line number Diff line change
Expand Up @@ -65,16 +65,21 @@ pcibios_align_resource(void *data, const struct resource *res,
resource_size_t size, resource_size_t align)
{
struct pci_dev *dev = data;
resource_size_t start = res->start;
resource_size_t start = round_down(res->end - size + 1, align);

if (res->flags & IORESOURCE_IO) {
if (skip_isa_ioresource_align(dev))
return start;
if (start & 0x300)
start = (start + 0x3ff) & ~0x3ff;

/*
* If we're avoiding ISA aliases, the largest contiguous I/O
* port space is 256 bytes. Clearing bits 9 and 10 preserves
* all 256-byte and smaller alignments, so the result will
* still be correctly aligned.
*/
if (!skip_isa_ioresource_align(dev))
start &= ~0x300;
} else if (res->flags & IORESOURCE_MEM) {
if (start < BIOS_END)
start = BIOS_END;
start = res->end; /* fail; no space */
}
return start;
}
Expand Down
11 changes: 6 additions & 5 deletions arch/x86/pci/irq.c
Original file line number Diff line number Diff line change
Expand Up @@ -584,27 +584,28 @@ static __init int intel_router_probe(struct irq_router *r, struct pci_dev *route
case PCI_DEVICE_ID_INTEL_ICH9_3:
case PCI_DEVICE_ID_INTEL_ICH9_4:
case PCI_DEVICE_ID_INTEL_ICH9_5:
case PCI_DEVICE_ID_INTEL_TOLAPAI_0:
case PCI_DEVICE_ID_INTEL_EP80579_0:
case PCI_DEVICE_ID_INTEL_ICH10_0:
case PCI_DEVICE_ID_INTEL_ICH10_1:
case PCI_DEVICE_ID_INTEL_ICH10_2:
case PCI_DEVICE_ID_INTEL_ICH10_3:
case PCI_DEVICE_ID_INTEL_PATSBURG_LPC:
r->name = "PIIX/ICH";
r->get = pirq_piix_get;
r->set = pirq_piix_set;
return 1;
}

if ((device >= PCI_DEVICE_ID_INTEL_PCH_LPC_MIN) &&
(device <= PCI_DEVICE_ID_INTEL_PCH_LPC_MAX)) {
if ((device >= PCI_DEVICE_ID_INTEL_5_3400_SERIES_LPC_MIN) &&
(device <= PCI_DEVICE_ID_INTEL_5_3400_SERIES_LPC_MAX)) {
r->name = "PIIX/ICH";
r->get = pirq_piix_get;
r->set = pirq_piix_set;
return 1;
}

if ((device >= PCI_DEVICE_ID_INTEL_CPT_LPC_MIN) &&
(device <= PCI_DEVICE_ID_INTEL_CPT_LPC_MAX)) {
if ((device >= PCI_DEVICE_ID_INTEL_COUGARPOINT_LPC_MIN) &&
(device <= PCI_DEVICE_ID_INTEL_COUGARPOINT_LPC_MAX)) {
r->name = "PIIX/ICH";
r->get = pirq_piix_get;
r->set = pirq_piix_set;
Expand Down
4 changes: 1 addition & 3 deletions arch/x86/pci/mmconfig-shared.c
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,6 @@ static __init struct pci_mmcfg_region *pci_mmconfig_add(int segment, int start,
int end, u64 addr)
{
struct pci_mmcfg_region *new;
int num_buses;
struct resource *res;

if (addr == 0)
Expand All @@ -82,10 +81,9 @@ static __init struct pci_mmcfg_region *pci_mmconfig_add(int segment, int start,

list_add_sorted(new);

num_buses = end - start + 1;
res = &new->res;
res->start = addr + PCI_MMCFG_BUS_OFFSET(start);
res->end = addr + PCI_MMCFG_BUS_OFFSET(num_buses) - 1;
res->end = addr + PCI_MMCFG_BUS_OFFSET(end + 1) - 1;
res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
snprintf(new->name, PCI_MMCFG_RESOURCE_NAME_LEN,
"PCI MMCONFIG %04x [bus %02x-%02x]", segment, start, end);
Expand Down
4 changes: 2 additions & 2 deletions drivers/i2c/busses/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -95,9 +95,9 @@ config I2C_I801
ESB2
ICH8
ICH9
Tolapai
EP80579 (Tolapai)
ICH10
3400/5 Series (PCH)
5/3400 Series (PCH)
Cougar Point (PCH)

This driver can also be built as a module. If so, the module
Expand Down
10 changes: 5 additions & 5 deletions drivers/i2c/busses/i2c-i801.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,10 @@
82801G (ICH7) 0x27da 32 hard yes yes yes
82801H (ICH8) 0x283e 32 hard yes yes yes
82801I (ICH9) 0x2930 32 hard yes yes yes
Tolapai 0x5032 32 hard yes yes yes
EP80579 (Tolapai) 0x5032 32 hard yes yes yes
ICH10 0x3a30 32 hard yes yes yes
ICH10 0x3a60 32 hard yes yes yes
3400/5 Series (PCH) 0x3b30 32 hard yes yes yes
5/3400 Series (PCH) 0x3b30 32 hard yes yes yes
Cougar Point (PCH) 0x1c22 32 hard yes yes yes
Features supported by this driver:
Expand Down Expand Up @@ -587,11 +587,11 @@ static const struct pci_device_id i801_ids[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB2_17) },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_5) },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH9_6) },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_TOLAPAI_1) },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_EP80579_1) },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH10_4) },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH10_5) },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PCH_SMBUS) },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CPT_SMBUS) },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_5_3400_SERIES_SMBUS) },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_COUGARPOINT_SMBUS) },
{ 0, }
};

Expand Down
4 changes: 1 addition & 3 deletions drivers/pci/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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
53 changes: 48 additions & 5 deletions drivers/pci/bus.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -89,20 +132,20 @@ 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;

/* don't allocate too high if the pref mem doesn't support 64bit*/
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;
Expand Down
4 changes: 2 additions & 2 deletions drivers/pci/hotplug/ibmphp_hpc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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__);
Expand Down
4 changes: 2 additions & 2 deletions drivers/pci/msi.h
Original file line number Diff line number Diff line change
Expand Up @@ -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))

Expand Down
79 changes: 78 additions & 1 deletion drivers/pci/pci.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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.
Expand All @@ -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");
}
Expand Down Expand Up @@ -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;
}
Expand Down
3 changes: 0 additions & 3 deletions drivers/pci/pci.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion drivers/pci/pcie/aer/aerdrv.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down
3 changes: 3 additions & 0 deletions drivers/pci/pcie/aer/aerdrv.h
Original file line number Diff line number Diff line change
Expand Up @@ -132,13 +132,16 @@ 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)
{
if (pci_dev->__aer_firmware_first_valid)
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,
Expand Down
Loading

0 comments on commit e9f29c9

Please sign in to comment.