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