mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-11 21:38:32 +08:00
Merge master.kernel.org:/pub/scm/linux/kernel/git/gregkh/pci-2.6
* master.kernel.org:/pub/scm/linux/kernel/git/gregkh/pci-2.6: (30 commits) [PATCH] PCI Hotplug: Fix recovery path from errors during pcie_init() [PATCH] PCI Hotplug: fake NULL pointer dereferences in IBM Hot Plug Controller Driver [PATCH] shpchp: Cleanup improper info messages [PATCH] shpchp: Remove Unused hpc_evelnt_lock [PATCH] shpchp: Cleanup interrupt polling timer [PATCH] shpchp: Cleanup SHPC commands [PATCH] shpchp: Cleanup interrupt handler [PATCH] shpchp: Remove unnecessary hpc_ctlr_handle check [PATCH] pciehp: Implement get_address callback [PATCH] pciehp: Add missing pci_dev_put [PATCH] pciehp: Replace pci_find_slot() with pci_get_slot() [PATCH] SGI Hotplug: Incorrect power status [PATCH] shpchp: Create shpchpd at controller probe time [PATCH] shpchp: Mask Global SERR and Intr at controller release time [PATCH] SHPC: Fix SHPC Contoller SERR-INT Register bits access [PATCH] SHPC: Fix SHPC Logical Slot Register bits access [PATCH] SHPC: Cleanup SHPC Logical Slot Register bits access [PATCH] SHPC: Cleanup SHPC Logical Slot Register access [PATCH] SHPC: Cleanup SHPC register access [PATCH] pciehp: Fix programming hotplug parameters ...
This commit is contained in:
commit
789e7dc8ee
@ -25,6 +25,7 @@
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/pci.h>
|
||||
@ -33,10 +34,184 @@
|
||||
#include <acpi/actypes.h>
|
||||
#include "pci_hotplug.h"
|
||||
|
||||
#define MY_NAME "acpi_pcihp"
|
||||
|
||||
#define dbg(fmt, arg...) do { if (debug_acpi) printk(KERN_DEBUG "%s: %s: " fmt , MY_NAME , __FUNCTION__ , ## arg); } while (0)
|
||||
#define err(format, arg...) printk(KERN_ERR "%s: " format , MY_NAME , ## arg)
|
||||
#define info(format, arg...) printk(KERN_INFO "%s: " format , MY_NAME , ## arg)
|
||||
#define warn(format, arg...) printk(KERN_WARNING "%s: " format , MY_NAME , ## arg)
|
||||
|
||||
#define METHOD_NAME__SUN "_SUN"
|
||||
#define METHOD_NAME__HPP "_HPP"
|
||||
#define METHOD_NAME_OSHP "OSHP"
|
||||
|
||||
static int debug_acpi;
|
||||
|
||||
static acpi_status
|
||||
decode_type0_hpx_record(union acpi_object *record, struct hotplug_params *hpx)
|
||||
{
|
||||
int i;
|
||||
union acpi_object *fields = record->package.elements;
|
||||
u32 revision = fields[1].integer.value;
|
||||
|
||||
switch (revision) {
|
||||
case 1:
|
||||
if (record->package.count != 6)
|
||||
return AE_ERROR;
|
||||
for (i = 2; i < 6; i++)
|
||||
if (fields[i].type != ACPI_TYPE_INTEGER)
|
||||
return AE_ERROR;
|
||||
hpx->t0 = &hpx->type0_data;
|
||||
hpx->t0->revision = revision;
|
||||
hpx->t0->cache_line_size = fields[2].integer.value;
|
||||
hpx->t0->latency_timer = fields[3].integer.value;
|
||||
hpx->t0->enable_serr = fields[4].integer.value;
|
||||
hpx->t0->enable_perr = fields[5].integer.value;
|
||||
break;
|
||||
default:
|
||||
printk(KERN_WARNING
|
||||
"%s: Type 0 Revision %d record not supported\n",
|
||||
__FUNCTION__, revision);
|
||||
return AE_ERROR;
|
||||
}
|
||||
return AE_OK;
|
||||
}
|
||||
|
||||
static acpi_status
|
||||
decode_type1_hpx_record(union acpi_object *record, struct hotplug_params *hpx)
|
||||
{
|
||||
int i;
|
||||
union acpi_object *fields = record->package.elements;
|
||||
u32 revision = fields[1].integer.value;
|
||||
|
||||
switch (revision) {
|
||||
case 1:
|
||||
if (record->package.count != 5)
|
||||
return AE_ERROR;
|
||||
for (i = 2; i < 5; i++)
|
||||
if (fields[i].type != ACPI_TYPE_INTEGER)
|
||||
return AE_ERROR;
|
||||
hpx->t1 = &hpx->type1_data;
|
||||
hpx->t1->revision = revision;
|
||||
hpx->t1->max_mem_read = fields[2].integer.value;
|
||||
hpx->t1->avg_max_split = fields[3].integer.value;
|
||||
hpx->t1->tot_max_split = fields[4].integer.value;
|
||||
break;
|
||||
default:
|
||||
printk(KERN_WARNING
|
||||
"%s: Type 1 Revision %d record not supported\n",
|
||||
__FUNCTION__, revision);
|
||||
return AE_ERROR;
|
||||
}
|
||||
return AE_OK;
|
||||
}
|
||||
|
||||
static acpi_status
|
||||
decode_type2_hpx_record(union acpi_object *record, struct hotplug_params *hpx)
|
||||
{
|
||||
int i;
|
||||
union acpi_object *fields = record->package.elements;
|
||||
u32 revision = fields[1].integer.value;
|
||||
|
||||
switch (revision) {
|
||||
case 1:
|
||||
if (record->package.count != 18)
|
||||
return AE_ERROR;
|
||||
for (i = 2; i < 18; i++)
|
||||
if (fields[i].type != ACPI_TYPE_INTEGER)
|
||||
return AE_ERROR;
|
||||
hpx->t2 = &hpx->type2_data;
|
||||
hpx->t2->revision = revision;
|
||||
hpx->t2->unc_err_mask_and = fields[2].integer.value;
|
||||
hpx->t2->unc_err_mask_or = fields[3].integer.value;
|
||||
hpx->t2->unc_err_sever_and = fields[4].integer.value;
|
||||
hpx->t2->unc_err_sever_or = fields[5].integer.value;
|
||||
hpx->t2->cor_err_mask_and = fields[6].integer.value;
|
||||
hpx->t2->cor_err_mask_or = fields[7].integer.value;
|
||||
hpx->t2->adv_err_cap_and = fields[8].integer.value;
|
||||
hpx->t2->adv_err_cap_or = fields[9].integer.value;
|
||||
hpx->t2->pci_exp_devctl_and = fields[10].integer.value;
|
||||
hpx->t2->pci_exp_devctl_or = fields[11].integer.value;
|
||||
hpx->t2->pci_exp_lnkctl_and = fields[12].integer.value;
|
||||
hpx->t2->pci_exp_lnkctl_or = fields[13].integer.value;
|
||||
hpx->t2->sec_unc_err_sever_and = fields[14].integer.value;
|
||||
hpx->t2->sec_unc_err_sever_or = fields[15].integer.value;
|
||||
hpx->t2->sec_unc_err_mask_and = fields[16].integer.value;
|
||||
hpx->t2->sec_unc_err_mask_or = fields[17].integer.value;
|
||||
break;
|
||||
default:
|
||||
printk(KERN_WARNING
|
||||
"%s: Type 2 Revision %d record not supported\n",
|
||||
__FUNCTION__, revision);
|
||||
return AE_ERROR;
|
||||
}
|
||||
return AE_OK;
|
||||
}
|
||||
|
||||
static acpi_status
|
||||
acpi_run_hpx(acpi_handle handle, struct hotplug_params *hpx)
|
||||
{
|
||||
acpi_status status;
|
||||
struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
|
||||
union acpi_object *package, *record, *fields;
|
||||
u32 type;
|
||||
int i;
|
||||
|
||||
/* Clear the return buffer with zeros */
|
||||
memset(hpx, 0, sizeof(struct hotplug_params));
|
||||
|
||||
status = acpi_evaluate_object(handle, "_HPX", NULL, &buffer);
|
||||
if (ACPI_FAILURE(status))
|
||||
return status;
|
||||
|
||||
package = (union acpi_object *)buffer.pointer;
|
||||
if (package->type != ACPI_TYPE_PACKAGE) {
|
||||
status = AE_ERROR;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
for (i = 0; i < package->package.count; i++) {
|
||||
record = &package->package.elements[i];
|
||||
if (record->type != ACPI_TYPE_PACKAGE) {
|
||||
status = AE_ERROR;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
fields = record->package.elements;
|
||||
if (fields[0].type != ACPI_TYPE_INTEGER ||
|
||||
fields[1].type != ACPI_TYPE_INTEGER) {
|
||||
status = AE_ERROR;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
type = fields[0].integer.value;
|
||||
switch (type) {
|
||||
case 0:
|
||||
status = decode_type0_hpx_record(record, hpx);
|
||||
if (ACPI_FAILURE(status))
|
||||
goto exit;
|
||||
break;
|
||||
case 1:
|
||||
status = decode_type1_hpx_record(record, hpx);
|
||||
if (ACPI_FAILURE(status))
|
||||
goto exit;
|
||||
break;
|
||||
case 2:
|
||||
status = decode_type2_hpx_record(record, hpx);
|
||||
if (ACPI_FAILURE(status))
|
||||
goto exit;
|
||||
break;
|
||||
default:
|
||||
printk(KERN_ERR "%s: Type %d record not supported\n",
|
||||
__FUNCTION__, type);
|
||||
status = AE_ERROR;
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
exit:
|
||||
kfree(buffer.pointer);
|
||||
return status;
|
||||
}
|
||||
|
||||
static acpi_status
|
||||
acpi_run_hpp(acpi_handle handle, struct hotplug_params *hpp)
|
||||
@ -50,6 +225,9 @@ acpi_run_hpp(acpi_handle handle, struct hotplug_params *hpp)
|
||||
|
||||
acpi_get_name(handle, ACPI_FULL_PATHNAME, &string);
|
||||
|
||||
/* Clear the return buffer with zeros */
|
||||
memset(hpp, 0, sizeof(struct hotplug_params));
|
||||
|
||||
/* get _hpp */
|
||||
status = acpi_evaluate_object(handle, METHOD_NAME__HPP, NULL, &ret_buf);
|
||||
switch (status) {
|
||||
@ -58,7 +236,7 @@ acpi_run_hpp(acpi_handle handle, struct hotplug_params *hpp)
|
||||
if (!ret_buf.pointer) {
|
||||
printk(KERN_ERR "%s:%s alloc for _HPP fail\n",
|
||||
__FUNCTION__, (char *)string.pointer);
|
||||
acpi_os_free(string.pointer);
|
||||
kfree(string.pointer);
|
||||
return AE_NO_MEMORY;
|
||||
}
|
||||
status = acpi_evaluate_object(handle, METHOD_NAME__HPP,
|
||||
@ -69,7 +247,7 @@ acpi_run_hpp(acpi_handle handle, struct hotplug_params *hpp)
|
||||
if (ACPI_FAILURE(status)) {
|
||||
pr_debug("%s:%s _HPP fail=0x%x\n", __FUNCTION__,
|
||||
(char *)string.pointer, status);
|
||||
acpi_os_free(string.pointer);
|
||||
kfree(string.pointer);
|
||||
return status;
|
||||
}
|
||||
}
|
||||
@ -98,19 +276,20 @@ acpi_run_hpp(acpi_handle handle, struct hotplug_params *hpp)
|
||||
}
|
||||
}
|
||||
|
||||
hpp->cache_line_size = nui[0];
|
||||
hpp->latency_timer = nui[1];
|
||||
hpp->enable_serr = nui[2];
|
||||
hpp->enable_perr = nui[3];
|
||||
hpp->t0 = &hpp->type0_data;
|
||||
hpp->t0->cache_line_size = nui[0];
|
||||
hpp->t0->latency_timer = nui[1];
|
||||
hpp->t0->enable_serr = nui[2];
|
||||
hpp->t0->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);
|
||||
pr_debug(" _HPP: cache_line_size=0x%x\n", hpp->t0->cache_line_size);
|
||||
pr_debug(" _HPP: latency timer =0x%x\n", hpp->t0->latency_timer);
|
||||
pr_debug(" _HPP: enable SERR =0x%x\n", hpp->t0->enable_serr);
|
||||
pr_debug(" _HPP: enable PERR =0x%x\n", hpp->t0->enable_perr);
|
||||
|
||||
free_and_return:
|
||||
acpi_os_free(string.pointer);
|
||||
acpi_os_free(ret_buf.pointer);
|
||||
kfree(string.pointer);
|
||||
kfree(ret_buf.pointer);
|
||||
return status;
|
||||
}
|
||||
|
||||
@ -130,13 +309,17 @@ acpi_status acpi_run_oshp(acpi_handle 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__,
|
||||
(char *)string.pointer, status);
|
||||
if (status != AE_NOT_FOUND)
|
||||
printk(KERN_ERR "%s:%s OSHP fails=0x%x\n",
|
||||
__FUNCTION__, (char *)string.pointer, status);
|
||||
else
|
||||
dbg("%s:%s OSHP not found\n",
|
||||
__FUNCTION__, (char *)string.pointer);
|
||||
else
|
||||
pr_debug("%s:%s OSHP passes\n", __FUNCTION__,
|
||||
(char *)string.pointer);
|
||||
|
||||
acpi_os_free(string.pointer);
|
||||
kfree(string.pointer);
|
||||
return status;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(acpi_run_oshp);
|
||||
@ -145,14 +328,27 @@ EXPORT_SYMBOL_GPL(acpi_run_oshp);
|
||||
|
||||
/* acpi_get_hp_params_from_firmware
|
||||
*
|
||||
* @dev - the pci_dev of the newly added device
|
||||
* @bus - the pci_bus of the bus on which the device is newly added
|
||||
* @hpp - allocated by the caller
|
||||
*/
|
||||
acpi_status acpi_get_hp_params_from_firmware(struct pci_dev *dev,
|
||||
acpi_status acpi_get_hp_params_from_firmware(struct pci_bus *bus,
|
||||
struct hotplug_params *hpp)
|
||||
{
|
||||
acpi_status status = AE_NOT_FOUND;
|
||||
struct pci_dev *pdev = dev;
|
||||
acpi_handle handle, phandle;
|
||||
struct pci_bus *pbus = bus;
|
||||
struct pci_dev *pdev;
|
||||
|
||||
do {
|
||||
pdev = pbus->self;
|
||||
if (!pdev) {
|
||||
handle = acpi_get_pci_rootbridge_handle(
|
||||
pci_domain_nr(pbus), pbus->number);
|
||||
break;
|
||||
}
|
||||
handle = DEVICE_ACPI_HANDLE(&(pdev->dev));
|
||||
pbus = pbus->parent;
|
||||
} while (!handle);
|
||||
|
||||
/*
|
||||
* _HPP settings apply to all child buses, until another _HPP is
|
||||
@ -160,15 +356,19 @@ acpi_status acpi_get_hp_params_from_firmware(struct pci_dev *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)
|
||||
while (handle) {
|
||||
status = acpi_run_hpx(handle, hpp);
|
||||
if (ACPI_SUCCESS(status))
|
||||
break;
|
||||
status = acpi_run_hpp(handle, hpp);
|
||||
if (!(pdev->bus->parent))
|
||||
if (ACPI_SUCCESS(status))
|
||||
break;
|
||||
/* Check if a parent object supports _HPP */
|
||||
pdev = pdev->bus->parent->self;
|
||||
if (acpi_root_bridge(handle))
|
||||
break;
|
||||
status = acpi_get_parent(handle, &phandle);
|
||||
if (ACPI_FAILURE(status))
|
||||
break;
|
||||
handle = phandle;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
@ -192,20 +392,23 @@ int acpi_root_bridge(acpi_handle handle)
|
||||
if ((info->valid & ACPI_VALID_HID) &&
|
||||
!strcmp(PCI_ROOT_HID_STRING,
|
||||
info->hardware_id.value)) {
|
||||
acpi_os_free(buffer.pointer);
|
||||
kfree(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);
|
||||
kfree(buffer.pointer);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
acpi_os_free(buffer.pointer);
|
||||
kfree(buffer.pointer);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(acpi_root_bridge);
|
||||
|
||||
module_param(debug_acpi, bool, 0644);
|
||||
MODULE_PARM_DESC(debug_acpi, "Debugging mode for ACPI enabled or not");
|
||||
|
@ -75,6 +75,10 @@ struct acpiphp_bridge {
|
||||
struct list_head list;
|
||||
acpi_handle handle;
|
||||
struct acpiphp_slot *slots;
|
||||
|
||||
/* Ejectable PCI-to-PCI bridge (PCI bridge and PCI function) */
|
||||
struct acpiphp_func *func;
|
||||
|
||||
int type;
|
||||
int nr_slots;
|
||||
|
||||
@ -122,6 +126,7 @@ struct acpiphp_slot {
|
||||
*/
|
||||
struct acpiphp_func {
|
||||
struct acpiphp_slot *slot; /* parent */
|
||||
struct acpiphp_bridge *bridge; /* Ejectable PCI-to-PCI bridge */
|
||||
|
||||
struct list_head sibling;
|
||||
struct pci_dev *pci_dev;
|
||||
|
@ -286,13 +286,19 @@ static void decode_hpp(struct acpiphp_bridge *bridge)
|
||||
{
|
||||
acpi_status status;
|
||||
|
||||
status = acpi_get_hp_params_from_firmware(bridge->pci_dev, &bridge->hpp);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
status = acpi_get_hp_params_from_firmware(bridge->pci_bus, &bridge->hpp);
|
||||
if (ACPI_FAILURE(status) ||
|
||||
!bridge->hpp.t0 || (bridge->hpp.t0->revision > 1)) {
|
||||
/* use default numbers */
|
||||
bridge->hpp.cache_line_size = 0x10;
|
||||
bridge->hpp.latency_timer = 0x40;
|
||||
bridge->hpp.enable_serr = 0;
|
||||
bridge->hpp.enable_perr = 0;
|
||||
printk(KERN_WARNING
|
||||
"%s: Could not get hotplug parameters. Use defaults\n",
|
||||
__FUNCTION__);
|
||||
bridge->hpp.t0 = &bridge->hpp.type0_data;
|
||||
bridge->hpp.t0->revision = 0;
|
||||
bridge->hpp.t0->cache_line_size = 0x10;
|
||||
bridge->hpp.t0->latency_timer = 0x40;
|
||||
bridge->hpp.t0->enable_serr = 0;
|
||||
bridge->hpp.t0->enable_perr = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -319,6 +325,13 @@ static void init_bridge_misc(struct acpiphp_bridge *bridge)
|
||||
|
||||
/* install notify handler */
|
||||
if (bridge->type != BRIDGE_TYPE_HOST) {
|
||||
if ((bridge->flags & BRIDGE_HAS_EJ0) && bridge->func) {
|
||||
status = acpi_remove_notify_handler(bridge->func->handle,
|
||||
ACPI_SYSTEM_NOTIFY,
|
||||
handle_hotplug_event_func);
|
||||
if (ACPI_FAILURE(status))
|
||||
err("failed to remove notify handler\n");
|
||||
}
|
||||
status = acpi_install_notify_handler(bridge->handle,
|
||||
ACPI_SYSTEM_NOTIFY,
|
||||
handle_hotplug_event_bridge,
|
||||
@ -331,6 +344,66 @@ static void init_bridge_misc(struct acpiphp_bridge *bridge)
|
||||
}
|
||||
|
||||
|
||||
/* find acpiphp_func from acpiphp_bridge */
|
||||
static struct acpiphp_func *acpiphp_bridge_handle_to_function(acpi_handle handle)
|
||||
{
|
||||
struct list_head *node, *l;
|
||||
struct acpiphp_bridge *bridge;
|
||||
struct acpiphp_slot *slot;
|
||||
struct acpiphp_func *func;
|
||||
|
||||
list_for_each(node, &bridge_list) {
|
||||
bridge = list_entry(node, struct acpiphp_bridge, list);
|
||||
for (slot = bridge->slots; slot; slot = slot->next) {
|
||||
list_for_each(l, &slot->funcs) {
|
||||
func = list_entry(l, struct acpiphp_func,
|
||||
sibling);
|
||||
if (func->handle == handle)
|
||||
return func;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static inline void config_p2p_bridge_flags(struct acpiphp_bridge *bridge)
|
||||
{
|
||||
acpi_handle dummy_handle;
|
||||
|
||||
if (ACPI_SUCCESS(acpi_get_handle(bridge->handle,
|
||||
"_STA", &dummy_handle)))
|
||||
bridge->flags |= BRIDGE_HAS_STA;
|
||||
|
||||
if (ACPI_SUCCESS(acpi_get_handle(bridge->handle,
|
||||
"_EJ0", &dummy_handle)))
|
||||
bridge->flags |= BRIDGE_HAS_EJ0;
|
||||
|
||||
if (ACPI_SUCCESS(acpi_get_handle(bridge->handle,
|
||||
"_PS0", &dummy_handle)))
|
||||
bridge->flags |= BRIDGE_HAS_PS0;
|
||||
|
||||
if (ACPI_SUCCESS(acpi_get_handle(bridge->handle,
|
||||
"_PS3", &dummy_handle)))
|
||||
bridge->flags |= BRIDGE_HAS_PS3;
|
||||
|
||||
/* is this ejectable p2p bridge? */
|
||||
if (bridge->flags & BRIDGE_HAS_EJ0) {
|
||||
struct acpiphp_func *func;
|
||||
|
||||
dbg("found ejectable p2p bridge\n");
|
||||
|
||||
/* make link between PCI bridge and PCI function */
|
||||
func = acpiphp_bridge_handle_to_function(bridge->handle);
|
||||
if (!func)
|
||||
return;
|
||||
bridge->func = func;
|
||||
func->bridge = bridge;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* allocate and initialize host bridge data structure */
|
||||
static void add_host_bridge(acpi_handle *handle, struct pci_bus *pci_bus)
|
||||
{
|
||||
@ -364,6 +437,7 @@ static void add_p2p_bridge(acpi_handle *handle, struct pci_dev *pci_dev)
|
||||
|
||||
bridge->type = BRIDGE_TYPE_P2P;
|
||||
bridge->handle = handle;
|
||||
config_p2p_bridge_flags(bridge);
|
||||
|
||||
bridge->pci_dev = pci_dev_get(pci_dev);
|
||||
bridge->pci_bus = pci_dev->subordinate;
|
||||
@ -423,7 +497,7 @@ find_p2p_bridge(acpi_handle handle, u32 lvl, void *context, void **rv)
|
||||
status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1,
|
||||
find_p2p_bridge, dev->subordinate, NULL);
|
||||
if (ACPI_FAILURE(status))
|
||||
warn("find_p2p_bridge faied (error code = 0x%x)\n", status);
|
||||
warn("find_p2p_bridge failed (error code = 0x%x)\n", status);
|
||||
|
||||
out:
|
||||
pci_dev_put(dev);
|
||||
@ -478,7 +552,6 @@ static int add_bridge(acpi_handle handle)
|
||||
if (detect_ejectable_slots(handle) > 0) {
|
||||
dbg("found PCI host-bus bridge with hot-pluggable slots\n");
|
||||
add_host_bridge(handle, pci_bus);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* search P2P bridges under this host bridge */
|
||||
@ -486,7 +559,7 @@ static int add_bridge(acpi_handle handle)
|
||||
find_p2p_bridge, pci_bus, NULL);
|
||||
|
||||
if (ACPI_FAILURE(status))
|
||||
warn("find_p2p_bridge faied (error code = 0x%x)\n",status);
|
||||
warn("find_p2p_bridge failed (error code = 0x%x)\n", status);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -516,6 +589,16 @@ static void cleanup_bridge(struct acpiphp_bridge *bridge)
|
||||
if (ACPI_FAILURE(status))
|
||||
err("failed to remove notify handler\n");
|
||||
|
||||
if ((bridge->type != BRIDGE_TYPE_HOST) &&
|
||||
((bridge->flags & BRIDGE_HAS_EJ0) && bridge->func)) {
|
||||
status = acpi_install_notify_handler(bridge->func->handle,
|
||||
ACPI_SYSTEM_NOTIFY,
|
||||
handle_hotplug_event_func,
|
||||
bridge->func);
|
||||
if (ACPI_FAILURE(status))
|
||||
err("failed to install interrupt notify handler\n");
|
||||
}
|
||||
|
||||
slot = bridge->slots;
|
||||
while (slot) {
|
||||
struct acpiphp_slot *next = slot->next;
|
||||
@ -549,6 +632,11 @@ cleanup_p2p_bridge(acpi_handle handle, u32 lvl, void *context, void **rv)
|
||||
{
|
||||
struct acpiphp_bridge *bridge;
|
||||
|
||||
/* cleanup p2p bridges under this P2P bridge
|
||||
in a depth-first manner */
|
||||
acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1,
|
||||
cleanup_p2p_bridge, NULL, NULL);
|
||||
|
||||
if (!(bridge = acpiphp_handle_to_bridge(handle)))
|
||||
return AE_OK;
|
||||
cleanup_bridge(bridge);
|
||||
@ -559,15 +647,14 @@ static void remove_bridge(acpi_handle handle)
|
||||
{
|
||||
struct acpiphp_bridge *bridge;
|
||||
|
||||
/* cleanup p2p bridges under this host bridge
|
||||
in a depth-first manner */
|
||||
acpi_walk_namespace(ACPI_TYPE_DEVICE, handle,
|
||||
(u32)1, cleanup_p2p_bridge, NULL, NULL);
|
||||
|
||||
bridge = acpiphp_handle_to_bridge(handle);
|
||||
if (bridge) {
|
||||
if (bridge)
|
||||
cleanup_bridge(bridge);
|
||||
} else {
|
||||
/* clean-up p2p bridges under this host bridge */
|
||||
acpi_walk_namespace(ACPI_TYPE_DEVICE, handle,
|
||||
ACPI_UINT32_MAX, cleanup_p2p_bridge,
|
||||
NULL, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static struct pci_dev * get_apic_pci_info(acpi_handle handle)
|
||||
@ -634,7 +721,7 @@ static int get_gsi_base(acpi_handle handle, u32 *gsi_base)
|
||||
break;
|
||||
}
|
||||
out:
|
||||
acpi_os_free(buffer.pointer);
|
||||
kfree(buffer.pointer);
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -797,36 +884,6 @@ static unsigned char acpiphp_max_busnr(struct pci_bus *bus)
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* get_func - get a pointer to acpiphp_func given a slot, device
|
||||
* @slot: slot to search
|
||||
* @dev: pci_dev struct to match.
|
||||
*
|
||||
* This function will increase the reference count of pci_dev,
|
||||
* so callers should call pci_dev_put when complete.
|
||||
*
|
||||
*/
|
||||
static struct acpiphp_func *
|
||||
get_func(struct acpiphp_slot *slot, struct pci_dev *dev)
|
||||
{
|
||||
struct acpiphp_func *func = NULL;
|
||||
struct pci_bus *bus = slot->bridge->pci_bus;
|
||||
struct pci_dev *pdev;
|
||||
|
||||
list_for_each_entry(func, &slot->funcs, sibling) {
|
||||
pdev = pci_get_slot(bus, PCI_DEVFN(slot->device,
|
||||
func->function));
|
||||
if (pdev) {
|
||||
if (pdev == dev)
|
||||
break;
|
||||
pci_dev_put(pdev);
|
||||
}
|
||||
}
|
||||
return func;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* acpiphp_bus_add - add a new bus to acpi subsystem
|
||||
* @func: acpiphp_func of the bridge
|
||||
@ -872,6 +929,28 @@ acpiphp_bus_add_out:
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* acpiphp_bus_trim - trim a bus from acpi subsystem
|
||||
* @handle: handle to acpi namespace
|
||||
*
|
||||
*/
|
||||
int acpiphp_bus_trim(acpi_handle handle)
|
||||
{
|
||||
struct acpi_device *device;
|
||||
int retval;
|
||||
|
||||
retval = acpi_bus_get_device(handle, &device);
|
||||
if (retval) {
|
||||
dbg("acpi_device not found\n");
|
||||
return retval;
|
||||
}
|
||||
|
||||
retval = acpi_bus_trim(device, 1);
|
||||
if (retval)
|
||||
err("cannot remove from acpi list\n");
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/**
|
||||
* enable_device - enable, configure a slot
|
||||
@ -889,6 +968,7 @@ static int enable_device(struct acpiphp_slot *slot)
|
||||
struct acpiphp_func *func;
|
||||
int retval = 0;
|
||||
int num, max, pass;
|
||||
acpi_status status;
|
||||
|
||||
if (slot->flags & SLOT_ENABLED)
|
||||
goto err_exit;
|
||||
@ -918,19 +998,17 @@ static int enable_device(struct acpiphp_slot *slot)
|
||||
if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE ||
|
||||
dev->hdr_type == PCI_HEADER_TYPE_CARDBUS) {
|
||||
max = pci_scan_bridge(bus, dev, max, pass);
|
||||
if (pass && dev->subordinate) {
|
||||
if (pass && dev->subordinate)
|
||||
pci_bus_size_bridges(dev->subordinate);
|
||||
func = get_func(slot, dev);
|
||||
if (func) {
|
||||
acpiphp_bus_add(func);
|
||||
/* side effect of get_func */
|
||||
pci_dev_put(dev);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
list_for_each (l, &slot->funcs) {
|
||||
func = list_entry(l, struct acpiphp_func, sibling);
|
||||
acpiphp_bus_add(func);
|
||||
}
|
||||
|
||||
pci_bus_assign_resources(bus);
|
||||
acpiphp_sanitize_bus(bus);
|
||||
pci_enable_bridges(bus);
|
||||
@ -943,6 +1021,17 @@ static int enable_device(struct acpiphp_slot *slot)
|
||||
func = list_entry(l, struct acpiphp_func, sibling);
|
||||
func->pci_dev = pci_get_slot(bus, PCI_DEVFN(slot->device,
|
||||
func->function));
|
||||
if (!func->pci_dev)
|
||||
continue;
|
||||
|
||||
if (func->pci_dev->hdr_type != PCI_HEADER_TYPE_BRIDGE &&
|
||||
func->pci_dev->hdr_type != PCI_HEADER_TYPE_CARDBUS)
|
||||
continue;
|
||||
|
||||
status = find_p2p_bridge(func->handle, (u32)1, bus, NULL);
|
||||
if (ACPI_FAILURE(status))
|
||||
warn("find_p2p_bridge failed (error code = 0x%x)\n",
|
||||
status);
|
||||
}
|
||||
|
||||
slot->flags |= SLOT_ENABLED;
|
||||
@ -967,6 +1056,18 @@ static int disable_device(struct acpiphp_slot *slot)
|
||||
|
||||
list_for_each (l, &slot->funcs) {
|
||||
func = list_entry(l, struct acpiphp_func, sibling);
|
||||
|
||||
if (func->bridge) {
|
||||
/* cleanup p2p bridges under this P2P bridge */
|
||||
cleanup_p2p_bridge(func->bridge->handle,
|
||||
(u32)1, NULL, NULL);
|
||||
func->bridge = NULL;
|
||||
}
|
||||
|
||||
acpiphp_bus_trim(func->handle);
|
||||
/* try to remove anyway.
|
||||
* acpiphp_bus_add might have been failed */
|
||||
|
||||
if (!func->pci_dev)
|
||||
continue;
|
||||
|
||||
@ -1111,16 +1212,17 @@ static void program_hpp(struct pci_dev *dev, struct acpiphp_bridge *bridge)
|
||||
(dev->hdr_type == PCI_HEADER_TYPE_BRIDGE &&
|
||||
(dev->class >> 8) == PCI_CLASS_BRIDGE_PCI)))
|
||||
return;
|
||||
|
||||
pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE,
|
||||
bridge->hpp.cache_line_size);
|
||||
bridge->hpp.t0->cache_line_size);
|
||||
pci_write_config_byte(dev, PCI_LATENCY_TIMER,
|
||||
bridge->hpp.latency_timer);
|
||||
bridge->hpp.t0->latency_timer);
|
||||
pci_read_config_word(dev, PCI_COMMAND, &pci_cmd);
|
||||
if (bridge->hpp.enable_serr)
|
||||
if (bridge->hpp.t0->enable_serr)
|
||||
pci_cmd |= PCI_COMMAND_SERR;
|
||||
else
|
||||
pci_cmd &= ~PCI_COMMAND_SERR;
|
||||
if (bridge->hpp.enable_perr)
|
||||
if (bridge->hpp.t0->enable_perr)
|
||||
pci_cmd |= PCI_COMMAND_PARITY;
|
||||
else
|
||||
pci_cmd &= ~PCI_COMMAND_PARITY;
|
||||
@ -1129,13 +1231,13 @@ static void program_hpp(struct pci_dev *dev, struct acpiphp_bridge *bridge)
|
||||
/* Program bridge control value and child devices */
|
||||
if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) {
|
||||
pci_write_config_byte(dev, PCI_SEC_LATENCY_TIMER,
|
||||
bridge->hpp.latency_timer);
|
||||
bridge->hpp.t0->latency_timer);
|
||||
pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &pci_bctl);
|
||||
if (bridge->hpp.enable_serr)
|
||||
if (bridge->hpp.t0->enable_serr)
|
||||
pci_bctl |= PCI_BRIDGE_CTL_SERR;
|
||||
else
|
||||
pci_bctl &= ~PCI_BRIDGE_CTL_SERR;
|
||||
if (bridge->hpp.enable_perr)
|
||||
if (bridge->hpp.t0->enable_perr)
|
||||
pci_bctl |= PCI_BRIDGE_CTL_PARITY;
|
||||
else
|
||||
pci_bctl &= ~PCI_BRIDGE_CTL_PARITY;
|
||||
@ -1155,6 +1257,7 @@ static void acpiphp_set_hpp_values(acpi_handle handle, struct pci_bus *bus)
|
||||
|
||||
memset(&bridge, 0, sizeof(bridge));
|
||||
bridge.handle = handle;
|
||||
bridge.pci_bus = bus;
|
||||
bridge.pci_dev = bus->self;
|
||||
decode_hpp(&bridge);
|
||||
list_for_each_entry(dev, &bus->devices, bus_list)
|
||||
@ -1297,6 +1400,13 @@ static void handle_hotplug_event_bridge(acpi_handle handle, u32 type, void *cont
|
||||
case ACPI_NOTIFY_EJECT_REQUEST:
|
||||
/* request device eject */
|
||||
dbg("%s: Device eject notify on %s\n", __FUNCTION__, objname);
|
||||
if ((bridge->type != BRIDGE_TYPE_HOST) &&
|
||||
(bridge->flags & BRIDGE_HAS_EJ0)) {
|
||||
struct acpiphp_slot *slot;
|
||||
slot = bridge->func->slot;
|
||||
if (!acpiphp_disable_slot(slot))
|
||||
acpiphp_eject_slot(slot);
|
||||
}
|
||||
break;
|
||||
|
||||
case ACPI_NOTIFY_FREQUENCY_MISMATCH:
|
||||
@ -1490,9 +1600,15 @@ int acpiphp_enable_slot(struct acpiphp_slot *slot)
|
||||
if (retval)
|
||||
goto err_exit;
|
||||
|
||||
if (get_slot_status(slot) == ACPI_STA_ALL)
|
||||
if (get_slot_status(slot) == ACPI_STA_ALL) {
|
||||
/* configure all functions */
|
||||
retval = enable_device(slot);
|
||||
if (retval)
|
||||
power_off_slot(slot);
|
||||
} else {
|
||||
dbg("%s: Slot status is not ACPI_STA_ALL\n", __FUNCTION__);
|
||||
power_off_slot(slot);
|
||||
}
|
||||
|
||||
err_exit:
|
||||
mutex_unlock(&slot->crit_sect);
|
||||
|
@ -285,7 +285,7 @@ static int get_attention_status(struct hotplug_slot *hotplug_slot, u8 * value)
|
||||
(ulong) hotplug_slot, (ulong) value);
|
||||
|
||||
ibmphp_lock_operations();
|
||||
if (hotplug_slot && value) {
|
||||
if (hotplug_slot) {
|
||||
pslot = hotplug_slot->private;
|
||||
if (pslot) {
|
||||
memcpy(&myslot, pslot, sizeof(struct slot));
|
||||
@ -315,7 +315,7 @@ static int get_latch_status(struct hotplug_slot *hotplug_slot, u8 * value)
|
||||
debug("get_latch_status - Entry hotplug_slot[%lx] pvalue[%lx]\n",
|
||||
(ulong) hotplug_slot, (ulong) value);
|
||||
ibmphp_lock_operations();
|
||||
if (hotplug_slot && value) {
|
||||
if (hotplug_slot) {
|
||||
pslot = hotplug_slot->private;
|
||||
if (pslot) {
|
||||
memcpy(&myslot, pslot, sizeof(struct slot));
|
||||
@ -342,7 +342,7 @@ static int get_power_status(struct hotplug_slot *hotplug_slot, u8 * value)
|
||||
debug("get_power_status - Entry hotplug_slot[%lx] pvalue[%lx]\n",
|
||||
(ulong) hotplug_slot, (ulong) value);
|
||||
ibmphp_lock_operations();
|
||||
if (hotplug_slot && value) {
|
||||
if (hotplug_slot) {
|
||||
pslot = hotplug_slot->private;
|
||||
if (pslot) {
|
||||
memcpy(&myslot, pslot, sizeof(struct slot));
|
||||
@ -369,7 +369,7 @@ static int get_adapter_present(struct hotplug_slot *hotplug_slot, u8 * value)
|
||||
debug("get_adapter_status - Entry hotplug_slot[%lx] pvalue[%lx]\n",
|
||||
(ulong) hotplug_slot, (ulong) value);
|
||||
ibmphp_lock_operations();
|
||||
if (hotplug_slot && value) {
|
||||
if (hotplug_slot) {
|
||||
pslot = hotplug_slot->private;
|
||||
if (pslot) {
|
||||
memcpy(&myslot, pslot, sizeof(struct slot));
|
||||
@ -401,7 +401,7 @@ static int get_max_bus_speed(struct hotplug_slot *hotplug_slot, enum pci_bus_spe
|
||||
|
||||
ibmphp_lock_operations();
|
||||
|
||||
if (hotplug_slot && value) {
|
||||
if (hotplug_slot) {
|
||||
pslot = hotplug_slot->private;
|
||||
if (pslot) {
|
||||
rc = 0;
|
||||
@ -441,7 +441,7 @@ static int get_cur_bus_speed(struct hotplug_slot *hotplug_slot, enum pci_bus_spe
|
||||
|
||||
ibmphp_lock_operations();
|
||||
|
||||
if (hotplug_slot && value) {
|
||||
if (hotplug_slot) {
|
||||
pslot = hotplug_slot->private;
|
||||
if (pslot) {
|
||||
rc = get_cur_bus_info(&pslot);
|
||||
|
@ -176,11 +176,51 @@ extern int pci_hp_change_slot_info (struct hotplug_slot *slot,
|
||||
struct hotplug_slot_info *info);
|
||||
extern struct subsystem pci_hotplug_slots_subsys;
|
||||
|
||||
/* PCI Setting Record (Type 0) */
|
||||
struct hpp_type0 {
|
||||
u32 revision;
|
||||
u8 cache_line_size;
|
||||
u8 latency_timer;
|
||||
u8 enable_serr;
|
||||
u8 enable_perr;
|
||||
};
|
||||
|
||||
/* PCI-X Setting Record (Type 1) */
|
||||
struct hpp_type1 {
|
||||
u32 revision;
|
||||
u8 max_mem_read;
|
||||
u8 avg_max_split;
|
||||
u16 tot_max_split;
|
||||
};
|
||||
|
||||
/* PCI Express Setting Record (Type 2) */
|
||||
struct hpp_type2 {
|
||||
u32 revision;
|
||||
u32 unc_err_mask_and;
|
||||
u32 unc_err_mask_or;
|
||||
u32 unc_err_sever_and;
|
||||
u32 unc_err_sever_or;
|
||||
u32 cor_err_mask_and;
|
||||
u32 cor_err_mask_or;
|
||||
u32 adv_err_cap_and;
|
||||
u32 adv_err_cap_or;
|
||||
u16 pci_exp_devctl_and;
|
||||
u16 pci_exp_devctl_or;
|
||||
u16 pci_exp_lnkctl_and;
|
||||
u16 pci_exp_lnkctl_or;
|
||||
u32 sec_unc_err_sever_and;
|
||||
u32 sec_unc_err_sever_or;
|
||||
u32 sec_unc_err_mask_and;
|
||||
u32 sec_unc_err_mask_or;
|
||||
};
|
||||
|
||||
struct hotplug_params {
|
||||
u8 cache_line_size;
|
||||
u8 latency_timer;
|
||||
u8 enable_serr;
|
||||
u8 enable_perr;
|
||||
struct hpp_type0 *t0; /* Type0: NULL if not available */
|
||||
struct hpp_type1 *t1; /* Type1: NULL if not available */
|
||||
struct hpp_type2 *t2; /* Type2: NULL if not available */
|
||||
struct hpp_type0 type0_data;
|
||||
struct hpp_type1 type1_data;
|
||||
struct hpp_type2 type2_data;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_ACPI
|
||||
@ -188,7 +228,7 @@ struct hotplug_params {
|
||||
#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,
|
||||
extern acpi_status acpi_get_hp_params_from_firmware(struct pci_bus *bus,
|
||||
struct hotplug_params *hpp);
|
||||
int acpi_root_bridge(acpi_handle handle);
|
||||
#endif
|
||||
|
@ -284,7 +284,7 @@ struct hpc_ops {
|
||||
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)))
|
||||
if (ACPI_FAILURE(acpi_get_hp_params_from_firmware(dev->bus, hpp)))
|
||||
return -ENODEV;
|
||||
return 0;
|
||||
}
|
||||
|
@ -69,6 +69,7 @@ static int get_power_status (struct hotplug_slot *slot, u8 *value);
|
||||
static int get_attention_status (struct hotplug_slot *slot, u8 *value);
|
||||
static int get_latch_status (struct hotplug_slot *slot, u8 *value);
|
||||
static int get_adapter_status (struct hotplug_slot *slot, u8 *value);
|
||||
static int get_address (struct hotplug_slot *slot, u32 *value);
|
||||
static int get_max_bus_speed (struct hotplug_slot *slot, enum pci_bus_speed *value);
|
||||
static int get_cur_bus_speed (struct hotplug_slot *slot, enum pci_bus_speed *value);
|
||||
|
||||
@ -81,6 +82,7 @@ static struct hotplug_slot_ops pciehp_hotplug_slot_ops = {
|
||||
.get_attention_status = get_attention_status,
|
||||
.get_latch_status = get_latch_status,
|
||||
.get_adapter_status = get_adapter_status,
|
||||
.get_address = get_address,
|
||||
.get_max_bus_speed = get_max_bus_speed,
|
||||
.get_cur_bus_speed = get_cur_bus_speed,
|
||||
};
|
||||
@ -331,6 +333,18 @@ static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 *value)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_address(struct hotplug_slot *hotplug_slot, u32 *value)
|
||||
{
|
||||
struct slot *slot = hotplug_slot->private;
|
||||
struct pci_bus *bus = slot->ctrl->pci_dev->subordinate;
|
||||
|
||||
dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
|
||||
|
||||
*value = (pci_domain_nr(bus) << 16) | (slot->bus << 8) | slot->device;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_max_bus_speed(struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value)
|
||||
{
|
||||
struct slot *slot = hotplug_slot->private;
|
||||
|
@ -1288,7 +1288,7 @@ int pciehp_acpi_get_hp_hw_control_from_firmware(struct pci_dev *dev)
|
||||
if (ACPI_SUCCESS(status)) {
|
||||
dbg("Gained control for hotplug HW for pci %s (%s)\n",
|
||||
pci_name(dev), (char *)string.pointer);
|
||||
acpi_os_free(string.pointer);
|
||||
kfree(string.pointer);
|
||||
return 0;
|
||||
}
|
||||
if (acpi_root_bridge(handle))
|
||||
@ -1302,7 +1302,7 @@ int pciehp_acpi_get_hp_hw_control_from_firmware(struct pci_dev *dev)
|
||||
err("Cannot get control of hotplug hardware for pci %s\n",
|
||||
pci_name(dev));
|
||||
|
||||
acpi_os_free(string.pointer);
|
||||
kfree(string.pointer);
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
@ -1404,9 +1404,6 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev)
|
||||
info("HPC vendor_id %x device_id %x ss_vid %x ss_did %x\n", pdev->vendor, pdev->device,
|
||||
pdev->subsystem_vendor, pdev->subsystem_device);
|
||||
|
||||
if (pci_enable_device(pdev))
|
||||
goto abort_free_ctlr;
|
||||
|
||||
mutex_init(&ctrl->crit_sect);
|
||||
/* setup wait queue */
|
||||
init_waitqueue_head(&ctrl->queue);
|
||||
@ -1474,7 +1471,7 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev)
|
||||
rc = hp_register_read_word(pdev, SLOT_CTRL(ctrl->cap_base), temp_word);
|
||||
if (rc) {
|
||||
err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__);
|
||||
goto abort_free_ctlr;
|
||||
goto abort_free_irq;
|
||||
}
|
||||
|
||||
intr_enable = intr_enable | PRSN_DETECT_ENABLE;
|
||||
@ -1500,19 +1497,19 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev)
|
||||
rc = hp_register_write_word(pdev, SLOT_CTRL(ctrl->cap_base), temp_word);
|
||||
if (rc) {
|
||||
err("%s : hp_register_write_word SLOT_CTRL failed\n", __FUNCTION__);
|
||||
goto abort_free_ctlr;
|
||||
goto abort_free_irq;
|
||||
}
|
||||
rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS(ctrl->cap_base), slot_status);
|
||||
if (rc) {
|
||||
err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__);
|
||||
goto abort_free_ctlr;
|
||||
goto abort_disable_intr;
|
||||
}
|
||||
|
||||
temp_word = 0x1F; /* Clear all events */
|
||||
rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_STATUS(ctrl->cap_base), temp_word);
|
||||
if (rc) {
|
||||
err("%s : hp_register_write_word SLOT_STATUS failed\n", __FUNCTION__);
|
||||
goto abort_free_ctlr;
|
||||
goto abort_disable_intr;
|
||||
}
|
||||
|
||||
if (pciehp_force) {
|
||||
@ -1521,7 +1518,7 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev)
|
||||
} else {
|
||||
rc = pciehp_get_hp_hw_control_from_firmware(ctrl->pci_dev);
|
||||
if (rc)
|
||||
goto abort_free_ctlr;
|
||||
goto abort_disable_intr;
|
||||
}
|
||||
|
||||
/* Add this HPC instance into the HPC list */
|
||||
@ -1548,6 +1545,21 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev)
|
||||
return 0;
|
||||
|
||||
/* We end up here for the many possible ways to fail this API. */
|
||||
abort_disable_intr:
|
||||
rc = hp_register_read_word(pdev, SLOT_CTRL(ctrl->cap_base), temp_word);
|
||||
if (!rc) {
|
||||
temp_word &= ~(intr_enable | HP_INTR_ENABLE);
|
||||
rc = hp_register_write_word(pdev, SLOT_CTRL(ctrl->cap_base), temp_word);
|
||||
}
|
||||
if (rc)
|
||||
err("%s : disabling interrupts failed\n", __FUNCTION__);
|
||||
|
||||
abort_free_irq:
|
||||
if (pciehp_poll_mode)
|
||||
del_timer_sync(&php_ctlr->int_poll_timer);
|
||||
else
|
||||
free_irq(php_ctlr->irq, ctrl);
|
||||
|
||||
abort_free_ctlr:
|
||||
pcie_cap_base = saved_cap_base;
|
||||
kfree(php_ctlr);
|
||||
|
@ -34,6 +34,144 @@
|
||||
#include "../pci.h"
|
||||
#include "pciehp.h"
|
||||
|
||||
static void program_hpp_type0(struct pci_dev *dev, struct hpp_type0 *hpp)
|
||||
{
|
||||
u16 pci_cmd, pci_bctl;
|
||||
|
||||
if (hpp->revision > 1) {
|
||||
printk(KERN_WARNING "%s: Rev.%d type0 record not supported\n",
|
||||
__FUNCTION__, hpp->revision);
|
||||
return;
|
||||
}
|
||||
|
||||
pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, hpp->cache_line_size);
|
||||
pci_write_config_byte(dev, PCI_LATENCY_TIMER, hpp->latency_timer);
|
||||
pci_read_config_word(dev, PCI_COMMAND, &pci_cmd);
|
||||
if (hpp->enable_serr)
|
||||
pci_cmd |= PCI_COMMAND_SERR;
|
||||
else
|
||||
pci_cmd &= ~PCI_COMMAND_SERR;
|
||||
if (hpp->enable_perr)
|
||||
pci_cmd |= PCI_COMMAND_PARITY;
|
||||
else
|
||||
pci_cmd &= ~PCI_COMMAND_PARITY;
|
||||
pci_write_config_word(dev, PCI_COMMAND, pci_cmd);
|
||||
|
||||
/* Program bridge control value */
|
||||
if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) {
|
||||
pci_write_config_byte(dev, PCI_SEC_LATENCY_TIMER,
|
||||
hpp->latency_timer);
|
||||
pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &pci_bctl);
|
||||
if (hpp->enable_serr)
|
||||
pci_bctl |= PCI_BRIDGE_CTL_SERR;
|
||||
else
|
||||
pci_bctl &= ~PCI_BRIDGE_CTL_SERR;
|
||||
if (hpp->enable_perr)
|
||||
pci_bctl |= PCI_BRIDGE_CTL_PARITY;
|
||||
else
|
||||
pci_bctl &= ~PCI_BRIDGE_CTL_PARITY;
|
||||
pci_write_config_word(dev, PCI_BRIDGE_CONTROL, pci_bctl);
|
||||
}
|
||||
}
|
||||
|
||||
static void program_hpp_type2(struct pci_dev *dev, struct hpp_type2 *hpp)
|
||||
{
|
||||
int pos;
|
||||
u16 reg16;
|
||||
u32 reg32;
|
||||
|
||||
if (hpp->revision > 1) {
|
||||
printk(KERN_WARNING "%s: Rev.%d type2 record not supported\n",
|
||||
__FUNCTION__, hpp->revision);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Find PCI Express capability */
|
||||
pos = pci_find_capability(dev, PCI_CAP_ID_EXP);
|
||||
if (!pos)
|
||||
return;
|
||||
|
||||
/* Initialize Device Control Register */
|
||||
pci_read_config_word(dev, pos + PCI_EXP_DEVCTL, ®16);
|
||||
reg16 = (reg16 & hpp->pci_exp_devctl_and) | hpp->pci_exp_devctl_or;
|
||||
pci_write_config_word(dev, pos + PCI_EXP_DEVCTL, reg16);
|
||||
|
||||
/* Initialize Link Control Register */
|
||||
if (dev->subordinate) {
|
||||
pci_read_config_word(dev, pos + PCI_EXP_LNKCTL, ®16);
|
||||
reg16 = (reg16 & hpp->pci_exp_lnkctl_and)
|
||||
| hpp->pci_exp_lnkctl_or;
|
||||
pci_write_config_word(dev, pos + PCI_EXP_LNKCTL, reg16);
|
||||
}
|
||||
|
||||
/* Find Advanced Error Reporting Enhanced Capability */
|
||||
pos = 256;
|
||||
do {
|
||||
pci_read_config_dword(dev, pos, ®32);
|
||||
if (PCI_EXT_CAP_ID(reg32) == PCI_EXT_CAP_ID_ERR)
|
||||
break;
|
||||
} while ((pos = PCI_EXT_CAP_NEXT(reg32)));
|
||||
if (!pos)
|
||||
return;
|
||||
|
||||
/* Initialize Uncorrectable Error Mask Register */
|
||||
pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_MASK, ®32);
|
||||
reg32 = (reg32 & hpp->unc_err_mask_and) | hpp->unc_err_mask_or;
|
||||
pci_write_config_dword(dev, pos + PCI_ERR_UNCOR_MASK, reg32);
|
||||
|
||||
/* Initialize Uncorrectable Error Severity Register */
|
||||
pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_SEVER, ®32);
|
||||
reg32 = (reg32 & hpp->unc_err_sever_and) | hpp->unc_err_sever_or;
|
||||
pci_write_config_dword(dev, pos + PCI_ERR_UNCOR_SEVER, reg32);
|
||||
|
||||
/* Initialize Correctable Error Mask Register */
|
||||
pci_read_config_dword(dev, pos + PCI_ERR_COR_MASK, ®32);
|
||||
reg32 = (reg32 & hpp->cor_err_mask_and) | hpp->cor_err_mask_or;
|
||||
pci_write_config_dword(dev, pos + PCI_ERR_COR_MASK, reg32);
|
||||
|
||||
/* Initialize Advanced Error Capabilities and Control Register */
|
||||
pci_read_config_dword(dev, pos + PCI_ERR_CAP, ®32);
|
||||
reg32 = (reg32 & hpp->adv_err_cap_and) | hpp->adv_err_cap_or;
|
||||
pci_write_config_dword(dev, pos + PCI_ERR_CAP, reg32);
|
||||
|
||||
/*
|
||||
* FIXME: The following two registers are not supported yet.
|
||||
*
|
||||
* o Secondary Uncorrectable Error Severity Register
|
||||
* o Secondary Uncorrectable Error Mask Register
|
||||
*/
|
||||
}
|
||||
|
||||
static void program_fw_provided_values(struct pci_dev *dev)
|
||||
{
|
||||
struct pci_dev *cdev;
|
||||
struct hotplug_params hpp;
|
||||
|
||||
/* Program hpp values for this device */
|
||||
if (!(dev->hdr_type == PCI_HEADER_TYPE_NORMAL ||
|
||||
(dev->hdr_type == PCI_HEADER_TYPE_BRIDGE &&
|
||||
(dev->class >> 8) == PCI_CLASS_BRIDGE_PCI)))
|
||||
return;
|
||||
|
||||
if (pciehp_get_hp_params_from_firmware(dev, &hpp)) {
|
||||
printk(KERN_WARNING "%s: Could not get hotplug parameters\n",
|
||||
__FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
if (hpp.t2)
|
||||
program_hpp_type2(dev, hpp.t2);
|
||||
if (hpp.t0)
|
||||
program_hpp_type0(dev, hpp.t0);
|
||||
|
||||
/* Program child devices */
|
||||
if (dev->subordinate) {
|
||||
list_for_each_entry(cdev, &dev->subordinate->devices,
|
||||
bus_list)
|
||||
program_fw_provided_values(cdev);
|
||||
}
|
||||
}
|
||||
|
||||
static int pciehp_add_bridge(struct pci_dev *dev)
|
||||
{
|
||||
struct pci_bus *parent = dev->bus;
|
||||
@ -66,10 +204,11 @@ int pciehp_configure_device(struct slot *p_slot)
|
||||
struct pci_bus *parent = p_slot->ctrl->pci_dev->subordinate;
|
||||
int num, fn;
|
||||
|
||||
dev = pci_find_slot(p_slot->bus, PCI_DEVFN(p_slot->device, 0));
|
||||
dev = pci_get_slot(parent, PCI_DEVFN(p_slot->device, 0));
|
||||
if (dev) {
|
||||
err("Device %s already exists at %x:%x, cannot hot-add\n",
|
||||
pci_name(dev), p_slot->bus, p_slot->device);
|
||||
pci_dev_put(dev);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@ -86,14 +225,15 @@ int pciehp_configure_device(struct slot *p_slot)
|
||||
if ((dev->class >> 16) == PCI_BASE_CLASS_DISPLAY) {
|
||||
err("Cannot hot-add display device %s\n",
|
||||
pci_name(dev));
|
||||
pci_dev_put(dev);
|
||||
continue;
|
||||
}
|
||||
if ((dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) ||
|
||||
(dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)) {
|
||||
pciehp_add_bridge(dev);
|
||||
}
|
||||
/* TBD: program firmware provided _HPP values */
|
||||
/* program_fw_provided_values(dev); */
|
||||
program_fw_provided_values(dev);
|
||||
pci_dev_put(dev);
|
||||
}
|
||||
|
||||
pci_bus_assign_resources(parent);
|
||||
@ -106,18 +246,20 @@ int pciehp_unconfigure_device(struct slot *p_slot)
|
||||
int rc = 0;
|
||||
int j;
|
||||
u8 bctl = 0;
|
||||
struct pci_bus *parent = p_slot->ctrl->pci_dev->subordinate;
|
||||
|
||||
dbg("%s: bus/dev = %x/%x\n", __FUNCTION__, p_slot->bus,
|
||||
p_slot->device);
|
||||
|
||||
for (j=0; j<8 ; j++) {
|
||||
struct pci_dev* temp = pci_find_slot(p_slot->bus,
|
||||
struct pci_dev* temp = pci_get_slot(parent,
|
||||
(p_slot->device << 3) | j);
|
||||
if (!temp)
|
||||
continue;
|
||||
if ((temp->class >> 16) == PCI_BASE_CLASS_DISPLAY) {
|
||||
err("Cannot remove display device %s\n",
|
||||
pci_name(temp));
|
||||
pci_dev_put(temp);
|
||||
continue;
|
||||
}
|
||||
if (temp->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
|
||||
@ -125,10 +267,12 @@ int pciehp_unconfigure_device(struct slot *p_slot)
|
||||
if (bctl & PCI_BRIDGE_CTL_VGA) {
|
||||
err("Cannot remove display device %s\n",
|
||||
pci_name(temp));
|
||||
pci_dev_put(temp);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
pci_remove_bus_device(temp);
|
||||
pci_dev_put(temp);
|
||||
}
|
||||
/*
|
||||
* Some PCI Express root ports require fixup after hot-plug operation.
|
||||
|
@ -18,11 +18,13 @@
|
||||
#include <linux/mutex.h>
|
||||
|
||||
#include <asm/sn/addrs.h>
|
||||
#include <asm/sn/geo.h>
|
||||
#include <asm/sn/l1.h>
|
||||
#include <asm/sn/module.h>
|
||||
#include <asm/sn/pcibr_provider.h>
|
||||
#include <asm/sn/pcibus_provider_defs.h>
|
||||
#include <asm/sn/pcidev.h>
|
||||
#include <asm/sn/sn_feature_sets.h>
|
||||
#include <asm/sn/sn_sal.h>
|
||||
#include <asm/sn/types.h>
|
||||
|
||||
@ -102,8 +104,7 @@ static struct hotplug_slot_attribute sn_slot_path_attr = __ATTR_RO(path);
|
||||
static int sn_pci_slot_valid(struct pci_bus *pci_bus, int device)
|
||||
{
|
||||
struct pcibus_info *pcibus_info;
|
||||
int bricktype;
|
||||
int bus_num;
|
||||
u16 busnum, segment, ioboard_type;
|
||||
|
||||
pcibus_info = SN_PCIBUS_BUSSOFT_INFO(pci_bus);
|
||||
|
||||
@ -111,12 +112,14 @@ static int sn_pci_slot_valid(struct pci_bus *pci_bus, int device)
|
||||
if (!(pcibus_info->pbi_valid_devices & (1 << device)))
|
||||
return -EPERM;
|
||||
|
||||
bricktype = MODULE_GET_BTYPE(pcibus_info->pbi_moduleid);
|
||||
bus_num = pcibus_info->pbi_buscommon.bs_persist_busnum & 0xf;
|
||||
ioboard_type = sn_ioboard_to_pci_bus(pci_bus);
|
||||
busnum = pcibus_info->pbi_buscommon.bs_persist_busnum;
|
||||
segment = pci_domain_nr(pci_bus) & 0xf;
|
||||
|
||||
/* Do not allow hotplug operations on base I/O cards */
|
||||
if ((bricktype == L1_BRICKTYPE_IX || bricktype == L1_BRICKTYPE_IA) &&
|
||||
(bus_num == 1 && device != 1))
|
||||
if ((ioboard_type == L1_BRICKTYPE_IX ||
|
||||
ioboard_type == L1_BRICKTYPE_IA) &&
|
||||
(segment == 1 && busnum == 0 && device != 1))
|
||||
return -EPERM;
|
||||
|
||||
return 1;
|
||||
@ -125,23 +128,23 @@ static int sn_pci_slot_valid(struct pci_bus *pci_bus, int device)
|
||||
static int sn_pci_bus_valid(struct pci_bus *pci_bus)
|
||||
{
|
||||
struct pcibus_info *pcibus_info;
|
||||
int asic_type;
|
||||
int bricktype;
|
||||
|
||||
pcibus_info = SN_PCIBUS_BUSSOFT_INFO(pci_bus);
|
||||
u32 asic_type;
|
||||
u16 ioboard_type;
|
||||
|
||||
/* Don't register slots hanging off the TIOCA bus */
|
||||
pcibus_info = SN_PCIBUS_BUSSOFT_INFO(pci_bus);
|
||||
asic_type = pcibus_info->pbi_buscommon.bs_asic_type;
|
||||
if (asic_type == PCIIO_ASIC_TYPE_TIOCA)
|
||||
return -EPERM;
|
||||
|
||||
/* Only register slots in I/O Bricks that support hotplug */
|
||||
bricktype = MODULE_GET_BTYPE(pcibus_info->pbi_moduleid);
|
||||
switch (bricktype) {
|
||||
ioboard_type = sn_ioboard_to_pci_bus(pci_bus);
|
||||
switch (ioboard_type) {
|
||||
case L1_BRICKTYPE_IX:
|
||||
case L1_BRICKTYPE_PX:
|
||||
case L1_BRICKTYPE_IA:
|
||||
case L1_BRICKTYPE_PA:
|
||||
case L1_BOARDTYPE_PCIX3SLOT:
|
||||
return 1;
|
||||
break;
|
||||
default:
|
||||
@ -175,14 +178,11 @@ static int sn_hp_slot_private_alloc(struct hotplug_slot *bss_hotplug_slot,
|
||||
slot->pci_bus = pci_bus;
|
||||
sprintf(bss_hotplug_slot->name, "%04x:%02x:%02x",
|
||||
pci_domain_nr(pci_bus),
|
||||
((int)pcibus_info->pbi_buscommon.bs_persist_busnum) & 0xf,
|
||||
((u16)pcibus_info->pbi_buscommon.bs_persist_busnum),
|
||||
device + 1);
|
||||
sprintf(slot->physical_path, "module_%c%c%c%c%.2d",
|
||||
'0'+RACK_GET_CLASS(MODULE_GET_RACK(pcibus_info->pbi_moduleid)),
|
||||
'0'+RACK_GET_GROUP(MODULE_GET_RACK(pcibus_info->pbi_moduleid)),
|
||||
'0'+RACK_GET_NUM(MODULE_GET_RACK(pcibus_info->pbi_moduleid)),
|
||||
MODULE_GET_BTCHAR(pcibus_info->pbi_moduleid),
|
||||
MODULE_GET_BPOS(pcibus_info->pbi_moduleid));
|
||||
|
||||
sn_generate_path(pci_bus, slot->physical_path);
|
||||
|
||||
slot->hotplug_slot = bss_hotplug_slot;
|
||||
list_add(&slot->hp_list, &sn_hp_list);
|
||||
|
||||
@ -461,10 +461,12 @@ static inline int get_power_status(struct hotplug_slot *bss_hotplug_slot,
|
||||
{
|
||||
struct slot *slot = bss_hotplug_slot->private;
|
||||
struct pcibus_info *pcibus_info;
|
||||
u32 power;
|
||||
|
||||
pcibus_info = SN_PCIBUS_BUSSOFT_INFO(slot->pci_bus);
|
||||
mutex_lock(&sn_hotplug_mutex);
|
||||
*value = pcibus_info->pbi_enabled_devices & (1 << slot->device_num);
|
||||
power = pcibus_info->pbi_enabled_devices & (1 << slot->device_num);
|
||||
*value = power ? 1 : 0;
|
||||
mutex_unlock(&sn_hotplug_mutex);
|
||||
return 0;
|
||||
}
|
||||
@ -553,8 +555,8 @@ static int sn_pci_hotplug_init(void)
|
||||
int rc;
|
||||
int registered = 0;
|
||||
|
||||
if (sn_sal_rev() < SGI_HOTPLUG_PROM_REV) {
|
||||
printk(KERN_ERR "%s: PROM version must be greater than 4.30\n",
|
||||
if (!sn_prom_feature_available(PRF_HOTPLUG_SUPPORT)) {
|
||||
printk(KERN_ERR "%s: PROM version does not support hotplug.\n",
|
||||
__FUNCTION__);
|
||||
return -EPERM;
|
||||
}
|
||||
|
@ -168,9 +168,9 @@ struct controller {
|
||||
* error Messages
|
||||
*/
|
||||
#define msg_initialization_err "Initialization failure, error=%d\n"
|
||||
#define msg_button_on "PCI slot #%d - powering on due to button press.\n"
|
||||
#define msg_button_off "PCI slot #%d - powering off due to button press.\n"
|
||||
#define msg_button_cancel "PCI slot #%d - action canceled due to button press.\n"
|
||||
#define msg_button_on "PCI slot #%s - powering on due to button press.\n"
|
||||
#define msg_button_off "PCI slot #%s - powering off due to button press.\n"
|
||||
#define msg_button_cancel "PCI slot #%s - action canceled due to button press.\n"
|
||||
|
||||
/* sysfs functions for the hotplug controller info */
|
||||
extern void shpchp_create_ctrl_files (struct controller *ctrl);
|
||||
@ -196,7 +196,7 @@ extern void queue_pushbutton_work(void *data);
|
||||
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)))
|
||||
if (ACPI_FAILURE(acpi_get_hp_params_from_firmware(dev->bus, hpp)))
|
||||
return -ENODEV;
|
||||
return 0;
|
||||
}
|
||||
|
@ -491,16 +491,9 @@ static int __init shpcd_init(void)
|
||||
shpchp_poll_mode = 1;
|
||||
#endif
|
||||
|
||||
shpchp_wq = create_singlethread_workqueue("shpchpd");
|
||||
if (!shpchp_wq)
|
||||
return -ENOMEM;
|
||||
|
||||
retval = pci_register_driver(&shpc_driver);
|
||||
dbg("%s: pci_register_driver = %d\n", __FUNCTION__, retval);
|
||||
info(DRIVER_DESC " version: " DRIVER_VERSION "\n");
|
||||
if (retval) {
|
||||
destroy_workqueue(shpchp_wq);
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
@ -508,7 +501,6 @@ static void __exit shpcd_cleanup(void)
|
||||
{
|
||||
dbg("unload_shpchpd()\n");
|
||||
pci_unregister_driver(&shpc_driver);
|
||||
destroy_workqueue(shpchp_wq);
|
||||
info(DRIVER_DESC " version: " DRIVER_VERSION " unloaded\n");
|
||||
}
|
||||
|
||||
|
@ -72,7 +72,7 @@ u8 shpchp_handle_attention_button(u8 hp_slot, void *inst_id)
|
||||
/*
|
||||
* Button pressed - See if need to TAKE ACTION!!!
|
||||
*/
|
||||
info("Button pressed on Slot(%d)\n", ctrl->first_slot + hp_slot);
|
||||
info("Button pressed on Slot(%s)\n", p_slot->name);
|
||||
event_type = INT_BUTTON_PRESS;
|
||||
|
||||
queue_interrupt_event(p_slot, event_type);
|
||||
@ -101,7 +101,7 @@ u8 shpchp_handle_switch_change(u8 hp_slot, void *inst_id)
|
||||
/*
|
||||
* Switch opened
|
||||
*/
|
||||
info("Latch open on Slot(%d)\n", ctrl->first_slot + hp_slot);
|
||||
info("Latch open on Slot(%s)\n", p_slot->name);
|
||||
event_type = INT_SWITCH_OPEN;
|
||||
if (p_slot->pwr_save && p_slot->presence_save) {
|
||||
event_type = INT_POWER_FAULT;
|
||||
@ -111,7 +111,7 @@ u8 shpchp_handle_switch_change(u8 hp_slot, void *inst_id)
|
||||
/*
|
||||
* Switch closed
|
||||
*/
|
||||
info("Latch close on Slot(%d)\n", ctrl->first_slot + hp_slot);
|
||||
info("Latch close on Slot(%s)\n", p_slot->name);
|
||||
event_type = INT_SWITCH_CLOSE;
|
||||
}
|
||||
|
||||
@ -139,13 +139,13 @@ u8 shpchp_handle_presence_change(u8 hp_slot, void *inst_id)
|
||||
/*
|
||||
* Card Present
|
||||
*/
|
||||
info("Card present on Slot(%d)\n", ctrl->first_slot + hp_slot);
|
||||
info("Card present on Slot(%s)\n", p_slot->name);
|
||||
event_type = INT_PRESENCE_ON;
|
||||
} else {
|
||||
/*
|
||||
* Not Present
|
||||
*/
|
||||
info("Card not present on Slot(%d)\n", ctrl->first_slot + hp_slot);
|
||||
info("Card not present on Slot(%s)\n", p_slot->name);
|
||||
event_type = INT_PRESENCE_OFF;
|
||||
}
|
||||
|
||||
@ -169,14 +169,14 @@ u8 shpchp_handle_power_fault(u8 hp_slot, void *inst_id)
|
||||
/*
|
||||
* Power fault Cleared
|
||||
*/
|
||||
info("Power fault cleared on Slot(%d)\n", ctrl->first_slot + hp_slot);
|
||||
info("Power fault cleared on Slot(%s)\n", p_slot->name);
|
||||
p_slot->status = 0x00;
|
||||
event_type = INT_POWER_FAULT_CLEAR;
|
||||
} else {
|
||||
/*
|
||||
* Power fault
|
||||
*/
|
||||
info("Power fault on Slot(%d)\n", ctrl->first_slot + hp_slot);
|
||||
info("Power fault on Slot(%s)\n", p_slot->name);
|
||||
event_type = INT_POWER_FAULT;
|
||||
/* set power fault status for this board */
|
||||
p_slot->status = 0xFF;
|
||||
@ -496,10 +496,10 @@ static void handle_button_press_event(struct slot *p_slot)
|
||||
p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
|
||||
if (getstatus) {
|
||||
p_slot->state = BLINKINGOFF_STATE;
|
||||
info(msg_button_off, p_slot->number);
|
||||
info(msg_button_off, p_slot->name);
|
||||
} else {
|
||||
p_slot->state = BLINKINGON_STATE;
|
||||
info(msg_button_on, p_slot->number);
|
||||
info(msg_button_on, p_slot->name);
|
||||
}
|
||||
/* blink green LED and turn off amber */
|
||||
p_slot->hpc_ops->green_led_blink(p_slot);
|
||||
@ -522,7 +522,7 @@ static void handle_button_press_event(struct slot *p_slot)
|
||||
else
|
||||
p_slot->hpc_ops->green_led_off(p_slot);
|
||||
p_slot->hpc_ops->set_attention_status(p_slot, 0);
|
||||
info(msg_button_cancel, p_slot->number);
|
||||
info(msg_button_cancel, p_slot->name);
|
||||
p_slot->state = STATIC_STATE;
|
||||
break;
|
||||
case POWEROFF_STATE:
|
||||
@ -575,17 +575,17 @@ static int shpchp_enable_slot (struct slot *p_slot)
|
||||
mutex_lock(&p_slot->ctrl->crit_sect);
|
||||
rc = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus);
|
||||
if (rc || !getstatus) {
|
||||
info("%s: no adapter on slot(%x)\n", __FUNCTION__, p_slot->number);
|
||||
info("No adapter on slot(%s)\n", p_slot->name);
|
||||
goto out;
|
||||
}
|
||||
rc = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
|
||||
if (rc || getstatus) {
|
||||
info("%s: latch open on slot(%x)\n", __FUNCTION__, p_slot->number);
|
||||
info("Latch open on slot(%s)\n", p_slot->name);
|
||||
goto out;
|
||||
}
|
||||
rc = p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
|
||||
if (rc || getstatus) {
|
||||
info("%s: already enabled on slot(%x)\n", __FUNCTION__, p_slot->number);
|
||||
info("Already enabled on slot(%s)\n", p_slot->name);
|
||||
goto out;
|
||||
}
|
||||
|
||||
@ -634,17 +634,17 @@ static int shpchp_disable_slot (struct slot *p_slot)
|
||||
|
||||
rc = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus);
|
||||
if (rc || !getstatus) {
|
||||
info("%s: no adapter on slot(%x)\n", __FUNCTION__, p_slot->number);
|
||||
info("No adapter on slot(%s)\n", p_slot->name);
|
||||
goto out;
|
||||
}
|
||||
rc = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
|
||||
if (rc || getstatus) {
|
||||
info("%s: latch open on slot(%x)\n", __FUNCTION__, p_slot->number);
|
||||
info("Latch open on slot(%s)\n", p_slot->name);
|
||||
goto out;
|
||||
}
|
||||
rc = p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
|
||||
if (rc || !getstatus) {
|
||||
info("%s: already disabled slot(%x)\n", __FUNCTION__, p_slot->number);
|
||||
info("Already disabled slot(%s)\n", p_slot->name);
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -47,21 +47,28 @@ static void program_fw_provided_values(struct pci_dev *dev)
|
||||
return;
|
||||
|
||||
/* 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;
|
||||
if (get_hp_params_from_firmware(dev, &hpp) ||
|
||||
!hpp.t0 || (hpp.t0->revision > 1)) {
|
||||
printk(KERN_WARNING
|
||||
"%s: Could not get hotplug parameters. Use defaults\n",
|
||||
__FUNCTION__);
|
||||
hpp.t0 = &hpp.type0_data;
|
||||
hpp.t0->revision = 0;
|
||||
hpp.t0->cache_line_size = 8;
|
||||
hpp.t0->latency_timer = 0x40;
|
||||
hpp.t0->enable_serr = 0;
|
||||
hpp.t0->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);
|
||||
pci_write_config_byte(dev,
|
||||
PCI_CACHE_LINE_SIZE, hpp.t0->cache_line_size);
|
||||
pci_write_config_byte(dev, PCI_LATENCY_TIMER, hpp.t0->latency_timer);
|
||||
pci_read_config_word(dev, PCI_COMMAND, &pci_cmd);
|
||||
if (hpp.enable_serr)
|
||||
if (hpp.t0->enable_serr)
|
||||
pci_cmd |= PCI_COMMAND_SERR;
|
||||
else
|
||||
pci_cmd &= ~PCI_COMMAND_SERR;
|
||||
if (hpp.enable_perr)
|
||||
if (hpp.t0->enable_perr)
|
||||
pci_cmd |= PCI_COMMAND_PARITY;
|
||||
else
|
||||
pci_cmd &= ~PCI_COMMAND_PARITY;
|
||||
@ -70,13 +77,13 @@ static void program_fw_provided_values(struct pci_dev *dev)
|
||||
/* Program bridge control value and child devices */
|
||||
if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) {
|
||||
pci_write_config_byte(dev, PCI_SEC_LATENCY_TIMER,
|
||||
hpp.latency_timer);
|
||||
hpp.t0->latency_timer);
|
||||
pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &pci_bctl);
|
||||
if (hpp.enable_serr)
|
||||
if (hpp.t0->enable_serr)
|
||||
pci_bctl |= PCI_BRIDGE_CTL_SERR;
|
||||
else
|
||||
pci_bctl &= ~PCI_BRIDGE_CTL_SERR;
|
||||
if (hpp.enable_perr)
|
||||
if (hpp.t0->enable_perr)
|
||||
pci_bctl |= PCI_BRIDGE_CTL_PARITY;
|
||||
else
|
||||
pci_bctl &= ~PCI_BRIDGE_CTL_PARITY;
|
||||
|
Loading…
Reference in New Issue
Block a user