]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/commitdiff
Merge branch 'linux-next' of git://git.kernel.org/pub/scm/linux/kernel/git/jbarnes...
authorLinus Torvalds <torvalds@linux-foundation.org>
Thu, 23 Oct 2008 17:16:53 +0000 (10:16 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 23 Oct 2008 17:16:53 +0000 (10:16 -0700)
* '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
  ...

34 files changed:
MAINTAINERS
drivers/acpi/pci_slot.c
drivers/pci/hotplug/acpiphp.h
drivers/pci/hotplug/acpiphp_core.c
drivers/pci/hotplug/cpci_hotplug.h
drivers/pci/hotplug/cpci_hotplug_core.c
drivers/pci/hotplug/cpci_hotplug_pci.c
drivers/pci/hotplug/cpqphp.h
drivers/pci/hotplug/cpqphp_core.c
drivers/pci/hotplug/cpqphp_ctrl.c
drivers/pci/hotplug/fakephp.c
drivers/pci/hotplug/ibmphp.h
drivers/pci/hotplug/ibmphp_ebda.c
drivers/pci/hotplug/pci_hotplug_core.c
drivers/pci/hotplug/pciehp.h
drivers/pci/hotplug/pciehp_core.c
drivers/pci/hotplug/pciehp_ctrl.c
drivers/pci/hotplug/pciehp_hpc.c
drivers/pci/hotplug/rpaphp_slot.c
drivers/pci/hotplug/sgi_hotplug.c
drivers/pci/hotplug/shpchp.h
drivers/pci/hotplug/shpchp_core.c
drivers/pci/hotplug/shpchp_ctrl.c
drivers/pci/msi.c
drivers/pci/pci-acpi.c
drivers/pci/pci.c
drivers/pci/pci.h
drivers/pci/probe.c
drivers/pci/search.c
drivers/pci/slot.c
include/linux/pci.h
include/linux/pci_hotplug.h
include/linux/pci_regs.h
init/Kconfig

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