mirror of https://gitee.com/openkylin/linux.git
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: PCI: label: remove #include of ACPI header to avoid warnings PCI: label: Fix compilation error when CONFIG_ACPI is unset PCI: pre-allocate additional resources to devices only after successful allocation of essential resources. PCI: introduce reset_resource() PCI: data structure agnostic free list function PCI: refactor io size calculation code PCI: do not create quirk I/O regions below PCIBIOS_MIN_IO for ICH PCI hotplug: acpiphp: set current_state to D0 in register_slot PCI: Export ACPI _DSM provided firmware instance number and string name to sysfs PCI: add more checking to ICH region quirks PCI: aer-inject: Override PCIe AER Mask Registers PCI: fix tlan build when CONFIG_PCI is not enabled PCI: remove quirk for pre-production systems PCI: Avoid potential NULL pointer dereference in pci_scan_bridge PCI/lpc: irq and pci_ids patch for Intel DH89xxCC DeviceIDs PCI: sysfs: Fix failure path for addition of "vpd" attribute
This commit is contained in:
commit
99759619b2
|
@ -145,9 +145,11 @@ Date: July 2010
|
|||
Contact: Narendra K <narendra_k@dell.com>, linux-bugs@dell.com
|
||||
Description:
|
||||
Reading this attribute will provide the firmware
|
||||
given name(SMBIOS type 41 string) of the PCI device.
|
||||
The attribute will be created only if the firmware
|
||||
has given a name to the PCI device.
|
||||
given name (SMBIOS type 41 string or ACPI _DSM string) of
|
||||
the PCI device. The attribute will be created only
|
||||
if the firmware has given a name to the PCI device.
|
||||
ACPI _DSM string name will be given priority if the
|
||||
system firmware provides SMBIOS type 41 string also.
|
||||
Users:
|
||||
Userspace applications interested in knowing the
|
||||
firmware assigned name of the PCI device.
|
||||
|
@ -157,12 +159,27 @@ Date: July 2010
|
|||
Contact: Narendra K <narendra_k@dell.com>, linux-bugs@dell.com
|
||||
Description:
|
||||
Reading this attribute will provide the firmware
|
||||
given instance(SMBIOS type 41 device type instance)
|
||||
of the PCI device. The attribute will be created
|
||||
only if the firmware has given a device type instance
|
||||
to the PCI device.
|
||||
given instance (SMBIOS type 41 device type instance) of the
|
||||
PCI device. The attribute will be created only if the firmware
|
||||
has given an instance number to the PCI device.
|
||||
Users:
|
||||
Userspace applications interested in knowing the
|
||||
firmware assigned device type instance of the PCI
|
||||
device that can help in understanding the firmware
|
||||
intended order of the PCI device.
|
||||
|
||||
What: /sys/bus/pci/devices/.../acpi_index
|
||||
Date: July 2010
|
||||
Contact: Narendra K <narendra_k@dell.com>, linux-bugs@dell.com
|
||||
Description:
|
||||
Reading this attribute will provide the firmware
|
||||
given instance (ACPI _DSM instance number) of the PCI device.
|
||||
The attribute will be created only if the firmware has given
|
||||
an instance number to the PCI device. ACPI _DSM instance number
|
||||
will be given priority if the system firmware provides SMBIOS
|
||||
type 41 device type instance also.
|
||||
Users:
|
||||
Userspace applications interested in knowing the
|
||||
firmware assigned instance number of the PCI
|
||||
device that can help in understanding the firmware
|
||||
intended order of the PCI device.
|
||||
|
|
|
@ -597,21 +597,18 @@ static __init int intel_router_probe(struct irq_router *r, struct pci_dev *route
|
|||
return 1;
|
||||
}
|
||||
|
||||
if ((device >= PCI_DEVICE_ID_INTEL_5_3400_SERIES_LPC_MIN) &&
|
||||
(device <= PCI_DEVICE_ID_INTEL_5_3400_SERIES_LPC_MAX)) {
|
||||
if ((device >= PCI_DEVICE_ID_INTEL_5_3400_SERIES_LPC_MIN &&
|
||||
device <= PCI_DEVICE_ID_INTEL_5_3400_SERIES_LPC_MAX)
|
||||
|| (device >= PCI_DEVICE_ID_INTEL_COUGARPOINT_LPC_MIN &&
|
||||
device <= PCI_DEVICE_ID_INTEL_COUGARPOINT_LPC_MAX)
|
||||
|| (device >= PCI_DEVICE_ID_INTEL_DH89XXCC_LPC_MIN &&
|
||||
device <= PCI_DEVICE_ID_INTEL_DH89XXCC_LPC_MAX)) {
|
||||
r->name = "PIIX/ICH";
|
||||
r->get = pirq_piix_get;
|
||||
r->set = pirq_piix_set;
|
||||
return 1;
|
||||
}
|
||||
|
||||
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;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -87,3 +87,5 @@ config PCI_IOAPIC
|
|||
depends on ACPI
|
||||
depends on HOTPLUG
|
||||
default y
|
||||
|
||||
select NLS if (DMI || ACPI)
|
||||
|
|
|
@ -54,8 +54,9 @@ obj-$(CONFIG_TILE) += setup-bus.o setup-irq.o
|
|||
|
||||
#
|
||||
# ACPI Related PCI FW Functions
|
||||
# ACPI _DSM provided firmware instance and string name
|
||||
#
|
||||
obj-$(CONFIG_ACPI) += pci-acpi.o
|
||||
obj-$(CONFIG_ACPI) += pci-acpi.o pci-label.o
|
||||
|
||||
# SMBIOS provided firmware instance and labels
|
||||
obj-$(CONFIG_DMI) += pci-label.o
|
||||
|
|
|
@ -212,6 +212,7 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv)
|
|||
|
||||
pdev = pci_get_slot(pbus, PCI_DEVFN(device, function));
|
||||
if (pdev) {
|
||||
pdev->current_state = PCI_D0;
|
||||
slot->flags |= (SLOT_ENABLED | SLOT_POWEREDON);
|
||||
pci_dev_put(pdev);
|
||||
}
|
||||
|
|
|
@ -5,6 +5,13 @@
|
|||
* by Narendra K <Narendra_K@dell.com>,
|
||||
* Jordan Hargrave <Jordan_Hargrave@dell.com>
|
||||
*
|
||||
* PCI Firmware Specification Revision 3.1 section 4.6.7 (DSM for Naming a
|
||||
* PCI or PCI Express Device Under Operating Systems) defines an instance
|
||||
* number and string name. This code retrieves them and exports them to sysfs.
|
||||
* If the system firmware does not provide the ACPI _DSM (Device Specific
|
||||
* Method), then the SMBIOS type 41 instance number and string is exported to
|
||||
* sysfs.
|
||||
*
|
||||
* SMBIOS defines type 41 for onboard pci devices. This code retrieves
|
||||
* the instance number and string from the type 41 record and exports
|
||||
* it to sysfs.
|
||||
|
@ -19,8 +26,29 @@
|
|||
#include <linux/pci_ids.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/nls.h>
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/pci-acpi.h>
|
||||
#include <acpi/acpi_bus.h>
|
||||
#include "pci.h"
|
||||
|
||||
#define DEVICE_LABEL_DSM 0x07
|
||||
|
||||
#ifndef CONFIG_DMI
|
||||
|
||||
static inline int
|
||||
pci_create_smbiosname_file(struct pci_dev *pdev)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline void
|
||||
pci_remove_smbiosname_file(struct pci_dev *pdev)
|
||||
{
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
enum smbios_attr_enum {
|
||||
SMBIOS_ATTR_NONE = 0,
|
||||
SMBIOS_ATTR_LABEL_SHOW,
|
||||
|
@ -120,9 +148,7 @@ static struct attribute_group smbios_attr_group = {
|
|||
static int
|
||||
pci_create_smbiosname_file(struct pci_dev *pdev)
|
||||
{
|
||||
if (!sysfs_create_group(&pdev->dev.kobj, &smbios_attr_group))
|
||||
return 0;
|
||||
return -ENODEV;
|
||||
return sysfs_create_group(&pdev->dev.kobj, &smbios_attr_group);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -131,13 +157,227 @@ pci_remove_smbiosname_file(struct pci_dev *pdev)
|
|||
sysfs_remove_group(&pdev->dev.kobj, &smbios_attr_group);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_ACPI
|
||||
|
||||
static inline int
|
||||
pci_create_acpi_index_label_files(struct pci_dev *pdev)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline int
|
||||
pci_remove_acpi_index_label_files(struct pci_dev *pdev)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
device_has_dsm(struct device *dev)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static const char device_label_dsm_uuid[] = {
|
||||
0xD0, 0x37, 0xC9, 0xE5, 0x53, 0x35, 0x7A, 0x4D,
|
||||
0x91, 0x17, 0xEA, 0x4D, 0x19, 0xC3, 0x43, 0x4D
|
||||
};
|
||||
|
||||
enum acpi_attr_enum {
|
||||
ACPI_ATTR_NONE = 0,
|
||||
ACPI_ATTR_LABEL_SHOW,
|
||||
ACPI_ATTR_INDEX_SHOW,
|
||||
};
|
||||
|
||||
static void dsm_label_utf16s_to_utf8s(union acpi_object *obj, char *buf)
|
||||
{
|
||||
int len;
|
||||
len = utf16s_to_utf8s((const wchar_t *)obj->
|
||||
package.elements[1].string.pointer,
|
||||
obj->package.elements[1].string.length,
|
||||
UTF16_LITTLE_ENDIAN,
|
||||
buf, PAGE_SIZE);
|
||||
buf[len] = '\n';
|
||||
}
|
||||
|
||||
static int
|
||||
dsm_get_label(acpi_handle handle, int func,
|
||||
struct acpi_buffer *output,
|
||||
char *buf, enum acpi_attr_enum attribute)
|
||||
{
|
||||
struct acpi_object_list input;
|
||||
union acpi_object params[4];
|
||||
union acpi_object *obj;
|
||||
int len = 0;
|
||||
|
||||
int err;
|
||||
|
||||
input.count = 4;
|
||||
input.pointer = params;
|
||||
params[0].type = ACPI_TYPE_BUFFER;
|
||||
params[0].buffer.length = sizeof(device_label_dsm_uuid);
|
||||
params[0].buffer.pointer = (char *)device_label_dsm_uuid;
|
||||
params[1].type = ACPI_TYPE_INTEGER;
|
||||
params[1].integer.value = 0x02;
|
||||
params[2].type = ACPI_TYPE_INTEGER;
|
||||
params[2].integer.value = func;
|
||||
params[3].type = ACPI_TYPE_PACKAGE;
|
||||
params[3].package.count = 0;
|
||||
params[3].package.elements = NULL;
|
||||
|
||||
err = acpi_evaluate_object(handle, "_DSM", &input, output);
|
||||
if (err)
|
||||
return -1;
|
||||
|
||||
obj = (union acpi_object *)output->pointer;
|
||||
|
||||
switch (obj->type) {
|
||||
case ACPI_TYPE_PACKAGE:
|
||||
if (obj->package.count != 2)
|
||||
break;
|
||||
len = obj->package.elements[0].integer.value;
|
||||
if (buf) {
|
||||
if (attribute == ACPI_ATTR_INDEX_SHOW)
|
||||
scnprintf(buf, PAGE_SIZE, "%llu\n",
|
||||
obj->package.elements[0].integer.value);
|
||||
else if (attribute == ACPI_ATTR_LABEL_SHOW)
|
||||
dsm_label_utf16s_to_utf8s(obj, buf);
|
||||
kfree(output->pointer);
|
||||
return strlen(buf);
|
||||
}
|
||||
kfree(output->pointer);
|
||||
return len;
|
||||
break;
|
||||
default:
|
||||
kfree(output->pointer);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static bool
|
||||
device_has_dsm(struct device *dev)
|
||||
{
|
||||
acpi_handle handle;
|
||||
struct acpi_buffer output = {ACPI_ALLOCATE_BUFFER, NULL};
|
||||
|
||||
handle = DEVICE_ACPI_HANDLE(dev);
|
||||
|
||||
if (!handle)
|
||||
return FALSE;
|
||||
|
||||
if (dsm_get_label(handle, DEVICE_LABEL_DSM, &output, NULL,
|
||||
ACPI_ATTR_NONE) > 0)
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static mode_t
|
||||
acpi_index_string_exist(struct kobject *kobj, struct attribute *attr, int n)
|
||||
{
|
||||
struct device *dev;
|
||||
|
||||
dev = container_of(kobj, struct device, kobj);
|
||||
|
||||
if (device_has_dsm(dev))
|
||||
return S_IRUGO;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
acpilabel_show(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct acpi_buffer output = {ACPI_ALLOCATE_BUFFER, NULL};
|
||||
acpi_handle handle;
|
||||
int length;
|
||||
|
||||
handle = DEVICE_ACPI_HANDLE(dev);
|
||||
|
||||
if (!handle)
|
||||
return -1;
|
||||
|
||||
length = dsm_get_label(handle, DEVICE_LABEL_DSM,
|
||||
&output, buf, ACPI_ATTR_LABEL_SHOW);
|
||||
|
||||
if (length < 1)
|
||||
return -1;
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
acpiindex_show(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct acpi_buffer output = {ACPI_ALLOCATE_BUFFER, NULL};
|
||||
acpi_handle handle;
|
||||
int length;
|
||||
|
||||
handle = DEVICE_ACPI_HANDLE(dev);
|
||||
|
||||
if (!handle)
|
||||
return -1;
|
||||
|
||||
length = dsm_get_label(handle, DEVICE_LABEL_DSM,
|
||||
&output, buf, ACPI_ATTR_INDEX_SHOW);
|
||||
|
||||
if (length < 0)
|
||||
return -1;
|
||||
|
||||
return length;
|
||||
|
||||
}
|
||||
|
||||
static struct device_attribute acpi_attr_label = {
|
||||
.attr = {.name = "label", .mode = 0444},
|
||||
.show = acpilabel_show,
|
||||
};
|
||||
|
||||
static struct device_attribute acpi_attr_index = {
|
||||
.attr = {.name = "acpi_index", .mode = 0444},
|
||||
.show = acpiindex_show,
|
||||
};
|
||||
|
||||
static struct attribute *acpi_attributes[] = {
|
||||
&acpi_attr_label.attr,
|
||||
&acpi_attr_index.attr,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static struct attribute_group acpi_attr_group = {
|
||||
.attrs = acpi_attributes,
|
||||
.is_visible = acpi_index_string_exist,
|
||||
};
|
||||
|
||||
static int
|
||||
pci_create_acpi_index_label_files(struct pci_dev *pdev)
|
||||
{
|
||||
return sysfs_create_group(&pdev->dev.kobj, &acpi_attr_group);
|
||||
}
|
||||
|
||||
static int
|
||||
pci_remove_acpi_index_label_files(struct pci_dev *pdev)
|
||||
{
|
||||
sysfs_remove_group(&pdev->dev.kobj, &acpi_attr_group);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
void pci_create_firmware_label_files(struct pci_dev *pdev)
|
||||
{
|
||||
if (!pci_create_smbiosname_file(pdev))
|
||||
;
|
||||
if (device_has_dsm(&pdev->dev))
|
||||
pci_create_acpi_index_label_files(pdev);
|
||||
else
|
||||
pci_create_smbiosname_file(pdev);
|
||||
}
|
||||
|
||||
void pci_remove_firmware_label_files(struct pci_dev *pdev)
|
||||
{
|
||||
pci_remove_smbiosname_file(pdev);
|
||||
if (device_has_dsm(&pdev->dev))
|
||||
pci_remove_acpi_index_label_files(pdev);
|
||||
else
|
||||
pci_remove_smbiosname_file(pdev);
|
||||
}
|
||||
|
|
|
@ -1088,7 +1088,7 @@ static int pci_create_capabilities_sysfs(struct pci_dev *dev)
|
|||
attr->write = write_vpd_attr;
|
||||
retval = sysfs_create_bin_file(&dev->dev.kobj, attr);
|
||||
if (retval) {
|
||||
kfree(dev->vpd->attr);
|
||||
kfree(attr);
|
||||
return retval;
|
||||
}
|
||||
dev->vpd->attr = attr;
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
extern int pci_uevent(struct device *dev, struct kobj_uevent_env *env);
|
||||
extern int pci_create_sysfs_dev_files(struct pci_dev *pdev);
|
||||
extern void pci_remove_sysfs_dev_files(struct pci_dev *pdev);
|
||||
#ifndef CONFIG_DMI
|
||||
#if !defined(CONFIG_DMI) && !defined(CONFIG_ACPI)
|
||||
static inline void pci_create_firmware_label_files(struct pci_dev *pdev)
|
||||
{ return; }
|
||||
static inline void pci_remove_firmware_label_files(struct pci_dev *pdev)
|
||||
|
|
|
@ -27,6 +27,10 @@
|
|||
#include <linux/stddef.h>
|
||||
#include "aerdrv.h"
|
||||
|
||||
/* Override the existing corrected and uncorrected error masks */
|
||||
static int aer_mask_override;
|
||||
module_param(aer_mask_override, bool, 0);
|
||||
|
||||
struct aer_error_inj {
|
||||
u8 bus;
|
||||
u8 dev;
|
||||
|
@ -322,7 +326,7 @@ static int aer_inject(struct aer_error_inj *einj)
|
|||
unsigned long flags;
|
||||
unsigned int devfn = PCI_DEVFN(einj->dev, einj->fn);
|
||||
int pos_cap_err, rp_pos_cap_err;
|
||||
u32 sever, cor_mask, uncor_mask;
|
||||
u32 sever, cor_mask, uncor_mask, cor_mask_orig, uncor_mask_orig;
|
||||
int ret = 0;
|
||||
|
||||
dev = pci_get_domain_bus_and_slot((int)einj->domain, einj->bus, devfn);
|
||||
|
@ -361,6 +365,18 @@ static int aer_inject(struct aer_error_inj *einj)
|
|||
goto out_put;
|
||||
}
|
||||
|
||||
if (aer_mask_override) {
|
||||
cor_mask_orig = cor_mask;
|
||||
cor_mask &= !(einj->cor_status);
|
||||
pci_write_config_dword(dev, pos_cap_err + PCI_ERR_COR_MASK,
|
||||
cor_mask);
|
||||
|
||||
uncor_mask_orig = uncor_mask;
|
||||
uncor_mask &= !(einj->uncor_status);
|
||||
pci_write_config_dword(dev, pos_cap_err + PCI_ERR_UNCOR_MASK,
|
||||
uncor_mask);
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&inject_lock, flags);
|
||||
|
||||
err = __find_aer_error_by_dev(dev);
|
||||
|
@ -378,14 +394,16 @@ static int aer_inject(struct aer_error_inj *einj)
|
|||
err->header_log2 = einj->header_log2;
|
||||
err->header_log3 = einj->header_log3;
|
||||
|
||||
if (einj->cor_status && !(einj->cor_status & ~cor_mask)) {
|
||||
if (!aer_mask_override && einj->cor_status &&
|
||||
!(einj->cor_status & ~cor_mask)) {
|
||||
ret = -EINVAL;
|
||||
printk(KERN_WARNING "The correctable error(s) is masked "
|
||||
"by device\n");
|
||||
spin_unlock_irqrestore(&inject_lock, flags);
|
||||
goto out_put;
|
||||
}
|
||||
if (einj->uncor_status && !(einj->uncor_status & ~uncor_mask)) {
|
||||
if (!aer_mask_override && einj->uncor_status &&
|
||||
!(einj->uncor_status & ~uncor_mask)) {
|
||||
ret = -EINVAL;
|
||||
printk(KERN_WARNING "The uncorrectable error(s) is masked "
|
||||
"by device\n");
|
||||
|
@ -425,6 +443,13 @@ static int aer_inject(struct aer_error_inj *einj)
|
|||
}
|
||||
spin_unlock_irqrestore(&inject_lock, flags);
|
||||
|
||||
if (aer_mask_override) {
|
||||
pci_write_config_dword(dev, pos_cap_err + PCI_ERR_COR_MASK,
|
||||
cor_mask_orig);
|
||||
pci_write_config_dword(dev, pos_cap_err + PCI_ERR_UNCOR_MASK,
|
||||
uncor_mask_orig);
|
||||
}
|
||||
|
||||
ret = pci_bus_set_aer_ops(dev->bus);
|
||||
if (ret)
|
||||
goto out_put;
|
||||
|
|
|
@ -764,6 +764,8 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max,
|
|||
if (pci_find_bus(pci_domain_nr(bus), max+1))
|
||||
goto out;
|
||||
child = pci_add_new_bus(bus, dev, ++max);
|
||||
if (!child)
|
||||
goto out;
|
||||
buses = (buses & 0xff000000)
|
||||
| ((unsigned int)(child->primary) << 0)
|
||||
| ((unsigned int)(child->secondary) << 8)
|
||||
|
@ -777,7 +779,7 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max,
|
|||
buses &= ~0xff000000;
|
||||
buses |= CARDBUS_LATENCY_TIMER << 24;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* We need to blast all three values with a single write.
|
||||
*/
|
||||
|
|
|
@ -533,6 +533,17 @@ static void __devinit quirk_piix4_acpi(struct pci_dev *dev)
|
|||
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3, quirk_piix4_acpi);
|
||||
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443MX_3, quirk_piix4_acpi);
|
||||
|
||||
#define ICH_PMBASE 0x40
|
||||
#define ICH_ACPI_CNTL 0x44
|
||||
#define ICH4_ACPI_EN 0x10
|
||||
#define ICH6_ACPI_EN 0x80
|
||||
#define ICH4_GPIOBASE 0x58
|
||||
#define ICH4_GPIO_CNTL 0x5c
|
||||
#define ICH4_GPIO_EN 0x10
|
||||
#define ICH6_GPIOBASE 0x48
|
||||
#define ICH6_GPIO_CNTL 0x4c
|
||||
#define ICH6_GPIO_EN 0x10
|
||||
|
||||
/*
|
||||
* ICH4, ICH4-M, ICH5, ICH5-M ACPI: Three IO regions pointed to by longwords at
|
||||
* 0x40 (128 bytes of ACPI, GPIO & TCO registers)
|
||||
|
@ -541,12 +552,33 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443MX_3, qui
|
|||
static void __devinit quirk_ich4_lpc_acpi(struct pci_dev *dev)
|
||||
{
|
||||
u32 region;
|
||||
u8 enable;
|
||||
|
||||
pci_read_config_dword(dev, 0x40, ®ion);
|
||||
quirk_io_region(dev, region, 128, PCI_BRIDGE_RESOURCES, "ICH4 ACPI/GPIO/TCO");
|
||||
/*
|
||||
* The check for PCIBIOS_MIN_IO is to ensure we won't create a conflict
|
||||
* with low legacy (and fixed) ports. We don't know the decoding
|
||||
* priority and can't tell whether the legacy device or the one created
|
||||
* here is really at that address. This happens on boards with broken
|
||||
* BIOSes.
|
||||
*/
|
||||
|
||||
pci_read_config_dword(dev, 0x58, ®ion);
|
||||
quirk_io_region(dev, region, 64, PCI_BRIDGE_RESOURCES+1, "ICH4 GPIO");
|
||||
pci_read_config_byte(dev, ICH_ACPI_CNTL, &enable);
|
||||
if (enable & ICH4_ACPI_EN) {
|
||||
pci_read_config_dword(dev, ICH_PMBASE, ®ion);
|
||||
region &= PCI_BASE_ADDRESS_IO_MASK;
|
||||
if (region >= PCIBIOS_MIN_IO)
|
||||
quirk_io_region(dev, region, 128, PCI_BRIDGE_RESOURCES,
|
||||
"ICH4 ACPI/GPIO/TCO");
|
||||
}
|
||||
|
||||
pci_read_config_byte(dev, ICH4_GPIO_CNTL, &enable);
|
||||
if (enable & ICH4_GPIO_EN) {
|
||||
pci_read_config_dword(dev, ICH4_GPIOBASE, ®ion);
|
||||
region &= PCI_BASE_ADDRESS_IO_MASK;
|
||||
if (region >= PCIBIOS_MIN_IO)
|
||||
quirk_io_region(dev, region, 64,
|
||||
PCI_BRIDGE_RESOURCES + 1, "ICH4 GPIO");
|
||||
}
|
||||
}
|
||||
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AA_0, quirk_ich4_lpc_acpi);
|
||||
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AB_0, quirk_ich4_lpc_acpi);
|
||||
|
@ -562,12 +594,25 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_1, qui
|
|||
static void __devinit ich6_lpc_acpi_gpio(struct pci_dev *dev)
|
||||
{
|
||||
u32 region;
|
||||
u8 enable;
|
||||
|
||||
pci_read_config_dword(dev, 0x40, ®ion);
|
||||
quirk_io_region(dev, region, 128, PCI_BRIDGE_RESOURCES, "ICH6 ACPI/GPIO/TCO");
|
||||
pci_read_config_byte(dev, ICH_ACPI_CNTL, &enable);
|
||||
if (enable & ICH6_ACPI_EN) {
|
||||
pci_read_config_dword(dev, ICH_PMBASE, ®ion);
|
||||
region &= PCI_BASE_ADDRESS_IO_MASK;
|
||||
if (region >= PCIBIOS_MIN_IO)
|
||||
quirk_io_region(dev, region, 128, PCI_BRIDGE_RESOURCES,
|
||||
"ICH6 ACPI/GPIO/TCO");
|
||||
}
|
||||
|
||||
pci_read_config_dword(dev, 0x48, ®ion);
|
||||
quirk_io_region(dev, region, 64, PCI_BRIDGE_RESOURCES+1, "ICH6 GPIO");
|
||||
pci_read_config_byte(dev, ICH6_GPIO_CNTL, &enable);
|
||||
if (enable & ICH4_GPIO_EN) {
|
||||
pci_read_config_dword(dev, ICH6_GPIOBASE, ®ion);
|
||||
region &= PCI_BASE_ADDRESS_IO_MASK;
|
||||
if (region >= PCIBIOS_MIN_IO)
|
||||
quirk_io_region(dev, region, 64,
|
||||
PCI_BRIDGE_RESOURCES + 1, "ICH6 GPIO");
|
||||
}
|
||||
}
|
||||
|
||||
static void __devinit ich6_lpc_generic_decode(struct pci_dev *dev, unsigned reg, const char *name, int dynsize)
|
||||
|
@ -2618,58 +2663,6 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x4375,
|
|||
|
||||
#endif /* CONFIG_PCI_MSI */
|
||||
|
||||
#ifdef CONFIG_PCI_IOV
|
||||
|
||||
/*
|
||||
* For Intel 82576 SR-IOV NIC, if BIOS doesn't allocate resources for the
|
||||
* SR-IOV BARs, zero the Flash BAR and program the SR-IOV BARs to use the
|
||||
* old Flash Memory Space.
|
||||
*/
|
||||
static void __devinit quirk_i82576_sriov(struct pci_dev *dev)
|
||||
{
|
||||
int pos, flags;
|
||||
u32 bar, start, size;
|
||||
|
||||
if (PAGE_SIZE > 0x10000)
|
||||
return;
|
||||
|
||||
flags = pci_resource_flags(dev, 0);
|
||||
if ((flags & PCI_BASE_ADDRESS_SPACE) !=
|
||||
PCI_BASE_ADDRESS_SPACE_MEMORY ||
|
||||
(flags & PCI_BASE_ADDRESS_MEM_TYPE_MASK) !=
|
||||
PCI_BASE_ADDRESS_MEM_TYPE_32)
|
||||
return;
|
||||
|
||||
pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_SRIOV);
|
||||
if (!pos)
|
||||
return;
|
||||
|
||||
pci_read_config_dword(dev, pos + PCI_SRIOV_BAR, &bar);
|
||||
if (bar & PCI_BASE_ADDRESS_MEM_MASK)
|
||||
return;
|
||||
|
||||
start = pci_resource_start(dev, 1);
|
||||
size = pci_resource_len(dev, 1);
|
||||
if (!start || size != 0x400000 || start & (size - 1))
|
||||
return;
|
||||
|
||||
pci_resource_flags(dev, 1) = 0;
|
||||
pci_write_config_dword(dev, PCI_BASE_ADDRESS_1, 0);
|
||||
pci_write_config_dword(dev, pos + PCI_SRIOV_BAR, start);
|
||||
pci_write_config_dword(dev, pos + PCI_SRIOV_BAR + 12, start + size / 2);
|
||||
|
||||
dev_info(&dev->dev, "use Flash Memory Space for SR-IOV BARs\n");
|
||||
}
|
||||
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x10c9, quirk_i82576_sriov);
|
||||
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x10e6, quirk_i82576_sriov);
|
||||
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x10e7, quirk_i82576_sriov);
|
||||
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x10e8, quirk_i82576_sriov);
|
||||
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x150a, quirk_i82576_sriov);
|
||||
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x150d, quirk_i82576_sriov);
|
||||
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x1518, quirk_i82576_sriov);
|
||||
|
||||
#endif /* CONFIG_PCI_IOV */
|
||||
|
||||
/* Allow manual resource allocation for PCI hotplug bridges
|
||||
* via pci=hpmemsize=nnM and pci=hpiosize=nnM parameters. For
|
||||
* some PCI-PCI hotplug bridges, like PLX 6254 (former HINT HB6),
|
||||
|
|
|
@ -33,11 +33,32 @@ struct resource_list_x {
|
|||
struct pci_dev *dev;
|
||||
resource_size_t start;
|
||||
resource_size_t end;
|
||||
resource_size_t add_size;
|
||||
unsigned long flags;
|
||||
};
|
||||
|
||||
static void add_to_failed_list(struct resource_list_x *head,
|
||||
struct pci_dev *dev, struct resource *res)
|
||||
#define free_list(type, head) do { \
|
||||
struct type *list, *tmp; \
|
||||
for (list = (head)->next; list;) { \
|
||||
tmp = list; \
|
||||
list = list->next; \
|
||||
kfree(tmp); \
|
||||
} \
|
||||
(head)->next = NULL; \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
* add_to_list() - add a new resource tracker to the list
|
||||
* @head: Head of the list
|
||||
* @dev: device corresponding to which the resource
|
||||
* belongs
|
||||
* @res: The resource to be tracked
|
||||
* @add_size: additional size to be optionally added
|
||||
* to the resource
|
||||
*/
|
||||
static void add_to_list(struct resource_list_x *head,
|
||||
struct pci_dev *dev, struct resource *res,
|
||||
resource_size_t add_size)
|
||||
{
|
||||
struct resource_list_x *list = head;
|
||||
struct resource_list_x *ln = list->next;
|
||||
|
@ -45,7 +66,7 @@ static void add_to_failed_list(struct resource_list_x *head,
|
|||
|
||||
tmp = kmalloc(sizeof(*tmp), GFP_KERNEL);
|
||||
if (!tmp) {
|
||||
pr_warning("add_to_failed_list: kmalloc() failed!\n");
|
||||
pr_warning("add_to_list: kmalloc() failed!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -55,20 +76,14 @@ static void add_to_failed_list(struct resource_list_x *head,
|
|||
tmp->start = res->start;
|
||||
tmp->end = res->end;
|
||||
tmp->flags = res->flags;
|
||||
tmp->add_size = add_size;
|
||||
list->next = tmp;
|
||||
}
|
||||
|
||||
static void free_failed_list(struct resource_list_x *head)
|
||||
static void add_to_failed_list(struct resource_list_x *head,
|
||||
struct pci_dev *dev, struct resource *res)
|
||||
{
|
||||
struct resource_list_x *list, *tmp;
|
||||
|
||||
for (list = head->next; list;) {
|
||||
tmp = list;
|
||||
list = list->next;
|
||||
kfree(tmp);
|
||||
}
|
||||
|
||||
head->next = NULL;
|
||||
add_to_list(head, dev, res, 0);
|
||||
}
|
||||
|
||||
static void __dev_sort_resources(struct pci_dev *dev,
|
||||
|
@ -91,18 +106,88 @@ static void __dev_sort_resources(struct pci_dev *dev,
|
|||
pdev_sort_resources(dev, head);
|
||||
}
|
||||
|
||||
static void __assign_resources_sorted(struct resource_list *head,
|
||||
static inline void reset_resource(struct resource *res)
|
||||
{
|
||||
res->start = 0;
|
||||
res->end = 0;
|
||||
res->flags = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* adjust_resources_sorted() - satisfy any additional resource requests
|
||||
*
|
||||
* @add_head : head of the list tracking requests requiring additional
|
||||
* resources
|
||||
* @head : head of the list tracking requests with allocated
|
||||
* resources
|
||||
*
|
||||
* Walk through each element of the add_head and try to procure
|
||||
* additional resources for the element, provided the element
|
||||
* is in the head list.
|
||||
*/
|
||||
static void adjust_resources_sorted(struct resource_list_x *add_head,
|
||||
struct resource_list *head)
|
||||
{
|
||||
struct resource *res;
|
||||
struct resource_list_x *list, *tmp, *prev;
|
||||
struct resource_list *hlist;
|
||||
resource_size_t add_size;
|
||||
int idx;
|
||||
|
||||
prev = add_head;
|
||||
for (list = add_head->next; list;) {
|
||||
res = list->res;
|
||||
/* skip resource that has been reset */
|
||||
if (!res->flags)
|
||||
goto out;
|
||||
|
||||
/* skip this resource if not found in head list */
|
||||
for (hlist = head->next; hlist && hlist->res != res;
|
||||
hlist = hlist->next);
|
||||
if (!hlist) { /* just skip */
|
||||
prev = list;
|
||||
list = list->next;
|
||||
continue;
|
||||
}
|
||||
|
||||
idx = res - &list->dev->resource[0];
|
||||
add_size=list->add_size;
|
||||
if (!resource_size(res) && add_size) {
|
||||
res->end = res->start + add_size - 1;
|
||||
if(pci_assign_resource(list->dev, idx))
|
||||
reset_resource(res);
|
||||
} else if (add_size) {
|
||||
adjust_resource(res, res->start,
|
||||
resource_size(res) + add_size);
|
||||
}
|
||||
out:
|
||||
tmp = list;
|
||||
prev->next = list = list->next;
|
||||
kfree(tmp);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* assign_requested_resources_sorted() - satisfy resource requests
|
||||
*
|
||||
* @head : head of the list tracking requests for resources
|
||||
* @failed_list : head of the list tracking requests that could
|
||||
* not be allocated
|
||||
*
|
||||
* Satisfy resource requests of each element in the list. Add
|
||||
* requests that could not satisfied to the failed_list.
|
||||
*/
|
||||
static void assign_requested_resources_sorted(struct resource_list *head,
|
||||
struct resource_list_x *fail_head)
|
||||
{
|
||||
struct resource *res;
|
||||
struct resource_list *list, *tmp;
|
||||
struct resource_list *list;
|
||||
int idx;
|
||||
|
||||
for (list = head->next; list;) {
|
||||
for (list = head->next; list; list = list->next) {
|
||||
res = list->res;
|
||||
idx = res - &list->dev->resource[0];
|
||||
|
||||
if (pci_assign_resource(list->dev, idx)) {
|
||||
if (resource_size(res) && pci_assign_resource(list->dev, idx)) {
|
||||
if (fail_head && !pci_is_root_bus(list->dev->bus)) {
|
||||
/*
|
||||
* if the failed res is for ROM BAR, and it will
|
||||
|
@ -112,16 +197,25 @@ static void __assign_resources_sorted(struct resource_list *head,
|
|||
(!(res->flags & IORESOURCE_ROM_ENABLE))))
|
||||
add_to_failed_list(fail_head, list->dev, res);
|
||||
}
|
||||
res->start = 0;
|
||||
res->end = 0;
|
||||
res->flags = 0;
|
||||
reset_resource(res);
|
||||
}
|
||||
tmp = list;
|
||||
list = list->next;
|
||||
kfree(tmp);
|
||||
}
|
||||
}
|
||||
|
||||
static void __assign_resources_sorted(struct resource_list *head,
|
||||
struct resource_list_x *add_head,
|
||||
struct resource_list_x *fail_head)
|
||||
{
|
||||
/* Satisfy the must-have resource requests */
|
||||
assign_requested_resources_sorted(head, fail_head);
|
||||
|
||||
/* Try to satisfy any additional nice-to-have resource
|
||||
requests */
|
||||
if (add_head)
|
||||
adjust_resources_sorted(add_head, head);
|
||||
free_list(resource_list, head);
|
||||
}
|
||||
|
||||
static void pdev_assign_resources_sorted(struct pci_dev *dev,
|
||||
struct resource_list_x *fail_head)
|
||||
{
|
||||
|
@ -129,11 +223,12 @@ static void pdev_assign_resources_sorted(struct pci_dev *dev,
|
|||
|
||||
head.next = NULL;
|
||||
__dev_sort_resources(dev, &head);
|
||||
__assign_resources_sorted(&head, fail_head);
|
||||
__assign_resources_sorted(&head, NULL, fail_head);
|
||||
|
||||
}
|
||||
|
||||
static void pbus_assign_resources_sorted(const struct pci_bus *bus,
|
||||
struct resource_list_x *add_head,
|
||||
struct resource_list_x *fail_head)
|
||||
{
|
||||
struct pci_dev *dev;
|
||||
|
@ -143,7 +238,7 @@ static void pbus_assign_resources_sorted(const struct pci_bus *bus,
|
|||
list_for_each_entry(dev, &bus->devices, bus_list)
|
||||
__dev_sort_resources(dev, &head);
|
||||
|
||||
__assign_resources_sorted(&head, fail_head);
|
||||
__assign_resources_sorted(&head, add_head, fail_head);
|
||||
}
|
||||
|
||||
void pci_setup_cardbus(struct pci_bus *bus)
|
||||
|
@ -404,15 +499,62 @@ static struct resource *find_free_bus_resource(struct pci_bus *bus, unsigned lon
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/* Sizing the IO windows of the PCI-PCI bridge is trivial,
|
||||
since these windows have 4K granularity and the IO ranges
|
||||
of non-bridge PCI devices are limited to 256 bytes.
|
||||
We must be careful with the ISA aliasing though. */
|
||||
static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size)
|
||||
static resource_size_t calculate_iosize(resource_size_t size,
|
||||
resource_size_t min_size,
|
||||
resource_size_t size1,
|
||||
resource_size_t old_size,
|
||||
resource_size_t align)
|
||||
{
|
||||
if (size < min_size)
|
||||
size = min_size;
|
||||
if (old_size == 1 )
|
||||
old_size = 0;
|
||||
/* To be fixed in 2.5: we should have sort of HAVE_ISA
|
||||
flag in the struct pci_bus. */
|
||||
#if defined(CONFIG_ISA) || defined(CONFIG_EISA)
|
||||
size = (size & 0xff) + ((size & ~0xffUL) << 2);
|
||||
#endif
|
||||
size = ALIGN(size + size1, align);
|
||||
if (size < old_size)
|
||||
size = old_size;
|
||||
return size;
|
||||
}
|
||||
|
||||
static resource_size_t calculate_memsize(resource_size_t size,
|
||||
resource_size_t min_size,
|
||||
resource_size_t size1,
|
||||
resource_size_t old_size,
|
||||
resource_size_t align)
|
||||
{
|
||||
if (size < min_size)
|
||||
size = min_size;
|
||||
if (old_size == 1 )
|
||||
old_size = 0;
|
||||
if (size < old_size)
|
||||
size = old_size;
|
||||
size = ALIGN(size + size1, align);
|
||||
return size;
|
||||
}
|
||||
|
||||
/**
|
||||
* pbus_size_io() - size the io window of a given bus
|
||||
*
|
||||
* @bus : the bus
|
||||
* @min_size : the minimum io window that must to be allocated
|
||||
* @add_size : additional optional io window
|
||||
* @add_head : track the additional io window on this list
|
||||
*
|
||||
* Sizing the IO windows of the PCI-PCI bridge is trivial,
|
||||
* since these windows have 4K granularity and the IO ranges
|
||||
* of non-bridge PCI devices are limited to 256 bytes.
|
||||
* We must be careful with the ISA aliasing though.
|
||||
*/
|
||||
static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size,
|
||||
resource_size_t add_size, struct resource_list_x *add_head)
|
||||
{
|
||||
struct pci_dev *dev;
|
||||
struct resource *b_res = find_free_bus_resource(bus, IORESOURCE_IO);
|
||||
unsigned long size = 0, size1 = 0, old_size;
|
||||
unsigned long size = 0, size0 = 0, size1 = 0;
|
||||
|
||||
if (!b_res)
|
||||
return;
|
||||
|
@ -435,20 +577,12 @@ static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size)
|
|||
size1 += r_size;
|
||||
}
|
||||
}
|
||||
if (size < min_size)
|
||||
size = min_size;
|
||||
old_size = resource_size(b_res);
|
||||
if (old_size == 1)
|
||||
old_size = 0;
|
||||
/* To be fixed in 2.5: we should have sort of HAVE_ISA
|
||||
flag in the struct pci_bus. */
|
||||
#if defined(CONFIG_ISA) || defined(CONFIG_EISA)
|
||||
size = (size & 0xff) + ((size & ~0xffUL) << 2);
|
||||
#endif
|
||||
size = ALIGN(size + size1, 4096);
|
||||
if (size < old_size)
|
||||
size = old_size;
|
||||
if (!size) {
|
||||
size0 = calculate_iosize(size, min_size, size1,
|
||||
resource_size(b_res), 4096);
|
||||
size1 = !add_size? size0:
|
||||
calculate_iosize(size, min_size+add_size, size1,
|
||||
resource_size(b_res), 4096);
|
||||
if (!size0 && !size1) {
|
||||
if (b_res->start || b_res->end)
|
||||
dev_info(&bus->self->dev, "disabling bridge window "
|
||||
"%pR to [bus %02x-%02x] (unused)\n", b_res,
|
||||
|
@ -458,17 +592,30 @@ static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size)
|
|||
}
|
||||
/* Alignment of the IO window is always 4K */
|
||||
b_res->start = 4096;
|
||||
b_res->end = b_res->start + size - 1;
|
||||
b_res->end = b_res->start + size0 - 1;
|
||||
b_res->flags |= IORESOURCE_STARTALIGN;
|
||||
if (size1 > size0 && add_head)
|
||||
add_to_list(add_head, bus->self, b_res, size1-size0);
|
||||
}
|
||||
|
||||
/* Calculate the size of the bus and minimal alignment which
|
||||
guarantees that all child resources fit in this size. */
|
||||
/**
|
||||
* pbus_size_mem() - size the memory window of a given bus
|
||||
*
|
||||
* @bus : the bus
|
||||
* @min_size : the minimum memory window that must to be allocated
|
||||
* @add_size : additional optional memory window
|
||||
* @add_head : track the additional memory window on this list
|
||||
*
|
||||
* Calculate the size of the bus and minimal alignment which
|
||||
* guarantees that all child resources fit in this size.
|
||||
*/
|
||||
static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
|
||||
unsigned long type, resource_size_t min_size)
|
||||
unsigned long type, resource_size_t min_size,
|
||||
resource_size_t add_size,
|
||||
struct resource_list_x *add_head)
|
||||
{
|
||||
struct pci_dev *dev;
|
||||
resource_size_t min_align, align, size, old_size;
|
||||
resource_size_t min_align, align, size, size0, size1;
|
||||
resource_size_t aligns[12]; /* Alignments from 1Mb to 2Gb */
|
||||
int order, max_order;
|
||||
struct resource *b_res = find_free_bus_resource(bus, type);
|
||||
|
@ -516,14 +663,6 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
|
|||
mem64_mask &= r->flags & IORESOURCE_MEM_64;
|
||||
}
|
||||
}
|
||||
if (size < min_size)
|
||||
size = min_size;
|
||||
old_size = resource_size(b_res);
|
||||
if (old_size == 1)
|
||||
old_size = 0;
|
||||
if (size < old_size)
|
||||
size = old_size;
|
||||
|
||||
align = 0;
|
||||
min_align = 0;
|
||||
for (order = 0; order <= max_order; order++) {
|
||||
|
@ -537,8 +676,11 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
|
|||
min_align = align1 >> 1;
|
||||
align += aligns[order];
|
||||
}
|
||||
size = ALIGN(size, min_align);
|
||||
if (!size) {
|
||||
size0 = calculate_memsize(size, min_size, 0, resource_size(b_res), align);
|
||||
size1 = !add_size ? size :
|
||||
calculate_memsize(size, min_size+add_size, 0,
|
||||
resource_size(b_res), align);
|
||||
if (!size0 && !size1) {
|
||||
if (b_res->start || b_res->end)
|
||||
dev_info(&bus->self->dev, "disabling bridge window "
|
||||
"%pR to [bus %02x-%02x] (unused)\n", b_res,
|
||||
|
@ -547,9 +689,10 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
|
|||
return 1;
|
||||
}
|
||||
b_res->start = min_align;
|
||||
b_res->end = size + min_align - 1;
|
||||
b_res->flags |= IORESOURCE_STARTALIGN;
|
||||
b_res->flags |= mem64_mask;
|
||||
b_res->end = size0 + min_align - 1;
|
||||
b_res->flags |= IORESOURCE_STARTALIGN | mem64_mask;
|
||||
if (size1 > size0 && add_head)
|
||||
add_to_list(add_head, bus->self, b_res, size1-size0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -602,11 +745,12 @@ static void pci_bus_size_cardbus(struct pci_bus *bus)
|
|||
}
|
||||
}
|
||||
|
||||
void __ref pci_bus_size_bridges(struct pci_bus *bus)
|
||||
void __ref __pci_bus_size_bridges(struct pci_bus *bus,
|
||||
struct resource_list_x *add_head)
|
||||
{
|
||||
struct pci_dev *dev;
|
||||
unsigned long mask, prefmask;
|
||||
resource_size_t min_mem_size = 0, min_io_size = 0;
|
||||
resource_size_t additional_mem_size = 0, additional_io_size = 0;
|
||||
|
||||
list_for_each_entry(dev, &bus->devices, bus_list) {
|
||||
struct pci_bus *b = dev->subordinate;
|
||||
|
@ -620,7 +764,7 @@ void __ref pci_bus_size_bridges(struct pci_bus *bus)
|
|||
|
||||
case PCI_CLASS_BRIDGE_PCI:
|
||||
default:
|
||||
pci_bus_size_bridges(b);
|
||||
__pci_bus_size_bridges(b, add_head);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -637,11 +781,14 @@ void __ref pci_bus_size_bridges(struct pci_bus *bus)
|
|||
case PCI_CLASS_BRIDGE_PCI:
|
||||
pci_bridge_check_ranges(bus);
|
||||
if (bus->self->is_hotplug_bridge) {
|
||||
min_io_size = pci_hotplug_io_size;
|
||||
min_mem_size = pci_hotplug_mem_size;
|
||||
additional_io_size = pci_hotplug_io_size;
|
||||
additional_mem_size = pci_hotplug_mem_size;
|
||||
}
|
||||
/*
|
||||
* Follow thru
|
||||
*/
|
||||
default:
|
||||
pbus_size_io(bus, min_io_size);
|
||||
pbus_size_io(bus, 0, additional_io_size, add_head);
|
||||
/* If the bridge supports prefetchable range, size it
|
||||
separately. If it doesn't, or its prefetchable window
|
||||
has already been allocated by arch code, try
|
||||
|
@ -649,30 +796,36 @@ void __ref pci_bus_size_bridges(struct pci_bus *bus)
|
|||
resources. */
|
||||
mask = IORESOURCE_MEM;
|
||||
prefmask = IORESOURCE_MEM | IORESOURCE_PREFETCH;
|
||||
if (pbus_size_mem(bus, prefmask, prefmask, min_mem_size))
|
||||
if (pbus_size_mem(bus, prefmask, prefmask, 0, additional_mem_size, add_head))
|
||||
mask = prefmask; /* Success, size non-prefetch only. */
|
||||
else
|
||||
min_mem_size += min_mem_size;
|
||||
pbus_size_mem(bus, mask, IORESOURCE_MEM, min_mem_size);
|
||||
additional_mem_size += additional_mem_size;
|
||||
pbus_size_mem(bus, mask, IORESOURCE_MEM, 0, additional_mem_size, add_head);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void __ref pci_bus_size_bridges(struct pci_bus *bus)
|
||||
{
|
||||
__pci_bus_size_bridges(bus, NULL);
|
||||
}
|
||||
EXPORT_SYMBOL(pci_bus_size_bridges);
|
||||
|
||||
static void __ref __pci_bus_assign_resources(const struct pci_bus *bus,
|
||||
struct resource_list_x *add_head,
|
||||
struct resource_list_x *fail_head)
|
||||
{
|
||||
struct pci_bus *b;
|
||||
struct pci_dev *dev;
|
||||
|
||||
pbus_assign_resources_sorted(bus, fail_head);
|
||||
pbus_assign_resources_sorted(bus, add_head, fail_head);
|
||||
|
||||
list_for_each_entry(dev, &bus->devices, bus_list) {
|
||||
b = dev->subordinate;
|
||||
if (!b)
|
||||
continue;
|
||||
|
||||
__pci_bus_assign_resources(b, fail_head);
|
||||
__pci_bus_assign_resources(b, add_head, fail_head);
|
||||
|
||||
switch (dev->class >> 8) {
|
||||
case PCI_CLASS_BRIDGE_PCI:
|
||||
|
@ -694,7 +847,7 @@ static void __ref __pci_bus_assign_resources(const struct pci_bus *bus,
|
|||
|
||||
void __ref pci_bus_assign_resources(const struct pci_bus *bus)
|
||||
{
|
||||
__pci_bus_assign_resources(bus, NULL);
|
||||
__pci_bus_assign_resources(bus, NULL, NULL);
|
||||
}
|
||||
EXPORT_SYMBOL(pci_bus_assign_resources);
|
||||
|
||||
|
@ -709,7 +862,7 @@ static void __ref __pci_bridge_assign_resources(const struct pci_dev *bridge,
|
|||
if (!b)
|
||||
return;
|
||||
|
||||
__pci_bus_assign_resources(b, fail_head);
|
||||
__pci_bus_assign_resources(b, NULL, fail_head);
|
||||
|
||||
switch (bridge->class >> 8) {
|
||||
case PCI_CLASS_BRIDGE_PCI:
|
||||
|
@ -842,17 +995,21 @@ void __init
|
|||
pci_assign_unassigned_resources(void)
|
||||
{
|
||||
struct pci_bus *bus;
|
||||
|
||||
struct resource_list_x add_list; /* list of resources that
|
||||
want additional resources */
|
||||
add_list.next = NULL;
|
||||
/* Depth first, calculate sizes and alignments of all
|
||||
subordinate buses. */
|
||||
list_for_each_entry(bus, &pci_root_buses, node) {
|
||||
pci_bus_size_bridges(bus);
|
||||
__pci_bus_size_bridges(bus, &add_list);
|
||||
}
|
||||
|
||||
/* Depth last, allocate resources and update the hardware. */
|
||||
list_for_each_entry(bus, &pci_root_buses, node) {
|
||||
pci_bus_assign_resources(bus);
|
||||
__pci_bus_assign_resources(bus, &add_list, NULL);
|
||||
pci_enable_bridges(bus);
|
||||
}
|
||||
BUG_ON(add_list.next);
|
||||
|
||||
/* dump the resource on buses */
|
||||
list_for_each_entry(bus, &pci_root_buses, node) {
|
||||
|
@ -882,7 +1039,7 @@ void pci_assign_unassigned_bridge_resources(struct pci_dev *bridge)
|
|||
|
||||
if (tried_times >= 2) {
|
||||
/* still fail, don't need to try more */
|
||||
free_failed_list(&head);
|
||||
free_list(resource_list_x, &head);
|
||||
goto enable_all;
|
||||
}
|
||||
|
||||
|
@ -913,7 +1070,7 @@ void pci_assign_unassigned_bridge_resources(struct pci_dev *bridge)
|
|||
|
||||
list = list->next;
|
||||
}
|
||||
free_failed_list(&head);
|
||||
free_list(resource_list_x, &head);
|
||||
|
||||
goto again;
|
||||
|
||||
|
|
|
@ -1191,6 +1191,11 @@ static inline int pci_set_power_state(struct pci_dev *dev, pci_power_t state)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static inline int pci_wake_from_d3(struct pci_dev *dev, bool enable)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline pci_power_t pci_choose_state(struct pci_dev *dev,
|
||||
pm_message_t state)
|
||||
{
|
||||
|
|
|
@ -2483,6 +2483,9 @@
|
|||
#define PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS 0x1d22
|
||||
#define PCI_DEVICE_ID_INTEL_PATSBURG_LPC_0 0x1d40
|
||||
#define PCI_DEVICE_ID_INTEL_PATSBURG_LPC_1 0x1d41
|
||||
#define PCI_DEVICE_ID_INTEL_DH89XXCC_LPC_MIN 0x2310
|
||||
#define PCI_DEVICE_ID_INTEL_DH89XXCC_LPC_MAX 0x231f
|
||||
#define PCI_DEVICE_ID_INTEL_DH89XXCC_SMBUS 0x2330
|
||||
#define PCI_DEVICE_ID_INTEL_82801AA_0 0x2410
|
||||
#define PCI_DEVICE_ID_INTEL_82801AA_1 0x2411
|
||||
#define PCI_DEVICE_ID_INTEL_82801AA_3 0x2413
|
||||
|
|
Loading…
Reference in New Issue