shpchprm_acpi.c and pciehprm_acpi.c are nearly identical.
In addition, there are functions in both these files that
are also in acpiphp_glue.c. This patch will remove duplicate
functions from shpchp, pciehp, and acpiphp and move this
functionality to pci_hotplug, as it is not hardware specific.
Get rid of shpchprm* and pciehprm* files since they are no longer needed.
shpchprm_nonacpi.c and pciehprm_nonacpi.c are identical, as well
as shpchprm_legacy.c and can be replaced with a macro.
Signed-off-by: Kristen Carlson Accardi <[email protected]>
---
dev/null |binary
dev/null |binary
drivers/pci/hotplug/pciehprm_acpi.c | 257 ---------------------------------
drivers/pci/hotplug/pciehprm_nonacpi.c | 47 ------
drivers/pci/hotplug/shpchprm_acpi.c | 186 -----------------------
drivers/pci/hotplug/shpchprm_legacy.c | 54 ------
drivers/pci/hotplug/shpchprm_nonacpi.c | 57 -------
drivers/pci/hotplug/Makefile | 17 --
drivers/pci/hotplug/acpi_pcihp.c | 201 +++++++++++++++++++++++++
drivers/pci/hotplug/acpiphp_glue.c | 28 ---
drivers/pci/hotplug/pci_hotplug.h | 17 ++
drivers/pci/hotplug/pciehp.h | 19 +-
drivers/pci/hotplug/pciehp_hpc.c | 69 ++++++++
drivers/pci/hotplug/shpchp.h | 25 +--
drivers/pci/hotplug/shpchp_core.c | 17 ++
13 files changed, 331 insertions(+), 663 deletions(-)
--- 2.6-git-gregkh.orig/drivers/pci/hotplug/Makefile
+++ 2.6-git-gregkh/drivers/pci/hotplug/Makefile
@@ -22,6 +22,9 @@ ifdef CONFIG_HOTPLUG_PCI_CPCI
pci_hotplug-objs += cpci_hotplug_core.o \
cpci_hotplug_pci.o
endif
+ifdef CONFIG_ACPI
+pci_hotplug-objs += acpi_pcihp.o
+endif
cpqphp-objs := cpqphp_core.o \
cpqphp_ctrl.o \
@@ -51,23 +54,9 @@ pciehp-objs := pciehp_core.o \
pciehp_ctrl.o \
pciehp_pci.o \
pciehp_hpc.o
-ifdef CONFIG_ACPI
- pciehp-objs += pciehprm_acpi.o
-else
- pciehp-objs += pciehprm_nonacpi.o
-endif
shpchp-objs := shpchp_core.o \
shpchp_ctrl.o \
shpchp_pci.o \
shpchp_sysfs.o \
shpchp_hpc.o
-ifdef CONFIG_ACPI
- shpchp-objs += shpchprm_acpi.o
-else
- ifdef CONFIG_HOTPLUG_PCI_SHPC_PHPRM_LEGACY
- shpchp-objs += shpchprm_legacy.o
- else
- shpchp-objs += shpchprm_nonacpi.o
- endif
-endif
--- /dev/null
+++ 2.6-git-gregkh/drivers/pci/hotplug/acpi_pcihp.c
@@ -0,0 +1,201 @@
+/*
+ * ACPI related functions for PCI hotplug drivers
+ *
+ * Copyright (C) 2006 Intel Corporation
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Send feedback to <[email protected]>
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <acpi/acpi.h>
+#include <acpi/acpi_bus.h>
+#include <acpi/actypes.h>
+#include "pci_hotplug.h"
+
+#define METHOD_NAME__SUN "_SUN"
+#define METHOD_NAME__HPP "_HPP"
+#define METHOD_NAME_OSHP "OSHP"
+
+u8 * acpi_path_name( acpi_handle handle)
+{
+ acpi_status status;
+ static u8 path_name[ACPI_PATHNAME_MAX];
+ struct acpi_buffer ret_buf = { ACPI_PATHNAME_MAX, path_name };
+
+ memset(path_name, 0, sizeof (path_name));
+ status = acpi_get_name(handle, ACPI_FULL_PATHNAME, &ret_buf);
+
+ if (ACPI_FAILURE(status))
+ return NULL;
+ else
+ return path_name;
+}
+EXPORT_SYMBOL_GPL(acpi_path_name);
+
+static acpi_status
+acpi_run_hpp(acpi_handle handle, struct hotplug_params *hpp)
+{
+ acpi_status status;
+ u8 nui[4];
+ struct acpi_buffer ret_buf = { 0, NULL};
+ union acpi_object *ext_obj, *package;
+ u8 *path_name = acpi_path_name(handle);
+ int i, len = 0;
+
+ /* get _hpp */
+ status = acpi_evaluate_object(handle, METHOD_NAME__HPP, NULL, &ret_buf);
+ switch (status) {
+ case AE_BUFFER_OVERFLOW:
+ ret_buf.pointer = kmalloc (ret_buf.length, GFP_KERNEL);
+ if (!ret_buf.pointer) {
+ printk(KERN_ERR "%s:%s alloc for _HPP fail\n",
+ __FUNCTION__, path_name);
+ return AE_NO_MEMORY;
+ }
+ status = acpi_evaluate_object(handle, METHOD_NAME__HPP,
+ NULL, &ret_buf);
+ if (ACPI_SUCCESS(status))
+ break;
+ default:
+ if (ACPI_FAILURE(status)) {
+ pr_debug("%s:%s _HPP fail=0x%x\n", __FUNCTION__,
+ path_name, status);
+ return status;
+ }
+ }
+
+ ext_obj = (union acpi_object *) ret_buf.pointer;
+ if (ext_obj->type != ACPI_TYPE_PACKAGE) {
+ printk(KERN_ERR "%s:%s _HPP obj not a package\n", __FUNCTION__,
+ path_name);
+ status = AE_ERROR;
+ goto free_and_return;
+ }
+
+ len = ext_obj->package.count;
+ package = (union acpi_object *) ret_buf.pointer;
+ for ( i = 0; (i < len) || (i < 4); i++) {
+ ext_obj = (union acpi_object *) &package->package.elements[i];
+ switch (ext_obj->type) {
+ case ACPI_TYPE_INTEGER:
+ nui[i] = (u8)ext_obj->integer.value;
+ break;
+ default:
+ printk(KERN_ERR "%s:%s _HPP obj type incorrect\n",
+ __FUNCTION__, path_name);
+ status = AE_ERROR;
+ goto free_and_return;
+ }
+ }
+
+ hpp->cache_line_size = nui[0];
+ hpp->latency_timer = nui[1];
+ hpp->enable_serr = nui[2];
+ hpp->enable_perr = nui[3];
+
+ pr_debug(" _HPP: cache_line_size=0x%x\n", hpp->cache_line_size);
+ pr_debug(" _HPP: latency timer =0x%x\n", hpp->latency_timer);
+ pr_debug(" _HPP: enable SERR =0x%x\n", hpp->enable_serr);
+ pr_debug(" _HPP: enable PERR =0x%x\n", hpp->enable_perr);
+
+free_and_return:
+ kfree(ret_buf.pointer);
+ return status;
+}
+
+acpi_status acpi_run_oshp(acpi_handle handle)
+{
+ acpi_status status;
+ u8 *path_name = acpi_path_name(handle);
+
+ /* run OSHP */
+ status = acpi_evaluate_object(handle, METHOD_NAME_OSHP, NULL, NULL);
+ if (ACPI_FAILURE(status)) {
+ printk(KERN_ERR "%s:%s OSHP fails=0x%x\n", __FUNCTION__,
+ path_name, status);
+ } else {
+ pr_debug("%s:%s OSHP passes\n", __FUNCTION__, path_name);
+ }
+ return status;
+}
+EXPORT_SYMBOL_GPL(acpi_run_oshp);
+
+
+
+void acpi_get_hp_params_from_firmware(struct pci_dev *dev,
+ struct hotplug_params *hpp)
+{
+ acpi_status status = AE_NOT_FOUND;
+ struct pci_dev *pdev = dev;
+
+ /*
+ * _HPP settings apply to all child buses, until another _HPP is
+ * encountered. If we don't find an _HPP for the input pci dev,
+ * look for it in the parent device scope since that would apply to
+ * this pci dev. If we don't find any _HPP, use hardcoded defaults
+ */
+ while (pdev && (ACPI_FAILURE(status))) {
+ acpi_handle handle = DEVICE_ACPI_HANDLE(&(pdev->dev));
+ if (!handle)
+ break;
+ status = acpi_run_hpp(handle, hpp);
+ if (!(pdev->bus->parent))
+ break;
+ /* Check if a parent object supports _HPP */
+ pdev = pdev->bus->parent->self;
+ }
+}
+EXPORT_SYMBOL_GPL(acpi_get_hp_params_from_firmware);
+
+
+
+int is_root_bridge(acpi_handle handle)
+{
+ acpi_status status;
+ struct acpi_device_info *info;
+ struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
+ int i;
+
+ status = acpi_get_object_info(handle, &buffer);
+ if (ACPI_SUCCESS(status)) {
+ info = buffer.pointer;
+ if ((info->valid & ACPI_VALID_HID) &&
+ !strcmp(PCI_ROOT_HID_STRING,
+ info->hardware_id.value)) {
+ acpi_os_free(buffer.pointer);
+ return 1;
+ }
+ if (info->valid & ACPI_VALID_CID) {
+ for (i=0; i < info->compatibility_id.count; i++) {
+ if (!strcmp(PCI_ROOT_HID_STRING,
+ info->compatibility_id.id[i].value)) {
+ acpi_os_free(buffer.pointer);
+ return 1;
+ }
+ }
+ }
+ }
+ return 0;
+}
+EXPORT_SYMBOL_GPL(is_root_bridge);
--- 2.6-git-gregkh.orig/drivers/pci/hotplug/acpiphp_glue.c
+++ 2.6-git-gregkh/drivers/pci/hotplug/acpiphp_glue.c
@@ -1408,34 +1408,6 @@ void handle_hotplug_event_func(acpi_hand
}
}
-static int is_root_bridge(acpi_handle handle)
-{
- acpi_status status;
- struct acpi_device_info *info;
- struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
- int i;
-
- status = acpi_get_object_info(handle, &buffer);
- if (ACPI_SUCCESS(status)) {
- info = buffer.pointer;
- if ((info->valid & ACPI_VALID_HID) &&
- !strcmp(PCI_ROOT_HID_STRING,
- info->hardware_id.value)) {
- acpi_os_free(buffer.pointer);
- return 1;
- }
- if (info->valid & ACPI_VALID_CID) {
- for (i=0; i < info->compatibility_id.count; i++) {
- if (!strcmp(PCI_ROOT_HID_STRING,
- info->compatibility_id.id[i].value)) {
- acpi_os_free(buffer.pointer);
- return 1;
- }
- }
- }
- }
- return 0;
-}
static acpi_status
find_root_bridges(acpi_handle handle, u32 lvl, void *context, void **rv)
--- 2.6-git-gregkh.orig/drivers/pci/hotplug/pci_hotplug.h
+++ 2.6-git-gregkh/drivers/pci/hotplug/pci_hotplug.h
@@ -176,5 +176,22 @@ extern int pci_hp_change_slot_info (stru
struct hotplug_slot_info *info);
extern struct subsystem pci_hotplug_slots_subsys;
+struct hotplug_params {
+ u8 cache_line_size;
+ u8 latency_timer;
+ u8 enable_serr;
+ u8 enable_perr;
+};
+
+#ifdef CONFIG_ACPI
+#include <acpi/acpi.h>
+#include <acpi/acpi_bus.h>
+#include <acpi/actypes.h>
+extern acpi_status acpi_run_oshp(acpi_handle handle);
+extern void acpi_get_hp_params_from_firmware(struct pci_dev *dev,
+ struct hotplug_params *hpp);
+extern u8 * acpi_path_name( acpi_handle handle);
+int is_root_bridge(acpi_handle handle);
+#endif
#endif
--- 2.6-git-gregkh.orig/drivers/pci/hotplug/pciehp.h
+++ 2.6-git-gregkh/drivers/pci/hotplug/pciehp.h
@@ -50,12 +50,6 @@ extern int pciehp_force;
#define info(format, arg...) printk(KERN_INFO "%s: " format, MY_NAME , ## arg)
#define warn(format, arg...) printk(KERN_WARNING "%s: " format, MY_NAME , ## arg)
-struct hotplug_params {
- u8 cache_line_size;
- u8 latency_timer;
- u8 enable_serr;
- u8 enable_perr;
-};
struct slot {
struct slot *next;
@@ -192,9 +186,6 @@ extern u8 pciehp_handle_power_fault (u8
/* pci functions */
extern int pciehp_configure_device (struct slot *p_slot);
extern int pciehp_unconfigure_device (struct slot *p_slot);
-extern int pciehp_get_hp_hw_control_from_firmware(struct pci_dev *dev);
-extern void pciehp_get_hp_params_from_firmware(struct pci_dev *dev,
- struct hotplug_params *hpp);
@@ -286,4 +277,14 @@ struct hpc_ops {
int (*check_lnk_status) (struct controller *ctrl);
};
+
+#ifdef CONFIG_ACPI
+#define pciehp_get_hp_hw_control_from_firmware(dev) \
+ pciehp_acpi_get_hp_hw_control_from_firmware(dev)
+#define pciehp_get_hp_params_from_firmware(dev, hpp) \
+ acpi_get_hp_params_from_firmware(dev, hpp)
+#else
+#define pciehp_get_hp_hw_control_from_firmware(dev) 0
+#define acpi_get_hp_params_from_firmware(dev, hpp)
+#endif /* CONFIG_ACPI */
#endif /* _PCIEHP_H */
--- 2.6-git-gregkh.orig/drivers/pci/hotplug/pciehp_hpc.c
+++ 2.6-git-gregkh/drivers/pci/hotplug/pciehp_hpc.c
@@ -38,6 +38,9 @@
#include "../pci.h"
#include "pciehp.h"
+#ifdef CONFIG_ACPI
+#include <linux/pci-acpi.h>
+#endif
#ifdef DEBUG
#define DBG_K_TRACE_ENTRY ((unsigned int)0x00000001) /* On function entry */
@@ -1236,6 +1239,72 @@ static struct hpc_ops pciehp_hpc_ops = {
.check_lnk_status = hpc_check_lnk_status,
};
+#ifdef CONFIG_ACPI
+int pciehp_acpi_get_hp_hw_control_from_firmware(struct pci_dev *dev)
+{
+ acpi_status status;
+ acpi_handle chandle, handle = DEVICE_ACPI_HANDLE(&(dev->dev));
+ struct pci_dev *pdev = dev;
+ struct pci_bus *parent;
+ u8 *path_name;
+
+ /*
+ * Per PCI firmware specification, we should run the ACPI _OSC
+ * method to get control of hotplug hardware before using it.
+ * If an _OSC is missing, we look for an OSHP to do the same thing.
+ * To handle different BIOS behavior, we look for _OSC and OSHP
+ * within the scope of the hotplug controller and its parents, upto
+ * the host bridge under which this controller exists.
+ */
+ while (!handle) {
+ /*
+ * This hotplug controller was not listed in the ACPI name
+ * space at all. Try to get acpi handle of parent pci bus.
+ */
+ if (!pdev || !pdev->bus->parent)
+ break;
+ parent = pdev->bus->parent;
+ dbg("Could not find %s in acpi namespace, trying parent\n",
+ pci_name(pdev));
+ if (!parent->self)
+ /* Parent must be a host bridge */
+ handle = acpi_get_pci_rootbridge_handle(
+ pci_domain_nr(parent),
+ parent->number);
+ else
+ handle = DEVICE_ACPI_HANDLE(
+ &(parent->self->dev));
+ pdev = parent->self;
+ }
+
+ while (handle) {
+ path_name = acpi_path_name(handle);
+ dbg("Trying to get hotplug control for %s \n", path_name);
+ status = pci_osc_control_set(handle,
+ OSC_PCI_EXPRESS_NATIVE_HP_CONTROL);
+ if (status == AE_NOT_FOUND)
+ status = acpi_run_oshp(handle);
+ if (ACPI_SUCCESS(status)) {
+ dbg("Gained control for hotplug HW for pci %s (%s)\n",
+ pci_name(dev), path_name);
+ return 0;
+ }
+ if (is_root_bridge(handle))
+ break;
+ chandle = handle;
+ status = acpi_get_parent(chandle, &handle);
+ if (ACPI_FAILURE(status))
+ break;
+ }
+
+ err("Cannot get control of hotplug hardware for pci %s\n",
+ pci_name(dev));
+ return -1;
+}
+#endif
+
+
+
int pcie_init(struct controller * ctrl, struct pcie_device *dev)
{
struct php_ctlr_state_s *php_ctlr, *p;
--- 2.6-git-gregkh.orig/drivers/pci/hotplug/pciehprm_acpi.c
+++ /dev/null
@@ -1,257 +0,0 @@
-/*
- * PCIEHPRM ACPI: PHP Resource Manager for ACPI platform
- *
- * Copyright (C) 2003-2004 Intel Corporation
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or (at
- * your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
- * NON INFRINGEMENT. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Send feedback to <[email protected]>
- *
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/pci.h>
-#include <linux/acpi.h>
-#include <linux/pci-acpi.h>
-#include <acpi/acpi_bus.h>
-#include <acpi/actypes.h>
-#include "pciehp.h"
-
-#define METHOD_NAME__SUN "_SUN"
-#define METHOD_NAME__HPP "_HPP"
-#define METHOD_NAME_OSHP "OSHP"
-
-static u8 * acpi_path_name( acpi_handle handle)
-{
- acpi_status status;
- static u8 path_name[ACPI_PATHNAME_MAX];
- struct acpi_buffer ret_buf = { ACPI_PATHNAME_MAX, path_name };
-
- memset(path_name, 0, sizeof (path_name));
- status = acpi_get_name(handle, ACPI_FULL_PATHNAME, &ret_buf);
-
- if (ACPI_FAILURE(status))
- return NULL;
- else
- return path_name;
-}
-
-static acpi_status
-acpi_run_hpp(acpi_handle handle, struct hotplug_params *hpp)
-{
- acpi_status status;
- u8 nui[4];
- struct acpi_buffer ret_buf = { 0, NULL};
- union acpi_object *ext_obj, *package;
- u8 *path_name = acpi_path_name(handle);
- int i, len = 0;
-
- /* get _hpp */
- status = acpi_evaluate_object(handle, METHOD_NAME__HPP, NULL, &ret_buf);
- switch (status) {
- case AE_BUFFER_OVERFLOW:
- ret_buf.pointer = kmalloc (ret_buf.length, GFP_KERNEL);
- if (!ret_buf.pointer) {
- err ("%s:%s alloc for _HPP fail\n", __FUNCTION__,
- path_name);
- return AE_NO_MEMORY;
- }
- status = acpi_evaluate_object(handle, METHOD_NAME__HPP,
- NULL, &ret_buf);
- if (ACPI_SUCCESS(status))
- break;
- default:
- if (ACPI_FAILURE(status)) {
- dbg("%s:%s _HPP fail=0x%x\n", __FUNCTION__,
- path_name, status);
- return status;
- }
- }
-
- ext_obj = (union acpi_object *) ret_buf.pointer;
- if (ext_obj->type != ACPI_TYPE_PACKAGE) {
- err ("%s:%s _HPP obj not a package\n", __FUNCTION__,
- path_name);
- status = AE_ERROR;
- goto free_and_return;
- }
-
- len = ext_obj->package.count;
- package = (union acpi_object *) ret_buf.pointer;
- for ( i = 0; (i < len) || (i < 4); i++) {
- ext_obj = (union acpi_object *) &package->package.elements[i];
- switch (ext_obj->type) {
- case ACPI_TYPE_INTEGER:
- nui[i] = (u8)ext_obj->integer.value;
- break;
- default:
- err ("%s:%s _HPP obj type incorrect\n", __FUNCTION__,
- path_name);
- status = AE_ERROR;
- goto free_and_return;
- }
- }
-
- hpp->cache_line_size = nui[0];
- hpp->latency_timer = nui[1];
- hpp->enable_serr = nui[2];
- hpp->enable_perr = nui[3];
-
- dbg(" _HPP: cache_line_size=0x%x\n", hpp->cache_line_size);
- dbg(" _HPP: latency timer =0x%x\n", hpp->latency_timer);
- dbg(" _HPP: enable SERR =0x%x\n", hpp->enable_serr);
- dbg(" _HPP: enable PERR =0x%x\n", hpp->enable_perr);
-
-free_and_return:
- kfree(ret_buf.pointer);
- return status;
-}
-
-static acpi_status acpi_run_oshp(acpi_handle handle)
-{
- acpi_status status;
- u8 *path_name = acpi_path_name(handle);
-
- /* run OSHP */
- status = acpi_evaluate_object(handle, METHOD_NAME_OSHP, NULL, NULL);
- if (ACPI_FAILURE(status)) {
- dbg("%s:%s OSHP fails=0x%x\n", __FUNCTION__, path_name,
- status);
- } else {
- dbg("%s:%s OSHP passes\n", __FUNCTION__, path_name);
- }
- return status;
-}
-
-static int is_root_bridge(acpi_handle handle)
-{
- acpi_status status;
- struct acpi_device_info *info;
- struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
- int i;
-
- status = acpi_get_object_info(handle, &buffer);
- if (ACPI_SUCCESS(status)) {
- info = buffer.pointer;
- if ((info->valid & ACPI_VALID_HID) &&
- !strcmp(PCI_ROOT_HID_STRING,
- info->hardware_id.value)) {
- acpi_os_free(buffer.pointer);
- return 1;
- }
- if (info->valid & ACPI_VALID_CID) {
- for (i=0; i < info->compatibility_id.count; i++) {
- if (!strcmp(PCI_ROOT_HID_STRING,
- info->compatibility_id.id[i].value)) {
- acpi_os_free(buffer.pointer);
- return 1;
- }
- }
- }
- }
- return 0;
-}
-
-int pciehp_get_hp_hw_control_from_firmware(struct pci_dev *dev)
-{
- acpi_status status;
- acpi_handle chandle, handle = DEVICE_ACPI_HANDLE(&(dev->dev));
- struct pci_dev *pdev = dev;
- struct pci_bus *parent;
- u8 *path_name;
-
- /*
- * Per PCI firmware specification, we should run the ACPI _OSC
- * method to get control of hotplug hardware before using it.
- * If an _OSC is missing, we look for an OSHP to do the same thing.
- * To handle different BIOS behavior, we look for _OSC and OSHP
- * within the scope of the hotplug controller and its parents, upto
- * the host bridge under which this controller exists.
- */
- while (!handle) {
- /*
- * This hotplug controller was not listed in the ACPI name
- * space at all. Try to get acpi handle of parent pci bus.
- */
- if (!pdev || !pdev->bus->parent)
- break;
- parent = pdev->bus->parent;
- dbg("Could not find %s in acpi namespace, trying parent\n",
- pci_name(pdev));
- if (!parent->self)
- /* Parent must be a host bridge */
- handle = acpi_get_pci_rootbridge_handle(
- pci_domain_nr(parent),
- parent->number);
- else
- handle = DEVICE_ACPI_HANDLE(
- &(parent->self->dev));
- pdev = parent->self;
- }
-
- while (handle) {
- path_name = acpi_path_name(handle);
- dbg("Trying to get hotplug control for %s \n", path_name);
- status = pci_osc_control_set(handle,
- OSC_PCI_EXPRESS_NATIVE_HP_CONTROL);
- if (status == AE_NOT_FOUND)
- status = acpi_run_oshp(handle);
- if (ACPI_SUCCESS(status)) {
- dbg("Gained control for hotplug HW for pci %s (%s)\n",
- pci_name(dev), path_name);
- return 0;
- }
- if (is_root_bridge(handle))
- break;
- chandle = handle;
- status = acpi_get_parent(chandle, &handle);
- if (ACPI_FAILURE(status))
- break;
- }
-
- err("Cannot get control of hotplug hardware for pci %s\n",
- pci_name(dev));
- return -1;
-}
-
-void pciehp_get_hp_params_from_firmware(struct pci_dev *dev,
- struct hotplug_params *hpp)
-{
- acpi_status status = AE_NOT_FOUND;
- struct pci_dev *pdev = dev;
-
- /*
- * _HPP settings apply to all child buses, until another _HPP is
- * encountered. If we don't find an _HPP for the input pci dev,
- * look for it in the parent device scope since that would apply to
- * this pci dev. If we don't find any _HPP, use hardcoded defaults
- */
- while (pdev && (ACPI_FAILURE(status))) {
- acpi_handle handle = DEVICE_ACPI_HANDLE(&(pdev->dev));
- if (!handle)
- break;
- status = acpi_run_hpp(handle, hpp);
- if (!(pdev->bus->parent))
- break;
- /* Check if a parent object supports _HPP */
- pdev = pdev->bus->parent->self;
- }
-}
-
--- 2.6-git-gregkh.orig/drivers/pci/hotplug/pciehprm_nonacpi.c
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * PCIEHPRM NONACPI: PHP Resource Manager for Non-ACPI/Legacy platform
- *
- * Copyright (C) 1995,2001 Compaq Computer Corporation
- * Copyright (C) 2001 Greg Kroah-Hartman ([email protected])
- * Copyright (C) 2001 IBM Corp.
- * Copyright (C) 2003-2004 Intel Corporation
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or (at
- * your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
- * NON INFRINGEMENT. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Send feedback to <[email protected]>, <[email protected]>
- *
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/sched.h>
-#include <linux/pci.h>
-#include <linux/slab.h>
-#include "pciehp.h"
-
-void pciehp_get_hp_params_from_firmware(struct pci_dev *dev,
- struct hotplug_params *hpp)
-{
- return;
-}
-
-int pciehp_get_hp_hw_control_from_firmware(struct pci_dev *dev)
-{
- return 0;
-}
--- 2.6-git-gregkh.orig/drivers/pci/hotplug/shpchp.h
+++ 2.6-git-gregkh/drivers/pci/hotplug/shpchp.h
@@ -106,12 +106,6 @@ struct controller {
volatile int cmd_busy;
};
-struct hotplug_params {
- u8 cache_line_size;
- u8 latency_timer;
- u8 enable_serr;
- u8 enable_perr;
-};
/* Define AMD SHPC ID */
#define PCI_DEVICE_ID_AMD_GOLAM_7450 0x7450
@@ -193,15 +187,24 @@ extern u8 shpchp_handle_power_fault(u8 h
extern int shpchp_save_config(struct controller *ctrl, int busnumber, int num_ctlr_slots, int first_device_num);
extern int shpchp_configure_device(struct slot *p_slot);
extern int shpchp_unconfigure_device(struct slot *p_slot);
-extern void get_hp_hw_control_from_firmware(struct pci_dev *dev);
-extern void get_hp_params_from_firmware(struct pci_dev *dev,
- struct hotplug_params *hpp);
-extern int shpchprm_get_physical_slot_number(struct controller *ctrl,
- u32 *sun, u8 busnum, u8 devnum);
extern void shpchp_remove_ctrl_files(struct controller *ctrl);
extern void cleanup_slots(struct controller *ctrl);
extern void queue_pushbutton_work(void *data);
+
+#ifdef CONFIG_ACPI
+#define get_hp_params_from_firmware(dev, hpp) \
+ acpi_get_hp_params_from_firmware(dev, hpp)
+#define get_hp_hw_control_from_firmware(pdev) \
+ do { \
+ if (DEVICE_ACPI_HANDLE(&(pdev->dev))) \
+ acpi_run_oshp(DEVICE_ACPI_HANDLE(&(pdev->dev))); \
+ } while (0)
+#else
+#define get_hp_params_from_firmware(dev, hpp)
+#define get_hp_hw_control_from_firmware(dev)
+#endif
+
struct ctrl_reg {
volatile u32 base_offset;
volatile u32 slot_avail1;
--- 2.6-git-gregkh.orig/drivers/pci/hotplug/shpchp_core.c
+++ 2.6-git-gregkh/drivers/pci/hotplug/shpchp_core.c
@@ -104,6 +104,23 @@ static void make_slot_name(struct slot *
slot->bus, slot->number);
}
+
+
+
+static int
+shpchprm_get_physical_slot_number(struct controller *ctrl, u32 *sun,
+ u8 busnum, u8 devnum)
+{
+ int offset = devnum - ctrl->slot_device_offset;
+
+ dbg("%s: ctrl->slot_num_inc %d, offset %d\n", __FUNCTION__,
+ ctrl->slot_num_inc, offset);
+ *sun = (u8) (ctrl->first_slot + ctrl->slot_num_inc *offset);
+ return 0;
+}
+
+
+
static int init_slots(struct controller *ctrl)
{
struct slot *slot;
--- 2.6-git-gregkh.orig/drivers/pci/hotplug/shpchprm_acpi.c
+++ /dev/null
@@ -1,186 +0,0 @@
-/*
- * SHPCHPRM ACPI: PHP Resource Manager for ACPI platform
- *
- * Copyright (C) 2003-2004 Intel Corporation
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or (at
- * your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
- * NON INFRINGEMENT. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Send feedback to <[email protected]>
- *
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/pci.h>
-#include <acpi/acpi.h>
-#include <acpi/acpi_bus.h>
-#include <acpi/actypes.h>
-#include "shpchp.h"
-
-#define METHOD_NAME__SUN "_SUN"
-#define METHOD_NAME__HPP "_HPP"
-#define METHOD_NAME_OSHP "OSHP"
-
-static u8 * acpi_path_name( acpi_handle handle)
-{
- acpi_status status;
- static u8 path_name[ACPI_PATHNAME_MAX];
- struct acpi_buffer ret_buf = { ACPI_PATHNAME_MAX, path_name };
-
- memset(path_name, 0, sizeof (path_name));
- status = acpi_get_name(handle, ACPI_FULL_PATHNAME, &ret_buf);
-
- if (ACPI_FAILURE(status))
- return NULL;
- else
- return path_name;
-}
-
-static acpi_status
-acpi_run_hpp(acpi_handle handle, struct hotplug_params *hpp)
-{
- acpi_status status;
- u8 nui[4];
- struct acpi_buffer ret_buf = { 0, NULL};
- union acpi_object *ext_obj, *package;
- u8 *path_name = acpi_path_name(handle);
- int i, len = 0;
-
- /* get _hpp */
- status = acpi_evaluate_object(handle, METHOD_NAME__HPP, NULL, &ret_buf);
- switch (status) {
- case AE_BUFFER_OVERFLOW:
- ret_buf.pointer = kmalloc (ret_buf.length, GFP_KERNEL);
- if (!ret_buf.pointer) {
- err ("%s:%s alloc for _HPP fail\n", __FUNCTION__,
- path_name);
- return AE_NO_MEMORY;
- }
- status = acpi_evaluate_object(handle, METHOD_NAME__HPP,
- NULL, &ret_buf);
- if (ACPI_SUCCESS(status))
- break;
- default:
- if (ACPI_FAILURE(status)) {
- dbg("%s:%s _HPP fail=0x%x\n", __FUNCTION__,
- path_name, status);
- return status;
- }
- }
-
- ext_obj = (union acpi_object *) ret_buf.pointer;
- if (ext_obj->type != ACPI_TYPE_PACKAGE) {
- err ("%s:%s _HPP obj not a package\n", __FUNCTION__,
- path_name);
- status = AE_ERROR;
- goto free_and_return;
- }
-
- len = ext_obj->package.count;
- package = (union acpi_object *) ret_buf.pointer;
- for ( i = 0; (i < len) || (i < 4); i++) {
- ext_obj = (union acpi_object *) &package->package.elements[i];
- switch (ext_obj->type) {
- case ACPI_TYPE_INTEGER:
- nui[i] = (u8)ext_obj->integer.value;
- break;
- default:
- err ("%s:%s _HPP obj type incorrect\n", __FUNCTION__,
- path_name);
- status = AE_ERROR;
- goto free_and_return;
- }
- }
-
- hpp->cache_line_size = nui[0];
- hpp->latency_timer = nui[1];
- hpp->enable_serr = nui[2];
- hpp->enable_perr = nui[3];
-
- dbg(" _HPP: cache_line_size=0x%x\n", hpp->cache_line_size);
- dbg(" _HPP: latency timer =0x%x\n", hpp->latency_timer);
- dbg(" _HPP: enable SERR =0x%x\n", hpp->enable_serr);
- dbg(" _HPP: enable PERR =0x%x\n", hpp->enable_perr);
-
-free_and_return:
- kfree(ret_buf.pointer);
- return status;
-}
-
-static void acpi_run_oshp(acpi_handle handle)
-{
- acpi_status status;
- u8 *path_name = acpi_path_name(handle);
-
- /* run OSHP */
- status = acpi_evaluate_object(handle, METHOD_NAME_OSHP, NULL, NULL);
- if (ACPI_FAILURE(status)) {
- err("%s:%s OSHP fails=0x%x\n", __FUNCTION__, path_name,
- status);
- } else {
- dbg("%s:%s OSHP passes\n", __FUNCTION__, path_name);
- }
-}
-
-int shpchprm_get_physical_slot_number(struct controller *ctrl, u32 *sun, u8 busnum, u8 devnum)
-{
- int offset = devnum - ctrl->slot_device_offset;
-
- dbg("%s: ctrl->slot_num_inc %d, offset %d\n", __FUNCTION__, ctrl->slot_num_inc, offset);
- *sun = (u8) (ctrl->first_slot + ctrl->slot_num_inc *offset);
- return 0;
-}
-
-void get_hp_hw_control_from_firmware(struct pci_dev *dev)
-{
- /*
- * OSHP is an optional ACPI firmware control method. If present,
- * we need to run it to inform BIOS that we will control SHPC
- * hardware from now on.
- */
- acpi_handle handle = DEVICE_ACPI_HANDLE(&(dev->dev));
- if (!handle)
- return;
- acpi_run_oshp(handle);
-}
-
-void get_hp_params_from_firmware(struct pci_dev *dev,
- struct hotplug_params *hpp)
-{
- acpi_status status = AE_NOT_FOUND;
- struct pci_dev *pdev = dev;
-
- /*
- * _HPP settings apply to all child buses, until another _HPP is
- * encountered. If we don't find an _HPP for the input pci dev,
- * look for it in the parent device scope since that would apply to
- * this pci dev. If we don't find any _HPP, use hardcoded defaults
- */
- while (pdev && (ACPI_FAILURE(status))) {
- acpi_handle handle = DEVICE_ACPI_HANDLE(&(pdev->dev));
- if (!handle)
- break;
- status = acpi_run_hpp(handle, hpp);
- if (!(pdev->bus->parent))
- break;
- /* Check if a parent object supports _HPP */
- pdev = pdev->bus->parent->self;
- }
-}
-
--- 2.6-git-gregkh.orig/drivers/pci/hotplug/shpchprm_legacy.c
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * SHPCHPRM Legacy: PHP Resource Manager for Non-ACPI/Legacy platform
- *
- * Copyright (C) 1995,2001 Compaq Computer Corporation
- * Copyright (C) 2001 Greg Kroah-Hartman ([email protected])
- * Copyright (C) 2001 IBM Corp.
- * Copyright (C) 2003-2004 Intel Corporation
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or (at
- * your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
- * NON INFRINGEMENT. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Send feedback to <[email protected]>,<[email protected]>
- *
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/pci.h>
-#include "shpchp.h"
-
-int shpchprm_get_physical_slot_number(struct controller *ctrl, u32 *sun, u8 busnum, u8 devnum)
-{
- int offset = devnum - ctrl->slot_device_offset;
-
- *sun = (u8) (ctrl->first_slot + ctrl->slot_num_inc * offset);
- return 0;
-}
-
-void get_hp_params_from_firmware(struct pci_dev *dev,
- struct hotplug_params *hpp)
-{
- return;
-}
-
-void get_hp_hw_control_from_firmware(struct pci_dev *dev)
-{
- return;
-}
-
--- 2.6-git-gregkh.orig/drivers/pci/hotplug/shpchprm_nonacpi.c
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * SHPCHPRM NONACPI: PHP Resource Manager for Non-ACPI/Legacy platform
- *
- * Copyright (C) 1995,2001 Compaq Computer Corporation
- * Copyright (C) 2001 Greg Kroah-Hartman ([email protected])
- * Copyright (C) 2001 IBM Corp.
- * Copyright (C) 2003-2004 Intel Corporation
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or (at
- * your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
- * NON INFRINGEMENT. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Send feedback to <[email protected]>, <[email protected]>
- *
- */
-
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/pci.h>
-#include <linux/slab.h>
-
-#include "shpchp.h"
-
-int shpchprm_get_physical_slot_number(struct controller *ctrl, u32 *sun, u8 busnum, u8 devnum)
-{
- int offset = devnum - ctrl->slot_device_offset;
-
- dbg("%s: ctrl->slot_num_inc %d, offset %d\n", __FUNCTION__, ctrl->slot_num_inc, offset);
- *sun = (u8) (ctrl->first_slot + ctrl->slot_num_inc * offset);
- return 0;
-}
-
-void get_hp_params_from_firmware(struct pci_dev *dev,
- struct hotplug_params *hpp)
-{
- return;
-}
-
-void get_hp_hw_control_from_firmware(struct pci_dev *dev)
-{
- return;
-}
On Tue, Feb 28, 2006 at 04:46:57PM -0800, Kristen Accardi wrote:
> shpchprm_acpi.c and pciehprm_acpi.c are nearly identical.
> In addition, there are functions in both these files that
> are also in acpiphp_glue.c. This patch will remove duplicate
> functions from shpchp, pciehp, and acpiphp and move this
> functionality to pci_hotplug, as it is not hardware specific.
> Get rid of shpchprm* and pciehprm* files since they are no longer needed.
> shpchprm_nonacpi.c and pciehprm_nonacpi.c are identical, as well
> as shpchprm_legacy.c and can be replaced with a macro.
Looks good, only a minor comment:
> +u8 * acpi_path_name( acpi_handle handle)
Funky spacing here.
> +int is_root_bridge(acpi_handle handle)
> +{
> + acpi_status status;
> + struct acpi_device_info *info;
> + struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
> + int i;
> +
> + status = acpi_get_object_info(handle, &buffer);
> + if (ACPI_SUCCESS(status)) {
> + info = buffer.pointer;
> + if ((info->valid & ACPI_VALID_HID) &&
> + !strcmp(PCI_ROOT_HID_STRING,
> + info->hardware_id.value)) {
> + acpi_os_free(buffer.pointer);
> + return 1;
> + }
> + if (info->valid & ACPI_VALID_CID) {
> + for (i=0; i < info->compatibility_id.count; i++) {
> + if (!strcmp(PCI_ROOT_HID_STRING,
> + info->compatibility_id.id[i].value)) {
> + acpi_os_free(buffer.pointer);
> + return 1;
> + }
> + }
> + }
> + }
> + return 0;
> +}
> +EXPORT_SYMBOL_GPL(is_root_bridge);
The name "is_root_bridge" is pretty generic. Especially as it wants an
acpi handle. "acpi_is_root_bridge" perhaps?
thanks,
greg k-h
On Tue, 28 Feb 2006 16:46:57 -0800 Kristen Accardi wrote:
> shpchprm_acpi.c and pciehprm_acpi.c are nearly identical.
> In addition, there are functions in both these files that
> are also in acpiphp_glue.c. This patch will remove duplicate
> functions from shpchp, pciehp, and acpiphp and move this
> functionality to pci_hotplug, as it is not hardware specific.
> Get rid of shpchprm* and pciehprm* files since they are no longer needed.
> shpchprm_nonacpi.c and pciehprm_nonacpi.c are identical, as well
> as shpchprm_legacy.c and can be replaced with a macro.
>
> Signed-off-by: Kristen Carlson Accardi <[email protected]>
> ---
> 13 files changed, 331 insertions(+), 663 deletions(-)
> --- /dev/null
> +++ 2.6-git-gregkh/drivers/pci/hotplug/acpi_pcihp.c
> @@ -0,0 +1,201 @@
> +/*
> + * ACPI related functions for PCI hotplug drivers
> + *
> + * Copyright (C) 2006 Intel Corporation
> + *
> + * All rights reserved.
> + *
> + * Send feedback to <[email protected]>
> + *
> + */
> +
> +#include <linux/module.h>
> +#include <linux/kernel.h>
> +#include <linux/types.h>
> +#include <linux/pci.h>
> +#include <acpi/acpi.h>
> +#include <acpi/acpi_bus.h>
> +#include <acpi/actypes.h>
> +#include "pci_hotplug.h"
> +
> +#define METHOD_NAME__SUN "_SUN"
> +#define METHOD_NAME__HPP "_HPP"
> +#define METHOD_NAME_OSHP "OSHP"
> +
> +u8 * acpi_path_name( acpi_handle handle)
odd spacing.
> +{
> + acpi_status status;
> + static u8 path_name[ACPI_PATHNAME_MAX];
> + struct acpi_buffer ret_buf = { ACPI_PATHNAME_MAX, path_name };
> +
> + memset(path_name, 0, sizeof (path_name));
> + status = acpi_get_name(handle, ACPI_FULL_PATHNAME, &ret_buf);
> +
> + if (ACPI_FAILURE(status))
> + return NULL;
> + else
> + return path_name;
> +}
> +EXPORT_SYMBOL_GPL(acpi_path_name);
Can acpi_path_name() be used safely by more than 1 caller?
Previously it was duplicated, so the return <path_name> was duplicated,
which made it multiple-caller safe. Now it seems that in a worst-case
scenario, one caller's path could be clobbered by another. ?
or maybe (probably) caller 1 is finished with it before caller 2
can ever run. ?
> +acpi_status acpi_run_oshp(acpi_handle handle)
> +{
> + acpi_status status;
> + u8 *path_name = acpi_path_name(handle);
> +
> + /* run OSHP */
> + status = acpi_evaluate_object(handle, METHOD_NAME_OSHP, NULL, NULL);
> + if (ACPI_FAILURE(status)) {
> + printk(KERN_ERR "%s:%s OSHP fails=0x%x\n", __FUNCTION__,
> + path_name, status);
> + } else {
> + pr_debug("%s:%s OSHP passes\n", __FUNCTION__, path_name);
{} braces not needed here (on the if nor the else).
> + }
> + return status;
> +}
> +EXPORT_SYMBOL_GPL(acpi_run_oshp);
A little kernel-doc for non-static (non-private) functions would
be a good thing.
> +int is_root_bridge(acpi_handle handle)
> +{
> + acpi_status status;
> + struct acpi_device_info *info;
> + struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
> + int i;
> +
> + status = acpi_get_object_info(handle, &buffer);
> + if (ACPI_SUCCESS(status)) {
> + info = buffer.pointer;
> + if ((info->valid & ACPI_VALID_HID) &&
> + !strcmp(PCI_ROOT_HID_STRING,
> + info->hardware_id.value)) {
> + acpi_os_free(buffer.pointer);
> + return 1;
> + }
> + if (info->valid & ACPI_VALID_CID) {
> + for (i=0; i < info->compatibility_id.count; i++) {
> + if (!strcmp(PCI_ROOT_HID_STRING,
> + info->compatibility_id.id[i].value)) {
> + acpi_os_free(buffer.pointer);
> + return 1;
> + }
> + }
> + }
> + }
> + return 0;
> +}
> +EXPORT_SYMBOL_GPL(is_root_bridge);
> --- 2.6-git-gregkh.orig/drivers/pci/hotplug/pci_hotplug.h
> +++ 2.6-git-gregkh/drivers/pci/hotplug/pci_hotplug.h
> @@ -176,5 +176,22 @@ extern int pci_hp_change_slot_info (stru
> +
> +#ifdef CONFIG_ACPI
> +#include <acpi/acpi.h>
> +#include <acpi/acpi_bus.h>
> +#include <acpi/actypes.h>
> +extern acpi_status acpi_run_oshp(acpi_handle handle);
> +extern void acpi_get_hp_params_from_firmware(struct pci_dev *dev,
> + struct hotplug_params *hpp);
> +extern u8 * acpi_path_name( acpi_handle handle);
odd spacing (again).
> +int is_root_bridge(acpi_handle handle);
> +#endif
> #endif
>
> --- 2.6-git-gregkh.orig/drivers/pci/hotplug/pciehp_hpc.c
> +++ 2.6-git-gregkh/drivers/pci/hotplug/pciehp_hpc.c
> @@ -38,6 +38,9 @@
>
> #include "../pci.h"
> #include "pciehp.h"
> +#ifdef CONFIG_ACPI
> +#include <linux/pci-acpi.h>
> +#endif
Does this driver work with or without ACPI, depending on CONFIG_ACPI?
We don't usually bracket #includes in .c files with ifdef/endif.
> --- 2.6-git-gregkh.orig/drivers/pci/hotplug/shpchp.h
> +++ 2.6-git-gregkh/drivers/pci/hotplug/shpchp.h
> @@ -193,15 +187,24 @@ extern u8 shpchp_handle_power_fault(u8 h
>
> +
> +#ifdef CONFIG_ACPI
> +#define get_hp_params_from_firmware(dev, hpp) \
> + acpi_get_hp_params_from_firmware(dev, hpp)
> +#define get_hp_hw_control_from_firmware(pdev) \
> + do { \
> + if (DEVICE_ACPI_HANDLE(&(pdev->dev))) \
> + acpi_run_oshp(DEVICE_ACPI_HANDLE(&(pdev->dev))); \
> + } while (0)
> +#else
> +#define get_hp_params_from_firmware(dev, hpp)
> +#define get_hp_hw_control_from_firmware(dev)
usually empty macros are like so in Linux:
#define foo(bar) do { } while(0)
> +#endif
> +
---
~Randy
Hi Kristen,
This looks very nice to me!
Here is one comment.
> +int is_root_bridge(acpi_handle handle)
> +{
> + acpi_status status;
> + struct acpi_device_info *info;
> + struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
> + int i;
> +
> + status = acpi_get_object_info(handle, &buffer);
> + if (ACPI_SUCCESS(status)) {
> + info = buffer.pointer;
> + if ((info->valid & ACPI_VALID_HID) &&
> + !strcmp(PCI_ROOT_HID_STRING,
> + info->hardware_id.value)) {
> + acpi_os_free(buffer.pointer);
> + return 1;
> + }
> + if (info->valid & ACPI_VALID_CID) {
> + for (i=0; i < info->compatibility_id.count; i++) {
> + if (!strcmp(PCI_ROOT_HID_STRING,
> + info->compatibility_id.id[i].value)) {
> + acpi_os_free(buffer.pointer);
> + return 1;
> + }
> + }
> + }
> + }
> + return 0;
> +}
> +EXPORT_SYMBOL_GPL(is_root_bridge);
I think this seems to leak memory (buffer.pointer), though
I guess you just copy and paste from the original code. I think
we need to free buffer.pointer whenever acpi_get_object_info()
returns as success.
Thanks,
Kenji Kaneshige
Kristen Accardi wrote:
> shpchprm_acpi.c and pciehprm_acpi.c are nearly identical.
> In addition, there are functions in both these files that
> are also in acpiphp_glue.c. This patch will remove duplicate
> functions from shpchp, pciehp, and acpiphp and move this
> functionality to pci_hotplug, as it is not hardware specific.
> Get rid of shpchprm* and pciehprm* files since they are no longer needed.
> shpchprm_nonacpi.c and pciehprm_nonacpi.c are identical, as well
> as shpchprm_legacy.c and can be replaced with a macro.
>
> Signed-off-by: Kristen Carlson Accardi <[email protected]>
> ---
> dev/null |binary
> dev/null |binary
> drivers/pci/hotplug/pciehprm_acpi.c | 257 ---------------------------------
> drivers/pci/hotplug/pciehprm_nonacpi.c | 47 ------
> drivers/pci/hotplug/shpchprm_acpi.c | 186 -----------------------
> drivers/pci/hotplug/shpchprm_legacy.c | 54 ------
> drivers/pci/hotplug/shpchprm_nonacpi.c | 57 -------
> drivers/pci/hotplug/Makefile | 17 --
> drivers/pci/hotplug/acpi_pcihp.c | 201 +++++++++++++++++++++++++
> drivers/pci/hotplug/acpiphp_glue.c | 28 ---
> drivers/pci/hotplug/pci_hotplug.h | 17 ++
> drivers/pci/hotplug/pciehp.h | 19 +-
> drivers/pci/hotplug/pciehp_hpc.c | 69 ++++++++
> drivers/pci/hotplug/shpchp.h | 25 +--
> drivers/pci/hotplug/shpchp_core.c | 17 ++
> 13 files changed, 331 insertions(+), 663 deletions(-)
>
> --- 2.6-git-gregkh.orig/drivers/pci/hotplug/Makefile
> +++ 2.6-git-gregkh/drivers/pci/hotplug/Makefile
> @@ -22,6 +22,9 @@ ifdef CONFIG_HOTPLUG_PCI_CPCI
> pci_hotplug-objs += cpci_hotplug_core.o \
> cpci_hotplug_pci.o
> endif
> +ifdef CONFIG_ACPI
> +pci_hotplug-objs += acpi_pcihp.o
> +endif
>
> cpqphp-objs := cpqphp_core.o \
> cpqphp_ctrl.o \
> @@ -51,23 +54,9 @@ pciehp-objs := pciehp_core.o \
> pciehp_ctrl.o \
> pciehp_pci.o \
> pciehp_hpc.o
> -ifdef CONFIG_ACPI
> - pciehp-objs += pciehprm_acpi.o
> -else
> - pciehp-objs += pciehprm_nonacpi.o
> -endif
>
> shpchp-objs := shpchp_core.o \
> shpchp_ctrl.o \
> shpchp_pci.o \
> shpchp_sysfs.o \
> shpchp_hpc.o
> -ifdef CONFIG_ACPI
> - shpchp-objs += shpchprm_acpi.o
> -else
> - ifdef CONFIG_HOTPLUG_PCI_SHPC_PHPRM_LEGACY
> - shpchp-objs += shpchprm_legacy.o
> - else
> - shpchp-objs += shpchprm_nonacpi.o
> - endif
> -endif
> --- /dev/null
> +++ 2.6-git-gregkh/drivers/pci/hotplug/acpi_pcihp.c
> @@ -0,0 +1,201 @@
> +/*
> + * ACPI related functions for PCI hotplug drivers
> + *
> + * Copyright (C) 2006 Intel Corporation
> + *
> + * All rights reserved.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or (at
> + * your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful, but
> + * WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
> + * NON INFRINGEMENT. See the GNU General Public License for more
> + * details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
> + *
> + * Send feedback to <[email protected]>
> + *
> + */
> +
> +#include <linux/module.h>
> +#include <linux/kernel.h>
> +#include <linux/types.h>
> +#include <linux/pci.h>
> +#include <acpi/acpi.h>
> +#include <acpi/acpi_bus.h>
> +#include <acpi/actypes.h>
> +#include "pci_hotplug.h"
> +
> +#define METHOD_NAME__SUN "_SUN"
> +#define METHOD_NAME__HPP "_HPP"
> +#define METHOD_NAME_OSHP "OSHP"
> +
> +u8 * acpi_path_name( acpi_handle handle)
> +{
> + acpi_status status;
> + static u8 path_name[ACPI_PATHNAME_MAX];
> + struct acpi_buffer ret_buf = { ACPI_PATHNAME_MAX, path_name };
> +
> + memset(path_name, 0, sizeof (path_name));
> + status = acpi_get_name(handle, ACPI_FULL_PATHNAME, &ret_buf);
> +
> + if (ACPI_FAILURE(status))
> + return NULL;
> + else
> + return path_name;
> +}
> +EXPORT_SYMBOL_GPL(acpi_path_name);
> +
> +static acpi_status
> +acpi_run_hpp(acpi_handle handle, struct hotplug_params *hpp)
> +{
> + acpi_status status;
> + u8 nui[4];
> + struct acpi_buffer ret_buf = { 0, NULL};
> + union acpi_object *ext_obj, *package;
> + u8 *path_name = acpi_path_name(handle);
> + int i, len = 0;
> +
> + /* get _hpp */
> + status = acpi_evaluate_object(handle, METHOD_NAME__HPP, NULL, &ret_buf);
> + switch (status) {
> + case AE_BUFFER_OVERFLOW:
> + ret_buf.pointer = kmalloc (ret_buf.length, GFP_KERNEL);
> + if (!ret_buf.pointer) {
> + printk(KERN_ERR "%s:%s alloc for _HPP fail\n",
> + __FUNCTION__, path_name);
> + return AE_NO_MEMORY;
> + }
> + status = acpi_evaluate_object(handle, METHOD_NAME__HPP,
> + NULL, &ret_buf);
> + if (ACPI_SUCCESS(status))
> + break;
> + default:
> + if (ACPI_FAILURE(status)) {
> + pr_debug("%s:%s _HPP fail=0x%x\n", __FUNCTION__,
> + path_name, status);
> + return status;
> + }
> + }
> +
> + ext_obj = (union acpi_object *) ret_buf.pointer;
> + if (ext_obj->type != ACPI_TYPE_PACKAGE) {
> + printk(KERN_ERR "%s:%s _HPP obj not a package\n", __FUNCTION__,
> + path_name);
> + status = AE_ERROR;
> + goto free_and_return;
> + }
> +
> + len = ext_obj->package.count;
> + package = (union acpi_object *) ret_buf.pointer;
> + for ( i = 0; (i < len) || (i < 4); i++) {
> + ext_obj = (union acpi_object *) &package->package.elements[i];
> + switch (ext_obj->type) {
> + case ACPI_TYPE_INTEGER:
> + nui[i] = (u8)ext_obj->integer.value;
> + break;
> + default:
> + printk(KERN_ERR "%s:%s _HPP obj type incorrect\n",
> + __FUNCTION__, path_name);
> + status = AE_ERROR;
> + goto free_and_return;
> + }
> + }
> +
> + hpp->cache_line_size = nui[0];
> + hpp->latency_timer = nui[1];
> + hpp->enable_serr = nui[2];
> + hpp->enable_perr = nui[3];
> +
> + pr_debug(" _HPP: cache_line_size=0x%x\n", hpp->cache_line_size);
> + pr_debug(" _HPP: latency timer =0x%x\n", hpp->latency_timer);
> + pr_debug(" _HPP: enable SERR =0x%x\n", hpp->enable_serr);
> + pr_debug(" _HPP: enable PERR =0x%x\n", hpp->enable_perr);
> +
> +free_and_return:
> + kfree(ret_buf.pointer);
> + return status;
> +}
> +
> +acpi_status acpi_run_oshp(acpi_handle handle)
> +{
> + acpi_status status;
> + u8 *path_name = acpi_path_name(handle);
> +
> + /* run OSHP */
> + status = acpi_evaluate_object(handle, METHOD_NAME_OSHP, NULL, NULL);
> + if (ACPI_FAILURE(status)) {
> + printk(KERN_ERR "%s:%s OSHP fails=0x%x\n", __FUNCTION__,
> + path_name, status);
> + } else {
> + pr_debug("%s:%s OSHP passes\n", __FUNCTION__, path_name);
> + }
> + return status;
> +}
> +EXPORT_SYMBOL_GPL(acpi_run_oshp);
> +
> +
> +
> +void acpi_get_hp_params_from_firmware(struct pci_dev *dev,
> + struct hotplug_params *hpp)
> +{
> + acpi_status status = AE_NOT_FOUND;
> + struct pci_dev *pdev = dev;
> +
> + /*
> + * _HPP settings apply to all child buses, until another _HPP is
> + * encountered. If we don't find an _HPP for the input pci dev,
> + * look for it in the parent device scope since that would apply to
> + * this pci dev. If we don't find any _HPP, use hardcoded defaults
> + */
> + while (pdev && (ACPI_FAILURE(status))) {
> + acpi_handle handle = DEVICE_ACPI_HANDLE(&(pdev->dev));
> + if (!handle)
> + break;
> + status = acpi_run_hpp(handle, hpp);
> + if (!(pdev->bus->parent))
> + break;
> + /* Check if a parent object supports _HPP */
> + pdev = pdev->bus->parent->self;
> + }
> +}
> +EXPORT_SYMBOL_GPL(acpi_get_hp_params_from_firmware);
> +
> +
> +
> +int is_root_bridge(acpi_handle handle)
> +{
> + acpi_status status;
> + struct acpi_device_info *info;
> + struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
> + int i;
> +
> + status = acpi_get_object_info(handle, &buffer);
> + if (ACPI_SUCCESS(status)) {
> + info = buffer.pointer;
> + if ((info->valid & ACPI_VALID_HID) &&
> + !strcmp(PCI_ROOT_HID_STRING,
> + info->hardware_id.value)) {
> + acpi_os_free(buffer.pointer);
> + return 1;
> + }
> + if (info->valid & ACPI_VALID_CID) {
> + for (i=0; i < info->compatibility_id.count; i++) {
> + if (!strcmp(PCI_ROOT_HID_STRING,
> + info->compatibility_id.id[i].value)) {
> + acpi_os_free(buffer.pointer);
> + return 1;
> + }
> + }
> + }
> + }
> + return 0;
> +}
> +EXPORT_SYMBOL_GPL(is_root_bridge);
> --- 2.6-git-gregkh.orig/drivers/pci/hotplug/acpiphp_glue.c
> +++ 2.6-git-gregkh/drivers/pci/hotplug/acpiphp_glue.c
> @@ -1408,34 +1408,6 @@ void handle_hotplug_event_func(acpi_hand
> }
> }
>
> -static int is_root_bridge(acpi_handle handle)
> -{
> - acpi_status status;
> - struct acpi_device_info *info;
> - struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
> - int i;
> -
> - status = acpi_get_object_info(handle, &buffer);
> - if (ACPI_SUCCESS(status)) {
> - info = buffer.pointer;
> - if ((info->valid & ACPI_VALID_HID) &&
> - !strcmp(PCI_ROOT_HID_STRING,
> - info->hardware_id.value)) {
> - acpi_os_free(buffer.pointer);
> - return 1;
> - }
> - if (info->valid & ACPI_VALID_CID) {
> - for (i=0; i < info->compatibility_id.count; i++) {
> - if (!strcmp(PCI_ROOT_HID_STRING,
> - info->compatibility_id.id[i].value)) {
> - acpi_os_free(buffer.pointer);
> - return 1;
> - }
> - }
> - }
> - }
> - return 0;
> -}
>
> static acpi_status
> find_root_bridges(acpi_handle handle, u32 lvl, void *context, void **rv)
> --- 2.6-git-gregkh.orig/drivers/pci/hotplug/pci_hotplug.h
> +++ 2.6-git-gregkh/drivers/pci/hotplug/pci_hotplug.h
> @@ -176,5 +176,22 @@ extern int pci_hp_change_slot_info (stru
> struct hotplug_slot_info *info);
> extern struct subsystem pci_hotplug_slots_subsys;
>
> +struct hotplug_params {
> + u8 cache_line_size;
> + u8 latency_timer;
> + u8 enable_serr;
> + u8 enable_perr;
> +};
> +
> +#ifdef CONFIG_ACPI
> +#include <acpi/acpi.h>
> +#include <acpi/acpi_bus.h>
> +#include <acpi/actypes.h>
> +extern acpi_status acpi_run_oshp(acpi_handle handle);
> +extern void acpi_get_hp_params_from_firmware(struct pci_dev *dev,
> + struct hotplug_params *hpp);
> +extern u8 * acpi_path_name( acpi_handle handle);
> +int is_root_bridge(acpi_handle handle);
> +#endif
> #endif
>
> --- 2.6-git-gregkh.orig/drivers/pci/hotplug/pciehp.h
> +++ 2.6-git-gregkh/drivers/pci/hotplug/pciehp.h
> @@ -50,12 +50,6 @@ extern int pciehp_force;
> #define info(format, arg...) printk(KERN_INFO "%s: " format, MY_NAME , ## arg)
> #define warn(format, arg...) printk(KERN_WARNING "%s: " format, MY_NAME , ## arg)
>
> -struct hotplug_params {
> - u8 cache_line_size;
> - u8 latency_timer;
> - u8 enable_serr;
> - u8 enable_perr;
> -};
>
> struct slot {
> struct slot *next;
> @@ -192,9 +186,6 @@ extern u8 pciehp_handle_power_fault (u8
> /* pci functions */
> extern int pciehp_configure_device (struct slot *p_slot);
> extern int pciehp_unconfigure_device (struct slot *p_slot);
> -extern int pciehp_get_hp_hw_control_from_firmware(struct pci_dev *dev);
> -extern void pciehp_get_hp_params_from_firmware(struct pci_dev *dev,
> - struct hotplug_params *hpp);
>
>
>
> @@ -286,4 +277,14 @@ struct hpc_ops {
> int (*check_lnk_status) (struct controller *ctrl);
> };
>
> +
> +#ifdef CONFIG_ACPI
> +#define pciehp_get_hp_hw_control_from_firmware(dev) \
> + pciehp_acpi_get_hp_hw_control_from_firmware(dev)
> +#define pciehp_get_hp_params_from_firmware(dev, hpp) \
> + acpi_get_hp_params_from_firmware(dev, hpp)
> +#else
> +#define pciehp_get_hp_hw_control_from_firmware(dev) 0
> +#define acpi_get_hp_params_from_firmware(dev, hpp)
> +#endif /* CONFIG_ACPI */
> #endif /* _PCIEHP_H */
> --- 2.6-git-gregkh.orig/drivers/pci/hotplug/pciehp_hpc.c
> +++ 2.6-git-gregkh/drivers/pci/hotplug/pciehp_hpc.c
> @@ -38,6 +38,9 @@
>
> #include "../pci.h"
> #include "pciehp.h"
> +#ifdef CONFIG_ACPI
> +#include <linux/pci-acpi.h>
> +#endif
>
> #ifdef DEBUG
> #define DBG_K_TRACE_ENTRY ((unsigned int)0x00000001) /* On function entry */
> @@ -1236,6 +1239,72 @@ static struct hpc_ops pciehp_hpc_ops = {
> .check_lnk_status = hpc_check_lnk_status,
> };
>
> +#ifdef CONFIG_ACPI
> +int pciehp_acpi_get_hp_hw_control_from_firmware(struct pci_dev *dev)
> +{
> + acpi_status status;
> + acpi_handle chandle, handle = DEVICE_ACPI_HANDLE(&(dev->dev));
> + struct pci_dev *pdev = dev;
> + struct pci_bus *parent;
> + u8 *path_name;
> +
> + /*
> + * Per PCI firmware specification, we should run the ACPI _OSC
> + * method to get control of hotplug hardware before using it.
> + * If an _OSC is missing, we look for an OSHP to do the same thing.
> + * To handle different BIOS behavior, we look for _OSC and OSHP
> + * within the scope of the hotplug controller and its parents, upto
> + * the host bridge under which this controller exists.
> + */
> + while (!handle) {
> + /*
> + * This hotplug controller was not listed in the ACPI name
> + * space at all. Try to get acpi handle of parent pci bus.
> + */
> + if (!pdev || !pdev->bus->parent)
> + break;
> + parent = pdev->bus->parent;
> + dbg("Could not find %s in acpi namespace, trying parent\n",
> + pci_name(pdev));
> + if (!parent->self)
> + /* Parent must be a host bridge */
> + handle = acpi_get_pci_rootbridge_handle(
> + pci_domain_nr(parent),
> + parent->number);
> + else
> + handle = DEVICE_ACPI_HANDLE(
> + &(parent->self->dev));
> + pdev = parent->self;
> + }
> +
> + while (handle) {
> + path_name = acpi_path_name(handle);
> + dbg("Trying to get hotplug control for %s \n", path_name);
> + status = pci_osc_control_set(handle,
> + OSC_PCI_EXPRESS_NATIVE_HP_CONTROL);
> + if (status == AE_NOT_FOUND)
> + status = acpi_run_oshp(handle);
> + if (ACPI_SUCCESS(status)) {
> + dbg("Gained control for hotplug HW for pci %s (%s)\n",
> + pci_name(dev), path_name);
> + return 0;
> + }
> + if (is_root_bridge(handle))
> + break;
> + chandle = handle;
> + status = acpi_get_parent(chandle, &handle);
> + if (ACPI_FAILURE(status))
> + break;
> + }
> +
> + err("Cannot get control of hotplug hardware for pci %s\n",
> + pci_name(dev));
> + return -1;
> +}
> +#endif
> +
> +
> +
> int pcie_init(struct controller * ctrl, struct pcie_device *dev)
> {
> struct php_ctlr_state_s *php_ctlr, *p;
> --- 2.6-git-gregkh.orig/drivers/pci/hotplug/pciehprm_acpi.c
> +++ /dev/null
> @@ -1,257 +0,0 @@
> -/*
> - * PCIEHPRM ACPI: PHP Resource Manager for ACPI platform
> - *
> - * Copyright (C) 2003-2004 Intel Corporation
> - *
> - * All rights reserved.
> - *
> - * This program is free software; you can redistribute it and/or modify
> - * it under the terms of the GNU General Public License as published by
> - * the Free Software Foundation; either version 2 of the License, or (at
> - * your option) any later version.
> - *
> - * This program is distributed in the hope that it will be useful, but
> - * WITHOUT ANY WARRANTY; without even the implied warranty of
> - * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
> - * NON INFRINGEMENT. See the GNU General Public License for more
> - * details.
> - *
> - * You should have received a copy of the GNU General Public License
> - * along with this program; if not, write to the Free Software
> - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
> - *
> - * Send feedback to <[email protected]>
> - *
> - */
> -
> -#include <linux/module.h>
> -#include <linux/kernel.h>
> -#include <linux/types.h>
> -#include <linux/pci.h>
> -#include <linux/acpi.h>
> -#include <linux/pci-acpi.h>
> -#include <acpi/acpi_bus.h>
> -#include <acpi/actypes.h>
> -#include "pciehp.h"
> -
> -#define METHOD_NAME__SUN "_SUN"
> -#define METHOD_NAME__HPP "_HPP"
> -#define METHOD_NAME_OSHP "OSHP"
> -
> -static u8 * acpi_path_name( acpi_handle handle)
> -{
> - acpi_status status;
> - static u8 path_name[ACPI_PATHNAME_MAX];
> - struct acpi_buffer ret_buf = { ACPI_PATHNAME_MAX, path_name };
> -
> - memset(path_name, 0, sizeof (path_name));
> - status = acpi_get_name(handle, ACPI_FULL_PATHNAME, &ret_buf);
> -
> - if (ACPI_FAILURE(status))
> - return NULL;
> - else
> - return path_name;
> -}
> -
> -static acpi_status
> -acpi_run_hpp(acpi_handle handle, struct hotplug_params *hpp)
> -{
> - acpi_status status;
> - u8 nui[4];
> - struct acpi_buffer ret_buf = { 0, NULL};
> - union acpi_object *ext_obj, *package;
> - u8 *path_name = acpi_path_name(handle);
> - int i, len = 0;
> -
> - /* get _hpp */
> - status = acpi_evaluate_object(handle, METHOD_NAME__HPP, NULL, &ret_buf);
> - switch (status) {
> - case AE_BUFFER_OVERFLOW:
> - ret_buf.pointer = kmalloc (ret_buf.length, GFP_KERNEL);
> - if (!ret_buf.pointer) {
> - err ("%s:%s alloc for _HPP fail\n", __FUNCTION__,
> - path_name);
> - return AE_NO_MEMORY;
> - }
> - status = acpi_evaluate_object(handle, METHOD_NAME__HPP,
> - NULL, &ret_buf);
> - if (ACPI_SUCCESS(status))
> - break;
> - default:
> - if (ACPI_FAILURE(status)) {
> - dbg("%s:%s _HPP fail=0x%x\n", __FUNCTION__,
> - path_name, status);
> - return status;
> - }
> - }
> -
> - ext_obj = (union acpi_object *) ret_buf.pointer;
> - if (ext_obj->type != ACPI_TYPE_PACKAGE) {
> - err ("%s:%s _HPP obj not a package\n", __FUNCTION__,
> - path_name);
> - status = AE_ERROR;
> - goto free_and_return;
> - }
> -
> - len = ext_obj->package.count;
> - package = (union acpi_object *) ret_buf.pointer;
> - for ( i = 0; (i < len) || (i < 4); i++) {
> - ext_obj = (union acpi_object *) &package->package.elements[i];
> - switch (ext_obj->type) {
> - case ACPI_TYPE_INTEGER:
> - nui[i] = (u8)ext_obj->integer.value;
> - break;
> - default:
> - err ("%s:%s _HPP obj type incorrect\n", __FUNCTION__,
> - path_name);
> - status = AE_ERROR;
> - goto free_and_return;
> - }
> - }
> -
> - hpp->cache_line_size = nui[0];
> - hpp->latency_timer = nui[1];
> - hpp->enable_serr = nui[2];
> - hpp->enable_perr = nui[3];
> -
> - dbg(" _HPP: cache_line_size=0x%x\n", hpp->cache_line_size);
> - dbg(" _HPP: latency timer =0x%x\n", hpp->latency_timer);
> - dbg(" _HPP: enable SERR =0x%x\n", hpp->enable_serr);
> - dbg(" _HPP: enable PERR =0x%x\n", hpp->enable_perr);
> -
> -free_and_return:
> - kfree(ret_buf.pointer);
> - return status;
> -}
> -
> -static acpi_status acpi_run_oshp(acpi_handle handle)
> -{
> - acpi_status status;
> - u8 *path_name = acpi_path_name(handle);
> -
> - /* run OSHP */
> - status = acpi_evaluate_object(handle, METHOD_NAME_OSHP, NULL, NULL);
> - if (ACPI_FAILURE(status)) {
> - dbg("%s:%s OSHP fails=0x%x\n", __FUNCTION__, path_name,
> - status);
> - } else {
> - dbg("%s:%s OSHP passes\n", __FUNCTION__, path_name);
> - }
> - return status;
> -}
> -
> -static int is_root_bridge(acpi_handle handle)
> -{
> - acpi_status status;
> - struct acpi_device_info *info;
> - struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
> - int i;
> -
> - status = acpi_get_object_info(handle, &buffer);
> - if (ACPI_SUCCESS(status)) {
> - info = buffer.pointer;
> - if ((info->valid & ACPI_VALID_HID) &&
> - !strcmp(PCI_ROOT_HID_STRING,
> - info->hardware_id.value)) {
> - acpi_os_free(buffer.pointer);
> - return 1;
> - }
> - if (info->valid & ACPI_VALID_CID) {
> - for (i=0; i < info->compatibility_id.count; i++) {
> - if (!strcmp(PCI_ROOT_HID_STRING,
> - info->compatibility_id.id[i].value)) {
> - acpi_os_free(buffer.pointer);
> - return 1;
> - }
> - }
> - }
> - }
> - return 0;
> -}
> -
> -int pciehp_get_hp_hw_control_from_firmware(struct pci_dev *dev)
> -{
> - acpi_status status;
> - acpi_handle chandle, handle = DEVICE_ACPI_HANDLE(&(dev->dev));
> - struct pci_dev *pdev = dev;
> - struct pci_bus *parent;
> - u8 *path_name;
> -
> - /*
> - * Per PCI firmware specification, we should run the ACPI _OSC
> - * method to get control of hotplug hardware before using it.
> - * If an _OSC is missing, we look for an OSHP to do the same thing.
> - * To handle different BIOS behavior, we look for _OSC and OSHP
> - * within the scope of the hotplug controller and its parents, upto
> - * the host bridge under which this controller exists.
> - */
> - while (!handle) {
> - /*
> - * This hotplug controller was not listed in the ACPI name
> - * space at all. Try to get acpi handle of parent pci bus.
> - */
> - if (!pdev || !pdev->bus->parent)
> - break;
> - parent = pdev->bus->parent;
> - dbg("Could not find %s in acpi namespace, trying parent\n",
> - pci_name(pdev));
> - if (!parent->self)
> - /* Parent must be a host bridge */
> - handle = acpi_get_pci_rootbridge_handle(
> - pci_domain_nr(parent),
> - parent->number);
> - else
> - handle = DEVICE_ACPI_HANDLE(
> - &(parent->self->dev));
> - pdev = parent->self;
> - }
> -
> - while (handle) {
> - path_name = acpi_path_name(handle);
> - dbg("Trying to get hotplug control for %s \n", path_name);
> - status = pci_osc_control_set(handle,
> - OSC_PCI_EXPRESS_NATIVE_HP_CONTROL);
> - if (status == AE_NOT_FOUND)
> - status = acpi_run_oshp(handle);
> - if (ACPI_SUCCESS(status)) {
> - dbg("Gained control for hotplug HW for pci %s (%s)\n",
> - pci_name(dev), path_name);
> - return 0;
> - }
> - if (is_root_bridge(handle))
> - break;
> - chandle = handle;
> - status = acpi_get_parent(chandle, &handle);
> - if (ACPI_FAILURE(status))
> - break;
> - }
> -
> - err("Cannot get control of hotplug hardware for pci %s\n",
> - pci_name(dev));
> - return -1;
> -}
> -
> -void pciehp_get_hp_params_from_firmware(struct pci_dev *dev,
> - struct hotplug_params *hpp)
> -{
> - acpi_status status = AE_NOT_FOUND;
> - struct pci_dev *pdev = dev;
> -
> - /*
> - * _HPP settings apply to all child buses, until another _HPP is
> - * encountered. If we don't find an _HPP for the input pci dev,
> - * look for it in the parent device scope since that would apply to
> - * this pci dev. If we don't find any _HPP, use hardcoded defaults
> - */
> - while (pdev && (ACPI_FAILURE(status))) {
> - acpi_handle handle = DEVICE_ACPI_HANDLE(&(pdev->dev));
> - if (!handle)
> - break;
> - status = acpi_run_hpp(handle, hpp);
> - if (!(pdev->bus->parent))
> - break;
> - /* Check if a parent object supports _HPP */
> - pdev = pdev->bus->parent->self;
> - }
> -}
> -
> --- 2.6-git-gregkh.orig/drivers/pci/hotplug/pciehprm_nonacpi.c
> +++ /dev/null
> @@ -1,47 +0,0 @@
> -/*
> - * PCIEHPRM NONACPI: PHP Resource Manager for Non-ACPI/Legacy platform
> - *
> - * Copyright (C) 1995,2001 Compaq Computer Corporation
> - * Copyright (C) 2001 Greg Kroah-Hartman ([email protected])
> - * Copyright (C) 2001 IBM Corp.
> - * Copyright (C) 2003-2004 Intel Corporation
> - *
> - * All rights reserved.
> - *
> - * This program is free software; you can redistribute it and/or modify
> - * it under the terms of the GNU General Public License as published by
> - * the Free Software Foundation; either version 2 of the License, or (at
> - * your option) any later version.
> - *
> - * This program is distributed in the hope that it will be useful, but
> - * WITHOUT ANY WARRANTY; without even the implied warranty of
> - * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
> - * NON INFRINGEMENT. See the GNU General Public License for more
> - * details.
> - *
> - * You should have received a copy of the GNU General Public License
> - * along with this program; if not, write to the Free Software
> - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
> - *
> - * Send feedback to <[email protected]>, <[email protected]>
> - *
> - */
> -
> -#include <linux/module.h>
> -#include <linux/kernel.h>
> -#include <linux/types.h>
> -#include <linux/sched.h>
> -#include <linux/pci.h>
> -#include <linux/slab.h>
> -#include "pciehp.h"
> -
> -void pciehp_get_hp_params_from_firmware(struct pci_dev *dev,
> - struct hotplug_params *hpp)
> -{
> - return;
> -}
> -
> -int pciehp_get_hp_hw_control_from_firmware(struct pci_dev *dev)
> -{
> - return 0;
> -}
> --- 2.6-git-gregkh.orig/drivers/pci/hotplug/shpchp.h
> +++ 2.6-git-gregkh/drivers/pci/hotplug/shpchp.h
> @@ -106,12 +106,6 @@ struct controller {
> volatile int cmd_busy;
> };
>
> -struct hotplug_params {
> - u8 cache_line_size;
> - u8 latency_timer;
> - u8 enable_serr;
> - u8 enable_perr;
> -};
>
> /* Define AMD SHPC ID */
> #define PCI_DEVICE_ID_AMD_GOLAM_7450 0x7450
> @@ -193,15 +187,24 @@ extern u8 shpchp_handle_power_fault(u8 h
> extern int shpchp_save_config(struct controller *ctrl, int busnumber, int num_ctlr_slots, int first_device_num);
> extern int shpchp_configure_device(struct slot *p_slot);
> extern int shpchp_unconfigure_device(struct slot *p_slot);
> -extern void get_hp_hw_control_from_firmware(struct pci_dev *dev);
> -extern void get_hp_params_from_firmware(struct pci_dev *dev,
> - struct hotplug_params *hpp);
> -extern int shpchprm_get_physical_slot_number(struct controller *ctrl,
> - u32 *sun, u8 busnum, u8 devnum);
> extern void shpchp_remove_ctrl_files(struct controller *ctrl);
> extern void cleanup_slots(struct controller *ctrl);
> extern void queue_pushbutton_work(void *data);
>
> +
> +#ifdef CONFIG_ACPI
> +#define get_hp_params_from_firmware(dev, hpp) \
> + acpi_get_hp_params_from_firmware(dev, hpp)
> +#define get_hp_hw_control_from_firmware(pdev) \
> + do { \
> + if (DEVICE_ACPI_HANDLE(&(pdev->dev))) \
> + acpi_run_oshp(DEVICE_ACPI_HANDLE(&(pdev->dev))); \
> + } while (0)
> +#else
> +#define get_hp_params_from_firmware(dev, hpp)
> +#define get_hp_hw_control_from_firmware(dev)
> +#endif
> +
> struct ctrl_reg {
> volatile u32 base_offset;
> volatile u32 slot_avail1;
> --- 2.6-git-gregkh.orig/drivers/pci/hotplug/shpchp_core.c
> +++ 2.6-git-gregkh/drivers/pci/hotplug/shpchp_core.c
> @@ -104,6 +104,23 @@ static void make_slot_name(struct slot *
> slot->bus, slot->number);
> }
>
> +
> +
> +
> +static int
> +shpchprm_get_physical_slot_number(struct controller *ctrl, u32 *sun,
> + u8 busnum, u8 devnum)
> +{
> + int offset = devnum - ctrl->slot_device_offset;
> +
> + dbg("%s: ctrl->slot_num_inc %d, offset %d\n", __FUNCTION__,
> + ctrl->slot_num_inc, offset);
> + *sun = (u8) (ctrl->first_slot + ctrl->slot_num_inc *offset);
> + return 0;
> +}
> +
> +
> +
> static int init_slots(struct controller *ctrl)
> {
> struct slot *slot;
> --- 2.6-git-gregkh.orig/drivers/pci/hotplug/shpchprm_acpi.c
> +++ /dev/null
> @@ -1,186 +0,0 @@
> -/*
> - * SHPCHPRM ACPI: PHP Resource Manager for ACPI platform
> - *
> - * Copyright (C) 2003-2004 Intel Corporation
> - *
> - * All rights reserved.
> - *
> - * This program is free software; you can redistribute it and/or modify
> - * it under the terms of the GNU General Public License as published by
> - * the Free Software Foundation; either version 2 of the License, or (at
> - * your option) any later version.
> - *
> - * This program is distributed in the hope that it will be useful, but
> - * WITHOUT ANY WARRANTY; without even the implied warranty of
> - * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
> - * NON INFRINGEMENT. See the GNU General Public License for more
> - * details.
> - *
> - * You should have received a copy of the GNU General Public License
> - * along with this program; if not, write to the Free Software
> - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
> - *
> - * Send feedback to <[email protected]>
> - *
> - */
> -
> -#include <linux/module.h>
> -#include <linux/kernel.h>
> -#include <linux/types.h>
> -#include <linux/pci.h>
> -#include <acpi/acpi.h>
> -#include <acpi/acpi_bus.h>
> -#include <acpi/actypes.h>
> -#include "shpchp.h"
> -
> -#define METHOD_NAME__SUN "_SUN"
> -#define METHOD_NAME__HPP "_HPP"
> -#define METHOD_NAME_OSHP "OSHP"
> -
> -static u8 * acpi_path_name( acpi_handle handle)
> -{
> - acpi_status status;
> - static u8 path_name[ACPI_PATHNAME_MAX];
> - struct acpi_buffer ret_buf = { ACPI_PATHNAME_MAX, path_name };
> -
> - memset(path_name, 0, sizeof (path_name));
> - status = acpi_get_name(handle, ACPI_FULL_PATHNAME, &ret_buf);
> -
> - if (ACPI_FAILURE(status))
> - return NULL;
> - else
> - return path_name;
> -}
> -
> -static acpi_status
> -acpi_run_hpp(acpi_handle handle, struct hotplug_params *hpp)
> -{
> - acpi_status status;
> - u8 nui[4];
> - struct acpi_buffer ret_buf = { 0, NULL};
> - union acpi_object *ext_obj, *package;
> - u8 *path_name = acpi_path_name(handle);
> - int i, len = 0;
> -
> - /* get _hpp */
> - status = acpi_evaluate_object(handle, METHOD_NAME__HPP, NULL, &ret_buf);
> - switch (status) {
> - case AE_BUFFER_OVERFLOW:
> - ret_buf.pointer = kmalloc (ret_buf.length, GFP_KERNEL);
> - if (!ret_buf.pointer) {
> - err ("%s:%s alloc for _HPP fail\n", __FUNCTION__,
> - path_name);
> - return AE_NO_MEMORY;
> - }
> - status = acpi_evaluate_object(handle, METHOD_NAME__HPP,
> - NULL, &ret_buf);
> - if (ACPI_SUCCESS(status))
> - break;
> - default:
> - if (ACPI_FAILURE(status)) {
> - dbg("%s:%s _HPP fail=0x%x\n", __FUNCTION__,
> - path_name, status);
> - return status;
> - }
> - }
> -
> - ext_obj = (union acpi_object *) ret_buf.pointer;
> - if (ext_obj->type != ACPI_TYPE_PACKAGE) {
> - err ("%s:%s _HPP obj not a package\n", __FUNCTION__,
> - path_name);
> - status = AE_ERROR;
> - goto free_and_return;
> - }
> -
> - len = ext_obj->package.count;
> - package = (union acpi_object *) ret_buf.pointer;
> - for ( i = 0; (i < len) || (i < 4); i++) {
> - ext_obj = (union acpi_object *) &package->package.elements[i];
> - switch (ext_obj->type) {
> - case ACPI_TYPE_INTEGER:
> - nui[i] = (u8)ext_obj->integer.value;
> - break;
> - default:
> - err ("%s:%s _HPP obj type incorrect\n", __FUNCTION__,
> - path_name);
> - status = AE_ERROR;
> - goto free_and_return;
> - }
> - }
> -
> - hpp->cache_line_size = nui[0];
> - hpp->latency_timer = nui[1];
> - hpp->enable_serr = nui[2];
> - hpp->enable_perr = nui[3];
> -
> - dbg(" _HPP: cache_line_size=0x%x\n", hpp->cache_line_size);
> - dbg(" _HPP: latency timer =0x%x\n", hpp->latency_timer);
> - dbg(" _HPP: enable SERR =0x%x\n", hpp->enable_serr);
> - dbg(" _HPP: enable PERR =0x%x\n", hpp->enable_perr);
> -
> -free_and_return:
> - kfree(ret_buf.pointer);
> - return status;
> -}
> -
> -static void acpi_run_oshp(acpi_handle handle)
> -{
> - acpi_status status;
> - u8 *path_name = acpi_path_name(handle);
> -
> - /* run OSHP */
> - status = acpi_evaluate_object(handle, METHOD_NAME_OSHP, NULL, NULL);
> - if (ACPI_FAILURE(status)) {
> - err("%s:%s OSHP fails=0x%x\n", __FUNCTION__, path_name,
> - status);
> - } else {
> - dbg("%s:%s OSHP passes\n", __FUNCTION__, path_name);
> - }
> -}
> -
> -int shpchprm_get_physical_slot_number(struct controller *ctrl, u32 *sun, u8 busnum, u8 devnum)
> -{
> - int offset = devnum - ctrl->slot_device_offset;
> -
> - dbg("%s: ctrl->slot_num_inc %d, offset %d\n", __FUNCTION__, ctrl->slot_num_inc, offset);
> - *sun = (u8) (ctrl->first_slot + ctrl->slot_num_inc *offset);
> - return 0;
> -}
> -
> -void get_hp_hw_control_from_firmware(struct pci_dev *dev)
> -{
> - /*
> - * OSHP is an optional ACPI firmware control method. If present,
> - * we need to run it to inform BIOS that we will control SHPC
> - * hardware from now on.
> - */
> - acpi_handle handle = DEVICE_ACPI_HANDLE(&(dev->dev));
> - if (!handle)
> - return;
> - acpi_run_oshp(handle);
> -}
> -
> -void get_hp_params_from_firmware(struct pci_dev *dev,
> - struct hotplug_params *hpp)
> -{
> - acpi_status status = AE_NOT_FOUND;
> - struct pci_dev *pdev = dev;
> -
> - /*
> - * _HPP settings apply to all child buses, until another _HPP is
> - * encountered. If we don't find an _HPP for the input pci dev,
> - * look for it in the parent device scope since that would apply to
> - * this pci dev. If we don't find any _HPP, use hardcoded defaults
> - */
> - while (pdev && (ACPI_FAILURE(status))) {
> - acpi_handle handle = DEVICE_ACPI_HANDLE(&(pdev->dev));
> - if (!handle)
> - break;
> - status = acpi_run_hpp(handle, hpp);
> - if (!(pdev->bus->parent))
> - break;
> - /* Check if a parent object supports _HPP */
> - pdev = pdev->bus->parent->self;
> - }
> -}
> -
> --- 2.6-git-gregkh.orig/drivers/pci/hotplug/shpchprm_legacy.c
> +++ /dev/null
> @@ -1,54 +0,0 @@
> -/*
> - * SHPCHPRM Legacy: PHP Resource Manager for Non-ACPI/Legacy platform
> - *
> - * Copyright (C) 1995,2001 Compaq Computer Corporation
> - * Copyright (C) 2001 Greg Kroah-Hartman ([email protected])
> - * Copyright (C) 2001 IBM Corp.
> - * Copyright (C) 2003-2004 Intel Corporation
> - *
> - * All rights reserved.
> - *
> - * This program is free software; you can redistribute it and/or modify
> - * it under the terms of the GNU General Public License as published by
> - * the Free Software Foundation; either version 2 of the License, or (at
> - * your option) any later version.
> - *
> - * This program is distributed in the hope that it will be useful, but
> - * WITHOUT ANY WARRANTY; without even the implied warranty of
> - * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
> - * NON INFRINGEMENT. See the GNU General Public License for more
> - * details.
> - *
> - * You should have received a copy of the GNU General Public License
> - * along with this program; if not, write to the Free Software
> - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
> - *
> - * Send feedback to <[email protected]>,<[email protected]>
> - *
> - */
> -
> -#include <linux/module.h>
> -#include <linux/kernel.h>
> -#include <linux/types.h>
> -#include <linux/pci.h>
> -#include "shpchp.h"
> -
> -int shpchprm_get_physical_slot_number(struct controller *ctrl, u32 *sun, u8 busnum, u8 devnum)
> -{
> - int offset = devnum - ctrl->slot_device_offset;
> -
> - *sun = (u8) (ctrl->first_slot + ctrl->slot_num_inc * offset);
> - return 0;
> -}
> -
> -void get_hp_params_from_firmware(struct pci_dev *dev,
> - struct hotplug_params *hpp)
> -{
> - return;
> -}
> -
> -void get_hp_hw_control_from_firmware(struct pci_dev *dev)
> -{
> - return;
> -}
> -
> --- 2.6-git-gregkh.orig/drivers/pci/hotplug/shpchprm_nonacpi.c
> +++ /dev/null
> @@ -1,57 +0,0 @@
> -/*
> - * SHPCHPRM NONACPI: PHP Resource Manager for Non-ACPI/Legacy platform
> - *
> - * Copyright (C) 1995,2001 Compaq Computer Corporation
> - * Copyright (C) 2001 Greg Kroah-Hartman ([email protected])
> - * Copyright (C) 2001 IBM Corp.
> - * Copyright (C) 2003-2004 Intel Corporation
> - *
> - * All rights reserved.
> - *
> - * This program is free software; you can redistribute it and/or modify
> - * it under the terms of the GNU General Public License as published by
> - * the Free Software Foundation; either version 2 of the License, or (at
> - * your option) any later version.
> - *
> - * This program is distributed in the hope that it will be useful, but
> - * WITHOUT ANY WARRANTY; without even the implied warranty of
> - * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
> - * NON INFRINGEMENT. See the GNU General Public License for more
> - * details.
> - *
> - * You should have received a copy of the GNU General Public License
> - * along with this program; if not, write to the Free Software
> - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
> - *
> - * Send feedback to <[email protected]>, <[email protected]>
> - *
> - */
> -
> -#include <linux/config.h>
> -#include <linux/module.h>
> -#include <linux/kernel.h>
> -#include <linux/types.h>
> -#include <linux/pci.h>
> -#include <linux/slab.h>
> -
> -#include "shpchp.h"
> -
> -int shpchprm_get_physical_slot_number(struct controller *ctrl, u32 *sun, u8 busnum, u8 devnum)
> -{
> - int offset = devnum - ctrl->slot_device_offset;
> -
> - dbg("%s: ctrl->slot_num_inc %d, offset %d\n", __FUNCTION__, ctrl->slot_num_inc, offset);
> - *sun = (u8) (ctrl->first_slot + ctrl->slot_num_inc * offset);
> - return 0;
> -}
> -
> -void get_hp_params_from_firmware(struct pci_dev *dev,
> - struct hotplug_params *hpp)
> -{
> - return;
> -}
> -
> -void get_hp_hw_control_from_firmware(struct pci_dev *dev)
> -{
> - return;
> -}
>
>
>
> -------------------------------------------------------
> This SF.Net email is sponsored by xPML, a groundbreaking scripting language
> that extends applications into web and mobile media. Attend the live webcast
> and join the prime developer group breaking into this new coding territory!
> http://sel.as-us.falkag.net/sel?cmd=lnk&kid=110944&bid=241720&dat=121642
> _______________________________________________
> Pcihpd-discuss mailing list
> [email protected]
> https://lists.sourceforge.net/lists/listinfo/pcihpd-discuss
>
Hi Kristen,
Here is one more comment.
> +void acpi_get_hp_params_from_firmware(struct pci_dev *dev,
> + struct hotplug_params *hpp)
> +{
> + acpi_status status = AE_NOT_FOUND;
> + struct pci_dev *pdev = dev;
> +
> + /*
> + * _HPP settings apply to all child buses, until another _HPP is
> + * encountered. If we don't find an _HPP for the input pci dev,
> + * look for it in the parent device scope since that would apply to
> + * this pci dev. If we don't find any _HPP, use hardcoded defaults
> + */
> + while (pdev && (ACPI_FAILURE(status))) {
> + acpi_handle handle = DEVICE_ACPI_HANDLE(&(pdev->dev));
> + if (!handle)
> + break;
> + status = acpi_run_hpp(handle, hpp);
> + if (!(pdev->bus->parent))
> + break;
> + /* Check if a parent object supports _HPP */
> + pdev = pdev->bus->parent->self;
> + }
> +}
> +EXPORT_SYMBOL_GPL(acpi_get_hp_params_from_firmware);
I think the acpi_get_hp_params_from_firmware() function assumes that
users set default hpp parameters into *hpp before calling this function.
I think it is very hard for new users of the function to notice it, so
I think this assumption should be removed.
Thanks,
Kenji Kaneshige
Kristen Accardi wrote:
> shpchprm_acpi.c and pciehprm_acpi.c are nearly identical.
> In addition, there are functions in both these files that
> are also in acpiphp_glue.c. This patch will remove duplicate
> functions from shpchp, pciehp, and acpiphp and move this
> functionality to pci_hotplug, as it is not hardware specific.
> Get rid of shpchprm* and pciehprm* files since they are no longer needed.
> shpchprm_nonacpi.c and pciehprm_nonacpi.c are identical, as well
> as shpchprm_legacy.c and can be replaced with a macro.
>
> Signed-off-by: Kristen Carlson Accardi <[email protected]>
> ---
> dev/null |binary
> dev/null |binary
> drivers/pci/hotplug/pciehprm_acpi.c | 257 ---------------------------------
> drivers/pci/hotplug/pciehprm_nonacpi.c | 47 ------
> drivers/pci/hotplug/shpchprm_acpi.c | 186 -----------------------
> drivers/pci/hotplug/shpchprm_legacy.c | 54 ------
> drivers/pci/hotplug/shpchprm_nonacpi.c | 57 -------
> drivers/pci/hotplug/Makefile | 17 --
> drivers/pci/hotplug/acpi_pcihp.c | 201 +++++++++++++++++++++++++
> drivers/pci/hotplug/acpiphp_glue.c | 28 ---
> drivers/pci/hotplug/pci_hotplug.h | 17 ++
> drivers/pci/hotplug/pciehp.h | 19 +-
> drivers/pci/hotplug/pciehp_hpc.c | 69 ++++++++
> drivers/pci/hotplug/shpchp.h | 25 +--
> drivers/pci/hotplug/shpchp_core.c | 17 ++
> 13 files changed, 331 insertions(+), 663 deletions(-)
>
> --- 2.6-git-gregkh.orig/drivers/pci/hotplug/Makefile
> +++ 2.6-git-gregkh/drivers/pci/hotplug/Makefile
> @@ -22,6 +22,9 @@ ifdef CONFIG_HOTPLUG_PCI_CPCI
> pci_hotplug-objs += cpci_hotplug_core.o \
> cpci_hotplug_pci.o
> endif
> +ifdef CONFIG_ACPI
> +pci_hotplug-objs += acpi_pcihp.o
> +endif
>
> cpqphp-objs := cpqphp_core.o \
> cpqphp_ctrl.o \
> @@ -51,23 +54,9 @@ pciehp-objs := pciehp_core.o \
> pciehp_ctrl.o \
> pciehp_pci.o \
> pciehp_hpc.o
> -ifdef CONFIG_ACPI
> - pciehp-objs += pciehprm_acpi.o
> -else
> - pciehp-objs += pciehprm_nonacpi.o
> -endif
>
> shpchp-objs := shpchp_core.o \
> shpchp_ctrl.o \
> shpchp_pci.o \
> shpchp_sysfs.o \
> shpchp_hpc.o
> -ifdef CONFIG_ACPI
> - shpchp-objs += shpchprm_acpi.o
> -else
> - ifdef CONFIG_HOTPLUG_PCI_SHPC_PHPRM_LEGACY
> - shpchp-objs += shpchprm_legacy.o
> - else
> - shpchp-objs += shpchprm_nonacpi.o
> - endif
> -endif
> --- /dev/null
> +++ 2.6-git-gregkh/drivers/pci/hotplug/acpi_pcihp.c
> @@ -0,0 +1,201 @@
> +/*
> + * ACPI related functions for PCI hotplug drivers
> + *
> + * Copyright (C) 2006 Intel Corporation
> + *
> + * All rights reserved.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or (at
> + * your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful, but
> + * WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
> + * NON INFRINGEMENT. See the GNU General Public License for more
> + * details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
> + *
> + * Send feedback to <[email protected]>
> + *
> + */
> +
> +#include <linux/module.h>
> +#include <linux/kernel.h>
> +#include <linux/types.h>
> +#include <linux/pci.h>
> +#include <acpi/acpi.h>
> +#include <acpi/acpi_bus.h>
> +#include <acpi/actypes.h>
> +#include "pci_hotplug.h"
> +
> +#define METHOD_NAME__SUN "_SUN"
> +#define METHOD_NAME__HPP "_HPP"
> +#define METHOD_NAME_OSHP "OSHP"
> +
> +u8 * acpi_path_name( acpi_handle handle)
> +{
> + acpi_status status;
> + static u8 path_name[ACPI_PATHNAME_MAX];
> + struct acpi_buffer ret_buf = { ACPI_PATHNAME_MAX, path_name };
> +
> + memset(path_name, 0, sizeof (path_name));
> + status = acpi_get_name(handle, ACPI_FULL_PATHNAME, &ret_buf);
> +
> + if (ACPI_FAILURE(status))
> + return NULL;
> + else
> + return path_name;
> +}
> +EXPORT_SYMBOL_GPL(acpi_path_name);
> +
> +static acpi_status
> +acpi_run_hpp(acpi_handle handle, struct hotplug_params *hpp)
> +{
> + acpi_status status;
> + u8 nui[4];
> + struct acpi_buffer ret_buf = { 0, NULL};
> + union acpi_object *ext_obj, *package;
> + u8 *path_name = acpi_path_name(handle);
> + int i, len = 0;
> +
> + /* get _hpp */
> + status = acpi_evaluate_object(handle, METHOD_NAME__HPP, NULL, &ret_buf);
> + switch (status) {
> + case AE_BUFFER_OVERFLOW:
> + ret_buf.pointer = kmalloc (ret_buf.length, GFP_KERNEL);
> + if (!ret_buf.pointer) {
> + printk(KERN_ERR "%s:%s alloc for _HPP fail\n",
> + __FUNCTION__, path_name);
> + return AE_NO_MEMORY;
> + }
> + status = acpi_evaluate_object(handle, METHOD_NAME__HPP,
> + NULL, &ret_buf);
> + if (ACPI_SUCCESS(status))
> + break;
> + default:
> + if (ACPI_FAILURE(status)) {
> + pr_debug("%s:%s _HPP fail=0x%x\n", __FUNCTION__,
> + path_name, status);
> + return status;
> + }
> + }
> +
> + ext_obj = (union acpi_object *) ret_buf.pointer;
> + if (ext_obj->type != ACPI_TYPE_PACKAGE) {
> + printk(KERN_ERR "%s:%s _HPP obj not a package\n", __FUNCTION__,
> + path_name);
> + status = AE_ERROR;
> + goto free_and_return;
> + }
> +
> + len = ext_obj->package.count;
> + package = (union acpi_object *) ret_buf.pointer;
> + for ( i = 0; (i < len) || (i < 4); i++) {
> + ext_obj = (union acpi_object *) &package->package.elements[i];
> + switch (ext_obj->type) {
> + case ACPI_TYPE_INTEGER:
> + nui[i] = (u8)ext_obj->integer.value;
> + break;
> + default:
> + printk(KERN_ERR "%s:%s _HPP obj type incorrect\n",
> + __FUNCTION__, path_name);
> + status = AE_ERROR;
> + goto free_and_return;
> + }
> + }
> +
> + hpp->cache_line_size = nui[0];
> + hpp->latency_timer = nui[1];
> + hpp->enable_serr = nui[2];
> + hpp->enable_perr = nui[3];
> +
> + pr_debug(" _HPP: cache_line_size=0x%x\n", hpp->cache_line_size);
> + pr_debug(" _HPP: latency timer =0x%x\n", hpp->latency_timer);
> + pr_debug(" _HPP: enable SERR =0x%x\n", hpp->enable_serr);
> + pr_debug(" _HPP: enable PERR =0x%x\n", hpp->enable_perr);
> +
> +free_and_return:
> + kfree(ret_buf.pointer);
> + return status;
> +}
> +
> +acpi_status acpi_run_oshp(acpi_handle handle)
> +{
> + acpi_status status;
> + u8 *path_name = acpi_path_name(handle);
> +
> + /* run OSHP */
> + status = acpi_evaluate_object(handle, METHOD_NAME_OSHP, NULL, NULL);
> + if (ACPI_FAILURE(status)) {
> + printk(KERN_ERR "%s:%s OSHP fails=0x%x\n", __FUNCTION__,
> + path_name, status);
> + } else {
> + pr_debug("%s:%s OSHP passes\n", __FUNCTION__, path_name);
> + }
> + return status;
> +}
> +EXPORT_SYMBOL_GPL(acpi_run_oshp);
> +
> +
> +
> +void acpi_get_hp_params_from_firmware(struct pci_dev *dev,
> + struct hotplug_params *hpp)
> +{
> + acpi_status status = AE_NOT_FOUND;
> + struct pci_dev *pdev = dev;
> +
> + /*
> + * _HPP settings apply to all child buses, until another _HPP is
> + * encountered. If we don't find an _HPP for the input pci dev,
> + * look for it in the parent device scope since that would apply to
> + * this pci dev. If we don't find any _HPP, use hardcoded defaults
> + */
> + while (pdev && (ACPI_FAILURE(status))) {
> + acpi_handle handle = DEVICE_ACPI_HANDLE(&(pdev->dev));
> + if (!handle)
> + break;
> + status = acpi_run_hpp(handle, hpp);
> + if (!(pdev->bus->parent))
> + break;
> + /* Check if a parent object supports _HPP */
> + pdev = pdev->bus->parent->self;
> + }
> +}
> +EXPORT_SYMBOL_GPL(acpi_get_hp_params_from_firmware);
> +
> +
> +
> +int is_root_bridge(acpi_handle handle)
> +{
> + acpi_status status;
> + struct acpi_device_info *info;
> + struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
> + int i;
> +
> + status = acpi_get_object_info(handle, &buffer);
> + if (ACPI_SUCCESS(status)) {
> + info = buffer.pointer;
> + if ((info->valid & ACPI_VALID_HID) &&
> + !strcmp(PCI_ROOT_HID_STRING,
> + info->hardware_id.value)) {
> + acpi_os_free(buffer.pointer);
> + return 1;
> + }
> + if (info->valid & ACPI_VALID_CID) {
> + for (i=0; i < info->compatibility_id.count; i++) {
> + if (!strcmp(PCI_ROOT_HID_STRING,
> + info->compatibility_id.id[i].value)) {
> + acpi_os_free(buffer.pointer);
> + return 1;
> + }
> + }
> + }
> + }
> + return 0;
> +}
> +EXPORT_SYMBOL_GPL(is_root_bridge);
> --- 2.6-git-gregkh.orig/drivers/pci/hotplug/acpiphp_glue.c
> +++ 2.6-git-gregkh/drivers/pci/hotplug/acpiphp_glue.c
> @@ -1408,34 +1408,6 @@ void handle_hotplug_event_func(acpi_hand
> }
> }
>
> -static int is_root_bridge(acpi_handle handle)
> -{
> - acpi_status status;
> - struct acpi_device_info *info;
> - struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
> - int i;
> -
> - status = acpi_get_object_info(handle, &buffer);
> - if (ACPI_SUCCESS(status)) {
> - info = buffer.pointer;
> - if ((info->valid & ACPI_VALID_HID) &&
> - !strcmp(PCI_ROOT_HID_STRING,
> - info->hardware_id.value)) {
> - acpi_os_free(buffer.pointer);
> - return 1;
> - }
> - if (info->valid & ACPI_VALID_CID) {
> - for (i=0; i < info->compatibility_id.count; i++) {
> - if (!strcmp(PCI_ROOT_HID_STRING,
> - info->compatibility_id.id[i].value)) {
> - acpi_os_free(buffer.pointer);
> - return 1;
> - }
> - }
> - }
> - }
> - return 0;
> -}
>
> static acpi_status
> find_root_bridges(acpi_handle handle, u32 lvl, void *context, void **rv)
> --- 2.6-git-gregkh.orig/drivers/pci/hotplug/pci_hotplug.h
> +++ 2.6-git-gregkh/drivers/pci/hotplug/pci_hotplug.h
> @@ -176,5 +176,22 @@ extern int pci_hp_change_slot_info (stru
> struct hotplug_slot_info *info);
> extern struct subsystem pci_hotplug_slots_subsys;
>
> +struct hotplug_params {
> + u8 cache_line_size;
> + u8 latency_timer;
> + u8 enable_serr;
> + u8 enable_perr;
> +};
> +
> +#ifdef CONFIG_ACPI
> +#include <acpi/acpi.h>
> +#include <acpi/acpi_bus.h>
> +#include <acpi/actypes.h>
> +extern acpi_status acpi_run_oshp(acpi_handle handle);
> +extern void acpi_get_hp_params_from_firmware(struct pci_dev *dev,
> + struct hotplug_params *hpp);
> +extern u8 * acpi_path_name( acpi_handle handle);
> +int is_root_bridge(acpi_handle handle);
> +#endif
> #endif
>
> --- 2.6-git-gregkh.orig/drivers/pci/hotplug/pciehp.h
> +++ 2.6-git-gregkh/drivers/pci/hotplug/pciehp.h
> @@ -50,12 +50,6 @@ extern int pciehp_force;
> #define info(format, arg...) printk(KERN_INFO "%s: " format, MY_NAME , ## arg)
> #define warn(format, arg...) printk(KERN_WARNING "%s: " format, MY_NAME , ## arg)
>
> -struct hotplug_params {
> - u8 cache_line_size;
> - u8 latency_timer;
> - u8 enable_serr;
> - u8 enable_perr;
> -};
>
> struct slot {
> struct slot *next;
> @@ -192,9 +186,6 @@ extern u8 pciehp_handle_power_fault (u8
> /* pci functions */
> extern int pciehp_configure_device (struct slot *p_slot);
> extern int pciehp_unconfigure_device (struct slot *p_slot);
> -extern int pciehp_get_hp_hw_control_from_firmware(struct pci_dev *dev);
> -extern void pciehp_get_hp_params_from_firmware(struct pci_dev *dev,
> - struct hotplug_params *hpp);
>
>
>
> @@ -286,4 +277,14 @@ struct hpc_ops {
> int (*check_lnk_status) (struct controller *ctrl);
> };
>
> +
> +#ifdef CONFIG_ACPI
> +#define pciehp_get_hp_hw_control_from_firmware(dev) \
> + pciehp_acpi_get_hp_hw_control_from_firmware(dev)
> +#define pciehp_get_hp_params_from_firmware(dev, hpp) \
> + acpi_get_hp_params_from_firmware(dev, hpp)
> +#else
> +#define pciehp_get_hp_hw_control_from_firmware(dev) 0
> +#define acpi_get_hp_params_from_firmware(dev, hpp)
> +#endif /* CONFIG_ACPI */
> #endif /* _PCIEHP_H */
> --- 2.6-git-gregkh.orig/drivers/pci/hotplug/pciehp_hpc.c
> +++ 2.6-git-gregkh/drivers/pci/hotplug/pciehp_hpc.c
> @@ -38,6 +38,9 @@
>
> #include "../pci.h"
> #include "pciehp.h"
> +#ifdef CONFIG_ACPI
> +#include <linux/pci-acpi.h>
> +#endif
>
> #ifdef DEBUG
> #define DBG_K_TRACE_ENTRY ((unsigned int)0x00000001) /* On function entry */
> @@ -1236,6 +1239,72 @@ static struct hpc_ops pciehp_hpc_ops = {
> .check_lnk_status = hpc_check_lnk_status,
> };
>
> +#ifdef CONFIG_ACPI
> +int pciehp_acpi_get_hp_hw_control_from_firmware(struct pci_dev *dev)
> +{
> + acpi_status status;
> + acpi_handle chandle, handle = DEVICE_ACPI_HANDLE(&(dev->dev));
> + struct pci_dev *pdev = dev;
> + struct pci_bus *parent;
> + u8 *path_name;
> +
> + /*
> + * Per PCI firmware specification, we should run the ACPI _OSC
> + * method to get control of hotplug hardware before using it.
> + * If an _OSC is missing, we look for an OSHP to do the same thing.
> + * To handle different BIOS behavior, we look for _OSC and OSHP
> + * within the scope of the hotplug controller and its parents, upto
> + * the host bridge under which this controller exists.
> + */
> + while (!handle) {
> + /*
> + * This hotplug controller was not listed in the ACPI name
> + * space at all. Try to get acpi handle of parent pci bus.
> + */
> + if (!pdev || !pdev->bus->parent)
> + break;
> + parent = pdev->bus->parent;
> + dbg("Could not find %s in acpi namespace, trying parent\n",
> + pci_name(pdev));
> + if (!parent->self)
> + /* Parent must be a host bridge */
> + handle = acpi_get_pci_rootbridge_handle(
> + pci_domain_nr(parent),
> + parent->number);
> + else
> + handle = DEVICE_ACPI_HANDLE(
> + &(parent->self->dev));
> + pdev = parent->self;
> + }
> +
> + while (handle) {
> + path_name = acpi_path_name(handle);
> + dbg("Trying to get hotplug control for %s \n", path_name);
> + status = pci_osc_control_set(handle,
> + OSC_PCI_EXPRESS_NATIVE_HP_CONTROL);
> + if (status == AE_NOT_FOUND)
> + status = acpi_run_oshp(handle);
> + if (ACPI_SUCCESS(status)) {
> + dbg("Gained control for hotplug HW for pci %s (%s)\n",
> + pci_name(dev), path_name);
> + return 0;
> + }
> + if (is_root_bridge(handle))
> + break;
> + chandle = handle;
> + status = acpi_get_parent(chandle, &handle);
> + if (ACPI_FAILURE(status))
> + break;
> + }
> +
> + err("Cannot get control of hotplug hardware for pci %s\n",
> + pci_name(dev));
> + return -1;
> +}
> +#endif
> +
> +
> +
> int pcie_init(struct controller * ctrl, struct pcie_device *dev)
> {
> struct php_ctlr_state_s *php_ctlr, *p;
> --- 2.6-git-gregkh.orig/drivers/pci/hotplug/pciehprm_acpi.c
> +++ /dev/null
> @@ -1,257 +0,0 @@
> -/*
> - * PCIEHPRM ACPI: PHP Resource Manager for ACPI platform
> - *
> - * Copyright (C) 2003-2004 Intel Corporation
> - *
> - * All rights reserved.
> - *
> - * This program is free software; you can redistribute it and/or modify
> - * it under the terms of the GNU General Public License as published by
> - * the Free Software Foundation; either version 2 of the License, or (at
> - * your option) any later version.
> - *
> - * This program is distributed in the hope that it will be useful, but
> - * WITHOUT ANY WARRANTY; without even the implied warranty of
> - * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
> - * NON INFRINGEMENT. See the GNU General Public License for more
> - * details.
> - *
> - * You should have received a copy of the GNU General Public License
> - * along with this program; if not, write to the Free Software
> - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
> - *
> - * Send feedback to <[email protected]>
> - *
> - */
> -
> -#include <linux/module.h>
> -#include <linux/kernel.h>
> -#include <linux/types.h>
> -#include <linux/pci.h>
> -#include <linux/acpi.h>
> -#include <linux/pci-acpi.h>
> -#include <acpi/acpi_bus.h>
> -#include <acpi/actypes.h>
> -#include "pciehp.h"
> -
> -#define METHOD_NAME__SUN "_SUN"
> -#define METHOD_NAME__HPP "_HPP"
> -#define METHOD_NAME_OSHP "OSHP"
> -
> -static u8 * acpi_path_name( acpi_handle handle)
> -{
> - acpi_status status;
> - static u8 path_name[ACPI_PATHNAME_MAX];
> - struct acpi_buffer ret_buf = { ACPI_PATHNAME_MAX, path_name };
> -
> - memset(path_name, 0, sizeof (path_name));
> - status = acpi_get_name(handle, ACPI_FULL_PATHNAME, &ret_buf);
> -
> - if (ACPI_FAILURE(status))
> - return NULL;
> - else
> - return path_name;
> -}
> -
> -static acpi_status
> -acpi_run_hpp(acpi_handle handle, struct hotplug_params *hpp)
> -{
> - acpi_status status;
> - u8 nui[4];
> - struct acpi_buffer ret_buf = { 0, NULL};
> - union acpi_object *ext_obj, *package;
> - u8 *path_name = acpi_path_name(handle);
> - int i, len = 0;
> -
> - /* get _hpp */
> - status = acpi_evaluate_object(handle, METHOD_NAME__HPP, NULL, &ret_buf);
> - switch (status) {
> - case AE_BUFFER_OVERFLOW:
> - ret_buf.pointer = kmalloc (ret_buf.length, GFP_KERNEL);
> - if (!ret_buf.pointer) {
> - err ("%s:%s alloc for _HPP fail\n", __FUNCTION__,
> - path_name);
> - return AE_NO_MEMORY;
> - }
> - status = acpi_evaluate_object(handle, METHOD_NAME__HPP,
> - NULL, &ret_buf);
> - if (ACPI_SUCCESS(status))
> - break;
> - default:
> - if (ACPI_FAILURE(status)) {
> - dbg("%s:%s _HPP fail=0x%x\n", __FUNCTION__,
> - path_name, status);
> - return status;
> - }
> - }
> -
> - ext_obj = (union acpi_object *) ret_buf.pointer;
> - if (ext_obj->type != ACPI_TYPE_PACKAGE) {
> - err ("%s:%s _HPP obj not a package\n", __FUNCTION__,
> - path_name);
> - status = AE_ERROR;
> - goto free_and_return;
> - }
> -
> - len = ext_obj->package.count;
> - package = (union acpi_object *) ret_buf.pointer;
> - for ( i = 0; (i < len) || (i < 4); i++) {
> - ext_obj = (union acpi_object *) &package->package.elements[i];
> - switch (ext_obj->type) {
> - case ACPI_TYPE_INTEGER:
> - nui[i] = (u8)ext_obj->integer.value;
> - break;
> - default:
> - err ("%s:%s _HPP obj type incorrect\n", __FUNCTION__,
> - path_name);
> - status = AE_ERROR;
> - goto free_and_return;
> - }
> - }
> -
> - hpp->cache_line_size = nui[0];
> - hpp->latency_timer = nui[1];
> - hpp->enable_serr = nui[2];
> - hpp->enable_perr = nui[3];
> -
> - dbg(" _HPP: cache_line_size=0x%x\n", hpp->cache_line_size);
> - dbg(" _HPP: latency timer =0x%x\n", hpp->latency_timer);
> - dbg(" _HPP: enable SERR =0x%x\n", hpp->enable_serr);
> - dbg(" _HPP: enable PERR =0x%x\n", hpp->enable_perr);
> -
> -free_and_return:
> - kfree(ret_buf.pointer);
> - return status;
> -}
> -
> -static acpi_status acpi_run_oshp(acpi_handle handle)
> -{
> - acpi_status status;
> - u8 *path_name = acpi_path_name(handle);
> -
> - /* run OSHP */
> - status = acpi_evaluate_object(handle, METHOD_NAME_OSHP, NULL, NULL);
> - if (ACPI_FAILURE(status)) {
> - dbg("%s:%s OSHP fails=0x%x\n", __FUNCTION__, path_name,
> - status);
> - } else {
> - dbg("%s:%s OSHP passes\n", __FUNCTION__, path_name);
> - }
> - return status;
> -}
> -
> -static int is_root_bridge(acpi_handle handle)
> -{
> - acpi_status status;
> - struct acpi_device_info *info;
> - struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
> - int i;
> -
> - status = acpi_get_object_info(handle, &buffer);
> - if (ACPI_SUCCESS(status)) {
> - info = buffer.pointer;
> - if ((info->valid & ACPI_VALID_HID) &&
> - !strcmp(PCI_ROOT_HID_STRING,
> - info->hardware_id.value)) {
> - acpi_os_free(buffer.pointer);
> - return 1;
> - }
> - if (info->valid & ACPI_VALID_CID) {
> - for (i=0; i < info->compatibility_id.count; i++) {
> - if (!strcmp(PCI_ROOT_HID_STRING,
> - info->compatibility_id.id[i].value)) {
> - acpi_os_free(buffer.pointer);
> - return 1;
> - }
> - }
> - }
> - }
> - return 0;
> -}
> -
> -int pciehp_get_hp_hw_control_from_firmware(struct pci_dev *dev)
> -{
> - acpi_status status;
> - acpi_handle chandle, handle = DEVICE_ACPI_HANDLE(&(dev->dev));
> - struct pci_dev *pdev = dev;
> - struct pci_bus *parent;
> - u8 *path_name;
> -
> - /*
> - * Per PCI firmware specification, we should run the ACPI _OSC
> - * method to get control of hotplug hardware before using it.
> - * If an _OSC is missing, we look for an OSHP to do the same thing.
> - * To handle different BIOS behavior, we look for _OSC and OSHP
> - * within the scope of the hotplug controller and its parents, upto
> - * the host bridge under which this controller exists.
> - */
> - while (!handle) {
> - /*
> - * This hotplug controller was not listed in the ACPI name
> - * space at all. Try to get acpi handle of parent pci bus.
> - */
> - if (!pdev || !pdev->bus->parent)
> - break;
> - parent = pdev->bus->parent;
> - dbg("Could not find %s in acpi namespace, trying parent\n",
> - pci_name(pdev));
> - if (!parent->self)
> - /* Parent must be a host bridge */
> - handle = acpi_get_pci_rootbridge_handle(
> - pci_domain_nr(parent),
> - parent->number);
> - else
> - handle = DEVICE_ACPI_HANDLE(
> - &(parent->self->dev));
> - pdev = parent->self;
> - }
> -
> - while (handle) {
> - path_name = acpi_path_name(handle);
> - dbg("Trying to get hotplug control for %s \n", path_name);
> - status = pci_osc_control_set(handle,
> - OSC_PCI_EXPRESS_NATIVE_HP_CONTROL);
> - if (status == AE_NOT_FOUND)
> - status = acpi_run_oshp(handle);
> - if (ACPI_SUCCESS(status)) {
> - dbg("Gained control for hotplug HW for pci %s (%s)\n",
> - pci_name(dev), path_name);
> - return 0;
> - }
> - if (is_root_bridge(handle))
> - break;
> - chandle = handle;
> - status = acpi_get_parent(chandle, &handle);
> - if (ACPI_FAILURE(status))
> - break;
> - }
> -
> - err("Cannot get control of hotplug hardware for pci %s\n",
> - pci_name(dev));
> - return -1;
> -}
> -
> -void pciehp_get_hp_params_from_firmware(struct pci_dev *dev,
> - struct hotplug_params *hpp)
> -{
> - acpi_status status = AE_NOT_FOUND;
> - struct pci_dev *pdev = dev;
> -
> - /*
> - * _HPP settings apply to all child buses, until another _HPP is
> - * encountered. If we don't find an _HPP for the input pci dev,
> - * look for it in the parent device scope since that would apply to
> - * this pci dev. If we don't find any _HPP, use hardcoded defaults
> - */
> - while (pdev && (ACPI_FAILURE(status))) {
> - acpi_handle handle = DEVICE_ACPI_HANDLE(&(pdev->dev));
> - if (!handle)
> - break;
> - status = acpi_run_hpp(handle, hpp);
> - if (!(pdev->bus->parent))
> - break;
> - /* Check if a parent object supports _HPP */
> - pdev = pdev->bus->parent->self;
> - }
> -}
> -
> --- 2.6-git-gregkh.orig/drivers/pci/hotplug/pciehprm_nonacpi.c
> +++ /dev/null
> @@ -1,47 +0,0 @@
> -/*
> - * PCIEHPRM NONACPI: PHP Resource Manager for Non-ACPI/Legacy platform
> - *
> - * Copyright (C) 1995,2001 Compaq Computer Corporation
> - * Copyright (C) 2001 Greg Kroah-Hartman ([email protected])
> - * Copyright (C) 2001 IBM Corp.
> - * Copyright (C) 2003-2004 Intel Corporation
> - *
> - * All rights reserved.
> - *
> - * This program is free software; you can redistribute it and/or modify
> - * it under the terms of the GNU General Public License as published by
> - * the Free Software Foundation; either version 2 of the License, or (at
> - * your option) any later version.
> - *
> - * This program is distributed in the hope that it will be useful, but
> - * WITHOUT ANY WARRANTY; without even the implied warranty of
> - * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
> - * NON INFRINGEMENT. See the GNU General Public License for more
> - * details.
> - *
> - * You should have received a copy of the GNU General Public License
> - * along with this program; if not, write to the Free Software
> - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
> - *
> - * Send feedback to <[email protected]>, <[email protected]>
> - *
> - */
> -
> -#include <linux/module.h>
> -#include <linux/kernel.h>
> -#include <linux/types.h>
> -#include <linux/sched.h>
> -#include <linux/pci.h>
> -#include <linux/slab.h>
> -#include "pciehp.h"
> -
> -void pciehp_get_hp_params_from_firmware(struct pci_dev *dev,
> - struct hotplug_params *hpp)
> -{
> - return;
> -}
> -
> -int pciehp_get_hp_hw_control_from_firmware(struct pci_dev *dev)
> -{
> - return 0;
> -}
> --- 2.6-git-gregkh.orig/drivers/pci/hotplug/shpchp.h
> +++ 2.6-git-gregkh/drivers/pci/hotplug/shpchp.h
> @@ -106,12 +106,6 @@ struct controller {
> volatile int cmd_busy;
> };
>
> -struct hotplug_params {
> - u8 cache_line_size;
> - u8 latency_timer;
> - u8 enable_serr;
> - u8 enable_perr;
> -};
>
> /* Define AMD SHPC ID */
> #define PCI_DEVICE_ID_AMD_GOLAM_7450 0x7450
> @@ -193,15 +187,24 @@ extern u8 shpchp_handle_power_fault(u8 h
> extern int shpchp_save_config(struct controller *ctrl, int busnumber, int num_ctlr_slots, int first_device_num);
> extern int shpchp_configure_device(struct slot *p_slot);
> extern int shpchp_unconfigure_device(struct slot *p_slot);
> -extern void get_hp_hw_control_from_firmware(struct pci_dev *dev);
> -extern void get_hp_params_from_firmware(struct pci_dev *dev,
> - struct hotplug_params *hpp);
> -extern int shpchprm_get_physical_slot_number(struct controller *ctrl,
> - u32 *sun, u8 busnum, u8 devnum);
> extern void shpchp_remove_ctrl_files(struct controller *ctrl);
> extern void cleanup_slots(struct controller *ctrl);
> extern void queue_pushbutton_work(void *data);
>
> +
> +#ifdef CONFIG_ACPI
> +#define get_hp_params_from_firmware(dev, hpp) \
> + acpi_get_hp_params_from_firmware(dev, hpp)
> +#define get_hp_hw_control_from_firmware(pdev) \
> + do { \
> + if (DEVICE_ACPI_HANDLE(&(pdev->dev))) \
> + acpi_run_oshp(DEVICE_ACPI_HANDLE(&(pdev->dev))); \
> + } while (0)
> +#else
> +#define get_hp_params_from_firmware(dev, hpp)
> +#define get_hp_hw_control_from_firmware(dev)
> +#endif
> +
> struct ctrl_reg {
> volatile u32 base_offset;
> volatile u32 slot_avail1;
> --- 2.6-git-gregkh.orig/drivers/pci/hotplug/shpchp_core.c
> +++ 2.6-git-gregkh/drivers/pci/hotplug/shpchp_core.c
> @@ -104,6 +104,23 @@ static void make_slot_name(struct slot *
> slot->bus, slot->number);
> }
>
> +
> +
> +
> +static int
> +shpchprm_get_physical_slot_number(struct controller *ctrl, u32 *sun,
> + u8 busnum, u8 devnum)
> +{
> + int offset = devnum - ctrl->slot_device_offset;
> +
> + dbg("%s: ctrl->slot_num_inc %d, offset %d\n", __FUNCTION__,
> + ctrl->slot_num_inc, offset);
> + *sun = (u8) (ctrl->first_slot + ctrl->slot_num_inc *offset);
> + return 0;
> +}
> +
> +
> +
> static int init_slots(struct controller *ctrl)
> {
> struct slot *slot;
> --- 2.6-git-gregkh.orig/drivers/pci/hotplug/shpchprm_acpi.c
> +++ /dev/null
> @@ -1,186 +0,0 @@
> -/*
> - * SHPCHPRM ACPI: PHP Resource Manager for ACPI platform
> - *
> - * Copyright (C) 2003-2004 Intel Corporation
> - *
> - * All rights reserved.
> - *
> - * This program is free software; you can redistribute it and/or modify
> - * it under the terms of the GNU General Public License as published by
> - * the Free Software Foundation; either version 2 of the License, or (at
> - * your option) any later version.
> - *
> - * This program is distributed in the hope that it will be useful, but
> - * WITHOUT ANY WARRANTY; without even the implied warranty of
> - * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
> - * NON INFRINGEMENT. See the GNU General Public License for more
> - * details.
> - *
> - * You should have received a copy of the GNU General Public License
> - * along with this program; if not, write to the Free Software
> - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
> - *
> - * Send feedback to <[email protected]>
> - *
> - */
> -
> -#include <linux/module.h>
> -#include <linux/kernel.h>
> -#include <linux/types.h>
> -#include <linux/pci.h>
> -#include <acpi/acpi.h>
> -#include <acpi/acpi_bus.h>
> -#include <acpi/actypes.h>
> -#include "shpchp.h"
> -
> -#define METHOD_NAME__SUN "_SUN"
> -#define METHOD_NAME__HPP "_HPP"
> -#define METHOD_NAME_OSHP "OSHP"
> -
> -static u8 * acpi_path_name( acpi_handle handle)
> -{
> - acpi_status status;
> - static u8 path_name[ACPI_PATHNAME_MAX];
> - struct acpi_buffer ret_buf = { ACPI_PATHNAME_MAX, path_name };
> -
> - memset(path_name, 0, sizeof (path_name));
> - status = acpi_get_name(handle, ACPI_FULL_PATHNAME, &ret_buf);
> -
> - if (ACPI_FAILURE(status))
> - return NULL;
> - else
> - return path_name;
> -}
> -
> -static acpi_status
> -acpi_run_hpp(acpi_handle handle, struct hotplug_params *hpp)
> -{
> - acpi_status status;
> - u8 nui[4];
> - struct acpi_buffer ret_buf = { 0, NULL};
> - union acpi_object *ext_obj, *package;
> - u8 *path_name = acpi_path_name(handle);
> - int i, len = 0;
> -
> - /* get _hpp */
> - status = acpi_evaluate_object(handle, METHOD_NAME__HPP, NULL, &ret_buf);
> - switch (status) {
> - case AE_BUFFER_OVERFLOW:
> - ret_buf.pointer = kmalloc (ret_buf.length, GFP_KERNEL);
> - if (!ret_buf.pointer) {
> - err ("%s:%s alloc for _HPP fail\n", __FUNCTION__,
> - path_name);
> - return AE_NO_MEMORY;
> - }
> - status = acpi_evaluate_object(handle, METHOD_NAME__HPP,
> - NULL, &ret_buf);
> - if (ACPI_SUCCESS(status))
> - break;
> - default:
> - if (ACPI_FAILURE(status)) {
> - dbg("%s:%s _HPP fail=0x%x\n", __FUNCTION__,
> - path_name, status);
> - return status;
> - }
> - }
> -
> - ext_obj = (union acpi_object *) ret_buf.pointer;
> - if (ext_obj->type != ACPI_TYPE_PACKAGE) {
> - err ("%s:%s _HPP obj not a package\n", __FUNCTION__,
> - path_name);
> - status = AE_ERROR;
> - goto free_and_return;
> - }
> -
> - len = ext_obj->package.count;
> - package = (union acpi_object *) ret_buf.pointer;
> - for ( i = 0; (i < len) || (i < 4); i++) {
> - ext_obj = (union acpi_object *) &package->package.elements[i];
> - switch (ext_obj->type) {
> - case ACPI_TYPE_INTEGER:
> - nui[i] = (u8)ext_obj->integer.value;
> - break;
> - default:
> - err ("%s:%s _HPP obj type incorrect\n", __FUNCTION__,
> - path_name);
> - status = AE_ERROR;
> - goto free_and_return;
> - }
> - }
> -
> - hpp->cache_line_size = nui[0];
> - hpp->latency_timer = nui[1];
> - hpp->enable_serr = nui[2];
> - hpp->enable_perr = nui[3];
> -
> - dbg(" _HPP: cache_line_size=0x%x\n", hpp->cache_line_size);
> - dbg(" _HPP: latency timer =0x%x\n", hpp->latency_timer);
> - dbg(" _HPP: enable SERR =0x%x\n", hpp->enable_serr);
> - dbg(" _HPP: enable PERR =0x%x\n", hpp->enable_perr);
> -
> -free_and_return:
> - kfree(ret_buf.pointer);
> - return status;
> -}
> -
> -static void acpi_run_oshp(acpi_handle handle)
> -{
> - acpi_status status;
> - u8 *path_name = acpi_path_name(handle);
> -
> - /* run OSHP */
> - status = acpi_evaluate_object(handle, METHOD_NAME_OSHP, NULL, NULL);
> - if (ACPI_FAILURE(status)) {
> - err("%s:%s OSHP fails=0x%x\n", __FUNCTION__, path_name,
> - status);
> - } else {
> - dbg("%s:%s OSHP passes\n", __FUNCTION__, path_name);
> - }
> -}
> -
> -int shpchprm_get_physical_slot_number(struct controller *ctrl, u32 *sun, u8 busnum, u8 devnum)
> -{
> - int offset = devnum - ctrl->slot_device_offset;
> -
> - dbg("%s: ctrl->slot_num_inc %d, offset %d\n", __FUNCTION__, ctrl->slot_num_inc, offset);
> - *sun = (u8) (ctrl->first_slot + ctrl->slot_num_inc *offset);
> - return 0;
> -}
> -
> -void get_hp_hw_control_from_firmware(struct pci_dev *dev)
> -{
> - /*
> - * OSHP is an optional ACPI firmware control method. If present,
> - * we need to run it to inform BIOS that we will control SHPC
> - * hardware from now on.
> - */
> - acpi_handle handle = DEVICE_ACPI_HANDLE(&(dev->dev));
> - if (!handle)
> - return;
> - acpi_run_oshp(handle);
> -}
> -
> -void get_hp_params_from_firmware(struct pci_dev *dev,
> - struct hotplug_params *hpp)
> -{
> - acpi_status status = AE_NOT_FOUND;
> - struct pci_dev *pdev = dev;
> -
> - /*
> - * _HPP settings apply to all child buses, until another _HPP is
> - * encountered. If we don't find an _HPP for the input pci dev,
> - * look for it in the parent device scope since that would apply to
> - * this pci dev. If we don't find any _HPP, use hardcoded defaults
> - */
> - while (pdev && (ACPI_FAILURE(status))) {
> - acpi_handle handle = DEVICE_ACPI_HANDLE(&(pdev->dev));
> - if (!handle)
> - break;
> - status = acpi_run_hpp(handle, hpp);
> - if (!(pdev->bus->parent))
> - break;
> - /* Check if a parent object supports _HPP */
> - pdev = pdev->bus->parent->self;
> - }
> -}
> -
> --- 2.6-git-gregkh.orig/drivers/pci/hotplug/shpchprm_legacy.c
> +++ /dev/null
> @@ -1,54 +0,0 @@
> -/*
> - * SHPCHPRM Legacy: PHP Resource Manager for Non-ACPI/Legacy platform
> - *
> - * Copyright (C) 1995,2001 Compaq Computer Corporation
> - * Copyright (C) 2001 Greg Kroah-Hartman ([email protected])
> - * Copyright (C) 2001 IBM Corp.
> - * Copyright (C) 2003-2004 Intel Corporation
> - *
> - * All rights reserved.
> - *
> - * This program is free software; you can redistribute it and/or modify
> - * it under the terms of the GNU General Public License as published by
> - * the Free Software Foundation; either version 2 of the License, or (at
> - * your option) any later version.
> - *
> - * This program is distributed in the hope that it will be useful, but
> - * WITHOUT ANY WARRANTY; without even the implied warranty of
> - * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
> - * NON INFRINGEMENT. See the GNU General Public License for more
> - * details.
> - *
> - * You should have received a copy of the GNU General Public License
> - * along with this program; if not, write to the Free Software
> - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
> - *
> - * Send feedback to <[email protected]>,<[email protected]>
> - *
> - */
> -
> -#include <linux/module.h>
> -#include <linux/kernel.h>
> -#include <linux/types.h>
> -#include <linux/pci.h>
> -#include "shpchp.h"
> -
> -int shpchprm_get_physical_slot_number(struct controller *ctrl, u32 *sun, u8 busnum, u8 devnum)
> -{
> - int offset = devnum - ctrl->slot_device_offset;
> -
> - *sun = (u8) (ctrl->first_slot + ctrl->slot_num_inc * offset);
> - return 0;
> -}
> -
> -void get_hp_params_from_firmware(struct pci_dev *dev,
> - struct hotplug_params *hpp)
> -{
> - return;
> -}
> -
> -void get_hp_hw_control_from_firmware(struct pci_dev *dev)
> -{
> - return;
> -}
> -
> --- 2.6-git-gregkh.orig/drivers/pci/hotplug/shpchprm_nonacpi.c
> +++ /dev/null
> @@ -1,57 +0,0 @@
> -/*
> - * SHPCHPRM NONACPI: PHP Resource Manager for Non-ACPI/Legacy platform
> - *
> - * Copyright (C) 1995,2001 Compaq Computer Corporation
> - * Copyright (C) 2001 Greg Kroah-Hartman ([email protected])
> - * Copyright (C) 2001 IBM Corp.
> - * Copyright (C) 2003-2004 Intel Corporation
> - *
> - * All rights reserved.
> - *
> - * This program is free software; you can redistribute it and/or modify
> - * it under the terms of the GNU General Public License as published by
> - * the Free Software Foundation; either version 2 of the License, or (at
> - * your option) any later version.
> - *
> - * This program is distributed in the hope that it will be useful, but
> - * WITHOUT ANY WARRANTY; without even the implied warranty of
> - * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
> - * NON INFRINGEMENT. See the GNU General Public License for more
> - * details.
> - *
> - * You should have received a copy of the GNU General Public License
> - * along with this program; if not, write to the Free Software
> - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
> - *
> - * Send feedback to <[email protected]>, <[email protected]>
> - *
> - */
> -
> -#include <linux/config.h>
> -#include <linux/module.h>
> -#include <linux/kernel.h>
> -#include <linux/types.h>
> -#include <linux/pci.h>
> -#include <linux/slab.h>
> -
> -#include "shpchp.h"
> -
> -int shpchprm_get_physical_slot_number(struct controller *ctrl, u32 *sun, u8 busnum, u8 devnum)
> -{
> - int offset = devnum - ctrl->slot_device_offset;
> -
> - dbg("%s: ctrl->slot_num_inc %d, offset %d\n", __FUNCTION__, ctrl->slot_num_inc, offset);
> - *sun = (u8) (ctrl->first_slot + ctrl->slot_num_inc * offset);
> - return 0;
> -}
> -
> -void get_hp_params_from_firmware(struct pci_dev *dev,
> - struct hotplug_params *hpp)
> -{
> - return;
> -}
> -
> -void get_hp_hw_control_from_firmware(struct pci_dev *dev)
> -{
> - return;
> -}
>
>
>
> -------------------------------------------------------
> This SF.Net email is sponsored by xPML, a groundbreaking scripting language
> that extends applications into web and mobile media. Attend the live webcast
> and join the prime developer group breaking into this new coding territory!
> http://sel.as-us.falkag.net/sel?cmd=lnk&kid=110944&bid=241720&dat=121642
> _______________________________________________
> Pcihpd-discuss mailing list
> [email protected]
> https://lists.sourceforge.net/lists/listinfo/pcihpd-discuss
>
On Wed, 2006-03-01 at 11:42 +0900, Kenji Kaneshige wrote:
> Hi Kristen,
>
> Here is one more comment.
>
> > +void acpi_get_hp_params_from_firmware(struct pci_dev *dev,
> > + struct hotplug_params *hpp)
> > +{
> > + acpi_status status = AE_NOT_FOUND;
> > + struct pci_dev *pdev = dev;
> > +
> > + /*
> > + * _HPP settings apply to all child buses, until another _HPP is
> > + * encountered. If we don't find an _HPP for the input pci dev,
> > + * look for it in the parent device scope since that would apply to
> > + * this pci dev. If we don't find any _HPP, use hardcoded defaults
> > + */
> > + while (pdev && (ACPI_FAILURE(status))) {
> > + acpi_handle handle = DEVICE_ACPI_HANDLE(&(pdev->dev));
> > + if (!handle)
> > + break;
> > + status = acpi_run_hpp(handle, hpp);
> > + if (!(pdev->bus->parent))
> > + break;
> > + /* Check if a parent object supports _HPP */
> > + pdev = pdev->bus->parent->self;
> > + }
> > +}
> > +EXPORT_SYMBOL_GPL(acpi_get_hp_params_from_firmware);
>
> I think the acpi_get_hp_params_from_firmware() function assumes that
> users set default hpp parameters into *hpp before calling this function.
> I think it is very hard for new users of the function to notice it, so
> I think this assumption should be removed.
>
> Thanks,
> Kenji Kaneshige
>
Are you suggesting that we have the defaults set within this function?
I would like to change acpiphp to use the same functions to get hpp
values eventually (in a different patch), but I notice that acpiphp sets
the default cache line size to 8, while shpchp sets the default cache
line size to 16. So it seems like it would be better to allow drivers
to set the default themselves, unless one of these drivers is doing the
wrong thing and using the wrong default value.
On Wed, 2006-03-01 at 11:03 +0900, Kenji Kaneshige wrote:
> Hi Kristen,
>
> This looks very nice to me!
>
> Here is one comment.
>
> > +int is_root_bridge(acpi_handle handle)
> > +{
> > + acpi_status status;
> > + struct acpi_device_info *info;
> > + struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
> > + int i;
> > +
> > + status = acpi_get_object_info(handle, &buffer);
> > + if (ACPI_SUCCESS(status)) {
> > + info = buffer.pointer;
> > + if ((info->valid & ACPI_VALID_HID) &&
> > + !strcmp(PCI_ROOT_HID_STRING,
> > + info->hardware_id.value)) {
> > + acpi_os_free(buffer.pointer);
> > + return 1;
> > + }
> > + if (info->valid & ACPI_VALID_CID) {
> > + for (i=0; i < info->compatibility_id.count; i++) {
> > + if (!strcmp(PCI_ROOT_HID_STRING,
> > + info->compatibility_id.id[i].value)) {
> > + acpi_os_free(buffer.pointer);
> > + return 1;
> > + }
> > + }
> > + }
> > + }
> > + return 0;
> > +}
> > +EXPORT_SYMBOL_GPL(is_root_bridge);
>
> I think this seems to leak memory (buffer.pointer), though
> I guess you just copy and paste from the original code. I think
> we need to free buffer.pointer whenever acpi_get_object_info()
> returns as success.
>
> Thanks,
> Kenji Kaneshige
Ah hah, you are right. Yes, I did just cut and paste the original code
- and this just makes me happy I'm doing this because this bug is
currently duplicated in 2 drivers since they all cut and pasted the same
buggy code. Soon we will just share the same 1 piece of buggy code.
Kristen Accardi wrote:
> On Wed, 2006-03-01 at 11:42 +0900, Kenji Kaneshige wrote:
>
>>Hi Kristen,
>>
>>Here is one more comment.
>>
>>
>>>+void acpi_get_hp_params_from_firmware(struct pci_dev *dev,
>>>+ struct hotplug_params *hpp)
>>>+{
>>>+ acpi_status status = AE_NOT_FOUND;
>>>+ struct pci_dev *pdev = dev;
>>>+
>>>+ /*
>>>+ * _HPP settings apply to all child buses, until another _HPP is
>>>+ * encountered. If we don't find an _HPP for the input pci dev,
>>>+ * look for it in the parent device scope since that would apply to
>>>+ * this pci dev. If we don't find any _HPP, use hardcoded defaults
>>>+ */
>>>+ while (pdev && (ACPI_FAILURE(status))) {
>>>+ acpi_handle handle = DEVICE_ACPI_HANDLE(&(pdev->dev));
>>>+ if (!handle)
>>>+ break;
>>>+ status = acpi_run_hpp(handle, hpp);
>>>+ if (!(pdev->bus->parent))
>>>+ break;
>>>+ /* Check if a parent object supports _HPP */
>>>+ pdev = pdev->bus->parent->self;
>>>+ }
>>>+}
>>>+EXPORT_SYMBOL_GPL(acpi_get_hp_params_from_firmware);
>>
>>I think the acpi_get_hp_params_from_firmware() function assumes that
>>users set default hpp parameters into *hpp before calling this function.
>>I think it is very hard for new users of the function to notice it, so
>>I think this assumption should be removed.
>>
>>Thanks,
>>Kenji Kaneshige
>>
>
>
> Are you suggesting that we have the defaults set within this function?
> I would like to change acpiphp to use the same functions to get hpp
> values eventually (in a different patch), but I notice that acpiphp sets
> the default cache line size to 8, while shpchp sets the default cache
> line size to 16. So it seems like it would be better to allow drivers
> to set the default themselves, unless one of these drivers is doing the
> wrong thing and using the wrong default value.
>
The other options are:
(a) Leave the code as it is, and put the comments to indicate users
how to use this function. That is, users have to set defaults
before calling this function, otherwise the parameters returned
from the function would be undefined.
(b) Change the return value to let users know whether _HPP parameters
were successfully parsed.
I'd prefer (b).
I'm attaching the sample patch for (b), though I've not tested it at all.
This patch is against 2.6.16-rc5-mm1 with the following patches applied
- shpchp: cleanup bus speed handling
- acpiphp: Scan slots under the nested P2P bridge
- Your set of patches
Thanks,
Kenji Kaneshige
---
drivers/pci/hotplug/acpi_pcihp.c | 4 +++-
drivers/pci/hotplug/pci_hotplug.h | 2 +-
drivers/pci/hotplug/pciehp.h | 9 +++++++++
drivers/pci/hotplug/shpchp.h | 12 +++++++++---
drivers/pci/hotplug/shpchp_pci.c | 15 +++++++++++++--
5 files changed, 35 insertions(+), 7 deletions(-)
Index: linux-2.6.16-rc5-mm1/drivers/pci/hotplug/acpi_pcihp.c
===================================================================
--- linux-2.6.16-rc5-mm1.orig/drivers/pci/hotplug/acpi_pcihp.c 2006-03-02 10:47:08.000000000 +0900
+++ linux-2.6.16-rc5-mm1/drivers/pci/hotplug/acpi_pcihp.c 2006-03-02 11:05:01.000000000 +0900
@@ -143,7 +143,7 @@
-void acpi_get_hp_params_from_firmware(struct pci_dev *dev,
+acpi_status acpi_get_hp_params_from_firmware(struct pci_dev *dev,
struct hotplug_params *hpp)
{
acpi_status status = AE_NOT_FOUND;
@@ -165,6 +165,8 @@
/* Check if a parent object supports _HPP */
pdev = pdev->bus->parent->self;
}
+
+ return status;
}
EXPORT_SYMBOL_GPL(acpi_get_hp_params_from_firmware);
Index: linux-2.6.16-rc5-mm1/drivers/pci/hotplug/pci_hotplug.h
===================================================================
--- linux-2.6.16-rc5-mm1.orig/drivers/pci/hotplug/pci_hotplug.h 2006-03-02 10:47:08.000000000 +0900
+++ linux-2.6.16-rc5-mm1/drivers/pci/hotplug/pci_hotplug.h 2006-03-02 11:05:35.000000000 +0900
@@ -188,7 +188,7 @@
#include <acpi/acpi_bus.h>
#include <acpi/actypes.h>
extern acpi_status acpi_run_oshp(acpi_handle handle);
-extern void acpi_get_hp_params_from_firmware(struct pci_dev *dev,
+extern acpi_status acpi_get_hp_params_from_firmware(struct pci_dev *dev,
struct hotplug_params *hpp);
extern u8 * acpi_path_name( acpi_handle handle);
int is_root_bridge(acpi_handle handle);
Index: linux-2.6.16-rc5-mm1/drivers/pci/hotplug/shpchp.h
===================================================================
--- linux-2.6.16-rc5-mm1.orig/drivers/pci/hotplug/shpchp.h 2006-03-02 10:47:08.000000000 +0900
+++ linux-2.6.16-rc5-mm1/drivers/pci/hotplug/shpchp.h 2006-03-02 11:25:20.000000000 +0900
@@ -193,15 +193,21 @@
#ifdef CONFIG_ACPI
-#define get_hp_params_from_firmware(dev, hpp) \
- acpi_get_hp_params_from_firmware(dev, hpp)
+static inline int get_hp_params_from_firmware(struct pci_dev *dev,
+ struct hotplug_params *hpp)
+{
+ acpi_status status = acpi_get_hp_params_from_firmware(dev, hpp);
+ if (ACPI_FAILURE(status))
+ return -ENODEV;
+ return 0;
+}
#define get_hp_hw_control_from_firmware(pdev) \
do { \
if (DEVICE_ACPI_HANDLE(&(pdev->dev))) \
acpi_run_oshp(DEVICE_ACPI_HANDLE(&(pdev->dev))); \
} while (0)
#else
-#define get_hp_params_from_firmware(dev, hpp)
+#define get_hp_params_from_firmware(dev, hpp) (-ENODEV)
#define get_hp_hw_control_from_firmware(dev)
#endif
Index: linux-2.6.16-rc5-mm1/drivers/pci/hotplug/shpchp_pci.c
===================================================================
--- linux-2.6.16-rc5-mm1.orig/drivers/pci/hotplug/shpchp_pci.c 2006-03-01 13:53:27.000000000 +0900
+++ linux-2.6.16-rc5-mm1/drivers/pci/hotplug/shpchp_pci.c 2006-03-02 11:32:52.000000000 +0900
@@ -38,7 +38,8 @@
{
u16 pci_cmd, pci_bctl;
struct pci_dev *cdev;
- struct hotplug_params hpp = {0x8, 0x40, 0, 0}; /* defaults */
+ struct hotplug_params hpp;
+ int rc;
/* Program hpp values for this device */
if (!(dev->hdr_type == PCI_HEADER_TYPE_NORMAL ||
@@ -46,7 +47,17 @@
(dev->class >> 8) == PCI_CLASS_BRIDGE_PCI)))
return;
- get_hp_params_from_firmware(dev, &hpp);
+ rc = get_hp_params_from_firmware(dev, &hpp);
+ if (rc) {
+ /*
+ * If we could not get hotplug parameters from
+ * firmware, use hardcoded defaults.
+ */
+ hpp.cache_line_size = 0x8;
+ hpp.latency_timer = 0x40;
+ hpp.enable_serr = 0;
+ hpp.enable_perr = 0;
+ }
pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, hpp.cache_line_size);
pci_write_config_byte(dev, PCI_LATENCY_TIMER, hpp.latency_timer);
Index: linux-2.6.16-rc5-mm1/drivers/pci/hotplug/pciehp.h
===================================================================
--- linux-2.6.16-rc5-mm1.orig/drivers/pci/hotplug/pciehp.h 2006-03-02 10:47:08.000000000 +0900
+++ linux-2.6.16-rc5-mm1/drivers/pci/hotplug/pciehp.h 2006-03-02 11:44:47.000000000 +0900
@@ -281,10 +281,19 @@
#ifdef CONFIG_ACPI
#define pciehp_get_hp_hw_control_from_firmware(dev) \
pciehp_acpi_get_hp_hw_control_from_firmware(dev)
+static inline int pciehp_get_hp_params_from_firmware(struct pci_dev *dev,
+ struct hotplug_params *hpp)
+{
+ acpi_status status = acpi_get_hp_params_from_firmware(dev, hpp);
+ if (ACPI_FAILURE(status))
+ return -ENODEV;
+ return 0;
+}
#define pciehp_get_hp_params_from_firmware(dev, hpp) \
acpi_get_hp_params_from_firmware(dev, hpp)
#else
#define pciehp_get_hp_hw_control_from_firmware(dev) 0
#define acpi_get_hp_params_from_firmware(dev, hpp)
+#define pciehp_get_hp_params_from_firmware(dev, hpp) (-ENODEV)
#endif /* CONFIG_ACPI */
#endif /* _PCIEHP_H */
On Thu, 2006-03-02 at 12:18 +0900, Kenji Kaneshige wrote:
> Kristen Accardi wrote:
> > On Wed, 2006-03-01 at 11:42 +0900, Kenji Kaneshige wrote:
> >
> >>Hi Kristen,
> >>
> >>Here is one more comment.
> >>
> >>
> >>>+void acpi_get_hp_params_from_firmware(struct pci_dev *dev,
> >>>+ struct hotplug_params *hpp)
> >>>+{
> >>>+ acpi_status status = AE_NOT_FOUND;
> >>>+ struct pci_dev *pdev = dev;
> >>>+
> >>>+ /*
> >>>+ * _HPP settings apply to all child buses, until another _HPP is
> >>>+ * encountered. If we don't find an _HPP for the input pci dev,
> >>>+ * look for it in the parent device scope since that would apply to
> >>>+ * this pci dev. If we don't find any _HPP, use hardcoded defaults
> >>>+ */
> >>>+ while (pdev && (ACPI_FAILURE(status))) {
> >>>+ acpi_handle handle = DEVICE_ACPI_HANDLE(&(pdev->dev));
> >>>+ if (!handle)
> >>>+ break;
> >>>+ status = acpi_run_hpp(handle, hpp);
> >>>+ if (!(pdev->bus->parent))
> >>>+ break;
> >>>+ /* Check if a parent object supports _HPP */
> >>>+ pdev = pdev->bus->parent->self;
> >>>+ }
> >>>+}
> >>>+EXPORT_SYMBOL_GPL(acpi_get_hp_params_from_firmware);
> >>
> >>I think the acpi_get_hp_params_from_firmware() function assumes that
> >>users set default hpp parameters into *hpp before calling this function.
> >>I think it is very hard for new users of the function to notice it, so
> >>I think this assumption should be removed.
> >>
> >>Thanks,
> >>Kenji Kaneshige
> >>
> >
> >
> > Are you suggesting that we have the defaults set within this function?
> > I would like to change acpiphp to use the same functions to get hpp
> > values eventually (in a different patch), but I notice that acpiphp sets
> > the default cache line size to 8, while shpchp sets the default cache
> > line size to 16. So it seems like it would be better to allow drivers
> > to set the default themselves, unless one of these drivers is doing the
> > wrong thing and using the wrong default value.
> >
>
> The other options are:
>
> (a) Leave the code as it is, and put the comments to indicate users
> how to use this function. That is, users have to set defaults
> before calling this function, otherwise the parameters returned
> from the function would be undefined.
>
> (b) Change the return value to let users know whether _HPP parameters
> were successfully parsed.
>
> I'd prefer (b).
> I'm attaching the sample patch for (b), though I've not tested it at all.
> This patch is against 2.6.16-rc5-mm1 with the following patches applied
>
> - shpchp: cleanup bus speed handling
> - acpiphp: Scan slots under the nested P2P bridge
> - Your set of patches
>
> Thanks,
> Kenji Kaneshige
>
Kenji,
Thanks for the feedback, I will implement (b) as part of my next patch
which also incorporates all the other feedback I've gotten - coming
hopefully tomorrow or so.
Kristen
shpchprm_acpi.c and pciehprm_acpi.c are nearly identical.
In addition, there are functions in both these files that
are also in acpiphp_glue.c. This patch will remove duplicate
functions from shpchp, pciehp, and acpiphp and move this
functionality to pci_hotplug, as it is not hardware specific.
Get rid of shpchprm* and pciehprm* files since they are no longer needed.
shpchprm_nonacpi.c and pciehprm_nonacpi.c are identical, as well
as shpchprm_legacy.c and can be replaced with a macro.
This patch also changes acpiphp to use the common hpp code.
Signed-off-by: Kristen Carlson Accardi <[email protected]>
---
dev/null |binary
dev/null |binary
drivers/pci/hotplug/pciehprm_acpi.c | 257 ---------------------------------
drivers/pci/hotplug/pciehprm_nonacpi.c | 47 ------
drivers/pci/hotplug/shpchprm_acpi.c | 186 -----------------------
drivers/pci/hotplug/shpchprm_legacy.c | 54 ------
drivers/pci/hotplug/shpchprm_nonacpi.c | 57 -------
drivers/pci/hotplug/Makefile | 17 --
drivers/pci/hotplug/acpi_pcihp.c | 227 +++++++++++++++++++++++++++++
drivers/pci/hotplug/acpiphp.h | 15 -
drivers/pci/hotplug/acpiphp_glue.c | 91 +----------
drivers/pci/hotplug/pci_hotplug.h | 17 ++
drivers/pci/hotplug/pciehp.h | 24 +--
drivers/pci/hotplug/pciehp_hpc.c | 74 +++++++++
drivers/pci/hotplug/shpchp.h | 30 ++-
drivers/pci/hotplug/shpchp_core.c | 17 ++
drivers/pci/hotplug/shpchp_pci.c | 10 +
15 files changed, 393 insertions(+), 730 deletions(-)
--- 2.6-git-gregkh.orig/drivers/pci/hotplug/Makefile
+++ 2.6-git-gregkh/drivers/pci/hotplug/Makefile
@@ -22,6 +22,9 @@ ifdef CONFIG_HOTPLUG_PCI_CPCI
pci_hotplug-objs += cpci_hotplug_core.o \
cpci_hotplug_pci.o
endif
+ifdef CONFIG_ACPI
+pci_hotplug-objs += acpi_pcihp.o
+endif
cpqphp-objs := cpqphp_core.o \
cpqphp_ctrl.o \
@@ -51,23 +54,9 @@ pciehp-objs := pciehp_core.o \
pciehp_ctrl.o \
pciehp_pci.o \
pciehp_hpc.o
-ifdef CONFIG_ACPI
- pciehp-objs += pciehprm_acpi.o
-else
- pciehp-objs += pciehprm_nonacpi.o
-endif
shpchp-objs := shpchp_core.o \
shpchp_ctrl.o \
shpchp_pci.o \
shpchp_sysfs.o \
shpchp_hpc.o
-ifdef CONFIG_ACPI
- shpchp-objs += shpchprm_acpi.o
-else
- ifdef CONFIG_HOTPLUG_PCI_SHPC_PHPRM_LEGACY
- shpchp-objs += shpchprm_legacy.o
- else
- shpchp-objs += shpchprm_nonacpi.o
- endif
-endif
--- /dev/null
+++ 2.6-git-gregkh/drivers/pci/hotplug/acpi_pcihp.c
@@ -0,0 +1,227 @@
+/*
+ * Common ACPI functions for hot plug platforms
+ *
+ * Copyright (C) 2006 Intel Corporation
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Send feedback to <[email protected]>
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <acpi/acpi.h>
+#include <acpi/acpi_bus.h>
+#include <acpi/actypes.h>
+#include "pci_hotplug.h"
+
+#define METHOD_NAME__SUN "_SUN"
+#define METHOD_NAME__HPP "_HPP"
+#define METHOD_NAME_OSHP "OSHP"
+
+/* acpi_path_name
+ *
+ * @handle - the acpi_handle of the object who's name you want.
+ *
+ * Caller must free buffer.
+ */
+u8 * acpi_path_name(acpi_handle handle)
+{
+ acpi_status status;
+ struct acpi_buffer ret_buf = {ACPI_ALLOCATE_BUFFER, NULL};
+ union acpi_object *obj;
+
+ status = acpi_get_name(handle, ACPI_FULL_PATHNAME, &ret_buf);
+ if (ACPI_FAILURE(status)) {
+ return NULL;
+ }
+ obj = ret_buf.pointer;
+ return obj->string.pointer;
+}
+EXPORT_SYMBOL_GPL(acpi_path_name);
+
+
+
+static acpi_status
+acpi_run_hpp(acpi_handle handle, struct hotplug_params *hpp)
+{
+ acpi_status status;
+ u8 nui[4];
+ struct acpi_buffer ret_buf = { 0, NULL};
+ union acpi_object *ext_obj, *package;
+ u8 *path_name = acpi_path_name(handle);
+ int i, len = 0;
+
+ /* get _hpp */
+ status = acpi_evaluate_object(handle, METHOD_NAME__HPP, NULL, &ret_buf);
+ switch (status) {
+ case AE_BUFFER_OVERFLOW:
+ ret_buf.pointer = kmalloc (ret_buf.length, GFP_KERNEL);
+ if (!ret_buf.pointer) {
+ printk(KERN_ERR "%s:%s alloc for _HPP fail\n",
+ __FUNCTION__, path_name);
+ acpi_os_free(path_name);
+ return AE_NO_MEMORY;
+ }
+ status = acpi_evaluate_object(handle, METHOD_NAME__HPP,
+ NULL, &ret_buf);
+ if (ACPI_SUCCESS(status))
+ break;
+ default:
+ if (ACPI_FAILURE(status)) {
+ pr_debug("%s:%s _HPP fail=0x%x\n", __FUNCTION__,
+ path_name, status);
+ acpi_os_free(path_name);
+ return status;
+ }
+ }
+
+ ext_obj = (union acpi_object *) ret_buf.pointer;
+ if (ext_obj->type != ACPI_TYPE_PACKAGE) {
+ printk(KERN_ERR "%s:%s _HPP obj not a package\n", __FUNCTION__,
+ path_name);
+ status = AE_ERROR;
+ goto free_and_return;
+ }
+
+ len = ext_obj->package.count;
+ package = (union acpi_object *) ret_buf.pointer;
+ for ( i = 0; (i < len) || (i < 4); i++) {
+ ext_obj = (union acpi_object *) &package->package.elements[i];
+ switch (ext_obj->type) {
+ case ACPI_TYPE_INTEGER:
+ nui[i] = (u8)ext_obj->integer.value;
+ break;
+ default:
+ printk(KERN_ERR "%s:%s _HPP obj type incorrect\n",
+ __FUNCTION__, path_name);
+ status = AE_ERROR;
+ goto free_and_return;
+ }
+ }
+
+ hpp->cache_line_size = nui[0];
+ hpp->latency_timer = nui[1];
+ hpp->enable_serr = nui[2];
+ hpp->enable_perr = nui[3];
+
+ pr_debug(" _HPP: cache_line_size=0x%x\n", hpp->cache_line_size);
+ pr_debug(" _HPP: latency timer =0x%x\n", hpp->latency_timer);
+ pr_debug(" _HPP: enable SERR =0x%x\n", hpp->enable_serr);
+ pr_debug(" _HPP: enable PERR =0x%x\n", hpp->enable_perr);
+
+free_and_return:
+ acpi_os_free(path_name);
+ kfree(ret_buf.pointer);
+ return status;
+}
+
+
+
+/* acpi_run_oshp - get control of hotplug from the firmware
+ *
+ * @handle - the handle of the hotplug controller.
+ */
+acpi_status acpi_run_oshp(acpi_handle handle)
+{
+ acpi_status status;
+ u8 *path_name = acpi_path_name(handle);
+
+ /* run OSHP */
+ status = acpi_evaluate_object(handle, METHOD_NAME_OSHP, NULL, NULL);
+ if (ACPI_FAILURE(status))
+ printk(KERN_ERR "%s:%s OSHP fails=0x%x\n", __FUNCTION__,
+ path_name, status);
+ else
+ pr_debug("%s:%s OSHP passes\n", __FUNCTION__, path_name);
+ acpi_os_free(path_name);
+ return status;
+}
+EXPORT_SYMBOL_GPL(acpi_run_oshp);
+
+
+
+/* acpi_get_hp_params_from_firmware
+ *
+ * @dev - the pci_dev of the newly added device
+ * @hpp - allocated by the caller
+ */
+acpi_status acpi_get_hp_params_from_firmware(struct pci_dev *dev,
+ struct hotplug_params *hpp)
+{
+ acpi_status status = AE_NOT_FOUND;
+ struct pci_dev *pdev = dev;
+
+ /*
+ * _HPP settings apply to all child buses, until another _HPP is
+ * encountered. If we don't find an _HPP for the input pci dev,
+ * look for it in the parent device scope since that would apply to
+ * this pci dev. If we don't find any _HPP, use hardcoded defaults
+ */
+ while (pdev && (ACPI_FAILURE(status))) {
+ acpi_handle handle = DEVICE_ACPI_HANDLE(&(pdev->dev));
+ if (!handle)
+ break;
+ status = acpi_run_hpp(handle, hpp);
+ if (!(pdev->bus->parent))
+ break;
+ /* Check if a parent object supports _HPP */
+ pdev = pdev->bus->parent->self;
+ }
+ return status;
+}
+EXPORT_SYMBOL_GPL(acpi_get_hp_params_from_firmware);
+
+
+/* acpi_root_bridge - check to see if this acpi object is a root bridge
+ *
+ * @handle - the acpi object in question.
+ */
+int acpi_root_bridge(acpi_handle handle)
+{
+ acpi_status status;
+ struct acpi_device_info *info;
+ struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
+ int i;
+
+ status = acpi_get_object_info(handle, &buffer);
+ if (ACPI_SUCCESS(status)) {
+ info = buffer.pointer;
+ if ((info->valid & ACPI_VALID_HID) &&
+ !strcmp(PCI_ROOT_HID_STRING,
+ info->hardware_id.value)) {
+ acpi_os_free(buffer.pointer);
+ return 1;
+ }
+ if (info->valid & ACPI_VALID_CID) {
+ for (i=0; i < info->compatibility_id.count; i++) {
+ if (!strcmp(PCI_ROOT_HID_STRING,
+ info->compatibility_id.id[i].value)) {
+ acpi_os_free(buffer.pointer);
+ return 1;
+ }
+ }
+ }
+ acpi_os_free(buffer.pointer);
+ }
+ return 0;
+}
+EXPORT_SYMBOL_GPL(acpi_root_bridge);
--- 2.6-git-gregkh.orig/drivers/pci/hotplug/acpiphp_glue.c
+++ 2.6-git-gregkh/drivers/pci/hotplug/acpiphp_glue.c
@@ -287,57 +287,19 @@ static int detect_ejectable_slots(acpi_h
static void decode_hpp(struct acpiphp_bridge *bridge)
{
acpi_status status;
- struct acpi_buffer buffer = { .length = ACPI_ALLOCATE_BUFFER,
- .pointer = NULL};
- union acpi_object *package;
- int i;
-
- /* default numbers */
- bridge->hpp.cache_line_size = 0x10;
- bridge->hpp.latency_timer = 0x40;
- bridge->hpp.enable_SERR = 0;
- bridge->hpp.enable_PERR = 0;
-
- status = acpi_evaluate_object(bridge->handle, "_HPP", NULL, &buffer);
+ status = acpi_get_hp_params_from_firmware(bridge->pci_dev, &bridge->hpp);
if (ACPI_FAILURE(status)) {
- dbg("_HPP evaluation failed\n");
- return;
- }
-
- package = (union acpi_object *) buffer.pointer;
-
- if (!package || package->type != ACPI_TYPE_PACKAGE ||
- package->package.count != 4 || !package->package.elements) {
- err("invalid _HPP object; ignoring\n");
- goto err_exit;
+ /* use default numbers */
+ bridge->hpp.cache_line_size = 0x10;
+ bridge->hpp.latency_timer = 0x40;
+ bridge->hpp.enable_serr = 0;
+ bridge->hpp.enable_perr = 0;
}
-
- for (i = 0; i < 4; i++) {
- if (package->package.elements[i].type != ACPI_TYPE_INTEGER) {
- err("invalid _HPP parameter type; ignoring\n");
- goto err_exit;
- }
- }
-
- bridge->hpp.cache_line_size = package->package.elements[0].integer.value;
- bridge->hpp.latency_timer = package->package.elements[1].integer.value;
- bridge->hpp.enable_SERR = package->package.elements[2].integer.value;
- bridge->hpp.enable_PERR = package->package.elements[3].integer.value;
-
- dbg("_HPP parameter = (%02x, %02x, %02x, %02x)\n",
- bridge->hpp.cache_line_size,
- bridge->hpp.latency_timer,
- bridge->hpp.enable_SERR,
- bridge->hpp.enable_PERR);
-
- bridge->flags |= BRIDGE_HAS_HPP;
-
- err_exit:
- kfree(buffer.pointer);
}
+
/* initialize miscellaneous stuff for both root and PCI-to-PCI bridge */
static void init_bridge_misc(struct acpiphp_bridge *bridge)
{
@@ -1153,11 +1115,11 @@ static void program_hpp(struct pci_dev *
pci_write_config_byte(dev, PCI_LATENCY_TIMER,
bridge->hpp.latency_timer);
pci_read_config_word(dev, PCI_COMMAND, &pci_cmd);
- if (bridge->hpp.enable_SERR)
+ if (bridge->hpp.enable_serr)
pci_cmd |= PCI_COMMAND_SERR;
else
pci_cmd &= ~PCI_COMMAND_SERR;
- if (bridge->hpp.enable_PERR)
+ if (bridge->hpp.enable_perr)
pci_cmd |= PCI_COMMAND_PARITY;
else
pci_cmd &= ~PCI_COMMAND_PARITY;
@@ -1168,11 +1130,11 @@ static void program_hpp(struct pci_dev *
pci_write_config_byte(dev, PCI_SEC_LATENCY_TIMER,
bridge->hpp.latency_timer);
pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &pci_bctl);
- if (bridge->hpp.enable_SERR)
+ if (bridge->hpp.enable_serr)
pci_bctl |= PCI_BRIDGE_CTL_SERR;
else
pci_bctl &= ~PCI_BRIDGE_CTL_SERR;
- if (bridge->hpp.enable_PERR)
+ if (bridge->hpp.enable_perr)
pci_bctl |= PCI_BRIDGE_CTL_PARITY;
else
pci_bctl &= ~PCI_BRIDGE_CTL_PARITY;
@@ -1192,6 +1154,7 @@ static void acpiphp_set_hpp_values(acpi_
memset(&bridge, 0, sizeof(bridge));
bridge.handle = handle;
+ bridge.pci_dev = bus->self;
decode_hpp(&bridge);
list_for_each_entry(dev, &bus->devices, bus_list)
program_hpp(dev, &bridge);
@@ -1408,41 +1371,13 @@ void handle_hotplug_event_func(acpi_hand
}
}
-static int is_root_bridge(acpi_handle handle)
-{
- acpi_status status;
- struct acpi_device_info *info;
- struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
- int i;
-
- status = acpi_get_object_info(handle, &buffer);
- if (ACPI_SUCCESS(status)) {
- info = buffer.pointer;
- if ((info->valid & ACPI_VALID_HID) &&
- !strcmp(PCI_ROOT_HID_STRING,
- info->hardware_id.value)) {
- acpi_os_free(buffer.pointer);
- return 1;
- }
- if (info->valid & ACPI_VALID_CID) {
- for (i=0; i < info->compatibility_id.count; i++) {
- if (!strcmp(PCI_ROOT_HID_STRING,
- info->compatibility_id.id[i].value)) {
- acpi_os_free(buffer.pointer);
- return 1;
- }
- }
- }
- }
- return 0;
-}
static acpi_status
find_root_bridges(acpi_handle handle, u32 lvl, void *context, void **rv)
{
int *count = (int *)context;
- if (is_root_bridge(handle)) {
+ if (acpi_root_bridge(handle)) {
acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
handle_hotplug_event_bridge, NULL);
(*count)++;
--- 2.6-git-gregkh.orig/drivers/pci/hotplug/pci_hotplug.h
+++ 2.6-git-gregkh/drivers/pci/hotplug/pci_hotplug.h
@@ -176,5 +176,22 @@ extern int pci_hp_change_slot_info (stru
struct hotplug_slot_info *info);
extern struct subsystem pci_hotplug_slots_subsys;
+struct hotplug_params {
+ u8 cache_line_size;
+ u8 latency_timer;
+ u8 enable_serr;
+ u8 enable_perr;
+};
+
+#ifdef CONFIG_ACPI
+#include <acpi/acpi.h>
+#include <acpi/acpi_bus.h>
+#include <acpi/actypes.h>
+extern acpi_status acpi_run_oshp(acpi_handle handle);
+extern acpi_status acpi_get_hp_params_from_firmware(struct pci_dev *dev,
+ struct hotplug_params *hpp);
+extern u8 * acpi_path_name(acpi_handle handle);
+int acpi_root_bridge(acpi_handle handle);
+#endif
#endif
--- 2.6-git-gregkh.orig/drivers/pci/hotplug/pciehp.h
+++ 2.6-git-gregkh/drivers/pci/hotplug/pciehp.h
@@ -50,12 +50,6 @@ extern int pciehp_force;
#define info(format, arg...) printk(KERN_INFO "%s: " format, MY_NAME , ## arg)
#define warn(format, arg...) printk(KERN_WARNING "%s: " format, MY_NAME , ## arg)
-struct hotplug_params {
- u8 cache_line_size;
- u8 latency_timer;
- u8 enable_serr;
- u8 enable_perr;
-};
struct slot {
struct slot *next;
@@ -192,9 +186,6 @@ extern u8 pciehp_handle_power_fault (u8
/* pci functions */
extern int pciehp_configure_device (struct slot *p_slot);
extern int pciehp_unconfigure_device (struct slot *p_slot);
-extern int pciehp_get_hp_hw_control_from_firmware(struct pci_dev *dev);
-extern void pciehp_get_hp_params_from_firmware(struct pci_dev *dev,
- struct hotplug_params *hpp);
@@ -286,4 +277,19 @@ struct hpc_ops {
int (*check_lnk_status) (struct controller *ctrl);
};
+
+#ifdef CONFIG_ACPI
+#define pciehp_get_hp_hw_control_from_firmware(dev) \
+ pciehp_acpi_get_hp_hw_control_from_firmware(dev)
+static inline int pciehp_get_hp_params_from_firmware(struct pci_dev *dev,
+ struct hotplug_params *hpp)
+{
+ if (ACPI_FAILURE(acpi_get_hp_params_from_firmware(dev, hpp)))
+ return -ENODEV;
+ return 0;
+}
+#else
+#define pciehp_get_hp_hw_control_from_firmware(dev) 0
+#define pciehp_get_hp_params_from_firmware(dev, hpp) (-ENODEV)
+#endif /* CONFIG_ACPI */
#endif /* _PCIEHP_H */
--- 2.6-git-gregkh.orig/drivers/pci/hotplug/pciehp_hpc.c
+++ 2.6-git-gregkh/drivers/pci/hotplug/pciehp_hpc.c
@@ -38,7 +38,10 @@
#include "../pci.h"
#include "pciehp.h"
-
+#include <acpi/acpi.h>
+#include <acpi/acpi_bus.h>
+#include <acpi/actypes.h>
+#include <linux/pci-acpi.h>
#ifdef DEBUG
#define DBG_K_TRACE_ENTRY ((unsigned int)0x00000001) /* On function entry */
#define DBG_K_TRACE_EXIT ((unsigned int)0x00000002) /* On function exit */
@@ -1236,6 +1239,75 @@ static struct hpc_ops pciehp_hpc_ops = {
.check_lnk_status = hpc_check_lnk_status,
};
+#ifdef CONFIG_ACPI
+int pciehp_acpi_get_hp_hw_control_from_firmware(struct pci_dev *dev)
+{
+ acpi_status status;
+ acpi_handle chandle, handle = DEVICE_ACPI_HANDLE(&(dev->dev));
+ struct pci_dev *pdev = dev;
+ struct pci_bus *parent;
+ u8 *path_name = NULL;
+
+ /*
+ * Per PCI firmware specification, we should run the ACPI _OSC
+ * method to get control of hotplug hardware before using it.
+ * If an _OSC is missing, we look for an OSHP to do the same thing.
+ * To handle different BIOS behavior, we look for _OSC and OSHP
+ * within the scope of the hotplug controller and its parents, upto
+ * the host bridge under which this controller exists.
+ */
+ while (!handle) {
+ /*
+ * This hotplug controller was not listed in the ACPI name
+ * space at all. Try to get acpi handle of parent pci bus.
+ */
+ if (!pdev || !pdev->bus->parent)
+ break;
+ parent = pdev->bus->parent;
+ dbg("Could not find %s in acpi namespace, trying parent\n",
+ pci_name(pdev));
+ if (!parent->self)
+ /* Parent must be a host bridge */
+ handle = acpi_get_pci_rootbridge_handle(
+ pci_domain_nr(parent),
+ parent->number);
+ else
+ handle = DEVICE_ACPI_HANDLE(
+ &(parent->self->dev));
+ pdev = parent->self;
+ }
+
+ while (handle) {
+ path_name = acpi_path_name(handle);
+ dbg("Trying to get hotplug control for %s \n", path_name);
+ status = pci_osc_control_set(handle,
+ OSC_PCI_EXPRESS_NATIVE_HP_CONTROL);
+ if (status == AE_NOT_FOUND)
+ status = acpi_run_oshp(handle);
+ if (ACPI_SUCCESS(status)) {
+ dbg("Gained control for hotplug HW for pci %s (%s)\n",
+ pci_name(dev), path_name);
+ acpi_os_free(path_name);
+ return 0;
+ }
+ if (acpi_root_bridge(handle))
+ break;
+ chandle = handle;
+ status = acpi_get_parent(chandle, &handle);
+ if (ACPI_FAILURE(status))
+ break;
+ }
+
+ err("Cannot get control of hotplug hardware for pci %s\n",
+ pci_name(dev));
+ if (path_name)
+ acpi_os_free(path_name);
+ return -1;
+}
+#endif
+
+
+
int pcie_init(struct controller * ctrl, struct pcie_device *dev)
{
struct php_ctlr_state_s *php_ctlr, *p;
--- 2.6-git-gregkh.orig/drivers/pci/hotplug/pciehprm_acpi.c
+++ /dev/null
@@ -1,257 +0,0 @@
-/*
- * PCIEHPRM ACPI: PHP Resource Manager for ACPI platform
- *
- * Copyright (C) 2003-2004 Intel Corporation
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or (at
- * your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
- * NON INFRINGEMENT. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Send feedback to <[email protected]>
- *
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/pci.h>
-#include <linux/acpi.h>
-#include <linux/pci-acpi.h>
-#include <acpi/acpi_bus.h>
-#include <acpi/actypes.h>
-#include "pciehp.h"
-
-#define METHOD_NAME__SUN "_SUN"
-#define METHOD_NAME__HPP "_HPP"
-#define METHOD_NAME_OSHP "OSHP"
-
-static u8 * acpi_path_name( acpi_handle handle)
-{
- acpi_status status;
- static u8 path_name[ACPI_PATHNAME_MAX];
- struct acpi_buffer ret_buf = { ACPI_PATHNAME_MAX, path_name };
-
- memset(path_name, 0, sizeof (path_name));
- status = acpi_get_name(handle, ACPI_FULL_PATHNAME, &ret_buf);
-
- if (ACPI_FAILURE(status))
- return NULL;
- else
- return path_name;
-}
-
-static acpi_status
-acpi_run_hpp(acpi_handle handle, struct hotplug_params *hpp)
-{
- acpi_status status;
- u8 nui[4];
- struct acpi_buffer ret_buf = { 0, NULL};
- union acpi_object *ext_obj, *package;
- u8 *path_name = acpi_path_name(handle);
- int i, len = 0;
-
- /* get _hpp */
- status = acpi_evaluate_object(handle, METHOD_NAME__HPP, NULL, &ret_buf);
- switch (status) {
- case AE_BUFFER_OVERFLOW:
- ret_buf.pointer = kmalloc (ret_buf.length, GFP_KERNEL);
- if (!ret_buf.pointer) {
- err ("%s:%s alloc for _HPP fail\n", __FUNCTION__,
- path_name);
- return AE_NO_MEMORY;
- }
- status = acpi_evaluate_object(handle, METHOD_NAME__HPP,
- NULL, &ret_buf);
- if (ACPI_SUCCESS(status))
- break;
- default:
- if (ACPI_FAILURE(status)) {
- dbg("%s:%s _HPP fail=0x%x\n", __FUNCTION__,
- path_name, status);
- return status;
- }
- }
-
- ext_obj = (union acpi_object *) ret_buf.pointer;
- if (ext_obj->type != ACPI_TYPE_PACKAGE) {
- err ("%s:%s _HPP obj not a package\n", __FUNCTION__,
- path_name);
- status = AE_ERROR;
- goto free_and_return;
- }
-
- len = ext_obj->package.count;
- package = (union acpi_object *) ret_buf.pointer;
- for ( i = 0; (i < len) || (i < 4); i++) {
- ext_obj = (union acpi_object *) &package->package.elements[i];
- switch (ext_obj->type) {
- case ACPI_TYPE_INTEGER:
- nui[i] = (u8)ext_obj->integer.value;
- break;
- default:
- err ("%s:%s _HPP obj type incorrect\n", __FUNCTION__,
- path_name);
- status = AE_ERROR;
- goto free_and_return;
- }
- }
-
- hpp->cache_line_size = nui[0];
- hpp->latency_timer = nui[1];
- hpp->enable_serr = nui[2];
- hpp->enable_perr = nui[3];
-
- dbg(" _HPP: cache_line_size=0x%x\n", hpp->cache_line_size);
- dbg(" _HPP: latency timer =0x%x\n", hpp->latency_timer);
- dbg(" _HPP: enable SERR =0x%x\n", hpp->enable_serr);
- dbg(" _HPP: enable PERR =0x%x\n", hpp->enable_perr);
-
-free_and_return:
- kfree(ret_buf.pointer);
- return status;
-}
-
-static acpi_status acpi_run_oshp(acpi_handle handle)
-{
- acpi_status status;
- u8 *path_name = acpi_path_name(handle);
-
- /* run OSHP */
- status = acpi_evaluate_object(handle, METHOD_NAME_OSHP, NULL, NULL);
- if (ACPI_FAILURE(status)) {
- dbg("%s:%s OSHP fails=0x%x\n", __FUNCTION__, path_name,
- status);
- } else {
- dbg("%s:%s OSHP passes\n", __FUNCTION__, path_name);
- }
- return status;
-}
-
-static int is_root_bridge(acpi_handle handle)
-{
- acpi_status status;
- struct acpi_device_info *info;
- struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
- int i;
-
- status = acpi_get_object_info(handle, &buffer);
- if (ACPI_SUCCESS(status)) {
- info = buffer.pointer;
- if ((info->valid & ACPI_VALID_HID) &&
- !strcmp(PCI_ROOT_HID_STRING,
- info->hardware_id.value)) {
- acpi_os_free(buffer.pointer);
- return 1;
- }
- if (info->valid & ACPI_VALID_CID) {
- for (i=0; i < info->compatibility_id.count; i++) {
- if (!strcmp(PCI_ROOT_HID_STRING,
- info->compatibility_id.id[i].value)) {
- acpi_os_free(buffer.pointer);
- return 1;
- }
- }
- }
- }
- return 0;
-}
-
-int pciehp_get_hp_hw_control_from_firmware(struct pci_dev *dev)
-{
- acpi_status status;
- acpi_handle chandle, handle = DEVICE_ACPI_HANDLE(&(dev->dev));
- struct pci_dev *pdev = dev;
- struct pci_bus *parent;
- u8 *path_name;
-
- /*
- * Per PCI firmware specification, we should run the ACPI _OSC
- * method to get control of hotplug hardware before using it.
- * If an _OSC is missing, we look for an OSHP to do the same thing.
- * To handle different BIOS behavior, we look for _OSC and OSHP
- * within the scope of the hotplug controller and its parents, upto
- * the host bridge under which this controller exists.
- */
- while (!handle) {
- /*
- * This hotplug controller was not listed in the ACPI name
- * space at all. Try to get acpi handle of parent pci bus.
- */
- if (!pdev || !pdev->bus->parent)
- break;
- parent = pdev->bus->parent;
- dbg("Could not find %s in acpi namespace, trying parent\n",
- pci_name(pdev));
- if (!parent->self)
- /* Parent must be a host bridge */
- handle = acpi_get_pci_rootbridge_handle(
- pci_domain_nr(parent),
- parent->number);
- else
- handle = DEVICE_ACPI_HANDLE(
- &(parent->self->dev));
- pdev = parent->self;
- }
-
- while (handle) {
- path_name = acpi_path_name(handle);
- dbg("Trying to get hotplug control for %s \n", path_name);
- status = pci_osc_control_set(handle,
- OSC_PCI_EXPRESS_NATIVE_HP_CONTROL);
- if (status == AE_NOT_FOUND)
- status = acpi_run_oshp(handle);
- if (ACPI_SUCCESS(status)) {
- dbg("Gained control for hotplug HW for pci %s (%s)\n",
- pci_name(dev), path_name);
- return 0;
- }
- if (is_root_bridge(handle))
- break;
- chandle = handle;
- status = acpi_get_parent(chandle, &handle);
- if (ACPI_FAILURE(status))
- break;
- }
-
- err("Cannot get control of hotplug hardware for pci %s\n",
- pci_name(dev));
- return -1;
-}
-
-void pciehp_get_hp_params_from_firmware(struct pci_dev *dev,
- struct hotplug_params *hpp)
-{
- acpi_status status = AE_NOT_FOUND;
- struct pci_dev *pdev = dev;
-
- /*
- * _HPP settings apply to all child buses, until another _HPP is
- * encountered. If we don't find an _HPP for the input pci dev,
- * look for it in the parent device scope since that would apply to
- * this pci dev. If we don't find any _HPP, use hardcoded defaults
- */
- while (pdev && (ACPI_FAILURE(status))) {
- acpi_handle handle = DEVICE_ACPI_HANDLE(&(pdev->dev));
- if (!handle)
- break;
- status = acpi_run_hpp(handle, hpp);
- if (!(pdev->bus->parent))
- break;
- /* Check if a parent object supports _HPP */
- pdev = pdev->bus->parent->self;
- }
-}
-
--- 2.6-git-gregkh.orig/drivers/pci/hotplug/pciehprm_nonacpi.c
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * PCIEHPRM NONACPI: PHP Resource Manager for Non-ACPI/Legacy platform
- *
- * Copyright (C) 1995,2001 Compaq Computer Corporation
- * Copyright (C) 2001 Greg Kroah-Hartman ([email protected])
- * Copyright (C) 2001 IBM Corp.
- * Copyright (C) 2003-2004 Intel Corporation
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or (at
- * your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
- * NON INFRINGEMENT. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Send feedback to <[email protected]>, <[email protected]>
- *
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/sched.h>
-#include <linux/pci.h>
-#include <linux/slab.h>
-#include "pciehp.h"
-
-void pciehp_get_hp_params_from_firmware(struct pci_dev *dev,
- struct hotplug_params *hpp)
-{
- return;
-}
-
-int pciehp_get_hp_hw_control_from_firmware(struct pci_dev *dev)
-{
- return 0;
-}
--- 2.6-git-gregkh.orig/drivers/pci/hotplug/shpchp.h
+++ 2.6-git-gregkh/drivers/pci/hotplug/shpchp.h
@@ -106,12 +106,6 @@ struct controller {
volatile int cmd_busy;
};
-struct hotplug_params {
- u8 cache_line_size;
- u8 latency_timer;
- u8 enable_serr;
- u8 enable_perr;
-};
/* Define AMD SHPC ID */
#define PCI_DEVICE_ID_AMD_GOLAM_7450 0x7450
@@ -193,15 +187,29 @@ extern u8 shpchp_handle_power_fault(u8 h
extern int shpchp_save_config(struct controller *ctrl, int busnumber, int num_ctlr_slots, int first_device_num);
extern int shpchp_configure_device(struct slot *p_slot);
extern int shpchp_unconfigure_device(struct slot *p_slot);
-extern void get_hp_hw_control_from_firmware(struct pci_dev *dev);
-extern void get_hp_params_from_firmware(struct pci_dev *dev,
- struct hotplug_params *hpp);
-extern int shpchprm_get_physical_slot_number(struct controller *ctrl,
- u32 *sun, u8 busnum, u8 devnum);
extern void shpchp_remove_ctrl_files(struct controller *ctrl);
extern void cleanup_slots(struct controller *ctrl);
extern void queue_pushbutton_work(void *data);
+
+#ifdef CONFIG_ACPI
+static inline int get_hp_params_from_firmware(struct pci_dev *dev,
+ struct hotplug_params *hpp)
+{
+ if (ACPI_FAILURE(acpi_get_hp_params_from_firmware(dev, hpp)))
+ return -ENODEV;
+ return 0;
+}
+#define get_hp_hw_control_from_firmware(pdev) \
+ do { \
+ if (DEVICE_ACPI_HANDLE(&(pdev->dev))) \
+ acpi_run_oshp(DEVICE_ACPI_HANDLE(&(pdev->dev))); \
+ } while (0)
+#else
+#define get_hp_params_from_firmware(dev, hpp) (-ENODEV)
+#define get_hp_hw_control_from_firmware(dev) do { } while (0)
+#endif
+
struct ctrl_reg {
volatile u32 base_offset;
volatile u32 slot_avail1;
--- 2.6-git-gregkh.orig/drivers/pci/hotplug/shpchp_core.c
+++ 2.6-git-gregkh/drivers/pci/hotplug/shpchp_core.c
@@ -104,6 +104,23 @@ static void make_slot_name(struct slot *
slot->bus, slot->number);
}
+
+
+
+static int
+shpchprm_get_physical_slot_number(struct controller *ctrl, u32 *sun,
+ u8 busnum, u8 devnum)
+{
+ int offset = devnum - ctrl->slot_device_offset;
+
+ dbg("%s: ctrl->slot_num_inc %d, offset %d\n", __FUNCTION__,
+ ctrl->slot_num_inc, offset);
+ *sun = (u8) (ctrl->first_slot + ctrl->slot_num_inc *offset);
+ return 0;
+}
+
+
+
static int init_slots(struct controller *ctrl)
{
struct slot *slot;
--- 2.6-git-gregkh.orig/drivers/pci/hotplug/shpchprm_acpi.c
+++ /dev/null
@@ -1,186 +0,0 @@
-/*
- * SHPCHPRM ACPI: PHP Resource Manager for ACPI platform
- *
- * Copyright (C) 2003-2004 Intel Corporation
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or (at
- * your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
- * NON INFRINGEMENT. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Send feedback to <[email protected]>
- *
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/pci.h>
-#include <acpi/acpi.h>
-#include <acpi/acpi_bus.h>
-#include <acpi/actypes.h>
-#include "shpchp.h"
-
-#define METHOD_NAME__SUN "_SUN"
-#define METHOD_NAME__HPP "_HPP"
-#define METHOD_NAME_OSHP "OSHP"
-
-static u8 * acpi_path_name( acpi_handle handle)
-{
- acpi_status status;
- static u8 path_name[ACPI_PATHNAME_MAX];
- struct acpi_buffer ret_buf = { ACPI_PATHNAME_MAX, path_name };
-
- memset(path_name, 0, sizeof (path_name));
- status = acpi_get_name(handle, ACPI_FULL_PATHNAME, &ret_buf);
-
- if (ACPI_FAILURE(status))
- return NULL;
- else
- return path_name;
-}
-
-static acpi_status
-acpi_run_hpp(acpi_handle handle, struct hotplug_params *hpp)
-{
- acpi_status status;
- u8 nui[4];
- struct acpi_buffer ret_buf = { 0, NULL};
- union acpi_object *ext_obj, *package;
- u8 *path_name = acpi_path_name(handle);
- int i, len = 0;
-
- /* get _hpp */
- status = acpi_evaluate_object(handle, METHOD_NAME__HPP, NULL, &ret_buf);
- switch (status) {
- case AE_BUFFER_OVERFLOW:
- ret_buf.pointer = kmalloc (ret_buf.length, GFP_KERNEL);
- if (!ret_buf.pointer) {
- err ("%s:%s alloc for _HPP fail\n", __FUNCTION__,
- path_name);
- return AE_NO_MEMORY;
- }
- status = acpi_evaluate_object(handle, METHOD_NAME__HPP,
- NULL, &ret_buf);
- if (ACPI_SUCCESS(status))
- break;
- default:
- if (ACPI_FAILURE(status)) {
- dbg("%s:%s _HPP fail=0x%x\n", __FUNCTION__,
- path_name, status);
- return status;
- }
- }
-
- ext_obj = (union acpi_object *) ret_buf.pointer;
- if (ext_obj->type != ACPI_TYPE_PACKAGE) {
- err ("%s:%s _HPP obj not a package\n", __FUNCTION__,
- path_name);
- status = AE_ERROR;
- goto free_and_return;
- }
-
- len = ext_obj->package.count;
- package = (union acpi_object *) ret_buf.pointer;
- for ( i = 0; (i < len) || (i < 4); i++) {
- ext_obj = (union acpi_object *) &package->package.elements[i];
- switch (ext_obj->type) {
- case ACPI_TYPE_INTEGER:
- nui[i] = (u8)ext_obj->integer.value;
- break;
- default:
- err ("%s:%s _HPP obj type incorrect\n", __FUNCTION__,
- path_name);
- status = AE_ERROR;
- goto free_and_return;
- }
- }
-
- hpp->cache_line_size = nui[0];
- hpp->latency_timer = nui[1];
- hpp->enable_serr = nui[2];
- hpp->enable_perr = nui[3];
-
- dbg(" _HPP: cache_line_size=0x%x\n", hpp->cache_line_size);
- dbg(" _HPP: latency timer =0x%x\n", hpp->latency_timer);
- dbg(" _HPP: enable SERR =0x%x\n", hpp->enable_serr);
- dbg(" _HPP: enable PERR =0x%x\n", hpp->enable_perr);
-
-free_and_return:
- kfree(ret_buf.pointer);
- return status;
-}
-
-static void acpi_run_oshp(acpi_handle handle)
-{
- acpi_status status;
- u8 *path_name = acpi_path_name(handle);
-
- /* run OSHP */
- status = acpi_evaluate_object(handle, METHOD_NAME_OSHP, NULL, NULL);
- if (ACPI_FAILURE(status)) {
- err("%s:%s OSHP fails=0x%x\n", __FUNCTION__, path_name,
- status);
- } else {
- dbg("%s:%s OSHP passes\n", __FUNCTION__, path_name);
- }
-}
-
-int shpchprm_get_physical_slot_number(struct controller *ctrl, u32 *sun, u8 busnum, u8 devnum)
-{
- int offset = devnum - ctrl->slot_device_offset;
-
- dbg("%s: ctrl->slot_num_inc %d, offset %d\n", __FUNCTION__, ctrl->slot_num_inc, offset);
- *sun = (u8) (ctrl->first_slot + ctrl->slot_num_inc *offset);
- return 0;
-}
-
-void get_hp_hw_control_from_firmware(struct pci_dev *dev)
-{
- /*
- * OSHP is an optional ACPI firmware control method. If present,
- * we need to run it to inform BIOS that we will control SHPC
- * hardware from now on.
- */
- acpi_handle handle = DEVICE_ACPI_HANDLE(&(dev->dev));
- if (!handle)
- return;
- acpi_run_oshp(handle);
-}
-
-void get_hp_params_from_firmware(struct pci_dev *dev,
- struct hotplug_params *hpp)
-{
- acpi_status status = AE_NOT_FOUND;
- struct pci_dev *pdev = dev;
-
- /*
- * _HPP settings apply to all child buses, until another _HPP is
- * encountered. If we don't find an _HPP for the input pci dev,
- * look for it in the parent device scope since that would apply to
- * this pci dev. If we don't find any _HPP, use hardcoded defaults
- */
- while (pdev && (ACPI_FAILURE(status))) {
- acpi_handle handle = DEVICE_ACPI_HANDLE(&(pdev->dev));
- if (!handle)
- break;
- status = acpi_run_hpp(handle, hpp);
- if (!(pdev->bus->parent))
- break;
- /* Check if a parent object supports _HPP */
- pdev = pdev->bus->parent->self;
- }
-}
-
--- 2.6-git-gregkh.orig/drivers/pci/hotplug/shpchprm_legacy.c
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * SHPCHPRM Legacy: PHP Resource Manager for Non-ACPI/Legacy platform
- *
- * Copyright (C) 1995,2001 Compaq Computer Corporation
- * Copyright (C) 2001 Greg Kroah-Hartman ([email protected])
- * Copyright (C) 2001 IBM Corp.
- * Copyright (C) 2003-2004 Intel Corporation
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or (at
- * your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
- * NON INFRINGEMENT. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Send feedback to <[email protected]>,<[email protected]>
- *
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/pci.h>
-#include "shpchp.h"
-
-int shpchprm_get_physical_slot_number(struct controller *ctrl, u32 *sun, u8 busnum, u8 devnum)
-{
- int offset = devnum - ctrl->slot_device_offset;
-
- *sun = (u8) (ctrl->first_slot + ctrl->slot_num_inc * offset);
- return 0;
-}
-
-void get_hp_params_from_firmware(struct pci_dev *dev,
- struct hotplug_params *hpp)
-{
- return;
-}
-
-void get_hp_hw_control_from_firmware(struct pci_dev *dev)
-{
- return;
-}
-
--- 2.6-git-gregkh.orig/drivers/pci/hotplug/shpchprm_nonacpi.c
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * SHPCHPRM NONACPI: PHP Resource Manager for Non-ACPI/Legacy platform
- *
- * Copyright (C) 1995,2001 Compaq Computer Corporation
- * Copyright (C) 2001 Greg Kroah-Hartman ([email protected])
- * Copyright (C) 2001 IBM Corp.
- * Copyright (C) 2003-2004 Intel Corporation
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or (at
- * your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
- * NON INFRINGEMENT. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Send feedback to <[email protected]>, <[email protected]>
- *
- */
-
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/pci.h>
-#include <linux/slab.h>
-
-#include "shpchp.h"
-
-int shpchprm_get_physical_slot_number(struct controller *ctrl, u32 *sun, u8 busnum, u8 devnum)
-{
- int offset = devnum - ctrl->slot_device_offset;
-
- dbg("%s: ctrl->slot_num_inc %d, offset %d\n", __FUNCTION__, ctrl->slot_num_inc, offset);
- *sun = (u8) (ctrl->first_slot + ctrl->slot_num_inc * offset);
- return 0;
-}
-
-void get_hp_params_from_firmware(struct pci_dev *dev,
- struct hotplug_params *hpp)
-{
- return;
-}
-
-void get_hp_hw_control_from_firmware(struct pci_dev *dev)
-{
- return;
-}
--- 2.6-git-gregkh.orig/drivers/pci/hotplug/shpchp_pci.c
+++ 2.6-git-gregkh/drivers/pci/hotplug/shpchp_pci.c
@@ -38,7 +38,7 @@ static void program_fw_provided_values(s
{
u16 pci_cmd, pci_bctl;
struct pci_dev *cdev;
- struct hotplug_params hpp = {0x8, 0x40, 0, 0}; /* defaults */
+ struct hotplug_params hpp;
/* Program hpp values for this device */
if (!(dev->hdr_type == PCI_HEADER_TYPE_NORMAL ||
@@ -46,7 +46,13 @@ static void program_fw_provided_values(s
(dev->class >> 8) == PCI_CLASS_BRIDGE_PCI)))
return;
- get_hp_params_from_firmware(dev, &hpp);
+ /* use default values if we can't get them from firmware */
+ if (get_hp_params_from_firmware(dev, &hpp)) {
+ hpp.cache_line_size = 8;
+ hpp.latency_timer = 0x40;
+ hpp.enable_serr = 0;
+ hpp.enable_perr = 0;
+ }
pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, hpp.cache_line_size);
pci_write_config_byte(dev, PCI_LATENCY_TIMER, hpp.latency_timer);
--- 2.6-git-gregkh.orig/drivers/pci/hotplug/acpiphp.h
+++ 2.6-git-gregkh/drivers/pci/hotplug/acpiphp.h
@@ -64,19 +64,6 @@ struct slot {
struct acpiphp_slot *acpi_slot;
};
-/**
- * struct hpp_param - ACPI 2.0 _HPP Hot Plug Parameters
- * @cache_line_size in DWORD
- * @latency_timer in PCI clock
- * @enable_SERR 0 or 1
- * @enable_PERR 0 or 1
- */
-struct hpp_param {
- u8 cache_line_size;
- u8 latency_timer;
- u8 enable_SERR;
- u8 enable_PERR;
-};
/**
@@ -100,7 +87,7 @@ struct acpiphp_bridge {
struct pci_dev *pci_dev;
/* ACPI 2.0 _HPP parameters */
- struct hpp_param hpp;
+ struct hotplug_params hpp;
spinlock_t res_lock;
};