Commit a3415dc3 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'linux-next' of git://git.kernel.org/pub/scm/linux/kernel/git/jbarnes/pci-2.6

* 'linux-next' of git://git.kernel.org/pub/scm/linux/kernel/git/jbarnes/pci-2.6: (32 commits)
  PCI hotplug: fix logic in Compaq hotplug controller bus speed setup
  PCI: don't export linux/io.h from pci.h
  PCI: PCI_QUIRKS depends on PCI
  PCI hotplug: pciehp: poll data link layer link active
  PCI hotplug: pciehp: fix possible memory leak in pcie_init
  PCI: Workaround invalid P2P bridge bus numbers
  PCI Hotplug: fakephp: add duplicate slot name debugging
  PCI: Hotplug core: remove 'name'
  PCI: shcphp: remove 'name' parameter
  PCI: SGI Hotplug: stop managing bss_hotplug_slot->name
  PCI: rpaphp: kmalloc/kfree slot->name directly
  PCI: pciehp: remove 'name' parameter
  PCI: ibmphp: stop managing hotplug_slot->name
  PCI: fakephp: remove 'name' parameter
  PCI, PCI Hotplug: introduce slot_name helpers
  PCI: cpqphp: stop managing hotplug_slot->name
  PCI: cpci_hotplug: stop managing hotplug_slot->name
  PCI: acpiphp: remove 'name' parameter
  PCI: prevent duplicate slot names
  PCI Hotplug: serialize pci_hp_register and pci_hp_deregister
  ...
parents b4d0b08a 05a34f51
......@@ -3257,11 +3257,6 @@ L: linux-pci@vger.kernel.org
T: git kernel.org:/pub/scm/linux/kernel/git/jbarnes/pci-2.6.git
S: Supported
PCI HOTPLUG CORE
P: Kristen Carlson Accardi
M: kristen.c.accardi@intel.com
S: Supported
PCIE HOTPLUG DRIVER
P: Kristen Carlson Accardi
M: kristen.c.accardi@intel.com
......
......@@ -150,7 +150,7 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv)
}
snprintf(name, sizeof(name), "%u", (u32)sun);
pci_slot = pci_create_slot(pci_bus, device, name);
pci_slot = pci_create_slot(pci_bus, device, name, NULL);
if (IS_ERR(pci_slot)) {
err("pci_create_slot returned %ld\n", PTR_ERR(pci_slot));
kfree(slot);
......
......@@ -50,9 +50,6 @@
#define info(format, arg...) printk(KERN_INFO "%s: " format, MY_NAME , ## arg)
#define warn(format, arg...) printk(KERN_WARNING "%s: " format, MY_NAME , ## arg)
/* name size which is used for entries in pcihpfs */
#define SLOT_NAME_SIZE 20 /* {_SUN} */
struct acpiphp_bridge;
struct acpiphp_slot;
......@@ -63,9 +60,13 @@ struct slot {
struct hotplug_slot *hotplug_slot;
struct acpiphp_slot *acpi_slot;
struct hotplug_slot_info info;
char name[SLOT_NAME_SIZE];
};
static inline const char *slot_name(struct slot *slot)
{
return hotplug_slot_name(slot->hotplug_slot);
}
/*
* struct acpiphp_bridge - PCI bridge information
*
......
......@@ -44,6 +44,9 @@
#define MY_NAME "acpiphp"
/* name size which is used for entries in pcihpfs */
#define SLOT_NAME_SIZE 21 /* {_SUN} */
static int debug;
int acpiphp_debug;
......@@ -84,7 +87,6 @@ static struct hotplug_slot_ops acpi_hotplug_slot_ops = {
.get_adapter_status = get_adapter_status,
};
/**
* acpiphp_register_attention - set attention LED callback
* @info: must be completely filled with LED callbacks
......@@ -136,7 +138,7 @@ static int enable_slot(struct hotplug_slot *hotplug_slot)
{
struct slot *slot = hotplug_slot->private;
dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
dbg("%s - physical_slot = %s\n", __func__, slot_name(slot));
/* enable the specified slot */
return acpiphp_enable_slot(slot->acpi_slot);
......@@ -154,7 +156,7 @@ static int disable_slot(struct hotplug_slot *hotplug_slot)
struct slot *slot = hotplug_slot->private;
int retval;
dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
dbg("%s - physical_slot = %s\n", __func__, slot_name(slot));
/* disable the specified slot */
retval = acpiphp_disable_slot(slot->acpi_slot);
......@@ -177,7 +179,7 @@ static int disable_slot(struct hotplug_slot *hotplug_slot)
{
int retval = -ENODEV;
dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
dbg("%s - physical_slot = %s\n", __func__, hotplug_slot_name(hotplug_slot));
if (attention_info && try_module_get(attention_info->owner)) {
retval = attention_info->set_attn(hotplug_slot, status);
......@@ -200,7 +202,7 @@ static int get_power_status(struct hotplug_slot *hotplug_slot, u8 *value)
{
struct slot *slot = hotplug_slot->private;
dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
dbg("%s - physical_slot = %s\n", __func__, slot_name(slot));
*value = acpiphp_get_power_status(slot->acpi_slot);
......@@ -222,7 +224,7 @@ static int get_attention_status(struct hotplug_slot *hotplug_slot, u8 *value)
{
int retval = -EINVAL;
dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
dbg("%s - physical_slot = %s\n", __func__, hotplug_slot_name(hotplug_slot));
if (attention_info && try_module_get(attention_info->owner)) {
retval = attention_info->get_attn(hotplug_slot, value);
......@@ -245,7 +247,7 @@ static int get_latch_status(struct hotplug_slot *hotplug_slot, u8 *value)
{
struct slot *slot = hotplug_slot->private;
dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
dbg("%s - physical_slot = %s\n", __func__, slot_name(slot));
*value = acpiphp_get_latch_status(slot->acpi_slot);
......@@ -265,7 +267,7 @@ static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 *value)
{
struct slot *slot = hotplug_slot->private;
dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
dbg("%s - physical_slot = %s\n", __func__, slot_name(slot));
*value = acpiphp_get_adapter_status(slot->acpi_slot);
......@@ -299,7 +301,7 @@ static void release_slot(struct hotplug_slot *hotplug_slot)
{
struct slot *slot = hotplug_slot->private;
dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
dbg("%s - physical_slot = %s\n", __func__, slot_name(slot));
kfree(slot->hotplug_slot);
kfree(slot);
......@@ -310,6 +312,7 @@ int acpiphp_register_hotplug_slot(struct acpiphp_slot *acpiphp_slot)
{
struct slot *slot;
int retval = -ENOMEM;
char name[SLOT_NAME_SIZE];
slot = kzalloc(sizeof(*slot), GFP_KERNEL);
if (!slot)
......@@ -321,8 +324,6 @@ int acpiphp_register_hotplug_slot(struct acpiphp_slot *acpiphp_slot)
slot->hotplug_slot->info = &slot->info;
slot->hotplug_slot->name = slot->name;
slot->hotplug_slot->private = slot;
slot->hotplug_slot->release = &release_slot;
slot->hotplug_slot->ops = &acpi_hotplug_slot_ops;
......@@ -336,11 +337,12 @@ int acpiphp_register_hotplug_slot(struct acpiphp_slot *acpiphp_slot)
slot->hotplug_slot->info->cur_bus_speed = PCI_SPEED_UNKNOWN;
acpiphp_slot->slot = slot;
snprintf(slot->name, sizeof(slot->name), "%u", slot->acpi_slot->sun);
snprintf(name, SLOT_NAME_SIZE, "%u", slot->acpi_slot->sun);
retval = pci_hp_register(slot->hotplug_slot,
acpiphp_slot->bridge->pci_bus,
acpiphp_slot->device);
acpiphp_slot->device,
name);
if (retval == -EBUSY)
goto error_hpslot;
if (retval) {
......@@ -348,7 +350,7 @@ int acpiphp_register_hotplug_slot(struct acpiphp_slot *acpiphp_slot)
goto error_hpslot;
}
info("Slot [%s] registered\n", slot->hotplug_slot->name);
info("Slot [%s] registered\n", slot_name(slot));
return 0;
error_hpslot:
......@@ -365,7 +367,7 @@ void acpiphp_unregister_hotplug_slot(struct acpiphp_slot *acpiphp_slot)
struct slot *slot = acpiphp_slot->slot;
int retval = 0;
info ("Slot [%s] unregistered\n", slot->hotplug_slot->name);
info("Slot [%s] unregistered\n", slot_name(slot));
retval = pci_hp_deregister(slot->hotplug_slot);
if (retval)
......
......@@ -30,6 +30,7 @@
#include <linux/types.h>
#include <linux/pci.h>
#include <linux/pci_hotplug.h>
/* PICMG 2.1 R2.0 HS CSR bits: */
#define HS_CSR_INS 0x0080
......@@ -69,6 +70,11 @@ struct cpci_hp_controller {
struct cpci_hp_controller_ops *ops;
};
static inline const char *slot_name(struct slot *slot)
{
return hotplug_slot_name(slot->hotplug_slot);
}
extern int cpci_hp_register_controller(struct cpci_hp_controller *controller);
extern int cpci_hp_unregister_controller(struct cpci_hp_controller *controller);
extern int cpci_hp_register_bus(struct pci_bus *bus, u8 first, u8 last);
......
......@@ -108,7 +108,7 @@ enable_slot(struct hotplug_slot *hotplug_slot)
struct slot *slot = hotplug_slot->private;
int retval = 0;
dbg("%s - physical_slot = %s", __func__, hotplug_slot->name);
dbg("%s - physical_slot = %s", __func__, slot_name(slot));
if (controller->ops->set_power)
retval = controller->ops->set_power(slot, 1);
......@@ -121,25 +121,23 @@ disable_slot(struct hotplug_slot *hotplug_slot)
struct slot *slot = hotplug_slot->private;
int retval = 0;
dbg("%s - physical_slot = %s", __func__, hotplug_slot->name);
dbg("%s - physical_slot = %s", __func__, slot_name(slot));
down_write(&list_rwsem);
/* Unconfigure device */
dbg("%s - unconfiguring slot %s",
__func__, slot->hotplug_slot->name);
dbg("%s - unconfiguring slot %s", __func__, slot_name(slot));
if ((retval = cpci_unconfigure_slot(slot))) {
err("%s - could not unconfigure slot %s",
__func__, slot->hotplug_slot->name);
__func__, slot_name(slot));
goto disable_error;
}
dbg("%s - finished unconfiguring slot %s",
__func__, slot->hotplug_slot->name);
dbg("%s - finished unconfiguring slot %s", __func__, slot_name(slot));
/* Clear EXT (by setting it) */
if (cpci_clear_ext(slot)) {
err("%s - could not clear EXT for slot %s",
__func__, slot->hotplug_slot->name);
__func__, slot_name(slot));
retval = -ENODEV;
goto disable_error;
}
......@@ -214,7 +212,6 @@ static void release_slot(struct hotplug_slot *hotplug_slot)
struct slot *slot = hotplug_slot->private;
kfree(slot->hotplug_slot->info);
kfree(slot->hotplug_slot->name);
kfree(slot->hotplug_slot);
if (slot->dev)
pci_dev_put(slot->dev);
......@@ -222,12 +219,6 @@ static void release_slot(struct hotplug_slot *hotplug_slot)
}
#define SLOT_NAME_SIZE 6
static void
make_slot_name(struct slot *slot)
{
snprintf(slot->hotplug_slot->name,
SLOT_NAME_SIZE, "%02x:%02x", slot->bus->number, slot->number);
}
int
cpci_hp_register_bus(struct pci_bus *bus, u8 first, u8 last)
......@@ -235,7 +226,7 @@ cpci_hp_register_bus(struct pci_bus *bus, u8 first, u8 last)
struct slot *slot;
struct hotplug_slot *hotplug_slot;
struct hotplug_slot_info *info;
char *name;
char name[SLOT_NAME_SIZE];
int status = -ENOMEM;
int i;
......@@ -262,34 +253,31 @@ cpci_hp_register_bus(struct pci_bus *bus, u8 first, u8 last)
goto error_hpslot;
hotplug_slot->info = info;
name = kmalloc(SLOT_NAME_SIZE, GFP_KERNEL);
if (!name)
goto error_info;
hotplug_slot->name = name;
slot->bus = bus;
slot->number = i;
slot->devfn = PCI_DEVFN(i, 0);
snprintf(name, SLOT_NAME_SIZE, "%02x:%02x", bus->number, i);
hotplug_slot->private = slot;
hotplug_slot->release = &release_slot;
make_slot_name(slot);
hotplug_slot->ops = &cpci_hotplug_slot_ops;
/*
* Initialize the slot info structure with some known
* good values.
*/
dbg("initializing slot %s", slot->hotplug_slot->name);
dbg("initializing slot %s", name);
info->power_status = cpci_get_power_status(slot);
info->attention_status = cpci_get_attention_status(slot);
dbg("registering slot %s", slot->hotplug_slot->name);
status = pci_hp_register(slot->hotplug_slot, bus, i);
dbg("registering slot %s", name);
status = pci_hp_register(slot->hotplug_slot, bus, i, name);
if (status) {
err("pci_hp_register failed with error %d", status);
goto error_name;
goto error_info;
}
dbg("slot registered with name: %s", slot_name(slot));
/* Add slot to our internal list */
down_write(&list_rwsem);
......@@ -298,8 +286,6 @@ cpci_hp_register_bus(struct pci_bus *bus, u8 first, u8 last)
up_write(&list_rwsem);
}
return 0;
error_name:
kfree(name);
error_info:
kfree(info);
error_hpslot:
......@@ -327,7 +313,7 @@ cpci_hp_unregister_bus(struct pci_bus *bus)
list_del(&slot->slot_list);
slots--;
dbg("deregistering slot %s", slot->hotplug_slot->name);
dbg("deregistering slot %s", slot_name(slot));
status = pci_hp_deregister(slot->hotplug_slot);
if (status) {
err("pci_hp_deregister failed with error %d",
......@@ -379,11 +365,10 @@ init_slots(int clear_ins)
return -1;
}
list_for_each_entry(slot, &slot_list, slot_list) {
dbg("%s - looking at slot %s",
__func__, slot->hotplug_slot->name);
dbg("%s - looking at slot %s", __func__, slot_name(slot));
if (clear_ins && cpci_check_and_clear_ins(slot))
dbg("%s - cleared INS for slot %s",
__func__, slot->hotplug_slot->name);
__func__, slot_name(slot));
dev = pci_get_slot(slot->bus, PCI_DEVFN(slot->number, 0));
if (dev) {
if (update_adapter_status(slot->hotplug_slot, 1))
......@@ -414,8 +399,7 @@ check_slots(void)
}
extracted = inserted = 0;
list_for_each_entry(slot, &slot_list, slot_list) {
dbg("%s - looking at slot %s",
__func__, slot->hotplug_slot->name);
dbg("%s - looking at slot %s", __func__, slot_name(slot));
if (cpci_check_and_clear_ins(slot)) {
/*
* Some broken hardware (e.g. PLX 9054AB) asserts
......@@ -423,35 +407,34 @@ check_slots(void)
*/
if (slot->dev) {
warn("slot %s already inserted",
slot->hotplug_slot->name);
slot_name(slot));
inserted++;
continue;
}
/* Process insertion */
dbg("%s - slot %s inserted",
__func__, slot->hotplug_slot->name);
dbg("%s - slot %s inserted", __func__, slot_name(slot));
/* GSM, debug */
hs_csr = cpci_get_hs_csr(slot);
dbg("%s - slot %s HS_CSR (1) = %04x",
__func__, slot->hotplug_slot->name, hs_csr);
__func__, slot_name(slot), hs_csr);
/* Configure device */
dbg("%s - configuring slot %s",
__func__, slot->hotplug_slot->name);
__func__, slot_name(slot));
if (cpci_configure_slot(slot)) {
err("%s - could not configure slot %s",
__func__, slot->hotplug_slot->name);
__func__, slot_name(slot));
continue;
}
dbg("%s - finished configuring slot %s",
__func__, slot->hotplug_slot->name);
__func__, slot_name(slot));
/* GSM, debug */
hs_csr = cpci_get_hs_csr(slot);
dbg("%s - slot %s HS_CSR (2) = %04x",
__func__, slot->hotplug_slot->name, hs_csr);
__func__, slot_name(slot), hs_csr);
if (update_latch_status(slot->hotplug_slot, 1))
warn("failure to update latch file");
......@@ -464,18 +447,18 @@ check_slots(void)
/* GSM, debug */
hs_csr = cpci_get_hs_csr(slot);
dbg("%s - slot %s HS_CSR (3) = %04x",
__func__, slot->hotplug_slot->name, hs_csr);
__func__, slot_name(slot), hs_csr);
inserted++;
} else if (cpci_check_ext(slot)) {
/* Process extraction request */
dbg("%s - slot %s extracted",
__func__, slot->hotplug_slot->name);
__func__, slot_name(slot));
/* GSM, debug */
hs_csr = cpci_get_hs_csr(slot);
dbg("%s - slot %s HS_CSR = %04x",
__func__, slot->hotplug_slot->name, hs_csr);
__func__, slot_name(slot), hs_csr);
if (!slot->extracting) {
if (update_latch_status(slot->hotplug_slot, 0)) {
......@@ -493,7 +476,7 @@ check_slots(void)
* bother trying to tell the driver or not?
*/
err("card in slot %s was improperly removed",
slot->hotplug_slot->name);
slot_name(slot));
if (update_adapter_status(slot->hotplug_slot, 0))
warn("failure to update adapter file");
slot->extracting = 0;
......
......@@ -209,7 +209,7 @@ int cpci_led_on(struct slot* slot)
hs_cap + 2,
hs_csr)) {
err("Could not set LOO for slot %s",
slot->hotplug_slot->name);
hotplug_slot_name(slot->hotplug_slot));
return -ENODEV;
}
}
......@@ -238,7 +238,7 @@ int cpci_led_off(struct slot* slot)
hs_cap + 2,
hs_csr)) {
err("Could not clear LOO for slot %s",
slot->hotplug_slot->name);
hotplug_slot_name(slot->hotplug_slot));
return -ENODEV;
}
}
......
......@@ -449,6 +449,11 @@ extern u8 cpqhp_disk_irq;
/* inline functions */
static inline char *slot_name(struct slot *slot)
{
return hotplug_slot_name(slot->hotplug_slot);
}
/*
* return_resource
*
......@@ -696,14 +701,6 @@ static inline int get_presence_status(struct controller *ctrl, struct slot *slot
return presence_save;
}
#define SLOT_NAME_SIZE 10
static inline void make_slot_name(char *buffer, int buffer_size, struct slot *slot)
{
snprintf(buffer, buffer_size, "%d", slot->number);
}
static inline int wait_for_ctrl_irq(struct controller *ctrl)
{
DECLARE_WAITQUEUE(wait, current);
......
......@@ -315,14 +315,15 @@ static void release_slot(struct hotplug_slot *hotplug_slot)
{
struct slot *slot = hotplug_slot->private;
dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
dbg("%s - physical_slot = %s\n", __func__, slot_name(slot));
kfree(slot->hotplug_slot->info);
kfree(slot->hotplug_slot->name);
kfree(slot->hotplug_slot);
kfree(slot);
}
#define SLOT_NAME_SIZE 10
static int ctrl_slot_setup(struct controller *ctrl,
void __iomem *smbios_start,
void __iomem *smbios_table)
......@@ -335,6 +336,7 @@ static int ctrl_slot_setup(struct controller *ctrl,
u8 slot_number;
u8 ctrl_slot;
u32 tempdword;
char name[SLOT_NAME_SIZE];
void __iomem *slot_entry= NULL;
int result = -ENOMEM;
......@@ -363,16 +365,12 @@ static int ctrl_slot_setup(struct controller *ctrl,
if (!hotplug_slot->info)
goto error_hpslot;
hotplug_slot_info = hotplug_slot->info;
hotplug_slot->name = kmalloc(SLOT_NAME_SIZE, GFP_KERNEL);
if (!hotplug_slot->name)
goto error_info;
slot->ctrl = ctrl;
slot->bus = ctrl->bus;
slot->device = slot_device;
slot->number = slot_number;
dbg("slot->number = %d\n", slot->number);
dbg("slot->number = %u\n", slot->number);
slot_entry = get_SMBIOS_entry(smbios_start, smbios_table, 9,
slot_entry);
......@@ -418,9 +416,9 @@ static int ctrl_slot_setup(struct controller *ctrl,
/* register this slot with the hotplug pci core */
hotplug_slot->release = &release_slot;
hotplug_slot->private = slot;
make_slot_name(hotplug_slot->name, SLOT_NAME_SIZE, slot);
snprintf(name, SLOT_NAME_SIZE, "%u", slot->number);
hotplug_slot->ops = &cpqphp_hotplug_slot_ops;
hotplug_slot_info->power_status = get_slot_enabled(ctrl, slot);
hotplug_slot_info->attention_status =
cpq_get_attention_status(ctrl, slot);
......@@ -436,10 +434,11 @@ static int ctrl_slot_setup(struct controller *ctrl,
slot_number);
result = pci_hp_register(hotplug_slot,
ctrl->pci_dev->subordinate,
slot->device);
slot->device,
name);
if (result) {
err("pci_hp_register failed with error %d\n", result);
goto error_name;
goto error_info;
}
slot->next = ctrl->slot;
......@@ -451,8 +450,6 @@ static int ctrl_slot_setup(struct controller *ctrl,
}
return 0;
error_name:
kfree(hotplug_slot->name);
error_info:
kfree(hotplug_slot_info);
error_hpslot:
......@@ -638,7 +635,7 @@ static int set_attention_status (struct hotplug_slot *hotplug_slot, u8 status)
u8 device;
u8 function;
dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
dbg("%s - physical_slot = %s\n", __func__, slot_name(slot));
if (cpqhp_get_bus_dev(ctrl, &bus, &devfn, slot->number) == -1)
return -ENODEV;
......@@ -665,7 +662,7 @@ static int process_SI(struct hotplug_slot *hotplug_slot)
u8 device;
u8 function;
dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
dbg("%s - physical_slot = %s\n", __func__, slot_name(slot));
if (cpqhp_get_bus_dev(ctrl, &bus, &devfn, slot->number) == -1)
return -ENODEV;
......@@ -697,7 +694,7 @@ static int process_SS(struct hotplug_slot *hotplug_slot)
u8 device;
u8 function;
dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
dbg("%s - physical_slot = %s\n", __func__, slot_name(slot));
if (cpqhp_get_bus_dev(ctrl, &bus, &devfn, slot->number) == -1)
return -ENODEV;
......@@ -720,7 +717,7 @@ static int hardware_test(struct hotplug_slot *hotplug_slot, u32 value)
struct slot *slot = hotplug_slot->private;
struct controller *ctrl = slot->ctrl;
dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
dbg("%s - physical_slot = %s\n", __func__, slot_name(slot));
return cpqhp_hardware_test(ctrl, value);
}
......@@ -731,7 +728,7 @@ static int get_power_status(struct hotplug_slot *hotplug_slot, u8 *value)
struct slot *slot = hotplug_slot->private;
struct controller *ctrl = slot->ctrl;
dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
dbg("%s - physical_slot = %s\n", __func__, slot_name(slot));
*value = get_slot_enabled(ctrl, slot);
return 0;
......@@ -742,7 +739,7 @@ static int get_attention_status(struct hotplug_slot *hotplug_slot, u8 *value)
struct slot *slot = hotplug_slot->private;
struct controller *ctrl = slot->ctrl;
dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
dbg("%s - physical_slot = %s\n", __func__, slot_name(slot));
*value = cpq_get_attention_status(ctrl, slot);
return 0;
......@@ -753,7 +750,7 @@ static int get_latch_status(struct hotplug_slot *hotplug_slot, u8 *value)
struct slot *slot = hotplug_slot->private;
struct controller *ctrl = slot->ctrl;
dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
dbg("%s - physical_slot = %s\n", __func__, slot_name(slot));
*value = cpq_get_latch_status(ctrl, slot);
......@@ -765,7 +762,7 @@ static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 *value)
struct slot *slot = hotplug_slot->private;
struct controller *ctrl = slot->ctrl;
dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
dbg("%s - physical_slot = %s\n", __func__, slot_name(slot));
*value = get_presence_status(ctrl, slot);
......@@ -777,7 +774,7 @@ static int get_max_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_sp
struct slot *slot = hotplug_slot->private;
struct controller *ctrl = slot->ctrl;
dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
dbg("%s - physical_slot = %s\n", __func__, slot_name(slot));
*value = ctrl->speed_capability;
......@@ -789,7 +786,7 @@ static int get_cur_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_sp
struct slot *slot = hotplug_slot->private;
struct controller *ctrl = slot->ctrl;
dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
dbg("%s - physical_slot = %s\n", __func__, slot_name(slot));
*value = ctrl->speed;
......
......@@ -1139,7 +1139,7 @@ static u8 set_controller_speed(struct controller *ctrl, u8 adapter_speed, u8 hp_
for(slot = ctrl->slot; slot; slot = slot->next) {
if (slot->device == (hp_slot + ctrl->slot_device_offset))
continue;
if (!slot->hotplug_slot && !slot->hotplug_slot->info)
if (!slot->hotplug_slot || !slot->hotplug_slot->info)
continue;
if (slot->hotplug_slot->info->adapter_status == 0)
continue;
......
......@@ -66,10 +66,10 @@ struct dummy_slot {
struct pci_dev *dev;
struct work_struct remove_work;
unsigned long removed;
char name[8];
};
static int debug;
static int dup_slots;
static LIST_HEAD(slot_list);
static struct workqueue_struct *dummyphp_wq;
......@@ -96,10 +96,13 @@ static void dummy_release(struct hotplug_slot *slot)
kfree(dslot);
}
#define SLOT_NAME_SIZE 8
static int add_slot(struct pci_dev *dev)
{
struct dummy_slot *dslot;
struct hotplug_slot *slot;
char name[SLOT_NAME_SIZE];
int retval = -ENOMEM;
static int count = 1;
......@@ -119,19 +122,22 @@ static int add_slot(struct pci_dev *dev)
if (!dslot)
goto error_info;
slot->name = dslot->name;
snprintf(slot->name, sizeof(dslot->name), "fake%d", count++);
dbg("slot->name = %s\n", slot->name);
if (dup_slots)
snprintf(name, SLOT_NAME_SIZE, "fake");
else
snprintf(name, SLOT_NAME_SIZE, "fake%d", count++);
dbg("slot->name = %s\n", name);
slot->ops = &dummy_hotplug_slot_ops;
slot->release = &dummy_release;
slot->private = dslot;
retval = pci_hp_register(slot, dev->bus, PCI_SLOT(dev->devfn));
retval = pci_hp_register(slot, dev->bus, PCI_SLOT(dev->devfn), name);
if (retval) {
err("pci_hp_register failed with error %d\n", retval);
goto error_dslot;
}
dbg("slot->name = %s\n", hotplug_slot_name(slot));
dslot->slot = slot;
dslot->dev = pci_dev_get(dev);
list_add (&dslot->node, &slot_list);
......@@ -167,10 +173,11 @@ static void remove_slot(struct dummy_slot *dslot)
{
int retval;
dbg("removing slot %s\n", dslot->slot->name);
dbg("removing slot %s\n", hotplug_slot_name(dslot->slot));
retval = pci_hp_deregister(dslot->slot);
if (retval)
err("Problem unregistering a slot %s\n", dslot->slot->name);
err("Problem unregistering a slot %s\n",
hotplug_slot_name(dslot->slot));
}
/* called from the single-threaded workqueue handler to remove a slot */
......@@ -308,7 +315,7 @@ static int disable_slot(struct hotplug_slot *slot)
return -ENODEV;
dslot = slot->private;
dbg("%s - physical_slot = %s\n", __func__, slot->name);
dbg("%s - physical_slot = %s\n", __func__, hotplug_slot_name(slot));
for (func = 7; func >= 0; func--) {
dev = pci_get_slot(dslot->dev->bus, dslot->dev->devfn + func);
......@@ -373,4 +380,5 @@ MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
module_param(debug, bool, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(debug, "Debugging mode enabled or not");
module_param(dup_slots, bool, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(dup_slots, "Force duplicate slot names for debugging");
......@@ -707,17 +707,16 @@ struct slot {
u8 device;
u8 number;
u8 real_physical_slot_num;
char name[100];
u32 capabilities;
u8 supported_speed;
u8 supported_bus_mode;
u8 flag; /* this is for disable slot and polling */
u8 ctlr_index;
struct hotplug_slot *hotplug_slot;
struct controller *ctrl;
struct pci_func *func;
u8 irq[4];
u8 flag; /* this is for disable slot and polling */
int bit_mode; /* 0 = 32, 1 = 64 */
u8 ctlr_index;
struct bus_info *bus_on;
struct list_head ibm_slot_list;
u8 status;
......
......@@ -587,11 +587,14 @@ static u8 calculate_first_slot (u8 slot_num)
return first_slot + 1;
}
#define SLOT_NAME_SIZE 30
static char *create_file_name (struct slot * slot_cur)
{
struct opt_rio *opt_vg_ptr = NULL;
struct opt_rio_lo *opt_lo_ptr = NULL;
static char str[30];
static char str[SLOT_NAME_SIZE];
int which = 0; /* rxe = 1, chassis = 0 */
u8 number = 1; /* either chassis or rxe # */
u8 first_slot = 1;
......@@ -703,7 +706,6 @@ static void release_slot(struct hotplug_slot *hotplug_slot)
slot = hotplug_slot->private;
kfree(slot->hotplug_slot->info);
kfree(slot->hotplug_slot->name);
kfree(slot->hotplug_slot);
slot->ctrl = NULL;
slot->bus_on = NULL;
......@@ -734,6 +736,7 @@ static int __init ebda_rsrc_controller (void)
struct bus_info *bus_info_ptr1, *bus_info_ptr2;
int rc;
struct slot *tmp_slot;
char name[SLOT_NAME_SIZE];
addr = hpc_list_ptr->phys_addr;
for (ctlr = 0; ctlr < hpc_list_ptr->num_ctlrs; ctlr++) {
......@@ -897,12 +900,6 @@ static int __init ebda_rsrc_controller (void)
goto error_no_hp_info;
}
hp_slot_ptr->name = kmalloc(30, GFP_KERNEL);
if (!hp_slot_ptr->name) {
rc = -ENOMEM;
goto error_no_hp_name;
}
tmp_slot = kzalloc(sizeof(*tmp_slot), GFP_KERNEL);
if (!tmp_slot) {
rc = -ENOMEM;
......@@ -964,9 +961,9 @@ static int __init ebda_rsrc_controller (void)
} /* each hpc */
list_for_each_entry(tmp_slot, &ibmphp_slot_head, ibm_slot_list) {
snprintf (tmp_slot->hotplug_slot->name, 30, "%s", create_file_name (tmp_slot));
snprintf(name, SLOT_NAME_SIZE, "%s", create_file_name(tmp_slot));
pci_hp_register(tmp_slot->hotplug_slot,
pci_find_bus(0, tmp_slot->bus), tmp_slot->device);
pci_find_bus(0, tmp_slot->bus), tmp_slot->device, name);
}
print_ebda_hpc ();
......@@ -976,8 +973,6 @@ static int __init ebda_rsrc_controller (void)
error:
kfree (hp_slot_ptr->private);
error_no_slot:
kfree (hp_slot_ptr->name);
error_no_hp_name:
kfree (hp_slot_ptr->info);
error_no_hp_info:
kfree (hp_slot_ptr);
......
......@@ -37,6 +37,7 @@
#include <linux/init.h>
#include <linux/mount.h>
#include <linux/namei.h>
#include <linux/mutex.h>
#include <linux/pci.h>
#include <linux/pci_hotplug.h>
#include <asm/uaccess.h>
......@@ -61,7 +62,7 @@ static int debug;
//////////////////////////////////////////////////////////////////
static LIST_HEAD(pci_hotplug_slot_list);
static DEFINE_SPINLOCK(pci_hotplug_slot_list_lock);
static DEFINE_MUTEX(pci_hp_mutex);
/* these strings match up with the values in pci_bus_speed */
static char *pci_bus_speed_strings[] = {
......@@ -530,16 +531,12 @@ static struct hotplug_slot *get_slot_from_name (const char *name)
struct hotplug_slot *slot;
struct list_head *tmp;
spin_lock(&pci_hotplug_slot_list_lock);
list_for_each (tmp, &pci_hotplug_slot_list) {
slot = list_entry (tmp, struct hotplug_slot, slot_list);
if (strcmp(slot->name, name) == 0)
goto out;
if (strcmp(hotplug_slot_name(slot), name) == 0)
return slot;
}
slot = NULL;
out:
spin_unlock(&pci_hotplug_slot_list_lock);
return slot;
return NULL;
}
/**
......@@ -547,13 +544,15 @@ static struct hotplug_slot *get_slot_from_name (const char *name)
* @bus: bus this slot is on
* @slot: pointer to the &struct hotplug_slot to register
* @slot_nr: slot number
* @name: name registered with kobject core
*
* Registers a hotplug slot with the pci hotplug subsystem, which will allow
* userspace interaction to the slot.
*
* Returns 0 if successful, anything else for an error.
*/
int pci_hp_register(struct hotplug_slot *slot, struct pci_bus *bus, int slot_nr)
int pci_hp_register(struct hotplug_slot *slot, struct pci_bus *bus, int slot_nr,
const char *name)
{
int result;
struct pci_slot *pci_slot;
......@@ -568,48 +567,29 @@ int pci_hp_register(struct hotplug_slot *slot, struct pci_bus *bus, int slot_nr)
return -EINVAL;
}
/* Check if we have already registered a slot with the same name. */
if (get_slot_from_name(slot->name))
return -EEXIST;
mutex_lock(&pci_hp_mutex);
/*
* No problems if we call this interface from both ACPI_PCI_SLOT
* driver and call it here again. If we've already created the
* pci_slot, the interface will simply bump the refcount.
*/
pci_slot = pci_create_slot(bus, slot_nr, slot->name);
if (IS_ERR(pci_slot))
return PTR_ERR(pci_slot);
if (pci_slot->hotplug) {
dbg("%s: already claimed\n", __func__);
pci_destroy_slot(pci_slot);
return -EBUSY;
pci_slot = pci_create_slot(bus, slot_nr, name, slot);
if (IS_ERR(pci_slot)) {
result = PTR_ERR(pci_slot);
goto out;
}
slot->pci_slot = pci_slot;
pci_slot->hotplug = slot;
/*
* Allow pcihp drivers to override the ACPI_PCI_SLOT name.
*/
if (strcmp(kobject_name(&pci_slot->kobj), slot->name)) {
result = kobject_rename(&pci_slot->kobj, slot->name);
if (result) {
pci_destroy_slot(pci_slot);
return result;
}
}
spin_lock(&pci_hotplug_slot_list_lock);
list_add(&slot->slot_list, &pci_hotplug_slot_list);
spin_unlock(&pci_hotplug_slot_list_lock);
result = fs_add_slot(pci_slot);
kobject_uevent(&pci_slot->kobj, KOBJ_ADD);
dbg("Added slot %s to the list\n", slot->name);
dbg("Added slot %s to the list\n", name);
out:
mutex_unlock(&pci_hp_mutex);
return result;
}
......@@ -630,21 +610,23 @@ int pci_hp_deregister(struct hotplug_slot *hotplug)
if (!hotplug)
return -ENODEV;
temp = get_slot_from_name(hotplug->name);
if (temp != hotplug)
mutex_lock(&pci_hp_mutex);
temp = get_slot_from_name(hotplug_slot_name(hotplug));
if (temp != hotplug) {
mutex_unlock(&pci_hp_mutex);
return -ENODEV;
}
spin_lock(&pci_hotplug_slot_list_lock);
list_del(&hotplug->slot_list);
spin_unlock(&pci_hotplug_slot_list_lock);
slot = hotplug->pci_slot;
fs_remove_slot(slot);
dbg("Removed slot %s from the list\n", hotplug->name);
dbg("Removed slot %s from the list\n", hotplug_slot_name(hotplug));
hotplug->release(hotplug);
slot->hotplug = NULL;
pci_destroy_slot(slot);
mutex_unlock(&pci_hp_mutex);
return 0;
}
......
......@@ -74,15 +74,13 @@ extern struct workqueue_struct *pciehp_wq;
struct slot {
u8 bus;
u8 device;
u32 number;
u8 state;
struct timer_list task_event;
u8 hp_slot;
u32 number;
struct controller *ctrl;
struct hpc_ops *hpc_ops;
struct hotplug_slot *hotplug_slot;
struct list_head slot_list;
char name[SLOT_NAME_SIZE];
unsigned long last_emi_toggle;
struct delayed_work work; /* work for button event */
struct mutex lock;
......@@ -112,6 +110,7 @@ struct controller {
struct timer_list poll_timer;
int cmd_busy;
unsigned int no_cmd_complete:1;
unsigned int link_active_reporting:1;
};
#define INT_BUTTON_IGNORE 0
......@@ -175,6 +174,11 @@ int pciehp_enable_slot(struct slot *p_slot);
int pciehp_disable_slot(struct slot *p_slot);
int pcie_enable_notification(struct controller *ctrl);
static inline const char *slot_name(struct slot *slot)
{
return hotplug_slot_name(slot->hotplug_slot);
}
static inline struct slot *pciehp_find_slot(struct controller *ctrl, u8 device)
{
struct slot *slot;
......
......@@ -185,7 +185,7 @@ static void release_slot(struct hotplug_slot *hotplug_slot)
struct slot *slot = hotplug_slot->private;
ctrl_dbg(slot->ctrl, "%s - physical_slot = %s\n",
__func__, hotplug_slot->name);
__func__, hotplug_slot_name(hotplug_slot));
kfree(hotplug_slot->info);
kfree(hotplug_slot);
......@@ -196,7 +196,7 @@ static int init_slots(struct controller *ctrl)
struct slot *slot;
struct hotplug_slot *hotplug_slot;
struct hotplug_slot_info *info;
int len, dup = 1;
char name[SLOT_NAME_SIZE];
int retval = -ENOMEM;
list_for_each_entry(slot, &ctrl->slot_list, slot_list) {
......@@ -210,41 +210,28 @@ static int init_slots(struct controller *ctrl)
/* register this slot with the hotplug pci core */
hotplug_slot->info = info;
hotplug_slot->name = slot->name;
hotplug_slot->private = slot;
hotplug_slot->release = &release_slot;
hotplug_slot->ops = &pciehp_hotplug_slot_ops;
get_power_status(hotplug_slot, &info->power_status);
get_attention_status(hotplug_slot, &info->attention_status);
get_latch_status(hotplug_slot, &info->latch_status);
get_adapter_status(hotplug_slot, &info->adapter_status);
slot->hotplug_slot = hotplug_slot;
snprintf(name, SLOT_NAME_SIZE, "%u", slot->number);
ctrl_dbg(ctrl, "Registering bus=%x dev=%x hp_slot=%x sun=%x "
"slot_device_offset=%x\n", slot->bus, slot->device,
slot->hp_slot, slot->number, ctrl->slot_device_offset);
duplicate_name:
retval = pci_hp_register(hotplug_slot,
ctrl->pci_dev->subordinate,
slot->device);
slot->device,
name);
if (retval) {
/*
* If slot N already exists, we'll try to create
* slot N-1, N-2 ... N-M, until we overflow.
*/
if (retval == -EEXIST) {
len = snprintf(slot->name, SLOT_NAME_SIZE,
"%d-%d", slot->number, dup++);
if (len < SLOT_NAME_SIZE)
goto duplicate_name;
else
ctrl_err(ctrl, "duplicate slot name "
"overflow\n");
}
ctrl_err(ctrl, "pci_hp_register failed with error %d\n",
retval);
goto error_info;
}
get_power_status(hotplug_slot, &info->power_status);
get_attention_status(hotplug_slot, &info->attention_status);
get_latch_status(hotplug_slot, &info->latch_status);
get_adapter_status(hotplug_slot, &info->adapter_status);
/* create additional sysfs entries */
if (EMI(ctrl)) {
retval = sysfs_create_file(&hotplug_slot->pci_slot->kobj,
......@@ -287,7 +274,7 @@ static int set_attention_status(struct hotplug_slot *hotplug_slot, u8 status)
struct slot *slot = hotplug_slot->private;
ctrl_dbg(slot->ctrl, "%s - physical_slot = %s\n",
__func__, hotplug_slot->name);
__func__, slot_name(slot));
hotplug_slot->info->attention_status = status;
......@@ -303,7 +290,7 @@ static int enable_slot(struct hotplug_slot *hotplug_slot)
struct slot *slot = hotplug_slot->private;
ctrl_dbg(slot->ctrl, "%s - physical_slot = %s\n",
__func__, hotplug_slot->name);
__func__, slot_name(slot));
return pciehp_sysfs_enable_slot(slot);
}
......@@ -314,7 +301,7 @@ static int disable_slot(struct hotplug_slot *hotplug_slot)
struct slot *slot = hotplug_slot->private;
ctrl_dbg(slot->ctrl, "%s - physical_slot = %s\n",
__func__, hotplug_slot->name);
__func__, slot_name(slot));
return pciehp_sysfs_disable_slot(slot);
}
......@@ -325,7 +312,7 @@ static int get_power_status(struct hotplug_slot *hotplug_slot, u8 *value)
int retval;
ctrl_dbg(slot->ctrl, "%s - physical_slot = %s\n",
__func__, hotplug_slot->name);
__func__, slot_name(slot));
retval = slot->hpc_ops->get_power_status(slot, value);
if (retval < 0)
......@@ -340,7 +327,7 @@ static int get_attention_status(struct hotplug_slot *hotplug_slot, u8 *value)
int retval;
ctrl_dbg(slot->ctrl, "%s - physical_slot = %s\n",
__func__, hotplug_slot->name);
__func__, slot_name(slot));
retval = slot->hpc_ops->get_attention_status(slot, value);
if (retval < 0)
......@@ -355,7 +342,7 @@ static int get_latch_status(struct hotplug_slot *hotplug_slot, u8 *value)
int retval;
ctrl_dbg(slot->ctrl, "%s - physical_slot = %s\n",
__func__, hotplug_slot->name);
__func__, slot_name(slot));
retval = slot->hpc_ops->get_latch_status(slot, value);
if (retval < 0)
......@@ -370,7 +357,7 @@ static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 *value)
int retval;
ctrl_dbg(slot->ctrl, "%s - physical_slot = %s\n",
__func__, hotplug_slot->name);
__func__, slot_name(slot));
retval = slot->hpc_ops->get_adapter_status(slot, value);
if (retval < 0)
......@@ -386,7 +373,7 @@ static int get_max_bus_speed(struct hotplug_slot *hotplug_slot,
int retval;
ctrl_dbg(slot->ctrl, "%s - physical_slot = %s\n",
__func__, hotplug_slot->name);
__func__, slot_name(slot));
retval = slot->hpc_ops->get_max_bus_speed(slot, value);
if (retval < 0)
......@@ -401,7 +388,7 @@ static int get_cur_bus_speed(struct hotplug_slot *hotplug_slot, enum pci_bus_spe
int retval;
ctrl_dbg(slot->ctrl, "%s - physical_slot = %s\n",
__func__, hotplug_slot->name);
__func__, slot_name(slot));
retval = slot->hpc_ops->get_cur_bus_speed(slot, value);
if (retval < 0)
......
......@@ -66,7 +66,7 @@ u8 pciehp_handle_attention_button(struct slot *p_slot)
/*
* Button pressed - See if need to TAKE ACTION!!!
*/
ctrl_info(ctrl, "Button pressed on Slot(%s)\n", p_slot->name);
ctrl_info(ctrl, "Button pressed on Slot(%s)\n", slot_name(p_slot));
event_type = INT_BUTTON_PRESS;
queue_interrupt_event(p_slot, event_type);
......@@ -88,13 +88,13 @@ u8 pciehp_handle_switch_change(struct slot *p_slot)
/*
* Switch opened
*/
ctrl_info(ctrl, "Latch open on Slot(%s)\n", p_slot->name);
ctrl_info(ctrl, "Latch open on Slot(%s)\n", slot_name(p_slot));
event_type = INT_SWITCH_OPEN;
} else {
/*
* Switch closed
*/
ctrl_info(ctrl, "Latch close on Slot(%s)\n", p_slot->name);
ctrl_info(ctrl, "Latch close on Slot(%s)\n", slot_name(p_slot));
event_type = INT_SWITCH_CLOSE;
}
......@@ -120,13 +120,14 @@ u8 pciehp_handle_presence_change(struct slot *p_slot)
/*
* Card Present
*/
ctrl_info(ctrl, "Card present on Slot(%s)\n", p_slot->name);
ctrl_info(ctrl, "Card present on Slot(%s)\n", slot_name(p_slot));
event_type = INT_PRESENCE_ON;
} else {
/*
* Not Present
*/
ctrl_info(ctrl, "Card not present on Slot(%s)\n", p_slot->name);
ctrl_info(ctrl, "Card not present on Slot(%s)\n",
slot_name(p_slot));
event_type = INT_PRESENCE_OFF;
}
......@@ -148,13 +149,13 @@ u8 pciehp_handle_power_fault(struct slot *p_slot)
* power fault Cleared
*/
ctrl_info(ctrl, "Power fault cleared on Slot(%s)\n",
p_slot->name);
slot_name(p_slot));
event_type = INT_POWER_FAULT_CLEAR;
} else {
/*
* power fault
*/
ctrl_info(ctrl, "Power fault on Slot(%s)\n", p_slot->name);
ctrl_info(ctrl, "Power fault on Slot(%s)\n", slot_name(p_slot));
event_type = INT_POWER_FAULT;
ctrl_info(ctrl, "power fault bit %x set\n", 0);
}
......@@ -225,9 +226,6 @@ static int board_added(struct slot *p_slot)
if (PWR_LED(ctrl))
p_slot->hpc_ops->green_led_blink(p_slot);
/* Wait for ~1 second */
msleep(1000);
/* Check link training status */
retval = p_slot->hpc_ops->check_lnk_status(ctrl);
if (retval) {
......@@ -412,12 +410,12 @@ static void handle_button_press_event(struct slot *p_slot)
p_slot->state = BLINKINGOFF_STATE;
ctrl_info(ctrl,
"PCI slot #%s - powering off due to button "
"press.\n", p_slot->name);
"press.\n", slot_name(p_slot));
} else {
p_slot->state = BLINKINGON_STATE;
ctrl_info(ctrl,
"PCI slot #%s - powering on due to button "
"press.\n", p_slot->name);
"press.\n", slot_name(p_slot));
}
/* blink green LED and turn off amber */
if (PWR_LED(ctrl))
......@@ -434,7 +432,7 @@ static void handle_button_press_event(struct slot *p_slot)
* press the attention again before the 5 sec. limit
* expires to cancel hot-add or hot-remove
*/
ctrl_info(ctrl, "Button cancel on Slot(%s)\n", p_slot->name);
ctrl_info(ctrl, "Button cancel on Slot(%s)\n", slot_name(p_slot));
ctrl_dbg(ctrl, "%s: button cancel\n", __func__);
cancel_delayed_work(&p_slot->work);
if (p_slot->state == BLINKINGOFF_STATE) {
......@@ -447,7 +445,7 @@ static void handle_button_press_event(struct slot *p_slot)
if (ATTN_LED(ctrl))
p_slot->hpc_ops->set_attention_status(p_slot, 0);
ctrl_info(ctrl, "PCI slot #%s - action canceled "
"due to button press\n", p_slot->name);
"due to button press\n", slot_name(p_slot));
p_slot->state = STATIC_STATE;
break;
case POWEROFF_STATE:
......@@ -457,7 +455,7 @@ static void handle_button_press_event(struct slot *p_slot)
* this means that the previous attention button action
* to hot-add or hot-remove is undergoing
*/
ctrl_info(ctrl, "Button ignore on Slot(%s)\n", p_slot->name);
ctrl_info(ctrl, "Button ignore on Slot(%s)\n", slot_name(p_slot));
update_slot_info(p_slot);
break;
default:
......@@ -540,7 +538,7 @@ int pciehp_enable_slot(struct slot *p_slot)
rc = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus);
if (rc || !getstatus) {
ctrl_info(ctrl, "%s: no adapter on slot(%s)\n",
__func__, p_slot->name);
__func__, slot_name(p_slot));
mutex_unlock(&p_slot->ctrl->crit_sect);
return -ENODEV;
}
......@@ -548,7 +546,7 @@ int pciehp_enable_slot(struct slot *p_slot)
rc = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
if (rc || getstatus) {
ctrl_info(ctrl, "%s: latch open on slot(%s)\n",
__func__, p_slot->name);
__func__, slot_name(p_slot));
mutex_unlock(&p_slot->ctrl->crit_sect);
return -ENODEV;
}
......@@ -558,7 +556,7 @@ int pciehp_enable_slot(struct slot *p_slot)
rc = p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
if (rc || getstatus) {
ctrl_info(ctrl, "%s: already enabled on slot(%s)\n",
__func__, p_slot->name);
__func__, slot_name(p_slot));
mutex_unlock(&p_slot->ctrl->crit_sect);
return -EINVAL;
}
......@@ -594,7 +592,7 @@ int pciehp_disable_slot(struct slot *p_slot)
ret = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus);
if (ret || !getstatus) {
ctrl_info(ctrl, "%s: no adapter on slot(%s)\n",
__func__, p_slot->name);
__func__, slot_name(p_slot));
mutex_unlock(&p_slot->ctrl->crit_sect);
return -ENODEV;
}
......@@ -604,7 +602,7 @@ int pciehp_disable_slot(struct slot *p_slot)
ret = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
if (ret || getstatus) {
ctrl_info(ctrl, "%s: latch open on slot(%s)\n",
__func__, p_slot->name);
__func__, slot_name(p_slot));
mutex_unlock(&p_slot->ctrl->crit_sect);
return -ENODEV;
}
......@@ -614,7 +612,7 @@ int pciehp_disable_slot(struct slot *p_slot)
ret = p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
if (ret || !getstatus) {
ctrl_info(ctrl, "%s: already disabled slot(%s)\n",
__func__, p_slot->name);
__func__, slot_name(p_slot));
mutex_unlock(&p_slot->ctrl->crit_sect);
return -EINVAL;
}
......@@ -645,14 +643,16 @@ int pciehp_sysfs_enable_slot(struct slot *p_slot)
break;
case POWERON_STATE:
ctrl_info(ctrl, "Slot %s is already in powering on state\n",
p_slot->name);
slot_name(p_slot));
break;
case BLINKINGOFF_STATE:
case POWEROFF_STATE:
ctrl_info(ctrl, "Already enabled on slot %s\n", p_slot->name);
ctrl_info(ctrl, "Already enabled on slot %s\n",
slot_name(p_slot));
break;
default:
ctrl_err(ctrl, "Not a valid state on slot %s\n", p_slot->name);
ctrl_err(ctrl, "Not a valid state on slot %s\n",
slot_name(p_slot));
break;
}
mutex_unlock(&p_slot->lock);
......@@ -678,14 +678,16 @@ int pciehp_sysfs_disable_slot(struct slot *p_slot)
break;
case POWEROFF_STATE:
ctrl_info(ctrl, "Slot %s is already in powering off state\n",
p_slot->name);
slot_name(p_slot));
break;
case BLINKINGON_STATE:
case POWERON_STATE:
ctrl_info(ctrl, "Already disabled on slot %s\n", p_slot->name);
ctrl_info(ctrl, "Already disabled on slot %s\n",
slot_name(p_slot));
break;
default:
ctrl_err(ctrl, "Not a valid state on slot %s\n", p_slot->name);
ctrl_err(ctrl, "Not a valid state on slot %s\n",
slot_name(p_slot));
break;
}
mutex_unlock(&p_slot->lock);
......
......@@ -125,6 +125,7 @@ static inline int pciehp_writel(struct controller *ctrl, int reg, u32 value)
/* Field definitions in Link Capabilities Register */
#define MAX_LNK_SPEED 0x000F
#define MAX_LNK_WIDTH 0x03F0
#define LINK_ACTIVE_REPORTING 0x00100000
/* Link Width Encoding */
#define LNK_X1 0x01
......@@ -141,6 +142,7 @@ static inline int pciehp_writel(struct controller *ctrl, int reg, u32 value)
#define LNK_TRN_ERR 0x0400
#define LNK_TRN 0x0800
#define SLOT_CLK_CONF 0x1000
#define LINK_ACTIVE 0x2000
/* Field definitions in Slot Capabilities Register */
#define ATTN_BUTTN_PRSN 0x00000001
......@@ -368,11 +370,52 @@ static int pcie_write_cmd(struct controller *ctrl, u16 cmd, u16 mask)
return retval;
}
static inline int check_link_active(struct controller *ctrl)
{
u16 link_status;
if (pciehp_readw(ctrl, LNKSTATUS, &link_status))
return 0;
return !!(link_status & LINK_ACTIVE);
}
static void pcie_wait_link_active(struct controller *ctrl)
{
int timeout = 1000;
if (check_link_active(ctrl))
return;
while (timeout > 0) {
msleep(10);
timeout -= 10;
if (check_link_active(ctrl))
return;
}
ctrl_dbg(ctrl, "Data Link Layer Link Active not set in 1000 msec\n");
}
static int hpc_check_lnk_status(struct controller *ctrl)
{
u16 lnk_status;
int retval = 0;
/*
* Data Link Layer Link Active Reporting must be capable for
* hot-plug capable downstream port. But old controller might
* not implement it. In this case, we wait for 1000 ms.
*/
if (ctrl->link_active_reporting){
/* Wait for Data Link Layer Link Active bit to be set */
pcie_wait_link_active(ctrl);
/*
* We must wait for 100 ms after the Data Link Layer
* Link Active bit reads 1b before initiating a
* configuration access to the hot added device.
*/
msleep(100);
} else
msleep(1000);
retval = pciehp_readw(ctrl, LNKSTATUS, &lnk_status);
if (retval) {
ctrl_err(ctrl, "%s: Cannot read LNKSTATUS register\n",
......@@ -1061,7 +1104,6 @@ static int pcie_init_slot(struct controller *ctrl)
slot->device = ctrl->slot_device_offset + slot->hp_slot;
slot->hpc_ops = ctrl->hpc_ops;
slot->number = ctrl->first_slot;
snprintf(slot->name, SLOT_NAME_SIZE, "%d", slot->number);
mutex_init(&slot->lock);
INIT_DELAYED_WORK(&slot->work, pciehp_queue_pushbutton_work);
list_add(&slot->slot_list, &ctrl->slot_list);
......@@ -1132,7 +1174,7 @@ static inline void dbg_ctrl(struct controller *ctrl)
struct controller *pcie_init(struct pcie_device *dev)
{
struct controller *ctrl;
u32 slot_cap;
u32 slot_cap, link_cap;
struct pci_dev *pdev = dev->port;
ctrl = kzalloc(sizeof(*ctrl), GFP_KERNEL);
......@@ -1148,11 +1190,11 @@ struct controller *pcie_init(struct pcie_device *dev)
if (!ctrl->cap_base) {
ctrl_err(ctrl, "%s: Cannot find PCI Express capability\n",
__func__);
goto abort;
goto abort_ctrl;
}
if (pciehp_readl(ctrl, SLOTCAP, &slot_cap)) {
ctrl_err(ctrl, "%s: Cannot read SLOTCAP register\n", __func__);
goto abort;
goto abort_ctrl;
}
ctrl->slot_cap = slot_cap;
......@@ -1174,6 +1216,16 @@ struct controller *pcie_init(struct pcie_device *dev)
!(POWER_CTRL(ctrl) | ATTN_LED(ctrl) | PWR_LED(ctrl) | EMI(ctrl)))
ctrl->no_cmd_complete = 1;
/* Check if Data Link Layer Link Active Reporting is implemented */
if (pciehp_readl(ctrl, LNKCAP, &link_cap)) {
ctrl_err(ctrl, "%s: Cannot read LNKCAP register\n", __func__);
goto abort_ctrl;
}
if (link_cap & LINK_ACTIVE_REPORTING) {
ctrl_dbg(ctrl, "Link Active Reporting supported\n");
ctrl->link_active_reporting = 1;
}
/* Clear all remaining event bits in Slot Status register */
if (pciehp_writew(ctrl, SLOTSTATUS, 0x1f))
goto abort_ctrl;
......
......@@ -43,7 +43,7 @@ static void rpaphp_release_slot(struct hotplug_slot *hotplug_slot)
void dealloc_slot_struct(struct slot *slot)
{
kfree(slot->hotplug_slot->info);
kfree(slot->hotplug_slot->name);
kfree(slot->name);
kfree(slot->hotplug_slot);
kfree(slot);
}
......@@ -63,11 +63,9 @@ struct slot *alloc_slot_struct(struct device_node *dn,
GFP_KERNEL);
if (!slot->hotplug_slot->info)
goto error_hpslot;
slot->hotplug_slot->name = kmalloc(strlen(drc_name) + 1, GFP_KERNEL);
if (!slot->hotplug_slot->name)
slot->name = kstrdup(drc_name, GFP_KERNEL);
if (!slot->name)
goto error_info;
slot->name = slot->hotplug_slot->name;
strcpy(slot->name, drc_name);
slot->dn = dn;
slot->index = drc_index;
slot->power_domain = power_domain;
......@@ -137,7 +135,7 @@ int rpaphp_register_slot(struct slot *slot)
slotno = PCI_SLOT(PCI_DN(slot->dn->child)->devfn);
else
slotno = -1;
retval = pci_hp_register(php_slot, slot->bus, slotno);
retval = pci_hp_register(php_slot, slot->bus, slotno, slot->name);
if (retval) {
err("pci_hp_register failed with error %d\n", retval);
return retval;
......
......@@ -161,7 +161,8 @@ static int sn_pci_bus_valid(struct pci_bus *pci_bus)
}
static int sn_hp_slot_private_alloc(struct hotplug_slot *bss_hotplug_slot,
struct pci_bus *pci_bus, int device)
struct pci_bus *pci_bus, int device,
char *name)
{
struct pcibus_info *pcibus_info;
struct slot *slot;
......@@ -173,15 +174,9 @@ static int sn_hp_slot_private_alloc(struct hotplug_slot *bss_hotplug_slot,
return -ENOMEM;
bss_hotplug_slot->private = slot;
bss_hotplug_slot->name = kmalloc(SN_SLOT_NAME_SIZE, GFP_KERNEL);
if (!bss_hotplug_slot->name) {
kfree(bss_hotplug_slot->private);
return -ENOMEM;
}
slot->device_num = device;
slot->pci_bus = pci_bus;
sprintf(bss_hotplug_slot->name, "%04x:%02x:%02x",
sprintf(name, "%04x:%02x:%02x",
pci_domain_nr(pci_bus),
((u16)pcibus_info->pbi_buscommon.bs_persist_busnum),
device + 1);
......@@ -608,7 +603,6 @@ static inline int get_power_status(struct hotplug_slot *bss_hotplug_slot,
static void sn_release_slot(struct hotplug_slot *bss_hotplug_slot)
{
kfree(bss_hotplug_slot->info);
kfree(bss_hotplug_slot->name);
kfree(bss_hotplug_slot->private);
kfree(bss_hotplug_slot);
}
......@@ -618,6 +612,7 @@ static int sn_hotplug_slot_register(struct pci_bus *pci_bus)
int device;
struct pci_slot *pci_slot;
struct hotplug_slot *bss_hotplug_slot;
char name[SN_SLOT_NAME_SIZE];
int rc = 0;
/*
......@@ -645,15 +640,14 @@ static int sn_hotplug_slot_register(struct pci_bus *pci_bus)
}
if (sn_hp_slot_private_alloc(bss_hotplug_slot,
pci_bus, device)) {
pci_bus, device, name)) {
rc = -ENOMEM;
goto alloc_err;
}
bss_hotplug_slot->ops = &sn_hotplug_slot_ops;
bss_hotplug_slot->release = &sn_release_slot;
rc = pci_hp_register(bss_hotplug_slot, pci_bus, device);
rc = pci_hp_register(bss_hotplug_slot, pci_bus, device, name);
if (rc)
goto register_err;
......
......@@ -69,15 +69,13 @@ struct slot {
u8 state;
u8 presence_save;
u8 pwr_save;
struct timer_list task_event;
u8 hp_slot;
struct controller *ctrl;
struct hpc_ops *hpc_ops;
struct hotplug_slot *hotplug_slot;
struct list_head slot_list;
char name[SLOT_NAME_SIZE];
struct delayed_work work; /* work for button event */
struct mutex lock;
u8 hp_slot;
};
struct event_info {
......@@ -169,6 +167,11 @@ extern void cleanup_slots(struct controller *ctrl);
extern void shpchp_queue_pushbutton_work(struct work_struct *work);
extern int shpc_init( struct controller *ctrl, struct pci_dev *pdev);
static inline const char *slot_name(struct slot *slot)
{
return hotplug_slot_name(slot->hotplug_slot);
}
#ifdef CONFIG_ACPI
#include <linux/pci-acpi.h>
static inline int get_hp_params_from_firmware(struct pci_dev *dev,
......
......@@ -89,7 +89,7 @@ static void release_slot(struct hotplug_slot *hotplug_slot)
{
struct slot *slot = hotplug_slot->private;
dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
dbg("%s - physical_slot = %s\n", __func__, slot_name(slot));
kfree(slot->hotplug_slot->info);
kfree(slot->hotplug_slot);
......@@ -101,8 +101,9 @@ static int init_slots(struct controller *ctrl)
struct slot *slot;
struct hotplug_slot *hotplug_slot;
struct hotplug_slot_info *info;
char name[SLOT_NAME_SIZE];
int retval = -ENOMEM;
int i, len, dup = 1;
int i;
for (i = 0; i < ctrl->num_slots; i++) {
slot = kzalloc(sizeof(*slot), GFP_KERNEL);
......@@ -119,8 +120,6 @@ static int init_slots(struct controller *ctrl)
goto error_hpslot;
hotplug_slot->info = info;
hotplug_slot->name = slot->name;
slot->hp_slot = i;
slot->ctrl = ctrl;
slot->bus = ctrl->pci_dev->subordinate->number;
......@@ -133,37 +132,24 @@ static int init_slots(struct controller *ctrl)
/* register this slot with the hotplug pci core */
hotplug_slot->private = slot;
hotplug_slot->release = &release_slot;
snprintf(slot->name, SLOT_NAME_SIZE, "%d", slot->number);
snprintf(name, SLOT_NAME_SIZE, "%d", slot->number);
hotplug_slot->ops = &shpchp_hotplug_slot_ops;
get_power_status(hotplug_slot, &info->power_status);
get_attention_status(hotplug_slot, &info->attention_status);
get_latch_status(hotplug_slot, &info->latch_status);
get_adapter_status(hotplug_slot, &info->adapter_status);
dbg("Registering bus=%x dev=%x hp_slot=%x sun=%x "
"slot_device_offset=%x\n", slot->bus, slot->device,
slot->hp_slot, slot->number, ctrl->slot_device_offset);
duplicate_name:
retval = pci_hp_register(slot->hotplug_slot,
ctrl->pci_dev->subordinate, slot->device);
ctrl->pci_dev->subordinate, slot->device, name);
if (retval) {
/*
* If slot N already exists, we'll try to create
* slot N-1, N-2 ... N-M, until we overflow.
*/
if (retval == -EEXIST) {
len = snprintf(slot->name, SLOT_NAME_SIZE,
"%d-%d", slot->number, dup++);
if (len < SLOT_NAME_SIZE)
goto duplicate_name;
else
err("duplicate slot name overflow\n");
}
err("pci_hp_register failed with error %d\n", retval);
goto error_info;
}
get_power_status(hotplug_slot, &info->power_status);
get_attention_status(hotplug_slot, &info->attention_status);
get_latch_status(hotplug_slot, &info->latch_status);
get_adapter_status(hotplug_slot, &info->adapter_status);
list_add(&slot->slot_list, &ctrl->slot_list);
}
......@@ -201,7 +187,7 @@ static int set_attention_status (struct hotplug_slot *hotplug_slot, u8 status)
{
struct slot *slot = get_slot(hotplug_slot);
dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
dbg("%s - physical_slot = %s\n", __func__, slot_name(slot));
hotplug_slot->info->attention_status = status;
slot->hpc_ops->set_attention_status(slot, status);
......@@ -213,7 +199,7 @@ static int enable_slot (struct hotplug_slot *hotplug_slot)
{
struct slot *slot = get_slot(hotplug_slot);
dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
dbg("%s - physical_slot = %s\n", __func__, slot_name(slot));
return shpchp_sysfs_enable_slot(slot);
}
......@@ -222,7 +208,7 @@ static int disable_slot (struct hotplug_slot *hotplug_slot)
{
struct slot *slot = get_slot(hotplug_slot);
dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
dbg("%s - physical_slot = %s\n", __func__, slot_name(slot));
return shpchp_sysfs_disable_slot(slot);
}
......@@ -232,7 +218,7 @@ static int get_power_status (struct hotplug_slot *hotplug_slot, u8 *value)
struct slot *slot = get_slot(hotplug_slot);
int retval;
dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
dbg("%s - physical_slot = %s\n", __func__, slot_name(slot));
retval = slot->hpc_ops->get_power_status(slot, value);
if (retval < 0)
......@@ -246,7 +232,7 @@ static int get_attention_status (struct hotplug_slot *hotplug_slot, u8 *value)
struct slot *slot = get_slot(hotplug_slot);
int retval;
dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
dbg("%s - physical_slot = %s\n", __func__, slot_name(slot));
retval = slot->hpc_ops->get_attention_status(slot, value);
if (retval < 0)
......@@ -260,7 +246,7 @@ static int get_latch_status (struct hotplug_slot *hotplug_slot, u8 *value)
struct slot *slot = get_slot(hotplug_slot);
int retval;
dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
dbg("%s - physical_slot = %s\n", __func__, slot_name(slot));
retval = slot->hpc_ops->get_latch_status(slot, value);
if (retval < 0)
......@@ -274,7 +260,7 @@ static int get_adapter_status (struct hotplug_slot *hotplug_slot, u8 *value)
struct slot *slot = get_slot(hotplug_slot);
int retval;
dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
dbg("%s - physical_slot = %s\n", __func__, slot_name(slot));
retval = slot->hpc_ops->get_adapter_status(slot, value);
if (retval < 0)
......@@ -289,7 +275,7 @@ static int get_max_bus_speed(struct hotplug_slot *hotplug_slot,
struct slot *slot = get_slot(hotplug_slot);
int retval;
dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
dbg("%s - physical_slot = %s\n", __func__, slot_name(slot));
retval = slot->hpc_ops->get_max_bus_speed(slot, value);
if (retval < 0)
......@@ -303,7 +289,7 @@ static int get_cur_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_sp
struct slot *slot = get_slot(hotplug_slot);
int retval;
dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
dbg("%s - physical_slot = %s\n", __func__, slot_name(slot));
retval = slot->hpc_ops->get_cur_bus_speed(slot, value);
if (retval < 0)
......
......@@ -70,7 +70,7 @@ u8 shpchp_handle_attention_button(u8 hp_slot, struct controller *ctrl)
/*
* Button pressed - See if need to TAKE ACTION!!!
*/
info("Button pressed on Slot(%s)\n", p_slot->name);
info("Button pressed on Slot(%s)\n", slot_name(p_slot));
event_type = INT_BUTTON_PRESS;
queue_interrupt_event(p_slot, event_type);
......@@ -98,7 +98,7 @@ u8 shpchp_handle_switch_change(u8 hp_slot, struct controller *ctrl)
/*
* Switch opened
*/
info("Latch open on Slot(%s)\n", p_slot->name);
info("Latch open on Slot(%s)\n", slot_name(p_slot));
event_type = INT_SWITCH_OPEN;
if (p_slot->pwr_save && p_slot->presence_save) {
event_type = INT_POWER_FAULT;
......@@ -108,7 +108,7 @@ u8 shpchp_handle_switch_change(u8 hp_slot, struct controller *ctrl)
/*
* Switch closed
*/
info("Latch close on Slot(%s)\n", p_slot->name);
info("Latch close on Slot(%s)\n", slot_name(p_slot));
event_type = INT_SWITCH_CLOSE;
}
......@@ -135,13 +135,13 @@ u8 shpchp_handle_presence_change(u8 hp_slot, struct controller *ctrl)
/*
* Card Present
*/
info("Card present on Slot(%s)\n", p_slot->name);
info("Card present on Slot(%s)\n", slot_name(p_slot));
event_type = INT_PRESENCE_ON;
} else {
/*
* Not Present
*/
info("Card not present on Slot(%s)\n", p_slot->name);
info("Card not present on Slot(%s)\n", slot_name(p_slot));
event_type = INT_PRESENCE_OFF;
}
......@@ -164,14 +164,14 @@ u8 shpchp_handle_power_fault(u8 hp_slot, struct controller *ctrl)
/*
* Power fault Cleared
*/
info("Power fault cleared on Slot(%s)\n", p_slot->name);
info("Power fault cleared on Slot(%s)\n", slot_name(p_slot));
p_slot->status = 0x00;
event_type = INT_POWER_FAULT_CLEAR;
} else {
/*
* Power fault
*/
info("Power fault on Slot(%s)\n", p_slot->name);
info("Power fault on Slot(%s)\n", slot_name(p_slot));
event_type = INT_POWER_FAULT;
/* set power fault status for this board */
p_slot->status = 0xFF;
......@@ -493,11 +493,11 @@ static void handle_button_press_event(struct slot *p_slot)
if (getstatus) {
p_slot->state = BLINKINGOFF_STATE;
info("PCI slot #%s - powering off due to button "
"press.\n", p_slot->name);
"press.\n", slot_name(p_slot));
} else {
p_slot->state = BLINKINGON_STATE;
info("PCI slot #%s - powering on due to button "
"press.\n", p_slot->name);
"press.\n", slot_name(p_slot));
}
/* blink green LED and turn off amber */
p_slot->hpc_ops->green_led_blink(p_slot);
......@@ -512,7 +512,7 @@ static void handle_button_press_event(struct slot *p_slot)
* press the attention again before the 5 sec. limit
* expires to cancel hot-add or hot-remove
*/
info("Button cancel on Slot(%s)\n", p_slot->name);
info("Button cancel on Slot(%s)\n", slot_name(p_slot));
dbg("%s: button cancel\n", __func__);
cancel_delayed_work(&p_slot->work);
if (p_slot->state == BLINKINGOFF_STATE)
......@@ -521,7 +521,7 @@ static void handle_button_press_event(struct slot *p_slot)
p_slot->hpc_ops->green_led_off(p_slot);
p_slot->hpc_ops->set_attention_status(p_slot, 0);
info("PCI slot #%s - action canceled due to button press\n",
p_slot->name);
slot_name(p_slot));
p_slot->state = STATIC_STATE;
break;
case POWEROFF_STATE:
......@@ -531,7 +531,7 @@ static void handle_button_press_event(struct slot *p_slot)
* this means that the previous attention button action
* to hot-add or hot-remove is undergoing
*/
info("Button ignore on Slot(%s)\n", p_slot->name);
info("Button ignore on Slot(%s)\n", slot_name(p_slot));
update_slot_info(p_slot);
break;
default:
......@@ -574,17 +574,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("No adapter on slot(%s)\n", p_slot->name);
info("No adapter on slot(%s)\n", slot_name(p_slot));
goto out;
}
rc = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
if (rc || getstatus) {
info("Latch open on slot(%s)\n", p_slot->name);
info("Latch open on slot(%s)\n", slot_name(p_slot));
goto out;
}
rc = p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
if (rc || getstatus) {
info("Already enabled on slot(%s)\n", p_slot->name);
info("Already enabled on slot(%s)\n", slot_name(p_slot));
goto out;
}
......@@ -633,17 +633,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("No adapter on slot(%s)\n", p_slot->name);
info("No adapter on slot(%s)\n", slot_name(p_slot));
goto out;
}
rc = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
if (rc || getstatus) {
info("Latch open on slot(%s)\n", p_slot->name);
info("Latch open on slot(%s)\n", slot_name(p_slot));
goto out;
}
rc = p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
if (rc || !getstatus) {
info("Already disabled slot(%s)\n", p_slot->name);
info("Already disabled slot(%s)\n", slot_name(p_slot));
goto out;
}
......@@ -671,14 +671,14 @@ int shpchp_sysfs_enable_slot(struct slot *p_slot)
break;
case POWERON_STATE:
info("Slot %s is already in powering on state\n",
p_slot->name);
slot_name(p_slot));
break;
case BLINKINGOFF_STATE:
case POWEROFF_STATE:
info("Already enabled on slot %s\n", p_slot->name);
info("Already enabled on slot %s\n", slot_name(p_slot));
break;
default:
err("Not a valid state on slot %s\n", p_slot->name);
err("Not a valid state on slot %s\n", slot_name(p_slot));
break;
}
mutex_unlock(&p_slot->lock);
......@@ -703,14 +703,14 @@ int shpchp_sysfs_disable_slot(struct slot *p_slot)
break;
case POWEROFF_STATE:
info("Slot %s is already in powering off state\n",
p_slot->name);
slot_name(p_slot));
break;
case BLINKINGON_STATE:
case POWERON_STATE:
info("Already disabled on slot %s\n", p_slot->name);
info("Already disabled on slot %s\n", slot_name(p_slot));
break;
default:
err("Not a valid state on slot %s\n", p_slot->name);
err("Not a valid state on slot %s\n", slot_name(p_slot));
break;
}
mutex_unlock(&p_slot->lock);
......
......@@ -759,3 +759,24 @@ void pci_msi_init_pci_dev(struct pci_dev *dev)
{
INIT_LIST_HEAD(&dev->msi_list);
}
#ifdef CONFIG_ACPI
#include <linux/acpi.h>
#include <linux/pci-acpi.h>
static void __devinit msi_acpi_init(void)
{
if (acpi_pci_disabled)
return;
pci_osc_support_set(OSC_MSI_SUPPORT);
pcie_osc_support_set(OSC_MSI_SUPPORT);
}
#else
static inline void msi_acpi_init(void) { }
#endif /* CONFIG_ACPI */
void __devinit msi_init(void)
{
if (!pci_msi_enable)
return;
msi_acpi_init();
}
......@@ -24,17 +24,17 @@ struct acpi_osc_data {
acpi_handle handle;
u32 support_set;
u32 control_set;
int is_queried;
u32 query_result;
struct list_head sibiling;
};
static LIST_HEAD(acpi_osc_data_list);
struct acpi_osc_args {
u32 capbuf[3];
u32 query_result;
u32 ctrl_result;
};
static DEFINE_MUTEX(pci_acpi_lock);
static struct acpi_osc_data *acpi_get_osc_data(acpi_handle handle)
{
struct acpi_osc_data *data;
......@@ -108,9 +108,8 @@ static acpi_status acpi_run_osc(acpi_handle handle,
goto out_kfree;
}
out_success:
if (flags & OSC_QUERY_ENABLE)
osc_args->query_result =
*((u32 *)(out_obj->buffer.pointer + 8));
osc_args->ctrl_result =
*((u32 *)(out_obj->buffer.pointer + 8));
status = AE_OK;
out_kfree:
......@@ -118,41 +117,53 @@ static acpi_status acpi_run_osc(acpi_handle handle,
return status;
}
static acpi_status acpi_query_osc(acpi_handle handle,
u32 level, void *context, void **retval)
static acpi_status __acpi_query_osc(u32 flags, struct acpi_osc_data *osc_data,
u32 *result)
{
acpi_status status;
struct acpi_osc_data *osc_data;
u32 flags = (unsigned long)context, support_set;
acpi_handle tmp;
u32 support_set;
struct acpi_osc_args osc_args;
status = acpi_get_handle(handle, "_OSC", &tmp);
if (ACPI_FAILURE(status))
return status;
osc_data = acpi_get_osc_data(handle);
if (!osc_data) {
printk(KERN_ERR "acpi osc data array is full\n");
return AE_ERROR;
}
/* do _OSC query for all possible controls */
support_set = osc_data->support_set | (flags & OSC_SUPPORT_MASKS);
osc_args.capbuf[OSC_QUERY_TYPE] = OSC_QUERY_ENABLE;
osc_args.capbuf[OSC_SUPPORT_TYPE] = support_set;
osc_args.capbuf[OSC_CONTROL_TYPE] = OSC_CONTROL_MASKS;
status = acpi_run_osc(handle, &osc_args);
status = acpi_run_osc(osc_data->handle, &osc_args);
if (ACPI_SUCCESS(status)) {
osc_data->support_set = support_set;
osc_data->query_result = osc_args.query_result;
osc_data->is_queried = 1;
*result = osc_args.ctrl_result;
}
return status;
}
static acpi_status acpi_query_osc(acpi_handle handle,
u32 level, void *context, void **retval)
{
acpi_status status;
struct acpi_osc_data *osc_data;
u32 flags = (unsigned long)context, dummy;
acpi_handle tmp;
status = acpi_get_handle(handle, "_OSC", &tmp);
if (ACPI_FAILURE(status))
return AE_OK;
mutex_lock(&pci_acpi_lock);
osc_data = acpi_get_osc_data(handle);
if (!osc_data) {
printk(KERN_ERR "acpi osc data array is full\n");
goto out;
}
__acpi_query_osc(flags, osc_data, &dummy);
out:
mutex_unlock(&pci_acpi_lock);
return AE_OK;
}
/**
* __pci_osc_support_set - register OS support to Firmware
* @flags: OS support bits
......@@ -181,7 +192,7 @@ acpi_status __pci_osc_support_set(u32 flags, const char *hid)
acpi_status pci_osc_control_set(acpi_handle handle, u32 flags)
{
acpi_status status;
u32 ctrlset, control_set;
u32 ctrlset, control_set, result;
acpi_handle tmp;
struct acpi_osc_data *osc_data;
struct acpi_osc_args osc_args;
......@@ -190,19 +201,28 @@ acpi_status pci_osc_control_set(acpi_handle handle, u32 flags)
if (ACPI_FAILURE(status))
return status;
mutex_lock(&pci_acpi_lock);
osc_data = acpi_get_osc_data(handle);
if (!osc_data) {
printk(KERN_ERR "acpi osc data array is full\n");
return AE_ERROR;
status = AE_ERROR;
goto out;
}
ctrlset = (flags & OSC_CONTROL_MASKS);
if (!ctrlset)
return AE_TYPE;
if (!ctrlset) {
status = AE_TYPE;
goto out;
}
if (osc_data->is_queried &&
((osc_data->query_result & ctrlset) != ctrlset))
return AE_SUPPORT;
status = __acpi_query_osc(osc_data->support_set, osc_data, &result);
if (ACPI_FAILURE(status))
goto out;
if ((result & ctrlset) != ctrlset) {
status = AE_SUPPORT;
goto out;
}
control_set = osc_data->control_set | ctrlset;
osc_args.capbuf[OSC_QUERY_TYPE] = 0;
......@@ -211,7 +231,8 @@ acpi_status pci_osc_control_set(acpi_handle handle, u32 flags)
status = acpi_run_osc(handle, &osc_args);
if (ACPI_SUCCESS(status))
osc_data->control_set = control_set;
out:
mutex_unlock(&pci_acpi_lock);
return status;
}
EXPORT_SYMBOL(pci_osc_control_set);
......
......@@ -18,6 +18,7 @@
#include <linux/log2.h>
#include <linux/pci-aspm.h>
#include <linux/pm_wakeup.h>
#include <linux/interrupt.h>
#include <asm/dma.h> /* isa_dma_bridge_buggy */
#include "pci.h"
......@@ -1745,6 +1746,103 @@ int pci_set_dma_seg_boundary(struct pci_dev *dev, unsigned long mask)
EXPORT_SYMBOL(pci_set_dma_seg_boundary);
#endif
/**
* pci_execute_reset_function() - Reset a PCI device function
* @dev: Device function to reset
*
* Some devices allow an individual function to be reset without affecting
* other functions in the same device. The PCI device must be responsive
* to PCI config space in order to use this function.
*
* The device function is presumed to be unused when this function is called.
* Resetting the device will make the contents of PCI configuration space
* random, so any caller of this must be prepared to reinitialise the
* device including MSI, bus mastering, BARs, decoding IO and memory spaces,
* etc.
*
* Returns 0 if the device function was successfully reset or -ENOTTY if the
* device doesn't support resetting a single function.
*/
int pci_execute_reset_function(struct pci_dev *dev)
{
u16 status;
u32 cap;
int exppos = pci_find_capability(dev, PCI_CAP_ID_EXP);
if (!exppos)
return -ENOTTY;
pci_read_config_dword(dev, exppos + PCI_EXP_DEVCAP, &cap);
if (!(cap & PCI_EXP_DEVCAP_FLR))
return -ENOTTY;
pci_block_user_cfg_access(dev);
/* Wait for Transaction Pending bit clean */
msleep(100);
pci_read_config_word(dev, exppos + PCI_EXP_DEVSTA, &status);
if (status & PCI_EXP_DEVSTA_TRPND) {
dev_info(&dev->dev, "Busy after 100ms while trying to reset; "
"sleeping for 1 second\n");
ssleep(1);
pci_read_config_word(dev, exppos + PCI_EXP_DEVSTA, &status);
if (status & PCI_EXP_DEVSTA_TRPND)
dev_info(&dev->dev, "Still busy after 1s; "
"proceeding with reset anyway\n");
}
pci_write_config_word(dev, exppos + PCI_EXP_DEVCTL,
PCI_EXP_DEVCTL_BCR_FLR);
mdelay(100);
pci_unblock_user_cfg_access(dev);
return 0;
}
EXPORT_SYMBOL_GPL(pci_execute_reset_function);
/**
* pci_reset_function() - quiesce and reset a PCI device function
* @dev: Device function to reset
*
* Some devices allow an individual function to be reset without affecting
* other functions in the same device. The PCI device must be responsive
* to PCI config space in order to use this function.
*
* This function does not just reset the PCI portion of a device, but
* clears all the state associated with the device. This function differs
* from pci_execute_reset_function in that it saves and restores device state
* over the reset.
*
* Returns 0 if the device function was successfully reset or -ENOTTY if the
* device doesn't support resetting a single function.
*/
int pci_reset_function(struct pci_dev *dev)
{
u32 cap;
int exppos = pci_find_capability(dev, PCI_CAP_ID_EXP);
int r;
if (!exppos)
return -ENOTTY;
pci_read_config_dword(dev, exppos + PCI_EXP_DEVCAP, &cap);
if (!(cap & PCI_EXP_DEVCAP_FLR))
return -ENOTTY;
if (!dev->msi_enabled && !dev->msix_enabled)
disable_irq(dev->irq);
pci_save_state(dev);
pci_write_config_word(dev, PCI_COMMAND, PCI_COMMAND_INTX_DISABLE);
r = pci_execute_reset_function(dev);
pci_restore_state(dev);
if (!dev->msi_enabled && !dev->msix_enabled)
enable_irq(dev->irq);
return r;
}
EXPORT_SYMBOL_GPL(pci_reset_function);
/**
* pcix_get_max_mmrbc - get PCI-X maximum designed memory read byte count
* @dev: PCI device to query
......@@ -1933,6 +2031,9 @@ static int __devinit pci_init(void)
while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
pci_fixup_device(pci_fixup_final, dev);
}
msi_init();
return 0;
}
......
......@@ -98,9 +98,11 @@ extern unsigned int pci_pm_d3_delay;
#ifdef CONFIG_PCI_MSI
void pci_no_msi(void);
extern void pci_msi_init_pci_dev(struct pci_dev *dev);
extern void __devinit msi_init(void);
#else
static inline void pci_no_msi(void) { }
static inline void pci_msi_init_pci_dev(struct pci_dev *dev) { }
static inline void msi_init(void) { }
#endif
#ifdef CONFIG_PCIEAER
......
......@@ -480,19 +480,27 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max,
int is_cardbus = (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS);
u32 buses, i, j = 0;
u16 bctl;
int broken = 0;
pci_read_config_dword(dev, PCI_PRIMARY_BUS, &buses);
dev_dbg(&dev->dev, "scanning behind bridge, config %06x, pass %d\n",
buses & 0xffffff, pass);
/* Check if setup is sensible at all */
if (!pass &&
((buses & 0xff) != bus->number || ((buses >> 8) & 0xff) <= bus->number)) {
dev_dbg(&dev->dev, "bus configuration invalid, reconfiguring\n");
broken = 1;
}
/* Disable MasterAbortMode during probing to avoid reporting
of bus errors (in some architectures) */
pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &bctl);
pci_write_config_word(dev, PCI_BRIDGE_CONTROL,
bctl & ~PCI_BRIDGE_CTL_MASTER_ABORT);
if ((buses & 0xffff00) && !pcibios_assign_all_busses() && !is_cardbus) {
if ((buses & 0xffff00) && !pcibios_assign_all_busses() && !is_cardbus && !broken) {
unsigned int cmax, busnr;
/*
* Bus already configured by firmware, process it in the first
......@@ -530,7 +538,7 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max,
* do in the second pass.
*/
if (!pass) {
if (pcibios_assign_all_busses())
if (pcibios_assign_all_busses() || broken)
/* Temporarily disable forwarding of the
configuration cycles on all bridges in
this bus segment to avoid possible
......
......@@ -166,6 +166,7 @@ struct pci_dev *pci_find_device(unsigned int vendor, unsigned int device,
{
struct pci_dev *pdev;
pci_dev_get(from);
pdev = pci_get_subsys(vendor, device, PCI_ANY_ID, PCI_ANY_ID, from);
pci_dev_put(pdev);
return pdev;
......@@ -270,12 +271,8 @@ static struct pci_dev *pci_get_dev_by_id(const struct pci_device_id *id,
struct pci_dev *pdev = NULL;
WARN_ON(in_interrupt());
if (from) {
/* FIXME
* take the cast off, when bus_find_device is made const.
*/
dev_start = (struct device *)&from->dev;
}
if (from)
dev_start = &from->dev;
dev = bus_find_device(&pci_bus_type, dev_start, (void *)id,
match_pci_dev_by_id);
if (dev)
......
......@@ -78,18 +78,100 @@ static struct kobj_type pci_slot_ktype = {
.default_attrs = pci_slot_default_attrs,
};
static char *make_slot_name(const char *name)
{
char *new_name;
int len, max, dup;
new_name = kstrdup(name, GFP_KERNEL);
if (!new_name)
return NULL;
/*
* Make sure we hit the realloc case the first time through the
* loop. 'len' will be strlen(name) + 3 at that point which is
* enough space for "name-X" and the trailing NUL.
*/
len = strlen(name) + 2;
max = 1;
dup = 1;
for (;;) {
struct kobject *dup_slot;
dup_slot = kset_find_obj(pci_slots_kset, new_name);
if (!dup_slot)
break;
kobject_put(dup_slot);
if (dup == max) {
len++;
max *= 10;
kfree(new_name);
new_name = kmalloc(len, GFP_KERNEL);
if (!new_name)
break;
}
sprintf(new_name, "%s-%d", name, dup++);
}
return new_name;
}
static int rename_slot(struct pci_slot *slot, const char *name)
{
int result = 0;
char *slot_name;
if (strcmp(pci_slot_name(slot), name) == 0)
return result;
slot_name = make_slot_name(name);
if (!slot_name)
return -ENOMEM;
result = kobject_rename(&slot->kobj, slot_name);
kfree(slot_name);
return result;
}
static struct pci_slot *get_slot(struct pci_bus *parent, int slot_nr)
{
struct pci_slot *slot;
/*
* We already hold pci_bus_sem so don't worry
*/
list_for_each_entry(slot, &parent->slots, list)
if (slot->number == slot_nr) {
kobject_get(&slot->kobj);
return slot;
}
return NULL;
}
/**
* pci_create_slot - create or increment refcount for physical PCI slot
* @parent: struct pci_bus of parent bridge
* @slot_nr: PCI_SLOT(pci_dev->devfn) or -1 for placeholder
* @name: user visible string presented in /sys/bus/pci/slots/<name>
* @hotplug: set if caller is hotplug driver, NULL otherwise
*
* PCI slots have first class attributes such as address, speed, width,
* and a &struct pci_slot is used to manage them. This interface will
* either return a new &struct pci_slot to the caller, or if the pci_slot
* already exists, its refcount will be incremented.
*
* Slots are uniquely identified by a @pci_bus, @slot_nr, @name tuple.
* Slots are uniquely identified by a @pci_bus, @slot_nr tuple.
*
* There are known platforms with broken firmware that assign the same
* name to multiple slots. Workaround these broken platforms by renaming
* the slots on behalf of the caller. If firmware assigns name N to
* multiple slots:
*
* The first slot is assigned N
* The second slot is assigned N-1
* The third slot is assigned N-2
* etc.
*
* Placeholder slots:
* In most cases, @pci_bus, @slot_nr will be sufficient to uniquely identify
......@@ -98,61 +180,67 @@ static struct kobj_type pci_slot_ktype = {
* the slot. In this scenario, the caller may pass -1 for @slot_nr.
*
* The following semantics are imposed when the caller passes @slot_nr ==
* -1. First, the check for existing %struct pci_slot is skipped, as the
* caller may know about several unpopulated slots on a given %struct
* pci_bus, and each slot would have a @slot_nr of -1. Uniqueness for
* these slots is then determined by the @name parameter. We expect
* kobject_init_and_add() to warn us if the caller attempts to create
* multiple slots with the same name. The other change in semantics is
* -1. First, we no longer check for an existing %struct pci_slot, as there
* may be many slots with @slot_nr of -1. The other change in semantics is
* user-visible, which is the 'address' parameter presented in sysfs will
* consist solely of a dddd:bb tuple, where dddd is the PCI domain of the
* %struct pci_bus and bb is the bus number. In other words, the devfn of
* the 'placeholder' slot will not be displayed.
*/
struct pci_slot *pci_create_slot(struct pci_bus *parent, int slot_nr,
const char *name)
const char *name,
struct hotplug_slot *hotplug)
{
struct pci_dev *dev;
struct pci_slot *slot;
int err;
int err = 0;
char *slot_name = NULL;
down_write(&pci_bus_sem);
if (slot_nr == -1)
goto placeholder;
/* If we've already created this slot, bump refcount and return. */
list_for_each_entry(slot, &parent->slots, list) {
if (slot->number == slot_nr) {
kobject_get(&slot->kobj);
pr_debug("%s: inc refcount to %d on %04x:%02x:%02x\n",
__func__,
atomic_read(&slot->kobj.kref.refcount),
pci_domain_nr(parent), parent->number,
slot_nr);
goto out;
/*
* Hotplug drivers are allowed to rename an existing slot,
* but only if not already claimed.
*/
slot = get_slot(parent, slot_nr);
if (slot) {
if (hotplug) {
if ((err = slot->hotplug ? -EBUSY : 0)
|| (err = rename_slot(slot, name))) {
kobject_put(&slot->kobj);
slot = NULL;
goto err;
}
}
goto out;
}
placeholder:
slot = kzalloc(sizeof(*slot), GFP_KERNEL);
if (!slot) {
slot = ERR_PTR(-ENOMEM);
goto out;
err = -ENOMEM;
goto err;
}
slot->bus = parent;
slot->number = slot_nr;
slot->kobj.kset = pci_slots_kset;
err = kobject_init_and_add(&slot->kobj, &pci_slot_ktype, NULL,
"%s", name);
if (err) {
printk(KERN_ERR "Unable to register kobject %s\n", name);
slot_name = make_slot_name(name);
if (!slot_name) {
err = -ENOMEM;
goto err;
}
err = kobject_init_and_add(&slot->kobj, &pci_slot_ktype, NULL,
"%s", slot_name);
if (err)
goto err;
INIT_LIST_HEAD(&slot->list);
list_add(&slot->list, &parent->slots);
......@@ -164,10 +252,10 @@ struct pci_slot *pci_create_slot(struct pci_bus *parent, int slot_nr,
pr_debug("%s: created pci_slot on %04x:%02x:%02x\n",
__func__, pci_domain_nr(parent), parent->number, slot_nr);
out:
out:
up_write(&pci_bus_sem);
return slot;
err:
err:
kfree(slot);
slot = ERR_PTR(err);
goto out;
......@@ -175,7 +263,7 @@ struct pci_slot *pci_create_slot(struct pci_bus *parent, int slot_nr,
EXPORT_SYMBOL_GPL(pci_create_slot);
/**
* pci_update_slot_number - update %struct pci_slot -> number
* pci_renumber_slot - update %struct pci_slot -> number
* @slot - %struct pci_slot to update
* @slot_nr - new number for slot
*
......@@ -183,27 +271,22 @@ EXPORT_SYMBOL_GPL(pci_create_slot);
* created a placeholder slot in pci_create_slot() by passing a -1 as
* slot_nr, to update their %struct pci_slot with the correct @slot_nr.
*/
void pci_update_slot_number(struct pci_slot *slot, int slot_nr)
void pci_renumber_slot(struct pci_slot *slot, int slot_nr)
{
int name_count = 0;
struct pci_slot *tmp;
down_write(&pci_bus_sem);
list_for_each_entry(tmp, &slot->bus->slots, list) {
WARN_ON(tmp->number == slot_nr);
if (!strcmp(kobject_name(&tmp->kobj), kobject_name(&slot->kobj)))
name_count++;
goto out;
}
if (name_count > 1)
printk(KERN_WARNING "pci_update_slot_number found %d slots with the same name: %s\n", name_count, kobject_name(&slot->kobj));
slot->number = slot_nr;
out:
up_write(&pci_bus_sem);
}
EXPORT_SYMBOL_GPL(pci_update_slot_number);
EXPORT_SYMBOL_GPL(pci_renumber_slot);
/**
* pci_destroy_slot - decrement refcount for physical PCI slot
......@@ -213,7 +296,6 @@ EXPORT_SYMBOL_GPL(pci_update_slot_number);
* just call kobject_put on its kobj and let our release methods do the
* rest.
*/
void pci_destroy_slot(struct pci_slot *slot)
{
pr_debug("%s: dec refcount to %d on %04x:%02x:%02x\n", __func__,
......
......@@ -51,6 +51,7 @@
#include <linux/kobject.h>
#include <asm/atomic.h>
#include <linux/device.h>
#include <linux/io.h>
/* Include the ID list */
#include <linux/pci_ids.h>
......@@ -64,6 +65,11 @@ struct pci_slot {
struct kobject kobj;
};
static inline const char *pci_slot_name(const struct pci_slot *slot)
{
return kobject_name(&slot->kobj);
}
/* File state for mmap()s on /proc/bus/pci/X/Y */
enum pci_mmap_state {
pci_mmap_io,
......@@ -509,9 +515,10 @@ struct pci_bus *pci_create_bus(struct device *parent, int bus,
struct pci_bus *pci_add_new_bus(struct pci_bus *parent, struct pci_dev *dev,
int busnr);
struct pci_slot *pci_create_slot(struct pci_bus *parent, int slot_nr,
const char *name);
const char *name,
struct hotplug_slot *hotplug);
void pci_destroy_slot(struct pci_slot *slot);
void pci_update_slot_number(struct pci_slot *slot, int slot_nr);
void pci_renumber_slot(struct pci_slot *slot, int slot_nr);
int pci_scan_slot(struct pci_bus *bus, int devfn);
struct pci_dev *pci_scan_single_device(struct pci_bus *bus, int devfn);
void pci_device_add(struct pci_dev *dev, struct pci_bus *bus);
......@@ -626,6 +633,8 @@ int pcix_get_mmrbc(struct pci_dev *dev);
int pcix_set_mmrbc(struct pci_dev *dev, int mmrbc);
int pcie_get_readrq(struct pci_dev *dev);
int pcie_set_readrq(struct pci_dev *dev, int rq);
int pci_reset_function(struct pci_dev *dev);
int pci_execute_reset_function(struct pci_dev *dev);
void pci_update_resource(struct pci_dev *dev, struct resource *res, int resno);
int __must_check pci_assign_resource(struct pci_dev *dev, int i);
int pci_select_bars(struct pci_dev *dev, unsigned long flags);
......
......@@ -142,8 +142,6 @@ struct hotplug_slot_info {
/**
* struct hotplug_slot - used to register a physical slot with the hotplug pci core
* @name: the name of the slot being registered. This string must
* be unique amoung slots registered on this system.
* @ops: pointer to the &struct hotplug_slot_ops to be used for this slot
* @info: pointer to the &struct hotplug_slot_info for the initial values for
* this slot.
......@@ -153,7 +151,6 @@ struct hotplug_slot_info {
* needs.
*/
struct hotplug_slot {
char *name;
struct hotplug_slot_ops *ops;
struct hotplug_slot_info *info;
void (*release) (struct hotplug_slot *slot);
......@@ -165,7 +162,13 @@ struct hotplug_slot {
};
#define to_hotplug_slot(n) container_of(n, struct hotplug_slot, kobj)
extern int pci_hp_register(struct hotplug_slot *, struct pci_bus *, int nr);
static inline const char *hotplug_slot_name(const struct hotplug_slot *slot)
{
return pci_slot_name(slot->pci_slot);
}
extern int pci_hp_register(struct hotplug_slot *, struct pci_bus *, int nr,
const char *name);
extern int pci_hp_deregister(struct hotplug_slot *slot);
extern int __must_check pci_hp_change_slot_info (struct hotplug_slot *slot,
struct hotplug_slot_info *info);
......
......@@ -377,6 +377,7 @@
#define PCI_EXP_DEVCAP_RBER 0x8000 /* Role-Based Error Reporting */
#define PCI_EXP_DEVCAP_PWR_VAL 0x3fc0000 /* Slot Power Limit Value */
#define PCI_EXP_DEVCAP_PWR_SCL 0xc000000 /* Slot Power Limit Scale */
#define PCI_EXP_DEVCAP_FLR 0x10000000 /* Function Level Reset */
#define PCI_EXP_DEVCTL 8 /* Device Control */
#define PCI_EXP_DEVCTL_CERE 0x0001 /* Correctable Error Reporting En. */
#define PCI_EXP_DEVCTL_NFERE 0x0002 /* Non-Fatal Error Reporting Enable */
......@@ -389,6 +390,7 @@
#define PCI_EXP_DEVCTL_AUX_PME 0x0400 /* Auxiliary Power PM Enable */
#define PCI_EXP_DEVCTL_NOSNOOP_EN 0x0800 /* Enable No Snoop */
#define PCI_EXP_DEVCTL_READRQ 0x7000 /* Max_Read_Request_Size */
#define PCI_EXP_DEVCTL_BCR_FLR 0x8000 /* Bridge Configuration Retry / FLR */
#define PCI_EXP_DEVSTA 10 /* Device Status */
#define PCI_EXP_DEVSTA_CED 0x01 /* Correctable Error Detected */
#define PCI_EXP_DEVSTA_NFED 0x02 /* Non-Fatal Error Detected */
......
......@@ -739,7 +739,8 @@ config VM_EVENT_COUNTERS
config PCI_QUIRKS
default y
bool "Enable PCI quirk workarounds" if EMBEDDED && PCI
bool "Enable PCI quirk workarounds" if EMBEDDED
depends on PCI
help
This enables workarounds for various PCI chipset
bugs/quirks. Disable this only if your target machine is
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment