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:
  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
  • Loading branch information
torvalds committed Mar 18, 2011
2 parents b061c59 + 65d8def commit 9975961
Show file tree
Hide file tree
Showing 14 changed files with 614 additions and 171 deletions.
31 changes: 24 additions & 7 deletions Documentation/ABI/testing/sysfs-bus-pci
Original file line number Diff line number Diff line change
Expand Up @@ -145,9 +145,11 @@ Date: July 2010
Contact: Narendra K <[email protected]>, [email protected]
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.
Expand All @@ -157,12 +159,27 @@ Date: July 2010
Contact: Narendra K <[email protected]>, [email protected]
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 <[email protected]>, [email protected]
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.
15 changes: 6 additions & 9 deletions arch/x86/pci/irq.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down
2 changes: 2 additions & 0 deletions drivers/pci/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -87,3 +87,5 @@ config PCI_IOAPIC
depends on ACPI
depends on HOTPLUG
default y

select NLS if (DMI || ACPI)
3 changes: 2 additions & 1 deletion drivers/pci/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions drivers/pci/hotplug/acpiphp_glue.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down
252 changes: 246 additions & 6 deletions drivers/pci/pci-label.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,13 @@
* by Narendra K <[email protected]>,
* Jordan Hargrave <[email protected]>
*
* 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.
Expand All @@ -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,
Expand Down Expand Up @@ -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
Expand All @@ -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);
}
2 changes: 1 addition & 1 deletion drivers/pci/pci-sysfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
Loading

0 comments on commit 9975961

Please sign in to comment.