Skip to content

Commit

Permalink
[PATCH] PCI Hotplug: add common acpi functions to core
Browse files Browse the repository at this point in the history
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 <kristen.c.accardi@intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
  • Loading branch information
Kristen Accardi authored and Greg Kroah-Hartman committed Mar 23, 2006
1 parent f5afe80 commit 783c49f
Show file tree
Hide file tree
Showing 14 changed files with 254 additions and 591 deletions.
17 changes: 3 additions & 14 deletions drivers/pci/hotplug/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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 \
Expand Down Expand Up @@ -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
206 changes: 88 additions & 118 deletions drivers/pci/hotplug/pciehprm_acpi.c → drivers/pci/hotplug/acpi_pcihp.c
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
* PCIEHPRM ACPI: PHP Resource Manager for ACPI platform
* Common ACPI functions for hot plug platforms
*
* Copyright (C) 2003-2004 Intel Corporation
* Copyright (C) 2006 Intel Corporation
*
* All rights reserved.
*
Expand All @@ -28,30 +28,37 @@
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/pci.h>
#include <linux/acpi.h>
#include <linux/pci-acpi.h>
#include <acpi/acpi.h>
#include <acpi/acpi_bus.h>
#include <acpi/actypes.h>
#include "pciehp.h"
#include "pci_hotplug.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_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;
static u8 path_name[ACPI_PATHNAME_MAX];
struct acpi_buffer ret_buf = { ACPI_PATHNAME_MAX, path_name };
acpi_status status;
struct acpi_buffer ret_buf = {ACPI_ALLOCATE_BUFFER, NULL};
union acpi_object *obj;

memset(path_name, 0, sizeof (path_name));
status = acpi_get_name(handle, ACPI_FULL_PATHNAME, &ret_buf);

if (ACPI_FAILURE(status))
if (ACPI_FAILURE(status)) {
return NULL;
else
return path_name;
}
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)
Expand All @@ -69,8 +76,9 @@ acpi_run_hpp(acpi_handle handle, struct hotplug_params *hpp)
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);
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,
Expand All @@ -79,15 +87,16 @@ acpi_run_hpp(acpi_handle handle, struct hotplug_params *hpp)
break;
default:
if (ACPI_FAILURE(status)) {
dbg("%s:%s _HPP fail=0x%x\n", __FUNCTION__,
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) {
err ("%s:%s _HPP obj not a package\n", __FUNCTION__,
printk(KERN_ERR "%s:%s _HPP obj not a package\n", __FUNCTION__,
path_name);
status = AE_ERROR;
goto free_and_return;
Expand All @@ -102,8 +111,8 @@ acpi_run_hpp(acpi_handle handle, struct hotplug_params *hpp)
nui[i] = (u8)ext_obj->integer.value;
break;
default:
err ("%s:%s _HPP obj type incorrect\n", __FUNCTION__,
path_name);
printk(KERN_ERR "%s:%s _HPP obj type incorrect\n",
__FUNCTION__, path_name);
status = AE_ERROR;
goto free_and_return;
}
Expand All @@ -114,33 +123,79 @@ acpi_run_hpp(acpi_handle handle, struct hotplug_params *hpp)
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);
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;
}

static acpi_status acpi_run_oshp(acpi_handle handle)


/* 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)) {
dbg("%s:%s OSHP fails=0x%x\n", __FUNCTION__, path_name,
status);
} else {
dbg("%s:%s OSHP passes\n", __FUNCTION__, path_name);
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);


static int is_root_bridge(acpi_handle handle)
/* 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;
Expand All @@ -165,93 +220,8 @@ static int is_root_bridge(acpi_handle handle)
}
}
}
acpi_os_free(buffer.pointer);
}
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;
}
}

EXPORT_SYMBOL_GPL(acpi_root_bridge);
15 changes: 1 addition & 14 deletions drivers/pci/hotplug/acpiphp.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
};


/**
Expand All @@ -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;
};
Expand Down
Loading

0 comments on commit 783c49f

Please sign in to comment.