From b64c05e7de6071694dd6840eac9724a006ee19f8 Mon Sep 17 00:00:00 2001 From: Grant Grundler Date: Sat, 14 Jan 2006 00:34:53 -0700 Subject: [PATCH 01/49] [PATCH] PCI: clean up msi.c a bit Clean up: move assignments outside of if() statements. AFAICT, no functional change. Easier to read/understand. Depends on "[PATCH 1/3] msi vector targeting abstractions" by Mark Maule . I expect one hunk to fail if applied against 2.6.15. This is essentially Joe Perches' patch. I've cleaned up the one instance added by Mark's patch. Signed-off-by: Grant Grundler Signed-off-by: Greg Kroah-Hartman --- drivers/pci/msi.c | 55 ++++++++++++++++++++++++++++++----------------- drivers/pci/pci.c | 5 ++--- 2 files changed, 37 insertions(+), 23 deletions(-) diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index 48723d6fa60f..d5a67c1bcb98 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c @@ -103,9 +103,9 @@ static void set_msi_affinity(unsigned int vector, cpumask_t cpu_mask) switch (entry->msi_attrib.type) { case PCI_CAP_ID_MSI: { - int pos; + int pos = pci_find_capability(entry->dev, PCI_CAP_ID_MSI); - if (!(pos = pci_find_capability(entry->dev, PCI_CAP_ID_MSI))) + if (!pos) return; pci_read_config_dword(entry->dev, msi_lower_address_reg(pos), @@ -347,9 +347,9 @@ static int assign_msi_vector(void) static int get_new_vector(void) { - int vector; + int vector = assign_msi_vector(); - if ((vector = assign_msi_vector()) > 0) + if (vector > 0) set_intr_gate(vector, interrupt[vector]); return vector; @@ -369,7 +369,8 @@ static int msi_init(void) return status; } - if ((status = msi_cache_init()) < 0) { + status = msi_cache_init(); + if (status < 0) { pci_msi_enable = 0; printk(KERN_WARNING "PCI: MSI cache init failed\n"); return status; @@ -523,10 +524,12 @@ static int msi_capability_init(struct pci_dev *dev) pos = pci_find_capability(dev, PCI_CAP_ID_MSI); pci_read_config_word(dev, msi_control_reg(pos), &control); /* MSI Entry Initialization */ - if (!(entry = alloc_msi_entry())) + entry = alloc_msi_entry(); + if (!entry) return -ENOMEM; - if ((vector = get_msi_vector(dev)) < 0) { + vector = get_msi_vector(dev); + if (vector < 0) { kmem_cache_free(msi_cachep, entry); return -EBUSY; } @@ -620,7 +623,8 @@ static int msix_capability_init(struct pci_dev *dev, entry = alloc_msi_entry(); if (!entry) break; - if ((vector = get_msi_vector(dev)) < 0) + vector = get_msi_vector(dev); + if (vector < 0) break; j = entries[i].entry; @@ -701,10 +705,12 @@ int pci_enable_msi(struct pci_dev* dev) temp = dev->irq; - if ((status = msi_init()) < 0) + status = msi_init(); + if (status < 0) return status; - if (!(pos = pci_find_capability(dev, PCI_CAP_ID_MSI))) + pos = pci_find_capability(dev, PCI_CAP_ID_MSI); + if (!pos) return -EINVAL; pci_read_config_word(dev, msi_control_reg(pos), &control); @@ -728,8 +734,8 @@ int pci_enable_msi(struct pci_dev* dev) dev->irq = temp; } /* Check whether driver already requested for MSI-X vectors */ - if ((pos = pci_find_capability(dev, PCI_CAP_ID_MSIX)) > 0 && - !msi_lookup_vector(dev, PCI_CAP_ID_MSIX)) { + pos = pci_find_capability(dev, PCI_CAP_ID_MSIX); + if (pos > 0 && !msi_lookup_vector(dev, PCI_CAP_ID_MSIX)) { printk(KERN_INFO "PCI: %s: Can't enable MSI. " "Device already has MSI-X vectors assigned\n", pci_name(dev)); @@ -755,7 +761,10 @@ void pci_disable_msi(struct pci_dev* dev) u16 control; unsigned long flags; - if (!dev || !(pos = pci_find_capability(dev, PCI_CAP_ID_MSI))) + if (!dev) + return; + pos = pci_find_capability(dev, PCI_CAP_ID_MSI); + if (!pos) return; pci_read_config_word(dev, msi_control_reg(pos), &control); @@ -924,10 +933,12 @@ int pci_enable_msix(struct pci_dev* dev, struct msix_entry *entries, int nvec) if (!pci_msi_enable || !dev || !entries) return -EINVAL; - if ((status = msi_init()) < 0) + status = msi_init(); + if (status < 0) return status; - if (!(pos = pci_find_capability(dev, PCI_CAP_ID_MSIX))) + pos = pci_find_capability(dev, PCI_CAP_ID_MSIX); + if (!pos) return -EINVAL; pci_read_config_word(dev, msi_control_reg(pos), &control); @@ -1006,7 +1017,11 @@ void pci_disable_msix(struct pci_dev* dev) int pos, temp; u16 control; - if (!dev || !(pos = pci_find_capability(dev, PCI_CAP_ID_MSIX))) + if (!dev) + return; + + pos = pci_find_capability(dev, PCI_CAP_ID_MSIX); + if (!pos) return; pci_read_config_word(dev, msi_control_reg(pos), &control); @@ -1066,8 +1081,8 @@ void msi_remove_pci_irq_vectors(struct pci_dev* dev) return; temp = dev->irq; /* Save IOAPIC IRQ */ - if ((pos = pci_find_capability(dev, PCI_CAP_ID_MSI)) > 0 && - !msi_lookup_vector(dev, PCI_CAP_ID_MSI)) { + pos = pci_find_capability(dev, PCI_CAP_ID_MSI); + if (pos > 0 && !msi_lookup_vector(dev, PCI_CAP_ID_MSI)) { spin_lock_irqsave(&msi_lock, flags); state = msi_desc[dev->irq]->msi_attrib.state; spin_unlock_irqrestore(&msi_lock, flags); @@ -1080,8 +1095,8 @@ void msi_remove_pci_irq_vectors(struct pci_dev* dev) msi_free_vector(dev, dev->irq, 0); dev->irq = temp; /* Restore IOAPIC IRQ */ } - if ((pos = pci_find_capability(dev, PCI_CAP_ID_MSIX)) > 0 && - !msi_lookup_vector(dev, PCI_CAP_ID_MSIX)) { + pos = pci_find_capability(dev, PCI_CAP_ID_MSIX); + if (pos > 0 && !msi_lookup_vector(dev, PCI_CAP_ID_MSIX)) { int vector, head, tail = 0, warning = 0; void __iomem *base = NULL; diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index d2d187916643..e17cd49d6244 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -495,9 +495,8 @@ pci_enable_device_bars(struct pci_dev *dev, int bars) int pci_enable_device(struct pci_dev *dev) { - int err; - - if ((err = pci_enable_device_bars(dev, (1 << PCI_NUM_RESOURCES) - 1))) + int err = pci_enable_device_bars(dev, (1 << PCI_NUM_RESOURCES) - 1); + if (err) return err; pci_fixup_device(pci_fixup_enable, dev); dev->is_enabled = 1; From b82db5cedf78bfeb4a1c8a28ae284dc671d26eb3 Mon Sep 17 00:00:00 2001 From: Kristen Accardi Date: Tue, 17 Jan 2006 16:56:56 -0800 Subject: [PATCH 02/49] [PATCH] PCI: return max reserved busnr Change the semantics of this call to return the max reserved bus number instead of just the max assigned bus number. Signed-off-by: Kristen Carlson Accardi Signed-off-by: Greg Kroah-Hartman --- drivers/pci/pci.c | 5 +++-- include/linux/pci.h | 1 + 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index e17cd49d6244..0bf6d254426b 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -19,7 +19,6 @@ #include /* isa_dma_bridge_buggy */ #include "pci.h" -#if 0 /** * pci_bus_max_busnr - returns maximum PCI bus number of given bus' children @@ -34,7 +33,7 @@ pci_bus_max_busnr(struct pci_bus* bus) struct list_head *tmp; unsigned char max, n; - max = bus->number; + max = bus->subordinate; list_for_each(tmp, &bus->children) { n = pci_bus_max_busnr(pci_bus_b(tmp)); if(n > max) @@ -42,7 +41,9 @@ pci_bus_max_busnr(struct pci_bus* bus) } return max; } +EXPORT_SYMBOL_GPL(pci_bus_max_busnr); +#if 0 /** * pci_max_busnr - returns maximum PCI bus number * diff --git a/include/linux/pci.h b/include/linux/pci.h index fe1a2b02fc55..2039da1f3672 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -516,6 +516,7 @@ int pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max, int pass void pci_walk_bus(struct pci_bus *top, void (*cb)(struct pci_dev *, void *), void *userdata); int pci_cfg_space_size(struct pci_dev *dev); +unsigned char pci_bus_max_busnr(struct pci_bus* bus); /* kmem_cache style wrapper around pci_alloc_consistent() */ From e3ac86d8b3f5cee1afaa3e9e6984d0321149b948 Mon Sep 17 00:00:00 2001 From: Kristen Accardi Date: Tue, 17 Jan 2006 16:57:01 -0800 Subject: [PATCH 03/49] [PATCH] PCI: really fix parent's subordinate busnr After you find the maximum value of the subordinate buses below the child bus, you must fix the parent's subordinate bus number again, otherwise it may be too small. Signed-off-by: Kristen Carlson Accardi Signed-off-by: Greg Kroah-Hartman --- drivers/pci/probe.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index adfad4fd6a13..63751a283817 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -537,6 +537,11 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max pci_fixup_parent_subordinate_busnr(child, max); /* Now we can scan all subordinate buses... */ max = pci_scan_child_bus(child); + /* + * now fix it up again since we have found + * the real value of max. + */ + pci_fixup_parent_subordinate_busnr(child, max); } else { /* * For CardBus bridges, we leave 4 bus numbers From c408a3794d6222ab43ab26648385f850a82f0803 Mon Sep 17 00:00:00 2001 From: Kristen Accardi Date: Tue, 17 Jan 2006 16:57:04 -0800 Subject: [PATCH 04/49] [PATCH] PCI: quirk for IBM Dock II cardbus controllers The IBM Dock II cardbus bridges require some extra configuration before Yenta is loaded in order to setup the Interrupts to be routed properly. Signed-off-by: Kristen Carlson Accardi Signed-off-by: Greg Kroah-Hartman --- drivers/pci/quirks.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index dda6099903c1..7ec9fc9a9a42 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -1242,6 +1242,33 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PXH_1, quirk_pc DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PXHV, quirk_pcie_pxh); +/* + * Fixup the cardbus bridges on the IBM Dock II docking station + */ +static void __devinit quirk_ibm_dock2_cardbus(struct pci_dev *dev) +{ + u32 val; + + /* + * tie the 2 interrupt pins to INTA, and configure the + * multifunction routing register to handle this. + */ + if ((dev->subsystem_vendor == PCI_VENDOR_ID_IBM) && + (dev->subsystem_device == 0x0148)) { + printk(KERN_INFO "PCI: Found IBM Dock II Cardbus Bridge " + "applying quirk\n"); + pci_read_config_dword(dev, 0x8c, &val); + val = ((val & 0xffffff00) | 0x1002); + pci_write_config_dword(dev, 0x8c, val); + pci_read_config_dword(dev, 0x80, &val); + val = ((val & 0x00ffff00) | 0x2864c077); + pci_write_config_dword(dev, 0x80, val); + } +} + +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1420, + quirk_ibm_dock2_cardbus); + static void __devinit quirk_netmos(struct pci_dev *dev) { unsigned int num_parallel = (dev->subsystem_device & 0xf0) >> 4; From 6aa4cdd07139ba4d5b89139b0070d795cc4dea88 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Fri, 13 Jan 2006 16:02:15 +0100 Subject: [PATCH 05/49] [PATCH] PCI hotplug: convert semaphores to mutex semaphore to mutex conversion. the conversion was generated via scripts, and the result was validated automatically via a script as well. build tested with allyesconfig. Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/acpiphp.h | 3 +- drivers/pci/hotplug/acpiphp_glue.c | 12 ++-- drivers/pci/hotplug/cpqphp.h | 3 +- drivers/pci/hotplug/cpqphp_core.c | 14 ++--- drivers/pci/hotplug/cpqphp_ctrl.c | 56 ++++++++--------- drivers/pci/hotplug/ibmphp_hpc.c | 10 +-- drivers/pci/hotplug/pciehp.h | 3 +- drivers/pci/hotplug/pciehp_core.c | 6 +- drivers/pci/hotplug/pciehp_ctrl.c | 68 ++++++++++----------- drivers/pci/hotplug/pciehp_hpc.c | 2 +- drivers/pci/hotplug/shpchp.h | 3 +- drivers/pci/hotplug/shpchp_ctrl.c | 98 +++++++++++++++--------------- drivers/pci/hotplug/shpchp_hpc.c | 2 +- 13 files changed, 143 insertions(+), 137 deletions(-) diff --git a/drivers/pci/hotplug/acpiphp.h b/drivers/pci/hotplug/acpiphp.h index 293603e1b7c3..6a91cfb0f688 100644 --- a/drivers/pci/hotplug/acpiphp.h +++ b/drivers/pci/hotplug/acpiphp.h @@ -37,6 +37,7 @@ #include #include /* for KOBJ_NAME_LEN */ +#include #include "pci_hotplug.h" #define dbg(format, arg...) \ @@ -118,7 +119,7 @@ struct acpiphp_slot { struct acpiphp_bridge *bridge; /* parent */ struct list_head funcs; /* one slot may have different objects (i.e. for each function) */ - struct semaphore crit_sect; + struct mutex crit_sect; u32 id; /* slot id (serial #) for hotplug core */ u8 device; /* pci device# */ diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index 509a5b3ae998..4e25d9c7cc39 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c @@ -46,7 +46,7 @@ #include #include #include -#include +#include #include "../pci.h" #include "pci_hotplug.h" @@ -188,7 +188,7 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) slot->device = device; slot->sun = sun; INIT_LIST_HEAD(&slot->funcs); - init_MUTEX(&slot->crit_sect); + mutex_init(&slot->crit_sect); slot->next = bridge->slots; bridge->slots = slot; @@ -1401,7 +1401,7 @@ int acpiphp_enable_slot(struct acpiphp_slot *slot) { int retval; - down(&slot->crit_sect); + mutex_lock(&slot->crit_sect); /* wake up all functions */ retval = power_on_slot(slot); @@ -1413,7 +1413,7 @@ int acpiphp_enable_slot(struct acpiphp_slot *slot) retval = enable_device(slot); err_exit: - up(&slot->crit_sect); + mutex_unlock(&slot->crit_sect); return retval; } @@ -1424,7 +1424,7 @@ int acpiphp_disable_slot(struct acpiphp_slot *slot) { int retval = 0; - down(&slot->crit_sect); + mutex_lock(&slot->crit_sect); /* unconfigure all functions */ retval = disable_device(slot); @@ -1437,7 +1437,7 @@ int acpiphp_disable_slot(struct acpiphp_slot *slot) goto err_exit; err_exit: - up(&slot->crit_sect); + mutex_unlock(&slot->crit_sect); return retval; } diff --git a/drivers/pci/hotplug/cpqphp.h b/drivers/pci/hotplug/cpqphp.h index cb88404c89fe..c74e9e37e76b 100644 --- a/drivers/pci/hotplug/cpqphp.h +++ b/drivers/pci/hotplug/cpqphp.h @@ -32,6 +32,7 @@ #include #include /* for read? and write? functions */ #include /* for delays */ +#include #define MY_NAME "cpqphp" @@ -286,7 +287,7 @@ struct event_info { struct controller { struct controller *next; u32 ctrl_int_comp; - struct semaphore crit_sect; /* critical section semaphore */ + struct mutex crit_sect; /* critical section mutex */ void __iomem *hpc_reg; /* cookie for our pci controller location */ struct pci_resource *mem_head; struct pci_resource *p_mem_head; diff --git a/drivers/pci/hotplug/cpqphp_core.c b/drivers/pci/hotplug/cpqphp_core.c index b3659ffccac9..8626901daeb8 100644 --- a/drivers/pci/hotplug/cpqphp_core.c +++ b/drivers/pci/hotplug/cpqphp_core.c @@ -599,7 +599,7 @@ cpqhp_set_attention_status(struct controller *ctrl, struct pci_func *func, hp_slot = func->device - ctrl->slot_device_offset; // Wait for exclusive access to hardware - down(&ctrl->crit_sect); + mutex_lock(&ctrl->crit_sect); if (status == 1) { amber_LED_on (ctrl, hp_slot); @@ -607,7 +607,7 @@ cpqhp_set_attention_status(struct controller *ctrl, struct pci_func *func, amber_LED_off (ctrl, hp_slot); } else { // Done with exclusive hardware access - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); return(1); } @@ -617,7 +617,7 @@ cpqhp_set_attention_status(struct controller *ctrl, struct pci_func *func, wait_for_ctrl_irq (ctrl); // Done with exclusive hardware access - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); return(0); } @@ -1084,7 +1084,7 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) dbg("bus device function rev: %d %d %d %d\n", ctrl->bus, PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn), ctrl->rev); - init_MUTEX(&ctrl->crit_sect); + mutex_init(&ctrl->crit_sect); init_waitqueue_head(&ctrl->queue); /* initialize our threads if they haven't already been started up */ @@ -1223,7 +1223,7 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) // turn off empty slots here unless command line option "ON" set // Wait for exclusive access to hardware - down(&ctrl->crit_sect); + mutex_lock(&ctrl->crit_sect); num_of_slots = readb(ctrl->hpc_reg + SLOT_MASK) & 0x0F; @@ -1270,12 +1270,12 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) rc = init_SERR(ctrl); if (rc) { err("init_SERR failed\n"); - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); goto err_free_irq; } // Done with exclusive hardware access - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); cpqhp_create_debugfs_files(ctrl); diff --git a/drivers/pci/hotplug/cpqphp_ctrl.c b/drivers/pci/hotplug/cpqphp_ctrl.c index 771ed34b1819..72eb8e2d2065 100644 --- a/drivers/pci/hotplug/cpqphp_ctrl.c +++ b/drivers/pci/hotplug/cpqphp_ctrl.c @@ -1299,7 +1299,7 @@ static u32 board_replaced(struct pci_func *func, struct controller *ctrl) **********************************/ rc = CARD_FUNCTIONING; } else { - down(&ctrl->crit_sect); + mutex_lock(&ctrl->crit_sect); /* turn on board without attaching to the bus */ enable_slot_power (ctrl, hp_slot); @@ -1333,12 +1333,12 @@ static u32 board_replaced(struct pci_func *func, struct controller *ctrl) /* Wait for SOBS to be unset */ wait_for_ctrl_irq (ctrl); - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); if (rc) return rc; - down(&ctrl->crit_sect); + mutex_lock(&ctrl->crit_sect); slot_enable (ctrl, hp_slot); green_LED_blink (ctrl, hp_slot); @@ -1350,7 +1350,7 @@ static u32 board_replaced(struct pci_func *func, struct controller *ctrl) /* Wait for SOBS to be unset */ wait_for_ctrl_irq (ctrl); - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); /* Wait for ~1 second because of hot plug spec */ long_delay(1*HZ); @@ -1375,7 +1375,7 @@ static u32 board_replaced(struct pci_func *func, struct controller *ctrl) * called for the "base" bus/dev/func of an * adapter. */ - down(&ctrl->crit_sect); + mutex_lock(&ctrl->crit_sect); amber_LED_on (ctrl, hp_slot); green_LED_off (ctrl, hp_slot); @@ -1386,7 +1386,7 @@ static u32 board_replaced(struct pci_func *func, struct controller *ctrl) /* Wait for SOBS to be unset */ wait_for_ctrl_irq (ctrl); - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); if (rc) return rc; @@ -1410,7 +1410,7 @@ static u32 board_replaced(struct pci_func *func, struct controller *ctrl) * called for the "base" bus/dev/func of an * adapter. */ - down(&ctrl->crit_sect); + mutex_lock(&ctrl->crit_sect); amber_LED_on (ctrl, hp_slot); green_LED_off (ctrl, hp_slot); @@ -1421,13 +1421,13 @@ static u32 board_replaced(struct pci_func *func, struct controller *ctrl) /* Wait for SOBS to be unset */ wait_for_ctrl_irq (ctrl); - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); return rc; } /* Done configuring so turn LED on full time */ - down(&ctrl->crit_sect); + mutex_lock(&ctrl->crit_sect); green_LED_on (ctrl, hp_slot); @@ -1436,7 +1436,7 @@ static u32 board_replaced(struct pci_func *func, struct controller *ctrl) /* Wait for SOBS to be unset */ wait_for_ctrl_irq (ctrl); - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); rc = 0; } else { /* Something is wrong @@ -1445,7 +1445,7 @@ static u32 board_replaced(struct pci_func *func, struct controller *ctrl) * in this case it will always be called for the "base" * bus/dev/func of an adapter. */ - down(&ctrl->crit_sect); + mutex_lock(&ctrl->crit_sect); amber_LED_on (ctrl, hp_slot); green_LED_off (ctrl, hp_slot); @@ -1456,7 +1456,7 @@ static u32 board_replaced(struct pci_func *func, struct controller *ctrl) /* Wait for SOBS to be unset */ wait_for_ctrl_irq (ctrl); - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); } } @@ -1488,7 +1488,7 @@ static u32 board_added(struct pci_func *func, struct controller *ctrl) dbg("%s: func->device, slot_offset, hp_slot = %d, %d ,%d\n", __FUNCTION__, func->device, ctrl->slot_device_offset, hp_slot); - down(&ctrl->crit_sect); + mutex_lock(&ctrl->crit_sect); /* turn on board without attaching to the bus */ enable_slot_power(ctrl, hp_slot); @@ -1522,7 +1522,7 @@ static u32 board_added(struct pci_func *func, struct controller *ctrl) /* Wait for SOBS to be unset */ wait_for_ctrl_irq(ctrl); - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); if (rc) return rc; @@ -1532,7 +1532,7 @@ static u32 board_added(struct pci_func *func, struct controller *ctrl) /* turn on board and blink green LED */ dbg("%s: before down\n", __FUNCTION__); - down(&ctrl->crit_sect); + mutex_lock(&ctrl->crit_sect); dbg("%s: after down\n", __FUNCTION__); dbg("%s: before slot_enable\n", __FUNCTION__); @@ -1553,7 +1553,7 @@ static u32 board_added(struct pci_func *func, struct controller *ctrl) dbg("%s: after wait_for_ctrl_irq\n", __FUNCTION__); dbg("%s: before up\n", __FUNCTION__); - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); dbg("%s: after up\n", __FUNCTION__); /* Wait for ~1 second because of hot plug spec */ @@ -1607,7 +1607,7 @@ static u32 board_added(struct pci_func *func, struct controller *ctrl) cpqhp_resource_sort_and_combine(&(ctrl->bus_head)); if (rc) { - down(&ctrl->crit_sect); + mutex_lock(&ctrl->crit_sect); amber_LED_on (ctrl, hp_slot); green_LED_off (ctrl, hp_slot); @@ -1618,7 +1618,7 @@ static u32 board_added(struct pci_func *func, struct controller *ctrl) /* Wait for SOBS to be unset */ wait_for_ctrl_irq (ctrl); - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); return rc; } else { cpqhp_save_slot_config(ctrl, func); @@ -1640,7 +1640,7 @@ static u32 board_added(struct pci_func *func, struct controller *ctrl) } } while (new_slot); - down(&ctrl->crit_sect); + mutex_lock(&ctrl->crit_sect); green_LED_on (ctrl, hp_slot); @@ -1649,9 +1649,9 @@ static u32 board_added(struct pci_func *func, struct controller *ctrl) /* Wait for SOBS to be unset */ wait_for_ctrl_irq (ctrl); - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); } else { - down(&ctrl->crit_sect); + mutex_lock(&ctrl->crit_sect); amber_LED_on (ctrl, hp_slot); green_LED_off (ctrl, hp_slot); @@ -1662,7 +1662,7 @@ static u32 board_added(struct pci_func *func, struct controller *ctrl) /* Wait for SOBS to be unset */ wait_for_ctrl_irq (ctrl); - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); return rc; } @@ -1721,7 +1721,7 @@ static u32 remove_board(struct pci_func * func, u32 replace_flag, struct control func->status = 0x01; func->configured = 0; - down(&ctrl->crit_sect); + mutex_lock(&ctrl->crit_sect); green_LED_off (ctrl, hp_slot); slot_disable (ctrl, hp_slot); @@ -1736,7 +1736,7 @@ static u32 remove_board(struct pci_func * func, u32 replace_flag, struct control /* Wait for SOBS to be unset */ wait_for_ctrl_irq (ctrl); - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); if (!replace_flag && ctrl->add_support) { while (func) { @@ -1899,7 +1899,7 @@ static void interrupt_event_handler(struct controller *ctrl) dbg("button cancel\n"); del_timer(&p_slot->task_event); - down(&ctrl->crit_sect); + mutex_lock(&ctrl->crit_sect); if (p_slot->state == BLINKINGOFF_STATE) { /* slot is on */ @@ -1922,7 +1922,7 @@ static void interrupt_event_handler(struct controller *ctrl) /* Wait for SOBS to be unset */ wait_for_ctrl_irq (ctrl); - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); } /*** button Released (No action on press...) */ else if (ctrl->event_queue[loop].event_type == INT_BUTTON_RELEASE) { @@ -1937,7 +1937,7 @@ static void interrupt_event_handler(struct controller *ctrl) p_slot->state = BLINKINGON_STATE; info(msg_button_on, p_slot->number); } - down(&ctrl->crit_sect); + mutex_lock(&ctrl->crit_sect); dbg("blink green LED and turn off amber\n"); @@ -1949,7 +1949,7 @@ static void interrupt_event_handler(struct controller *ctrl) /* Wait for SOBS to be unset */ wait_for_ctrl_irq (ctrl); - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); init_timer(&p_slot->task_event); p_slot->hp_slot = hp_slot; p_slot->ctrl = ctrl; diff --git a/drivers/pci/hotplug/ibmphp_hpc.c b/drivers/pci/hotplug/ibmphp_hpc.c index 1a3eb8d3d4cb..d680bb472c7b 100644 --- a/drivers/pci/hotplug/ibmphp_hpc.c +++ b/drivers/pci/hotplug/ibmphp_hpc.c @@ -34,6 +34,8 @@ #include #include #include +#include + #include "ibmphp.h" static int to_debug = FALSE; @@ -101,7 +103,7 @@ static int to_debug = FALSE; //---------------------------------------------------------------------------- static int ibmphp_shutdown; static int tid_poll; -static struct semaphore sem_hpcaccess; // lock access to HPC +static struct mutex sem_hpcaccess; // lock access to HPC static struct semaphore semOperations; // lock all operations and // access to data structures static struct semaphore sem_exit; // make sure polling thread goes away @@ -131,7 +133,7 @@ void __init ibmphp_hpc_initvars (void) { debug ("%s - Entry\n", __FUNCTION__); - init_MUTEX (&sem_hpcaccess); + mutex_init(&sem_hpcaccess); init_MUTEX (&semOperations); init_MUTEX_LOCKED (&sem_exit); to_debug = FALSE; @@ -778,7 +780,7 @@ int ibmphp_hpc_writeslot (struct slot * pslot, u8 cmd) *---------------------------------------------------------------------*/ static void get_hpc_access (void) { - down (&sem_hpcaccess); + mutex_lock(&sem_hpcaccess); } /*---------------------------------------------------------------------- @@ -786,7 +788,7 @@ static void get_hpc_access (void) *---------------------------------------------------------------------*/ void free_hpc_access (void) { - up (&sem_hpcaccess); + mutex_unlock(&sem_hpcaccess); } /*---------------------------------------------------------------------- diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h index 0aac6a61337d..e0adf4bc89e8 100644 --- a/drivers/pci/hotplug/pciehp.h +++ b/drivers/pci/hotplug/pciehp.h @@ -34,6 +34,7 @@ #include #include /* signal_pending() */ #include +#include #include "pci_hotplug.h" #define MY_NAME "pciehp" @@ -96,7 +97,7 @@ struct php_ctlr_state_s { #define MAX_EVENTS 10 struct controller { struct controller *next; - struct semaphore crit_sect; /* critical section semaphore */ + struct mutex crit_sect; /* critical section mutex */ struct php_ctlr_state_s *hpc_ctlr_handle; /* HPC controller handle */ int num_slots; /* Number of slots on ctlr */ int slot_num_inc; /* 1 or -1 */ diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c index 4fb569018a24..1e8506e0fd87 100644 --- a/drivers/pci/hotplug/pciehp_core.c +++ b/drivers/pci/hotplug/pciehp_core.c @@ -439,7 +439,7 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_ } /* Wait for exclusive access to hardware */ - down(&ctrl->crit_sect); + mutex_lock(&ctrl->crit_sect); t_slot->hpc_ops->get_adapter_status(t_slot, &value); /* Check if slot is occupied */ @@ -447,7 +447,7 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_ rc = t_slot->hpc_ops->power_off_slot(t_slot); /* Power off slot if not occupied*/ if (rc) { /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); goto err_out_free_ctrl_slot; } else /* Wait for the command to complete */ @@ -455,7 +455,7 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_ } /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); return 0; diff --git a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c index 83c4b865718a..33d198768356 100644 --- a/drivers/pci/hotplug/pciehp_ctrl.c +++ b/drivers/pci/hotplug/pciehp_ctrl.c @@ -229,13 +229,13 @@ u8 pciehp_handle_power_fault(u8 hp_slot, void *inst_id) static void set_slot_off(struct controller *ctrl, struct slot * pslot) { /* Wait for exclusive access to hardware */ - down(&ctrl->crit_sect); + mutex_lock(&ctrl->crit_sect); /* turn off slot, turn on Amber LED, turn off Green LED if supported*/ if (POWER_CTRL(ctrl->ctrlcap)) { if (pslot->hpc_ops->power_off_slot(pslot)) { err("%s: Issue of Slot Power Off command failed\n", __FUNCTION__); - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); return; } wait_for_ctrl_irq (ctrl); @@ -249,14 +249,14 @@ static void set_slot_off(struct controller *ctrl, struct slot * pslot) if (ATTN_LED(ctrl->ctrlcap)) { if (pslot->hpc_ops->set_attention_status(pslot, 1)) { err("%s: Issue of Set Attention Led command failed\n", __FUNCTION__); - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); return; } wait_for_ctrl_irq (ctrl); } /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); } /** @@ -279,13 +279,13 @@ static int board_added(struct slot *p_slot) ctrl->slot_device_offset, hp_slot); /* Wait for exclusive access to hardware */ - down(&ctrl->crit_sect); + mutex_lock(&ctrl->crit_sect); if (POWER_CTRL(ctrl->ctrlcap)) { /* Power on slot */ rc = p_slot->hpc_ops->power_on_slot(p_slot); if (rc) { - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); return -1; } @@ -301,7 +301,7 @@ static int board_added(struct slot *p_slot) } /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); /* Wait for ~1 second */ wait_for_ctrl_irq (ctrl); @@ -335,7 +335,7 @@ static int board_added(struct slot *p_slot) pci_fixup_device(pci_fixup_final, ctrl->pci_dev); if (PWR_LED(ctrl->ctrlcap)) { /* Wait for exclusive access to hardware */ - down(&ctrl->crit_sect); + mutex_lock(&ctrl->crit_sect); p_slot->hpc_ops->green_led_on(p_slot); @@ -343,7 +343,7 @@ static int board_added(struct slot *p_slot) wait_for_ctrl_irq (ctrl); /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); } return 0; @@ -375,14 +375,14 @@ static int remove_board(struct slot *p_slot) dbg("In %s, hp_slot = %d\n", __FUNCTION__, hp_slot); /* Wait for exclusive access to hardware */ - down(&ctrl->crit_sect); + mutex_lock(&ctrl->crit_sect); if (POWER_CTRL(ctrl->ctrlcap)) { /* power off slot */ rc = p_slot->hpc_ops->power_off_slot(p_slot); if (rc) { err("%s: Issue of Slot Disable command failed\n", __FUNCTION__); - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); return rc; } /* Wait for the command to complete */ @@ -398,7 +398,7 @@ static int remove_board(struct slot *p_slot) } /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); return 0; } @@ -445,7 +445,7 @@ static void pciehp_pushbutton_thread(unsigned long slot) if (pciehp_enable_slot(p_slot) && PWR_LED(p_slot->ctrl->ctrlcap)) { /* Wait for exclusive access to hardware */ - down(&p_slot->ctrl->crit_sect); + mutex_lock(&p_slot->ctrl->crit_sect); p_slot->hpc_ops->green_led_off(p_slot); @@ -453,7 +453,7 @@ static void pciehp_pushbutton_thread(unsigned long slot) wait_for_ctrl_irq (p_slot->ctrl); /* Done with exclusive hardware access */ - up(&p_slot->ctrl->crit_sect); + mutex_unlock(&p_slot->ctrl->crit_sect); } p_slot->state = STATIC_STATE; } @@ -495,7 +495,7 @@ static void pciehp_surprise_rm_thread(unsigned long slot) if (pciehp_enable_slot(p_slot) && PWR_LED(p_slot->ctrl->ctrlcap)) { /* Wait for exclusive access to hardware */ - down(&p_slot->ctrl->crit_sect); + mutex_lock(&p_slot->ctrl->crit_sect); p_slot->hpc_ops->green_led_off(p_slot); @@ -503,7 +503,7 @@ static void pciehp_surprise_rm_thread(unsigned long slot) wait_for_ctrl_irq (p_slot->ctrl); /* Done with exclusive hardware access */ - up(&p_slot->ctrl->crit_sect); + mutex_unlock(&p_slot->ctrl->crit_sect); } p_slot->state = STATIC_STATE; } @@ -616,7 +616,7 @@ static void interrupt_event_handler(struct controller *ctrl) switch (p_slot->state) { case BLINKINGOFF_STATE: /* Wait for exclusive access to hardware */ - down(&ctrl->crit_sect); + mutex_lock(&ctrl->crit_sect); if (PWR_LED(ctrl->ctrlcap)) { p_slot->hpc_ops->green_led_on(p_slot); @@ -630,11 +630,11 @@ static void interrupt_event_handler(struct controller *ctrl) wait_for_ctrl_irq (ctrl); } /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); break; case BLINKINGON_STATE: /* Wait for exclusive access to hardware */ - down(&ctrl->crit_sect); + mutex_lock(&ctrl->crit_sect); if (PWR_LED(ctrl->ctrlcap)) { p_slot->hpc_ops->green_led_off(p_slot); @@ -647,7 +647,7 @@ static void interrupt_event_handler(struct controller *ctrl) wait_for_ctrl_irq (ctrl); } /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); break; default: @@ -676,7 +676,7 @@ static void interrupt_event_handler(struct controller *ctrl) } /* Wait for exclusive access to hardware */ - down(&ctrl->crit_sect); + mutex_lock(&ctrl->crit_sect); /* blink green LED and turn off amber */ if (PWR_LED(ctrl->ctrlcap)) { @@ -693,7 +693,7 @@ static void interrupt_event_handler(struct controller *ctrl) } /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); init_timer(&p_slot->task_event); p_slot->task_event.expires = jiffies + 5 * HZ; /* 5 second delay */ @@ -708,7 +708,7 @@ static void interrupt_event_handler(struct controller *ctrl) if (POWER_CTRL(ctrl->ctrlcap)) { dbg("power fault\n"); /* Wait for exclusive access to hardware */ - down(&ctrl->crit_sect); + mutex_lock(&ctrl->crit_sect); if (ATTN_LED(ctrl->ctrlcap)) { p_slot->hpc_ops->set_attention_status(p_slot, 1); @@ -721,7 +721,7 @@ static void interrupt_event_handler(struct controller *ctrl) } /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); } } /***********SURPRISE REMOVAL********************/ @@ -756,19 +756,19 @@ int pciehp_enable_slot(struct slot *p_slot) int rc; /* Check to see if (latch closed, card present, power off) */ - down(&p_slot->ctrl->crit_sect); + mutex_lock(&p_slot->ctrl->crit_sect); rc = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus); if (rc || !getstatus) { info("%s: no adapter on slot(%x)\n", __FUNCTION__, p_slot->number); - up(&p_slot->ctrl->crit_sect); + mutex_unlock(&p_slot->ctrl->crit_sect); return 1; } if (MRL_SENS(p_slot->ctrl->ctrlcap)) { rc = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); if (rc || getstatus) { info("%s: latch open on slot(%x)\n", __FUNCTION__, p_slot->number); - up(&p_slot->ctrl->crit_sect); + mutex_unlock(&p_slot->ctrl->crit_sect); return 1; } } @@ -777,11 +777,11 @@ int pciehp_enable_slot(struct slot *p_slot) rc = p_slot->hpc_ops->get_power_status(p_slot, &getstatus); if (rc || getstatus) { info("%s: already enabled on slot(%x)\n", __FUNCTION__, p_slot->number); - up(&p_slot->ctrl->crit_sect); + mutex_unlock(&p_slot->ctrl->crit_sect); return 1; } } - up(&p_slot->ctrl->crit_sect); + mutex_unlock(&p_slot->ctrl->crit_sect); p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); @@ -806,13 +806,13 @@ int pciehp_disable_slot(struct slot *p_slot) return 1; /* Check to see if (latch closed, card present, power on) */ - down(&p_slot->ctrl->crit_sect); + mutex_lock(&p_slot->ctrl->crit_sect); if (!HP_SUPR_RM(p_slot->ctrl->ctrlcap)) { ret = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus); if (ret || !getstatus) { info("%s: no adapter on slot(%x)\n", __FUNCTION__, p_slot->number); - up(&p_slot->ctrl->crit_sect); + mutex_unlock(&p_slot->ctrl->crit_sect); return 1; } } @@ -821,7 +821,7 @@ int pciehp_disable_slot(struct slot *p_slot) ret = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); if (ret || getstatus) { info("%s: latch open on slot(%x)\n", __FUNCTION__, p_slot->number); - up(&p_slot->ctrl->crit_sect); + mutex_unlock(&p_slot->ctrl->crit_sect); return 1; } } @@ -830,12 +830,12 @@ int pciehp_disable_slot(struct slot *p_slot) ret = p_slot->hpc_ops->get_power_status(p_slot, &getstatus); if (ret || !getstatus) { info("%s: already disabled slot(%x)\n", __FUNCTION__, p_slot->number); - up(&p_slot->ctrl->crit_sect); + mutex_unlock(&p_slot->ctrl->crit_sect); return 1; } } - up(&p_slot->ctrl->crit_sect); + mutex_unlock(&p_slot->ctrl->crit_sect); ret = remove_board(p_slot); update_slot_info(p_slot); diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index 77e530321de2..2427b0862cbf 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c @@ -1334,7 +1334,7 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev) if (pci_enable_device(pdev)) goto abort_free_ctlr; - init_MUTEX(&ctrl->crit_sect); + mutex_init(&ctrl->crit_sect); /* setup wait queue */ init_waitqueue_head(&ctrl->queue); diff --git a/drivers/pci/hotplug/shpchp.h b/drivers/pci/hotplug/shpchp.h index 7d6f521d02ea..5a22a43cc387 100644 --- a/drivers/pci/hotplug/shpchp.h +++ b/drivers/pci/hotplug/shpchp.h @@ -33,6 +33,7 @@ #include #include #include /* signal_pending(), struct timer_list */ +#include #include "pci_hotplug.h" @@ -79,7 +80,7 @@ struct event_info { struct controller { struct controller *next; - struct semaphore crit_sect; /* critical section semaphore */ + struct mutex crit_sect; /* critical section mutex */ struct php_ctlr_state_s *hpc_ctlr_handle; /* HPC controller handle */ int num_slots; /* Number of slots on ctlr */ int slot_num_inc; /* 1 or -1 */ diff --git a/drivers/pci/hotplug/shpchp_ctrl.c b/drivers/pci/hotplug/shpchp_ctrl.c index 643252d9bf3b..65e69252e2f9 100644 --- a/drivers/pci/hotplug/shpchp_ctrl.c +++ b/drivers/pci/hotplug/shpchp_ctrl.c @@ -242,10 +242,10 @@ static int change_bus_speed(struct controller *ctrl, struct slot *p_slot, int rc = 0; dbg("%s: change to speed %d\n", __FUNCTION__, speed); - down(&ctrl->crit_sect); + mutex_lock(&ctrl->crit_sect); if ((rc = p_slot->hpc_ops->set_bus_speed_mode(p_slot, speed))) { err("%s: Issue of set bus speed mode command failed\n", __FUNCTION__); - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); return WRONG_BUS_FREQUENCY; } @@ -253,10 +253,10 @@ static int change_bus_speed(struct controller *ctrl, struct slot *p_slot, err("%s: Can't set bus speed/mode in the case of adapter & bus mismatch\n", __FUNCTION__); err("%s: Error code (%d)\n", __FUNCTION__, rc); - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); return WRONG_BUS_FREQUENCY; } - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); return rc; } @@ -319,14 +319,14 @@ static int board_added(struct slot *p_slot) ctrl->slot_device_offset, hp_slot); /* Wait for exclusive access to hardware */ - down(&ctrl->crit_sect); + mutex_lock(&ctrl->crit_sect); /* Power on slot without connecting to bus */ rc = p_slot->hpc_ops->power_on_slot(p_slot); if (rc) { err("%s: Failed to power on slot\n", __FUNCTION__); /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); return -1; } @@ -334,7 +334,7 @@ static int board_added(struct slot *p_slot) if (rc) { err("%s: Failed to power on slot, error code(%d)\n", __FUNCTION__, rc); /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); return -1; } @@ -345,7 +345,7 @@ static int board_added(struct slot *p_slot) if ((rc = p_slot->hpc_ops->set_bus_speed_mode(p_slot, PCI_SPEED_33MHz))) { err("%s: Issue of set bus speed mode command failed\n", __FUNCTION__); - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); return WRONG_BUS_FREQUENCY; } @@ -353,19 +353,19 @@ static int board_added(struct slot *p_slot) err("%s: Can't set bus speed/mode in the case of adapter & bus mismatch\n", __FUNCTION__); err("%s: Error code (%d)\n", __FUNCTION__, rc); - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); return WRONG_BUS_FREQUENCY; } /* turn on board, blink green LED, turn off Amber LED */ if ((rc = p_slot->hpc_ops->slot_enable(p_slot))) { err("%s: Issue of Slot Enable command failed\n", __FUNCTION__); - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); return rc; } if ((rc = p_slot->hpc_ops->check_cmd_status(ctrl))) { err("%s: Failed to enable slot, error code(%d)\n", __FUNCTION__, rc); - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); return rc; } } @@ -380,7 +380,7 @@ static int board_added(struct slot *p_slot) if (rc || adapter_speed == PCI_SPEED_UNKNOWN) { err("%s: Can't get adapter speed or bus mode mismatch\n", __FUNCTION__); /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); return WRONG_BUS_FREQUENCY; } @@ -388,7 +388,7 @@ static int board_added(struct slot *p_slot) if (rc || bus_speed == PCI_SPEED_UNKNOWN) { err("%s: Can't get bus operation speed\n", __FUNCTION__); /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); return WRONG_BUS_FREQUENCY; } @@ -399,7 +399,7 @@ static int board_added(struct slot *p_slot) } /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); if ((rc = p_slot->hpc_ops->get_prog_int(p_slot, &pi))) { err("%s: Can't get controller programming interface, set it to 1\n", __FUNCTION__); @@ -481,21 +481,21 @@ static int board_added(struct slot *p_slot) return rc; } - down(&ctrl->crit_sect); + mutex_lock(&ctrl->crit_sect); /* turn on board, blink green LED, turn off Amber LED */ if ((rc = p_slot->hpc_ops->slot_enable(p_slot))) { err("%s: Issue of Slot Enable command failed\n", __FUNCTION__); - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); return rc; } if ((rc = p_slot->hpc_ops->check_cmd_status(ctrl))) { err("%s: Failed to enable slot, error code(%d)\n", __FUNCTION__, rc); - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); return rc; } - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); /* Wait for ~1 second */ wait_for_ctrl_irq (ctrl); @@ -521,25 +521,25 @@ static int board_added(struct slot *p_slot) p_slot->pwr_save = 1; /* Wait for exclusive access to hardware */ - down(&ctrl->crit_sect); + mutex_lock(&ctrl->crit_sect); p_slot->hpc_ops->green_led_on(p_slot); /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); return 0; err_exit: /* Wait for exclusive access to hardware */ - down(&ctrl->crit_sect); + mutex_lock(&ctrl->crit_sect); /* turn off slot, turn on Amber LED, turn off Green LED */ rc = p_slot->hpc_ops->slot_disable(p_slot); if (rc) { err("%s: Issue of Slot Disable command failed\n", __FUNCTION__); /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); return rc; } @@ -547,12 +547,12 @@ err_exit: if (rc) { err("%s: Failed to disable slot, error code(%d)\n", __FUNCTION__, rc); /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); return rc; } /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); return(rc); } @@ -581,14 +581,14 @@ static int remove_board(struct slot *p_slot) p_slot->status = 0x01; /* Wait for exclusive access to hardware */ - down(&ctrl->crit_sect); + mutex_lock(&ctrl->crit_sect); /* turn off slot, turn on Amber LED, turn off Green LED */ rc = p_slot->hpc_ops->slot_disable(p_slot); if (rc) { err("%s: Issue of Slot Disable command failed\n", __FUNCTION__); /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); return rc; } @@ -596,7 +596,7 @@ static int remove_board(struct slot *p_slot) if (rc) { err("%s: Failed to disable slot, error code(%d)\n", __FUNCTION__, rc); /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); return rc; } @@ -604,12 +604,12 @@ static int remove_board(struct slot *p_slot) if (rc) { err("%s: Issue of Set Attention command failed\n", __FUNCTION__); /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); return rc; } /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); p_slot->pwr_save = 0; p_slot->is_a_board = 0; @@ -656,12 +656,12 @@ static void shpchp_pushbutton_thread (unsigned long slot) if (shpchp_enable_slot(p_slot)) { /* Wait for exclusive access to hardware */ - down(&p_slot->ctrl->crit_sect); + mutex_lock(&p_slot->ctrl->crit_sect); p_slot->hpc_ops->green_led_off(p_slot); /* Done with exclusive hardware access */ - up(&p_slot->ctrl->crit_sect); + mutex_unlock(&p_slot->ctrl->crit_sect); } p_slot->state = STATIC_STATE; } @@ -768,25 +768,25 @@ static void interrupt_event_handler(struct controller *ctrl) switch (p_slot->state) { case BLINKINGOFF_STATE: /* Wait for exclusive access to hardware */ - down(&ctrl->crit_sect); + mutex_lock(&ctrl->crit_sect); p_slot->hpc_ops->green_led_on(p_slot); p_slot->hpc_ops->set_attention_status(p_slot, 0); /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); break; case BLINKINGON_STATE: /* Wait for exclusive access to hardware */ - down(&ctrl->crit_sect); + mutex_lock(&ctrl->crit_sect); p_slot->hpc_ops->green_led_off(p_slot); p_slot->hpc_ops->set_attention_status(p_slot, 0); /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); break; default: @@ -813,7 +813,7 @@ static void interrupt_event_handler(struct controller *ctrl) } /* Wait for exclusive access to hardware */ - down(&ctrl->crit_sect); + mutex_lock(&ctrl->crit_sect); /* blink green LED and turn off amber */ p_slot->hpc_ops->green_led_blink(p_slot); @@ -821,7 +821,7 @@ static void interrupt_event_handler(struct controller *ctrl) p_slot->hpc_ops->set_attention_status(p_slot, 0); /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); init_timer(&p_slot->task_event); p_slot->task_event.expires = jiffies + 5 * HZ; /* 5 second delay */ @@ -834,14 +834,14 @@ static void interrupt_event_handler(struct controller *ctrl) /***********POWER FAULT********************/ dbg("%s: power fault\n", __FUNCTION__); /* Wait for exclusive access to hardware */ - down(&ctrl->crit_sect); + mutex_lock(&ctrl->crit_sect); p_slot->hpc_ops->set_attention_status(p_slot, 1); p_slot->hpc_ops->green_led_off(p_slot); /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); + mutex_unlock(&ctrl->crit_sect); } else { /* refresh notification */ if (p_slot) @@ -865,26 +865,26 @@ int shpchp_enable_slot (struct slot *p_slot) int rc; /* Check to see if (latch closed, card present, power off) */ - down(&p_slot->ctrl->crit_sect); + mutex_lock(&p_slot->ctrl->crit_sect); rc = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus); if (rc || !getstatus) { info("%s: no adapter on slot(%x)\n", __FUNCTION__, p_slot->number); - up(&p_slot->ctrl->crit_sect); + mutex_unlock(&p_slot->ctrl->crit_sect); return -ENODEV; } rc = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); if (rc || getstatus) { info("%s: latch open on slot(%x)\n", __FUNCTION__, p_slot->number); - up(&p_slot->ctrl->crit_sect); + mutex_unlock(&p_slot->ctrl->crit_sect); return -ENODEV; } rc = p_slot->hpc_ops->get_power_status(p_slot, &getstatus); if (rc || getstatus) { info("%s: already enabled on slot(%x)\n", __FUNCTION__, p_slot->number); - up(&p_slot->ctrl->crit_sect); + mutex_unlock(&p_slot->ctrl->crit_sect); return -ENODEV; } - up(&p_slot->ctrl->crit_sect); + mutex_unlock(&p_slot->ctrl->crit_sect); p_slot->is_a_board = 1; @@ -925,27 +925,27 @@ int shpchp_disable_slot (struct slot *p_slot) return -ENODEV; /* Check to see if (latch closed, card present, power on) */ - down(&p_slot->ctrl->crit_sect); + mutex_lock(&p_slot->ctrl->crit_sect); ret = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus); if (ret || !getstatus) { info("%s: no adapter on slot(%x)\n", __FUNCTION__, p_slot->number); - up(&p_slot->ctrl->crit_sect); + mutex_unlock(&p_slot->ctrl->crit_sect); return -ENODEV; } ret = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); if (ret || getstatus) { info("%s: latch open on slot(%x)\n", __FUNCTION__, p_slot->number); - up(&p_slot->ctrl->crit_sect); + mutex_unlock(&p_slot->ctrl->crit_sect); return -ENODEV; } ret = p_slot->hpc_ops->get_power_status(p_slot, &getstatus); if (ret || !getstatus) { info("%s: already disabled slot(%x)\n", __FUNCTION__, p_slot->number); - up(&p_slot->ctrl->crit_sect); + mutex_unlock(&p_slot->ctrl->crit_sect); return -ENODEV; } - up(&p_slot->ctrl->crit_sect); + mutex_unlock(&p_slot->ctrl->crit_sect); ret = remove_board(p_slot); update_slot_info(p_slot); diff --git a/drivers/pci/hotplug/shpchp_hpc.c b/drivers/pci/hotplug/shpchp_hpc.c index b4226ff3a854..ae81427e42b1 100644 --- a/drivers/pci/hotplug/shpchp_hpc.c +++ b/drivers/pci/hotplug/shpchp_hpc.c @@ -1454,7 +1454,7 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev) } dbg("%s: php_ctlr->creg %p\n", __FUNCTION__, php_ctlr->creg); - init_MUTEX(&ctrl->crit_sect); + mutex_init(&ctrl->crit_sect); /* Setup wait queue */ init_waitqueue_head(&ctrl->queue); From 926030f6af856d5681af7940239da2b0269cd755 Mon Sep 17 00:00:00 2001 From: Kenji Kaneshige Date: Thu, 26 Jan 2006 09:55:35 +0900 Subject: [PATCH 06/49] [PATCH] shpchp - cleanup init_slots() This patch cleanups init_slots() function of SHPCHP driver based on pcihp_skelton.c. This patch has no functional change. Signed-off-by: Kenji Kaneshige Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/shpchp.h | 7 -- drivers/pci/hotplug/shpchp_core.c | 116 ++++++++++++++++-------------- 2 files changed, 61 insertions(+), 62 deletions(-) diff --git a/drivers/pci/hotplug/shpchp.h b/drivers/pci/hotplug/shpchp.h index 5a22a43cc387..e03ee0826700 100644 --- a/drivers/pci/hotplug/shpchp.h +++ b/drivers/pci/hotplug/shpchp.h @@ -428,13 +428,6 @@ static inline void amd_pogo_errata_restore_misc_reg(struct slot *p_slot) pci_write_config_dword(p_slot->ctrl->pci_dev, PCIX_MISCII_OFFSET, pcix_misc2_temp); } -#define SLOT_NAME_SIZE 10 - -static inline void make_slot_name(char *buffer, int buffer_size, struct slot *slot) -{ - snprintf(buffer, buffer_size, "%04d_%04d", slot->bus, slot->number); -} - enum php_ctlr_type { PCI, ISA, diff --git a/drivers/pci/hotplug/shpchp_core.c b/drivers/pci/hotplug/shpchp_core.c index a2b3f0010cec..29261b8824c8 100644 --- a/drivers/pci/hotplug/shpchp_core.c +++ b/drivers/pci/hotplug/shpchp_core.c @@ -99,89 +99,95 @@ static void release_slot(struct hotplug_slot *hotplug_slot) kfree(slot); } +#define SLOT_NAME_SIZE 10 +static void make_slot_name(struct slot *slot) +{ + snprintf(slot->hotplug_slot->name, SLOT_NAME_SIZE, "%04d_%04d", + slot->bus, slot->number); +} + static int init_slots(struct controller *ctrl) { - struct slot *new_slot; - u8 number_of_slots; - u8 slot_device; - u32 slot_number, sun; - int result = -ENOMEM; + struct slot *slot; + struct hotplug_slot *hotplug_slot; + struct hotplug_slot_info *info; + char *name; + int retval = -ENOMEM; + int i; + u32 sun; - number_of_slots = ctrl->num_slots; - slot_device = ctrl->slot_device_offset; - slot_number = ctrl->first_slot; - - while (number_of_slots) { - new_slot = (struct slot *) kmalloc(sizeof(struct slot), GFP_KERNEL); - if (!new_slot) + for (i = 0; i < ctrl->num_slots; i++) { + slot = kmalloc(sizeof(struct slot), GFP_KERNEL); + if (!slot) goto error; + memset(slot, 0, sizeof(struct slot)); - memset(new_slot, 0, sizeof(struct slot)); - new_slot->hotplug_slot = kmalloc (sizeof (struct hotplug_slot), GFP_KERNEL); - if (!new_slot->hotplug_slot) + hotplug_slot = kmalloc(sizeof(struct hotplug_slot), + GFP_KERNEL); + if (!hotplug_slot) goto error_slot; - memset(new_slot->hotplug_slot, 0, sizeof (struct hotplug_slot)); + memset(hotplug_slot, 0, sizeof(struct hotplug_slot)); + slot->hotplug_slot = hotplug_slot; - new_slot->hotplug_slot->info = kmalloc (sizeof (struct hotplug_slot_info), GFP_KERNEL); - if (!new_slot->hotplug_slot->info) + info = kmalloc(sizeof(struct hotplug_slot_info), GFP_KERNEL); + if (!info) goto error_hpslot; - memset(new_slot->hotplug_slot->info, 0, sizeof (struct hotplug_slot_info)); - new_slot->hotplug_slot->name = kmalloc (SLOT_NAME_SIZE, GFP_KERNEL); - if (!new_slot->hotplug_slot->name) - goto error_info; + memset(info, 0, sizeof (struct hotplug_slot_info)); + hotplug_slot->info = info; - new_slot->magic = SLOT_MAGIC; - new_slot->ctrl = ctrl; - new_slot->bus = ctrl->slot_bus; - new_slot->device = slot_device; - new_slot->hpc_ops = ctrl->hpc_ops; + name = kmalloc(SLOT_NAME_SIZE, GFP_KERNEL); + if (!name) + goto error_info; + hotplug_slot->name = name; + + slot->hp_slot = i; + slot->magic = SLOT_MAGIC; + slot->ctrl = ctrl; + slot->bus = ctrl->slot_bus; + slot->device = ctrl->slot_device_offset + i; + slot->hpc_ops = ctrl->hpc_ops; if (shpchprm_get_physical_slot_number(ctrl, &sun, - new_slot->bus, new_slot->device)) + slot->bus, slot->device)) goto error_name; - new_slot->number = sun; - new_slot->hp_slot = slot_device - ctrl->slot_device_offset; + slot->number = sun; /* register this slot with the hotplug pci core */ - new_slot->hotplug_slot->private = new_slot; - new_slot->hotplug_slot->release = &release_slot; - make_slot_name(new_slot->hotplug_slot->name, SLOT_NAME_SIZE, new_slot); - new_slot->hotplug_slot->ops = &shpchp_hotplug_slot_ops; + hotplug_slot->private = slot; + hotplug_slot->release = &release_slot; + make_slot_name(slot); + hotplug_slot->ops = &shpchp_hotplug_slot_ops; - new_slot->hpc_ops->get_power_status(new_slot, &(new_slot->hotplug_slot->info->power_status)); - new_slot->hpc_ops->get_attention_status(new_slot, &(new_slot->hotplug_slot->info->attention_status)); - new_slot->hpc_ops->get_latch_status(new_slot, &(new_slot->hotplug_slot->info->latch_status)); - new_slot->hpc_ops->get_adapter_status(new_slot, &(new_slot->hotplug_slot->info->adapter_status)); + 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", new_slot->bus, - new_slot->device, new_slot->hp_slot, new_slot->number, ctrl->slot_device_offset); - result = pci_hp_register (new_slot->hotplug_slot); - if (result) { - err ("pci_hp_register failed with error %d\n", result); + 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); + retval = pci_hp_register(slot->hotplug_slot); + if (retval) { + err("pci_hp_register failed with error %d\n", retval); goto error_name; } - new_slot->next = ctrl->slot; - ctrl->slot = new_slot; - - number_of_slots--; - slot_device++; - slot_number += ctrl->slot_num_inc; + slot->next = ctrl->slot; + ctrl->slot = slot; } return 0; - error_name: - kfree(new_slot->hotplug_slot->name); + kfree(name); error_info: - kfree(new_slot->hotplug_slot->info); + kfree(info); error_hpslot: - kfree(new_slot->hotplug_slot); + kfree(hotplug_slot); error_slot: - kfree(new_slot); + kfree(slot); error: - return result; + return retval; } static void cleanup_slots(struct controller *ctrl) From dfcd5f68ec916414532e88583d1557b6ac0197f5 Mon Sep 17 00:00:00 2001 From: Kenji Kaneshige Date: Thu, 26 Jan 2006 09:56:53 +0900 Subject: [PATCH 07/49] [PATCH] shpchp - cleanup shpchp_core.c This patch cleanups some codes in shpchp_core.c. This patch has no functional changes. Signed-off-by: Kenji Kaneshige Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/shpchp_core.c | 84 +++++++++++++------------------ 1 file changed, 36 insertions(+), 48 deletions(-) diff --git a/drivers/pci/hotplug/shpchp_core.c b/drivers/pci/hotplug/shpchp_core.c index 29261b8824c8..7f2e775534eb 100644 --- a/drivers/pci/hotplug/shpchp_core.c +++ b/drivers/pci/hotplug/shpchp_core.c @@ -213,9 +213,12 @@ static int get_ctlr_slot_config(struct controller *ctrl) int rc; int flags; - rc = shpc_get_ctlr_slot_config(ctrl, &num_ctlr_slots, &first_device_num, &physical_slot_num, &updown, &flags); + rc = shpc_get_ctlr_slot_config(ctrl, &num_ctlr_slots, + &first_device_num, &physical_slot_num, + &updown, &flags); if (rc) { - err("%s: get_ctlr_slot_config fail for b:d (%x:%x)\n", __FUNCTION__, ctrl->bus, ctrl->device); + err("%s: get_ctlr_slot_config fail for b:d (%x:%x)\n", + __FUNCTION__, ctrl->bus, ctrl->device); return -1; } @@ -224,19 +227,19 @@ static int get_ctlr_slot_config(struct controller *ctrl) ctrl->first_slot = physical_slot_num; ctrl->slot_num_inc = updown; /* either -1 or 1 */ - dbg("%s: num_slot(0x%x) 1st_dev(0x%x) psn(0x%x) updown(%d) for b:d (%x:%x)\n", - __FUNCTION__, num_ctlr_slots, first_device_num, physical_slot_num, updown, ctrl->bus, ctrl->device); + dbg("%s: num_slot(0x%x) 1st_dev(0x%x) psn(0x%x) updown(%d) for b:d " + "(%x:%x)\n", __FUNCTION__, num_ctlr_slots, first_device_num, + physical_slot_num, updown, ctrl->bus, ctrl->device); return 0; } - /* * set_attention_status - Turns the Amber LED for a slot on, off or blink */ static int set_attention_status (struct hotplug_slot *hotplug_slot, u8 status) { - struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); + struct slot *slot = get_slot(hotplug_slot, __FUNCTION__); dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); @@ -246,20 +249,18 @@ static int set_attention_status (struct hotplug_slot *hotplug_slot, u8 status) return 0; } - static int enable_slot (struct hotplug_slot *hotplug_slot) { - struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); + struct slot *slot = get_slot(hotplug_slot, __FUNCTION__); dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); return shpchp_enable_slot(slot); } - static int disable_slot (struct hotplug_slot *hotplug_slot) { - struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); + struct slot *slot = get_slot(hotplug_slot, __FUNCTION__); dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); @@ -268,7 +269,7 @@ static int disable_slot (struct hotplug_slot *hotplug_slot) static int get_power_status (struct hotplug_slot *hotplug_slot, u8 *value) { - struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); + struct slot *slot = get_slot(hotplug_slot, __FUNCTION__); int retval; dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); @@ -282,7 +283,7 @@ static int get_power_status (struct hotplug_slot *hotplug_slot, u8 *value) static int get_attention_status (struct hotplug_slot *hotplug_slot, u8 *value) { - struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); + struct slot *slot = get_slot(hotplug_slot, __FUNCTION__); int retval; dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); @@ -296,7 +297,7 @@ static int get_attention_status (struct hotplug_slot *hotplug_slot, u8 *value) static int get_latch_status (struct hotplug_slot *hotplug_slot, u8 *value) { - struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); + struct slot *slot = get_slot(hotplug_slot, __FUNCTION__); int retval; dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); @@ -310,7 +311,7 @@ static int get_latch_status (struct hotplug_slot *hotplug_slot, u8 *value) static int get_adapter_status (struct hotplug_slot *hotplug_slot, u8 *value) { - struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); + struct slot *slot = get_slot(hotplug_slot, __FUNCTION__); int retval; dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); @@ -324,7 +325,7 @@ static int get_adapter_status (struct hotplug_slot *hotplug_slot, u8 *value) static int get_address (struct hotplug_slot *hotplug_slot, u32 *value) { - struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); + struct slot *slot = get_slot(hotplug_slot, __FUNCTION__); struct pci_bus *bus = slot->ctrl->pci_dev->subordinate; dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); @@ -336,11 +337,11 @@ static int get_address (struct hotplug_slot *hotplug_slot, u32 *value) static int get_max_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value) { - struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); + struct slot *slot = get_slot(hotplug_slot, __FUNCTION__); int retval; dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); - + retval = slot->hpc_ops->get_max_bus_speed(slot, value); if (retval < 0) *value = PCI_SPEED_UNKNOWN; @@ -350,11 +351,11 @@ static int get_max_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_sp static int get_cur_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value) { - struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); + struct slot *slot = get_slot(hotplug_slot, __FUNCTION__); int retval; dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); - + retval = slot->hpc_ops->get_cur_bus_speed(slot, value); if (retval < 0) *value = PCI_SPEED_UNKNOWN; @@ -378,13 +379,13 @@ static int shpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) int rc; struct controller *ctrl; struct slot *t_slot; - int first_device_num; /* first PCI device number supported by this SHPC */ - int num_ctlr_slots; /* number of slots supported by this SHPC */ + int first_device_num; /* first PCI device number */ + int num_ctlr_slots; /* number of slots implemented */ if (!is_shpc_capable(pdev)) return -ENODEV; - ctrl = (struct controller *) kmalloc(sizeof(struct controller), GFP_KERNEL); + ctrl = kmalloc(sizeof(struct controller), GFP_KERNEL); if (!ctrl) { err("%s : out of memory\n", __FUNCTION__); goto err_out_none; @@ -393,31 +394,32 @@ static int shpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) rc = shpc_init(ctrl, pdev); if (rc) { - dbg("%s: controller initialization failed\n", SHPC_MODULE_NAME); + dbg("%s: controller initialization failed\n", + SHPC_MODULE_NAME); goto err_out_free_ctrl; } pci_set_drvdata(pdev, ctrl); - ctrl->pci_bus = kmalloc (sizeof (*ctrl->pci_bus), GFP_KERNEL); + ctrl->pci_bus = kmalloc(sizeof (*ctrl->pci_bus), GFP_KERNEL); if (!ctrl->pci_bus) { err("out of memory\n"); rc = -ENOMEM; goto err_out_unmap_mmio_region; } - + memcpy (ctrl->pci_bus, pdev->bus, sizeof (*ctrl->pci_bus)); ctrl->bus = pdev->bus->number; ctrl->slot_bus = pdev->subordinate->number; - ctrl->device = PCI_SLOT(pdev->devfn); ctrl->function = PCI_FUNC(pdev->devfn); - dbg("ctrl bus=0x%x, device=%x, function=%x, irq=%x\n", ctrl->bus, ctrl->device, ctrl->function, pdev->irq); + + dbg("ctrl bus=0x%x, device=%x, function=%x, irq=%x\n", + ctrl->bus, ctrl->device, ctrl->function, pdev->irq); /* - * Save configuration headers for this and subordinate PCI buses + * Save configuration headers for this and subordinate PCI buses */ - rc = get_ctlr_slot_config(ctrl); if (rc) { err(msg_initialization_err, rc); @@ -427,7 +429,7 @@ static int shpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) num_ctlr_slots = ctrl->num_slots; ctrl->add_support = 1; - + /* Setup the slot information structures */ rc = init_slots(ctrl); if (rc) { @@ -443,7 +445,8 @@ static int shpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) dbg("%s: t_slot->hp_slot %x\n", __FUNCTION__,t_slot->hp_slot); if (rc || ctrl->speed == PCI_SPEED_UNKNOWN) { - err(SHPC_MODULE_NAME ": Can't get current bus speed. Set to 33MHz PCI.\n"); + err(SHPC_MODULE_NAME ": Can't get current bus speed. " + "Set to 33MHz PCI.\n"); ctrl->speed = PCI_SPEED_33MHz; } @@ -474,11 +477,10 @@ err_out_none: return -ENODEV; } - static int shpc_start_thread(void) { int retval = 0; - + dbg("Initialize + Start the notification/polling mechanism \n"); retval = shpchp_event_start_thread(); @@ -515,24 +517,12 @@ static void __exit unload_shpchpd(void) } - static struct pci_device_id shpcd_pci_tbl[] = { - { - .class = ((PCI_CLASS_BRIDGE_PCI << 8) | 0x00), - .class_mask = ~0, - .vendor = PCI_ANY_ID, - .device = PCI_ANY_ID, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - }, - + {PCI_DEVICE_CLASS(((PCI_CLASS_BRIDGE_PCI << 8) | 0x00), ~0)}, { /* end: all zeroes */ } }; - MODULE_DEVICE_TABLE(pci, shpcd_pci_tbl); - - static struct pci_driver shpc_driver = { .name = SHPC_MODULE_NAME, .id_table = shpcd_pci_tbl, @@ -540,8 +530,6 @@ static struct pci_driver shpc_driver = { /* remove: shpc_remove_one, */ }; - - static int __init shpcd_init(void) { int retval = 0; From 5b1a960d180e9660a87b0c661a754efabc1b1d3a Mon Sep 17 00:00:00 2001 From: Kenji Kaneshige Date: Thu, 26 Jan 2006 09:57:40 +0900 Subject: [PATCH 08/49] [PATCH] shpchp - cleanup slot list This patch changes SHPCHP driver to use list_head structure for managing slot list. Signed-off-by: Kenji Kaneshige Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/shpchp.h | 21 ++++++++------------- drivers/pci/hotplug/shpchp_core.c | 19 +++++++++---------- 2 files changed, 17 insertions(+), 23 deletions(-) diff --git a/drivers/pci/hotplug/shpchp.h b/drivers/pci/hotplug/shpchp.h index e03ee0826700..c0be7a1c3ff7 100644 --- a/drivers/pci/hotplug/shpchp.h +++ b/drivers/pci/hotplug/shpchp.h @@ -56,7 +56,6 @@ extern int shpchp_debug; #define SLOT_MAGIC 0x67267321 struct slot { u32 magic; - struct slot *next; u8 bus; u8 device; u16 status; @@ -87,7 +86,7 @@ struct controller { struct pci_dev *pci_dev; struct pci_bus *pci_bus; struct event_info event_queue[10]; - struct slot *slot; + struct list_head slot_list; struct hpc_ops *hpc_ops; wait_queue_head_t queue; /* sleep & wake process */ u8 next_event; @@ -315,23 +314,19 @@ static inline struct slot *get_slot (struct hotplug_slot *hotplug_slot, const ch static inline struct slot *shpchp_find_slot (struct controller *ctrl, u8 device) { - struct slot *p_slot, *tmp_slot = NULL; + struct slot *slot; if (!ctrl) return NULL; - p_slot = ctrl->slot; - - while (p_slot && (p_slot->device != device)) { - tmp_slot = p_slot; - p_slot = p_slot->next; - } - if (p_slot == NULL) { - err("ERROR: shpchp_find_slot device=0x%x\n", device); - p_slot = tmp_slot; + list_for_each_entry(slot, &ctrl->slot_list, slot_list) { + if (slot->device == device) + return slot; } - return (p_slot); + err("%s: slot (device=0x%x) not found\n", __FUNCTION__, device); + + return NULL; } static inline int wait_for_ctrl_irq (struct controller *ctrl) diff --git a/drivers/pci/hotplug/shpchp_core.c b/drivers/pci/hotplug/shpchp_core.c index 7f2e775534eb..547bf5d6fcca 100644 --- a/drivers/pci/hotplug/shpchp_core.c +++ b/drivers/pci/hotplug/shpchp_core.c @@ -173,8 +173,7 @@ static int init_slots(struct controller *ctrl) goto error_name; } - slot->next = ctrl->slot; - ctrl->slot = slot; + list_add(&slot->slot_list, &ctrl->slot_list); } return 0; @@ -192,15 +191,14 @@ error: static void cleanup_slots(struct controller *ctrl) { - struct slot *old_slot, *next_slot; + struct list_head *tmp; + struct list_head *next; + struct slot *slot; - old_slot = ctrl->slot; - ctrl->slot = NULL; - - while (old_slot) { - next_slot = old_slot->next; - pci_hp_deregister(old_slot->hotplug_slot); - old_slot = next_slot; + list_for_each_safe(tmp, next, &ctrl->slot_list) { + slot = list_entry(tmp, struct slot, slot_list); + list_del(&slot->slot_list); + pci_hp_deregister(slot->hotplug_slot); } } @@ -391,6 +389,7 @@ static int shpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) goto err_out_none; } memset(ctrl, 0, sizeof(struct controller)); + INIT_LIST_HEAD(&ctrl->slot_list); rc = shpc_init(ctrl, pdev); if (rc) { From a4534560815ffc525bfbe465a290ce048aab4c01 Mon Sep 17 00:00:00 2001 From: Kenji Kaneshige Date: Thu, 26 Jan 2006 09:58:30 +0900 Subject: [PATCH 09/49] [PATCH] shpchp - cleanup controller list This patch changes SHPCHP driver to use list_head structure for managing controller list. Signed-off-by: Kenji Kaneshige Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/shpchp.h | 4 ++-- drivers/pci/hotplug/shpchp_core.c | 25 +++++++------------------ drivers/pci/hotplug/shpchp_ctrl.c | 2 +- 3 files changed, 10 insertions(+), 21 deletions(-) diff --git a/drivers/pci/hotplug/shpchp.h b/drivers/pci/hotplug/shpchp.h index c0be7a1c3ff7..f6d606dde691 100644 --- a/drivers/pci/hotplug/shpchp.h +++ b/drivers/pci/hotplug/shpchp.h @@ -78,7 +78,7 @@ struct event_info { }; struct controller { - struct controller *next; + struct list_head ctrl_list; struct mutex crit_sect; /* critical section mutex */ struct php_ctlr_state_s *hpc_ctlr_handle; /* HPC controller handle */ int num_slots; /* Number of slots on ctlr */ @@ -204,7 +204,7 @@ extern void shpchp_remove_ctrl_files(struct controller *ctrl); /* Global variables */ -extern struct controller *shpchp_ctrl_list; +extern struct list_head shpchp_ctrl_list; struct ctrl_reg { volatile u32 base_offset; diff --git a/drivers/pci/hotplug/shpchp_core.c b/drivers/pci/hotplug/shpchp_core.c index 547bf5d6fcca..0dd0642e691b 100644 --- a/drivers/pci/hotplug/shpchp_core.c +++ b/drivers/pci/hotplug/shpchp_core.c @@ -38,7 +38,7 @@ int shpchp_debug; int shpchp_poll_mode; int shpchp_poll_time; -struct controller *shpchp_ctrl_list; /* = NULL */ +LIST_HEAD(shpchp_ctrl_list); #define DRIVER_VERSION "0.4" #define DRIVER_AUTHOR "Dan Zink , Greg Kroah-Hartman , Dely Sy " @@ -452,13 +452,7 @@ static int shpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) /* Finish setting up the hot plug ctrl device */ ctrl->next_event = 0; - if (!shpchp_ctrl_list) { - shpchp_ctrl_list = ctrl; - ctrl->next = NULL; - } else { - ctrl->next = shpchp_ctrl_list; - shpchp_ctrl_list = ctrl; - } + list_add(&ctrl->ctrl_list, &shpchp_ctrl_list); shpchp_create_ctrl_files(ctrl); @@ -493,22 +487,17 @@ static int shpc_start_thread(void) static void __exit unload_shpchpd(void) { + struct list_head *tmp; + struct list_head *next; struct controller *ctrl; - struct controller *tctrl; - ctrl = shpchp_ctrl_list; - - while (ctrl) { + list_for_each_safe(tmp, next, &shpchp_ctrl_list) { + ctrl = list_entry(tmp, struct controller, ctrl_list); shpchp_remove_ctrl_files(ctrl); cleanup_slots(ctrl); - kfree (ctrl->pci_bus); ctrl->hpc_ops->release_ctlr(ctrl); - - tctrl = ctrl; - ctrl = ctrl->next; - - kfree(tctrl); + kfree(ctrl); } /* Stop the notification mechanism */ diff --git a/drivers/pci/hotplug/shpchp_ctrl.c b/drivers/pci/hotplug/shpchp_ctrl.c index 65e69252e2f9..3a8e733aead5 100644 --- a/drivers/pci/hotplug/shpchp_ctrl.c +++ b/drivers/pci/hotplug/shpchp_ctrl.c @@ -688,7 +688,7 @@ static int event_thread(void* data) if (pushbutton_pending) shpchp_pushbutton_thread(pushbutton_pending); else - for (ctrl = shpchp_ctrl_list; ctrl; ctrl=ctrl->next) + list_for_each_entry(ctrl, &shpchp_ctrl_list, ctrl_list) interrupt_event_handler(ctrl); } dbg("event_thread signals exit\n"); From d29aaddab3ef3bdaecf3c9c6d9423f0bf0452ccf Mon Sep 17 00:00:00 2001 From: Kenji Kaneshige Date: Thu, 26 Jan 2006 09:59:24 +0900 Subject: [PATCH 10/49] [PATCH] shpchp - cleanup check command status This patch cleanups codes that check the command status. For this, it introduces a new semaphore "cmd_sem" for each controller. Signed-off-by: Kenji Kaneshige Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/shpchp.h | 1 + drivers/pci/hotplug/shpchp_ctrl.c | 120 +----------------------------- drivers/pci/hotplug/shpchp_hpc.c | 25 ++++++- 3 files changed, 23 insertions(+), 123 deletions(-) diff --git a/drivers/pci/hotplug/shpchp.h b/drivers/pci/hotplug/shpchp.h index f6d606dde691..b1e2a7705835 100644 --- a/drivers/pci/hotplug/shpchp.h +++ b/drivers/pci/hotplug/shpchp.h @@ -80,6 +80,7 @@ struct event_info { struct controller { struct list_head ctrl_list; struct mutex crit_sect; /* critical section mutex */ + struct mutex cmd_lock; /* command lock */ struct php_ctlr_state_s *hpc_ctlr_handle; /* HPC controller handle */ int num_slots; /* Number of slots on ctlr */ int slot_num_inc; /* 1 or -1 */ diff --git a/drivers/pci/hotplug/shpchp_ctrl.c b/drivers/pci/hotplug/shpchp_ctrl.c index 3a8e733aead5..802c4c48d186 100644 --- a/drivers/pci/hotplug/shpchp_ctrl.c +++ b/drivers/pci/hotplug/shpchp_ctrl.c @@ -242,21 +242,10 @@ static int change_bus_speed(struct controller *ctrl, struct slot *p_slot, int rc = 0; dbg("%s: change to speed %d\n", __FUNCTION__, speed); - mutex_lock(&ctrl->crit_sect); if ((rc = p_slot->hpc_ops->set_bus_speed_mode(p_slot, speed))) { err("%s: Issue of set bus speed mode command failed\n", __FUNCTION__); - mutex_unlock(&ctrl->crit_sect); return WRONG_BUS_FREQUENCY; } - - if ((rc = p_slot->hpc_ops->check_cmd_status(ctrl))) { - err("%s: Can't set bus speed/mode in the case of adapter & bus mismatch\n", - __FUNCTION__); - err("%s: Error code (%d)\n", __FUNCTION__, rc); - mutex_unlock(&ctrl->crit_sect); - return WRONG_BUS_FREQUENCY; - } - mutex_unlock(&ctrl->crit_sect); return rc; } @@ -330,15 +319,6 @@ static int board_added(struct slot *p_slot) return -1; } - rc = p_slot->hpc_ops->check_cmd_status(ctrl); - if (rc) { - err("%s: Failed to power on slot, error code(%d)\n", __FUNCTION__, rc); - /* Done with exclusive hardware access */ - mutex_unlock(&ctrl->crit_sect); - return -1; - } - - if ((ctrl->pci_dev->vendor == 0x8086) && (ctrl->pci_dev->device == 0x0332)) { if (slots_not_empty) return WRONG_BUS_FREQUENCY; @@ -349,25 +329,12 @@ static int board_added(struct slot *p_slot) return WRONG_BUS_FREQUENCY; } - if ((rc = p_slot->hpc_ops->check_cmd_status(ctrl))) { - err("%s: Can't set bus speed/mode in the case of adapter & bus mismatch\n", - __FUNCTION__); - err("%s: Error code (%d)\n", __FUNCTION__, rc); - mutex_unlock(&ctrl->crit_sect); - return WRONG_BUS_FREQUENCY; - } /* turn on board, blink green LED, turn off Amber LED */ if ((rc = p_slot->hpc_ops->slot_enable(p_slot))) { err("%s: Issue of Slot Enable command failed\n", __FUNCTION__); mutex_unlock(&ctrl->crit_sect); return rc; } - - if ((rc = p_slot->hpc_ops->check_cmd_status(ctrl))) { - err("%s: Failed to enable slot, error code(%d)\n", __FUNCTION__, rc); - mutex_unlock(&ctrl->crit_sect); - return rc; - } } rc = p_slot->hpc_ops->get_adapter_speed(p_slot, &adapter_speed); @@ -481,22 +448,12 @@ static int board_added(struct slot *p_slot) return rc; } - mutex_lock(&ctrl->crit_sect); /* turn on board, blink green LED, turn off Amber LED */ if ((rc = p_slot->hpc_ops->slot_enable(p_slot))) { err("%s: Issue of Slot Enable command failed\n", __FUNCTION__); - mutex_unlock(&ctrl->crit_sect); return rc; } - if ((rc = p_slot->hpc_ops->check_cmd_status(ctrl))) { - err("%s: Failed to enable slot, error code(%d)\n", __FUNCTION__, rc); - mutex_unlock(&ctrl->crit_sect); - return rc; - } - - mutex_unlock(&ctrl->crit_sect); - /* Wait for ~1 second */ wait_for_ctrl_irq (ctrl); @@ -520,40 +477,18 @@ static int board_added(struct slot *p_slot) p_slot->is_a_board = 0x01; p_slot->pwr_save = 1; - /* Wait for exclusive access to hardware */ - mutex_lock(&ctrl->crit_sect); - p_slot->hpc_ops->green_led_on(p_slot); - /* Done with exclusive hardware access */ - mutex_unlock(&ctrl->crit_sect); - return 0; err_exit: - /* Wait for exclusive access to hardware */ - mutex_lock(&ctrl->crit_sect); - /* turn off slot, turn on Amber LED, turn off Green LED */ rc = p_slot->hpc_ops->slot_disable(p_slot); if (rc) { err("%s: Issue of Slot Disable command failed\n", __FUNCTION__); - /* Done with exclusive hardware access */ - mutex_unlock(&ctrl->crit_sect); return rc; } - rc = p_slot->hpc_ops->check_cmd_status(ctrl); - if (rc) { - err("%s: Failed to disable slot, error code(%d)\n", __FUNCTION__, rc); - /* Done with exclusive hardware access */ - mutex_unlock(&ctrl->crit_sect); - return rc; - } - - /* Done with exclusive hardware access */ - mutex_unlock(&ctrl->crit_sect); - return(rc); } @@ -580,37 +515,19 @@ static int remove_board(struct slot *p_slot) if (p_slot->is_a_board) p_slot->status = 0x01; - /* Wait for exclusive access to hardware */ - mutex_lock(&ctrl->crit_sect); - /* turn off slot, turn on Amber LED, turn off Green LED */ rc = p_slot->hpc_ops->slot_disable(p_slot); if (rc) { err("%s: Issue of Slot Disable command failed\n", __FUNCTION__); - /* Done with exclusive hardware access */ - mutex_unlock(&ctrl->crit_sect); return rc; } - - rc = p_slot->hpc_ops->check_cmd_status(ctrl); - if (rc) { - err("%s: Failed to disable slot, error code(%d)\n", __FUNCTION__, rc); - /* Done with exclusive hardware access */ - mutex_unlock(&ctrl->crit_sect); - return rc; - } rc = p_slot->hpc_ops->set_attention_status(p_slot, 0); if (rc) { err("%s: Issue of Set Attention command failed\n", __FUNCTION__); - /* Done with exclusive hardware access */ - mutex_unlock(&ctrl->crit_sect); return rc; } - /* Done with exclusive hardware access */ - mutex_unlock(&ctrl->crit_sect); - p_slot->pwr_save = 0; p_slot->is_a_board = 0; @@ -654,15 +571,9 @@ static void shpchp_pushbutton_thread (unsigned long slot) } else { p_slot->state = POWERON_STATE; - if (shpchp_enable_slot(p_slot)) { - /* Wait for exclusive access to hardware */ - mutex_lock(&p_slot->ctrl->crit_sect); - + if (shpchp_enable_slot(p_slot)) p_slot->hpc_ops->green_led_off(p_slot); - /* Done with exclusive hardware access */ - mutex_unlock(&p_slot->ctrl->crit_sect); - } p_slot->state = STATIC_STATE; } @@ -767,27 +678,12 @@ static void interrupt_event_handler(struct controller *ctrl) switch (p_slot->state) { case BLINKINGOFF_STATE: - /* Wait for exclusive access to hardware */ - mutex_lock(&ctrl->crit_sect); - p_slot->hpc_ops->green_led_on(p_slot); - p_slot->hpc_ops->set_attention_status(p_slot, 0); - - /* Done with exclusive hardware access */ - mutex_unlock(&ctrl->crit_sect); break; case BLINKINGON_STATE: - /* Wait for exclusive access to hardware */ - mutex_lock(&ctrl->crit_sect); - p_slot->hpc_ops->green_led_off(p_slot); - p_slot->hpc_ops->set_attention_status(p_slot, 0); - - /* Done with exclusive hardware access */ - mutex_unlock(&ctrl->crit_sect); - break; default: warn("Not a valid state\n"); @@ -812,17 +708,10 @@ static void interrupt_event_handler(struct controller *ctrl) info(msg_button_on, p_slot->number); } - /* Wait for exclusive access to hardware */ - mutex_lock(&ctrl->crit_sect); - /* blink green LED and turn off amber */ p_slot->hpc_ops->green_led_blink(p_slot); - p_slot->hpc_ops->set_attention_status(p_slot, 0); - /* Done with exclusive hardware access */ - mutex_unlock(&ctrl->crit_sect); - init_timer(&p_slot->task_event); p_slot->task_event.expires = jiffies + 5 * HZ; /* 5 second delay */ p_slot->task_event.function = (void (*)(unsigned long)) pushbutton_helper_thread; @@ -833,15 +722,8 @@ static void interrupt_event_handler(struct controller *ctrl) } else if (ctrl->event_queue[loop].event_type == INT_POWER_FAULT) { /***********POWER FAULT********************/ dbg("%s: power fault\n", __FUNCTION__); - /* Wait for exclusive access to hardware */ - mutex_lock(&ctrl->crit_sect); - p_slot->hpc_ops->set_attention_status(p_slot, 1); - p_slot->hpc_ops->green_led_off(p_slot); - - /* Done with exclusive hardware access */ - mutex_unlock(&ctrl->crit_sect); } else { /* refresh notification */ if (p_slot) diff --git a/drivers/pci/hotplug/shpchp_hpc.c b/drivers/pci/hotplug/shpchp_hpc.c index ae81427e42b1..c32a1b16704f 100644 --- a/drivers/pci/hotplug/shpchp_hpc.c +++ b/drivers/pci/hotplug/shpchp_hpc.c @@ -231,6 +231,7 @@ static spinlock_t list_lock; static irqreturn_t shpc_isr(int IRQ, void *dev_id, struct pt_regs *regs); static void start_int_poll_timer(struct php_ctlr_state_s *php_ctlr, int seconds); +static int hpc_check_cmd_status(struct controller *ctrl); /* This is the interrupt polling timeout function. */ static void int_poll_timeout(unsigned long lphp_ctlr) @@ -303,10 +304,13 @@ static int shpc_write_cmd(struct slot *slot, u8 t_slot, u8 cmd) int i; DBG_ENTER_ROUTINE - + + mutex_lock(&slot->ctrl->cmd_lock); + if (!php_ctlr) { err("%s: Invalid HPC controller handle!\n", __FUNCTION__); - return -1; + retval = -EINVAL; + goto out; } for (i = 0; i < 10; i++) { @@ -323,7 +327,8 @@ static int shpc_write_cmd(struct slot *slot, u8 t_slot, u8 cmd) if (cmd_status & 0x1) { /* After 1 sec and and the controller is still busy */ err("%s : Controller is still busy after 1 sec.\n", __FUNCTION__); - return -1; + retval = -EBUSY; + goto out; } ++t_slot; @@ -340,6 +345,17 @@ static int shpc_write_cmd(struct slot *slot, u8 t_slot, u8 cmd) * Wait for command completion. */ retval = shpc_wait_cmd(slot->ctrl); + if (retval) + goto out; + + cmd_status = hpc_check_cmd_status(slot->ctrl); + if (cmd_status) { + err("%s: Failed to issued command 0x%x (error code = %d)\n", + __FUNCTION__, cmd, cmd_status); + retval = -EIO; + } + out: + mutex_unlock(&slot->ctrl->cmd_lock); DBG_LEAVE_ROUTINE return retval; @@ -1343,7 +1359,6 @@ static struct hpc_ops shpchp_hpc_ops = { .green_led_blink = hpc_set_green_led_blink, .release_ctlr = hpc_release_ctlr, - .check_cmd_status = hpc_check_cmd_status, }; inline static int shpc_indirect_creg_read(struct controller *ctrl, int index, @@ -1455,6 +1470,8 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev) dbg("%s: php_ctlr->creg %p\n", __FUNCTION__, php_ctlr->creg); mutex_init(&ctrl->crit_sect); + mutex_init(&ctrl->cmd_lock); + /* Setup wait queue */ init_waitqueue_head(&ctrl->queue); From ef3be54777901e570185089f21fbe4498453f67e Mon Sep 17 00:00:00 2001 From: Kenji Kaneshige Date: Thu, 26 Jan 2006 10:00:33 +0900 Subject: [PATCH 11/49] [PATCH] shpchp - bugfix: add missing serialization Current shpchp driver might cause system panic because of lack of serialization. It can be reproduced very easily by the following operation. # cd /sys/bus/pci/slots/ # while true; do echo 0 > power ; echo 1 > power ; done & # while true; do echo 0 > power ; echo 1 > power ; done & This patch fixes this issue by changing shpchp to get appropreate semaphore for hot-plug operation. Signed-off-by: Kenji Kaneshige Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/shpchp_ctrl.c | 66 +++++++++++-------------------- 1 file changed, 24 insertions(+), 42 deletions(-) diff --git a/drivers/pci/hotplug/shpchp_ctrl.c b/drivers/pci/hotplug/shpchp_ctrl.c index 802c4c48d186..1a7003d4ba96 100644 --- a/drivers/pci/hotplug/shpchp_ctrl.c +++ b/drivers/pci/hotplug/shpchp_ctrl.c @@ -307,15 +307,10 @@ static int board_added(struct slot *p_slot) __FUNCTION__, p_slot->device, ctrl->slot_device_offset, hp_slot); - /* Wait for exclusive access to hardware */ - mutex_lock(&ctrl->crit_sect); - /* Power on slot without connecting to bus */ rc = p_slot->hpc_ops->power_on_slot(p_slot); if (rc) { err("%s: Failed to power on slot\n", __FUNCTION__); - /* Done with exclusive hardware access */ - mutex_unlock(&ctrl->crit_sect); return -1; } @@ -325,14 +320,12 @@ static int board_added(struct slot *p_slot) if ((rc = p_slot->hpc_ops->set_bus_speed_mode(p_slot, PCI_SPEED_33MHz))) { err("%s: Issue of set bus speed mode command failed\n", __FUNCTION__); - mutex_unlock(&ctrl->crit_sect); return WRONG_BUS_FREQUENCY; } /* turn on board, blink green LED, turn off Amber LED */ if ((rc = p_slot->hpc_ops->slot_enable(p_slot))) { err("%s: Issue of Slot Enable command failed\n", __FUNCTION__); - mutex_unlock(&ctrl->crit_sect); return rc; } } @@ -346,16 +339,12 @@ static int board_added(struct slot *p_slot) if (rc || adapter_speed == PCI_SPEED_UNKNOWN) { err("%s: Can't get adapter speed or bus mode mismatch\n", __FUNCTION__); - /* Done with exclusive hardware access */ - mutex_unlock(&ctrl->crit_sect); return WRONG_BUS_FREQUENCY; } rc = p_slot->hpc_ops->get_cur_bus_speed(p_slot, &bus_speed); if (rc || bus_speed == PCI_SPEED_UNKNOWN) { err("%s: Can't get bus operation speed\n", __FUNCTION__); - /* Done with exclusive hardware access */ - mutex_unlock(&ctrl->crit_sect); return WRONG_BUS_FREQUENCY; } @@ -365,9 +354,6 @@ static int board_added(struct slot *p_slot) max_bus_speed = bus_speed; } - /* Done with exclusive hardware access */ - mutex_unlock(&ctrl->crit_sect); - if ((rc = p_slot->hpc_ops->get_prog_int(p_slot, &pi))) { err("%s: Can't get controller programming interface, set it to 1\n", __FUNCTION__); pi = 1; @@ -744,29 +730,25 @@ static void interrupt_event_handler(struct controller *ctrl) int shpchp_enable_slot (struct slot *p_slot) { u8 getstatus = 0; - int rc; + int rc, retval = -ENODEV; /* Check to see if (latch closed, card present, power off) */ mutex_lock(&p_slot->ctrl->crit_sect); rc = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus); if (rc || !getstatus) { info("%s: no adapter on slot(%x)\n", __FUNCTION__, p_slot->number); - mutex_unlock(&p_slot->ctrl->crit_sect); - return -ENODEV; + goto out; } rc = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); if (rc || getstatus) { info("%s: latch open on slot(%x)\n", __FUNCTION__, p_slot->number); - mutex_unlock(&p_slot->ctrl->crit_sect); - return -ENODEV; + goto out; } rc = p_slot->hpc_ops->get_power_status(p_slot, &getstatus); if (rc || getstatus) { info("%s: already enabled on slot(%x)\n", __FUNCTION__, p_slot->number); - mutex_unlock(&p_slot->ctrl->crit_sect); - return -ENODEV; + goto out; } - mutex_unlock(&p_slot->ctrl->crit_sect); p_slot->is_a_board = 1; @@ -781,27 +763,29 @@ int shpchp_enable_slot (struct slot *p_slot) && p_slot->ctrl->num_slots == 1) { /* handle amd pogo errata; this must be done before enable */ amd_pogo_errata_save_misc_reg(p_slot); - rc = board_added(p_slot); + retval = board_added(p_slot); /* handle amd pogo errata; this must be done after enable */ amd_pogo_errata_restore_misc_reg(p_slot); } else - rc = board_added(p_slot); + retval = board_added(p_slot); - if (rc) { + if (retval) { p_slot->hpc_ops->get_adapter_status(p_slot, &(p_slot->presence_save)); p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); } update_slot_info(p_slot); - return rc; + out: + mutex_unlock(&p_slot->ctrl->crit_sect); + return retval; } int shpchp_disable_slot (struct slot *p_slot) { u8 getstatus = 0; - int ret = 0; + int rc, retval = -ENODEV; if (!p_slot->ctrl) return -ENODEV; @@ -809,28 +793,26 @@ int shpchp_disable_slot (struct slot *p_slot) /* Check to see if (latch closed, card present, power on) */ mutex_lock(&p_slot->ctrl->crit_sect); - ret = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus); - if (ret || !getstatus) { + rc = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus); + if (rc || !getstatus) { info("%s: no adapter on slot(%x)\n", __FUNCTION__, p_slot->number); - mutex_unlock(&p_slot->ctrl->crit_sect); - return -ENODEV; + goto out; } - ret = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); - if (ret || getstatus) { + rc = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); + if (rc || getstatus) { info("%s: latch open on slot(%x)\n", __FUNCTION__, p_slot->number); - mutex_unlock(&p_slot->ctrl->crit_sect); - return -ENODEV; + goto out; } - ret = p_slot->hpc_ops->get_power_status(p_slot, &getstatus); - if (ret || !getstatus) { + rc = p_slot->hpc_ops->get_power_status(p_slot, &getstatus); + if (rc || !getstatus) { info("%s: already disabled slot(%x)\n", __FUNCTION__, p_slot->number); - mutex_unlock(&p_slot->ctrl->crit_sect); - return -ENODEV; + goto out; } - mutex_unlock(&p_slot->ctrl->crit_sect); - ret = remove_board(p_slot); + retval = remove_board(p_slot); update_slot_info(p_slot); - return ret; + out: + mutex_unlock(&p_slot->ctrl->crit_sect); + return retval; } From 287588b3537d0ce56a83f54d0e6ffcd60e54b569 Mon Sep 17 00:00:00 2001 From: Kenji Kaneshige Date: Thu, 26 Jan 2006 10:01:35 +0900 Subject: [PATCH 12/49] [PATCH] pcihp_skeleton.c cleanup This patch cleans up pcihp_skelton.c as follows. o Move slot name area into struct slot. o Replace kmalloc with kzalloc and clean up the arg of sizeof() o Fix the wrong use of get_*_status() functions. Signed-off-by: Kenji Kaneshige Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/pcihp_skeleton.c | 33 ++++++++++------------------ 1 file changed, 11 insertions(+), 22 deletions(-) diff --git a/drivers/pci/hotplug/pcihp_skeleton.c b/drivers/pci/hotplug/pcihp_skeleton.c index 3194d51c6ec9..0a46f549676a 100644 --- a/drivers/pci/hotplug/pcihp_skeleton.c +++ b/drivers/pci/hotplug/pcihp_skeleton.c @@ -37,10 +37,12 @@ #include #include "pci_hotplug.h" +#define SLOT_NAME_SIZE 10 struct slot { u8 number; struct hotplug_slot *hotplug_slot; struct list_head slot_list; + char name[SLOT_NAME_SIZE]; }; static LIST_HEAD(slot_list); @@ -233,12 +235,10 @@ static void release_slot(struct hotplug_slot *hotplug_slot) dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); kfree(slot->hotplug_slot->info); - kfree(slot->hotplug_slot->name); kfree(slot->hotplug_slot); kfree(slot); } -#define SLOT_NAME_SIZE 10 static void make_slot_name(struct slot *slot) { /* @@ -257,7 +257,6 @@ static int __init init_slots(void) struct slot *slot; struct hotplug_slot *hotplug_slot; struct hotplug_slot_info *info; - char *name; int retval = -ENOMEM; int i; @@ -266,31 +265,23 @@ static int __init init_slots(void) * with the pci_hotplug subsystem. */ for (i = 0; i < num_slots; ++i) { - slot = kmalloc(sizeof(struct slot), GFP_KERNEL); + slot = kzalloc(sizeof(*slot), GFP_KERNEL); if (!slot) goto error; - memset(slot, 0, sizeof(struct slot)); - hotplug_slot = kmalloc(sizeof(struct hotplug_slot), - GFP_KERNEL); + hotplug_slot = kzalloc(sizeof(*hotplug_slot), GFP_KERNEL); if (!hotplug_slot) goto error_slot; - memset(hotplug_slot, 0, sizeof (struct hotplug_slot)); slot->hotplug_slot = hotplug_slot; - info = kmalloc(sizeof(struct hotplug_slot_info), GFP_KERNEL); + info = kzalloc(sizeof(*info), GFP_KERNEL); if (!info) goto error_hpslot; - memset(info, 0, sizeof (struct hotplug_slot_info)); hotplug_slot->info = info; - name = kmalloc(SLOT_NAME_SIZE, GFP_KERNEL); - if (!name) - goto error_info; - hotplug_slot->name = name; - slot->number = i; + hotplug_slot->name = slot->name; hotplug_slot->private = slot; hotplug_slot->release = &release_slot; make_slot_name(slot); @@ -300,16 +291,16 @@ static int __init init_slots(void) * Initialize the slot info structure with some known * good values. */ - info->power_status = get_power_status(slot); - info->attention_status = get_attention_status(slot); - info->latch_status = get_latch_status(slot); - info->adapter_status = get_adapter_status(slot); + 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 slot %d\n", i); retval = pci_hp_register(slot->hotplug_slot); if (retval) { err("pci_hp_register failed with error %d\n", retval); - goto error_name; + goto error_info; } /* add slot to our internal list */ @@ -317,8 +308,6 @@ static int __init init_slots(void) } return 0; -error_name: - kfree(name); error_info: kfree(info); error_hpslot: From 57c95c0d1c9ec83877dfea2f62bebf31059bc93c Mon Sep 17 00:00:00 2001 From: Kenji Kaneshige Date: Thu, 26 Jan 2006 10:02:41 +0900 Subject: [PATCH 13/49] [PATCH] shpchp - replace kmalloc() with kzalloc() and cleanup arg of sizeof() This patch replaces kmalloc() and memset() pair with kzalloc() and cleans up the arg of sizeof() in SHPCHP driver. Signed-off-by: Kenji Kaneshige Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/shpchp_core.c | 15 +++++---------- drivers/pci/hotplug/shpchp_hpc.c | 4 +--- 2 files changed, 6 insertions(+), 13 deletions(-) diff --git a/drivers/pci/hotplug/shpchp_core.c b/drivers/pci/hotplug/shpchp_core.c index 0dd0642e691b..08be8c1f5dcc 100644 --- a/drivers/pci/hotplug/shpchp_core.c +++ b/drivers/pci/hotplug/shpchp_core.c @@ -117,22 +117,18 @@ static int init_slots(struct controller *ctrl) u32 sun; for (i = 0; i < ctrl->num_slots; i++) { - slot = kmalloc(sizeof(struct slot), GFP_KERNEL); + slot = kzalloc(sizeof(*slot), GFP_KERNEL); if (!slot) goto error; - memset(slot, 0, sizeof(struct slot)); - hotplug_slot = kmalloc(sizeof(struct hotplug_slot), - GFP_KERNEL); + hotplug_slot = kzalloc(sizeof(*hotplug_slot), GFP_KERNEL); if (!hotplug_slot) goto error_slot; - memset(hotplug_slot, 0, sizeof(struct hotplug_slot)); slot->hotplug_slot = hotplug_slot; - info = kmalloc(sizeof(struct hotplug_slot_info), GFP_KERNEL); + info = kzalloc(sizeof(*info), GFP_KERNEL); if (!info) goto error_hpslot; - memset(info, 0, sizeof (struct hotplug_slot_info)); hotplug_slot->info = info; name = kmalloc(SLOT_NAME_SIZE, GFP_KERNEL); @@ -383,12 +379,11 @@ static int shpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) if (!is_shpc_capable(pdev)) return -ENODEV; - ctrl = kmalloc(sizeof(struct controller), GFP_KERNEL); + ctrl = kzalloc(sizeof(*ctrl), GFP_KERNEL); if (!ctrl) { err("%s : out of memory\n", __FUNCTION__); goto err_out_none; } - memset(ctrl, 0, sizeof(struct controller)); INIT_LIST_HEAD(&ctrl->slot_list); rc = shpc_init(ctrl, pdev); @@ -400,7 +395,7 @@ static int shpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) pci_set_drvdata(pdev, ctrl); - ctrl->pci_bus = kmalloc(sizeof (*ctrl->pci_bus), GFP_KERNEL); + ctrl->pci_bus = kmalloc(sizeof(*ctrl->pci_bus), GFP_KERNEL); if (!ctrl->pci_bus) { err("out of memory\n"); rc = -ENOMEM; diff --git a/drivers/pci/hotplug/shpchp_hpc.c b/drivers/pci/hotplug/shpchp_hpc.c index c32a1b16704f..1a6b5448f81d 100644 --- a/drivers/pci/hotplug/shpchp_hpc.c +++ b/drivers/pci/hotplug/shpchp_hpc.c @@ -1390,15 +1390,13 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev) ctrl->pci_dev = pdev; /* pci_dev of the P2P bridge */ spin_lock_init(&list_lock); - php_ctlr = (struct php_ctlr_state_s *) kmalloc(sizeof(struct php_ctlr_state_s), GFP_KERNEL); + php_ctlr = kzalloc(sizeof(*php_ctlr), GFP_KERNEL); if (!php_ctlr) { /* allocate controller state data */ err("%s: HPC controller memory allocation error!\n", __FUNCTION__); goto abort; } - memset(php_ctlr, 0, sizeof(struct php_ctlr_state_s)); - php_ctlr->pci_dev = pdev; /* save pci_dev in context */ if ((pdev->vendor == PCI_VENDOR_ID_AMD) || (pdev->device == From 8abebe13f9df5b93be521eeefbf349236ddcd4eb Mon Sep 17 00:00:00 2001 From: Kenji Kaneshige Date: Thu, 26 Jan 2006 10:03:40 +0900 Subject: [PATCH 14/49] [PATCH] shpchp - removed unncessary 'magic' member from slot This patch removes unnecessary 'magic' member from struct slot of SHPCHP driver. Signed-off-by: Kenji Kaneshige Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/shpchp.h | 6 ------ drivers/pci/hotplug/shpchp_core.c | 1 - 2 files changed, 7 deletions(-) diff --git a/drivers/pci/hotplug/shpchp.h b/drivers/pci/hotplug/shpchp.h index b1e2a7705835..1e6d354fff38 100644 --- a/drivers/pci/hotplug/shpchp.h +++ b/drivers/pci/hotplug/shpchp.h @@ -53,9 +53,7 @@ extern int shpchp_debug; #define info(format, arg...) printk(KERN_INFO "%s: " format, MY_NAME , ## arg) #define warn(format, arg...) printk(KERN_WARNING "%s: " format, MY_NAME , ## arg) -#define SLOT_MAGIC 0x67267321 struct slot { - u32 magic; u8 bus; u8 device; u16 status; @@ -287,10 +285,6 @@ static inline int slot_paranoia_check (struct slot *slot, const char *function) dbg("%s - slot == NULL", function); return -1; } - if (slot->magic != SLOT_MAGIC) { - dbg("%s - bad magic number for slot", function); - return -1; - } if (!slot->hotplug_slot) { dbg("%s - slot->hotplug_slot == NULL!", function); return -1; diff --git a/drivers/pci/hotplug/shpchp_core.c b/drivers/pci/hotplug/shpchp_core.c index 08be8c1f5dcc..4161da4bf4ba 100644 --- a/drivers/pci/hotplug/shpchp_core.c +++ b/drivers/pci/hotplug/shpchp_core.c @@ -137,7 +137,6 @@ static int init_slots(struct controller *ctrl) hotplug_slot->name = name; slot->hp_slot = i; - slot->magic = SLOT_MAGIC; slot->ctrl = ctrl; slot->bus = ctrl->slot_bus; slot->device = ctrl->slot_device_offset + i; From bbe779db9f97e1c99b3c7ce1ebb26bbaecbdb2a9 Mon Sep 17 00:00:00 2001 From: Kenji Kaneshige Date: Thu, 26 Jan 2006 10:04:56 +0900 Subject: [PATCH 15/49] [PATCH] shpchp - move slot name into struct slot This patch moves slot name area into struct slot. Signed-off-by: Kenji Kaneshige Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/shpchp.h | 2 ++ drivers/pci/hotplug/shpchp_core.c | 14 +++----------- 2 files changed, 5 insertions(+), 11 deletions(-) diff --git a/drivers/pci/hotplug/shpchp.h b/drivers/pci/hotplug/shpchp.h index 1e6d354fff38..dc12b0dbb9b2 100644 --- a/drivers/pci/hotplug/shpchp.h +++ b/drivers/pci/hotplug/shpchp.h @@ -53,6 +53,7 @@ extern int shpchp_debug; #define info(format, arg...) printk(KERN_INFO "%s: " format, MY_NAME , ## arg) #define warn(format, arg...) printk(KERN_WARNING "%s: " format, MY_NAME , ## arg) +#define SLOT_NAME_SIZE 10 struct slot { u8 bus; u8 device; @@ -68,6 +69,7 @@ struct slot { struct hpc_ops *hpc_ops; struct hotplug_slot *hotplug_slot; struct list_head slot_list; + char name[SLOT_NAME_SIZE]; }; struct event_info { diff --git a/drivers/pci/hotplug/shpchp_core.c b/drivers/pci/hotplug/shpchp_core.c index 4161da4bf4ba..cb4ac43ea95c 100644 --- a/drivers/pci/hotplug/shpchp_core.c +++ b/drivers/pci/hotplug/shpchp_core.c @@ -94,12 +94,10 @@ static void release_slot(struct hotplug_slot *hotplug_slot) dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); kfree(slot->hotplug_slot->info); - kfree(slot->hotplug_slot->name); kfree(slot->hotplug_slot); kfree(slot); } -#define SLOT_NAME_SIZE 10 static void make_slot_name(struct slot *slot) { snprintf(slot->hotplug_slot->name, SLOT_NAME_SIZE, "%04d_%04d", @@ -111,7 +109,6 @@ static int init_slots(struct controller *ctrl) struct slot *slot; struct hotplug_slot *hotplug_slot; struct hotplug_slot_info *info; - char *name; int retval = -ENOMEM; int i; u32 sun; @@ -131,10 +128,7 @@ static int init_slots(struct controller *ctrl) goto error_hpslot; hotplug_slot->info = info; - name = kmalloc(SLOT_NAME_SIZE, GFP_KERNEL); - if (!name) - goto error_info; - hotplug_slot->name = name; + hotplug_slot->name = slot->name; slot->hp_slot = i; slot->ctrl = ctrl; @@ -144,7 +138,7 @@ static int init_slots(struct controller *ctrl) if (shpchprm_get_physical_slot_number(ctrl, &sun, slot->bus, slot->device)) - goto error_name; + goto error_info; slot->number = sun; @@ -165,15 +159,13 @@ static int init_slots(struct controller *ctrl) retval = pci_hp_register(slot->hotplug_slot); if (retval) { err("pci_hp_register failed with error %d\n", retval); - goto error_name; + goto error_info; } list_add(&slot->slot_list, &ctrl->slot_list); } return 0; -error_name: - kfree(name); error_info: kfree(info); error_hpslot: From e4e73041ecc4a3559c42ed9489f58531c2a8646b Mon Sep 17 00:00:00 2001 From: Kenji Kaneshige Date: Thu, 26 Jan 2006 10:05:57 +0900 Subject: [PATCH 16/49] [PATCH] shpchp - Fix incorrect return value of interrupt handler Current SHPCHP driver has a bug in its interrupt handler which cause "IRQ #: nobody cared" oops. This problem can be reproduced easily by the following operation. # cd /sys/bus/pci/slots/ # while true; do echo 1 > attention ; done & The reason is that when command complete interrupt is raised, current SHPCHP driver's interrupt handler returns IRQ_NONE regardless of if the interrupt is handled or not. This patch fixes this issue. Signed-off-by: Kenji Kaneshige Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/shpchp_hpc.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/drivers/pci/hotplug/shpchp_hpc.c b/drivers/pci/hotplug/shpchp_hpc.c index 1a6b5448f81d..943ed2b4dabe 100644 --- a/drivers/pci/hotplug/shpchp_hpc.c +++ b/drivers/pci/hotplug/shpchp_hpc.c @@ -1109,14 +1109,8 @@ static irqreturn_t shpc_isr(int IRQ, void *dev_id, struct pt_regs *regs) wake_up_interruptible(&ctrl->queue); } - if ((intr_loc = (intr_loc >> 1)) == 0) { - /* Unmask Global Interrupt Mask */ - temp_dword = readl(php_ctlr->creg + SERR_INTR_ENABLE); - temp_dword &= 0xfffffffe; - writel(temp_dword, php_ctlr->creg + SERR_INTR_ENABLE); - - return IRQ_NONE; - } + if ((intr_loc = (intr_loc >> 1)) == 0) + goto out; for (hp_slot = 0; hp_slot < ctrl->num_slots; hp_slot++) { /* To find out which slot has interrupt pending */ @@ -1146,6 +1140,7 @@ static irqreturn_t shpc_isr(int IRQ, void *dev_id, struct pt_regs *regs) dbg("%s: intr_loc2 = %x\n",__FUNCTION__, intr_loc2); } } + out: if (!shpchp_poll_mode) { /* Unmask Global Interrupt Mask */ temp_dword = readl(php_ctlr->creg + SERR_INTR_ENABLE); From 92c05fc1a32e5ccef5e0e8201f32dcdab041524c Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Thu, 23 Mar 2006 14:35:12 -0800 Subject: [PATCH 17/49] [PATCH] PCI: Give PCI config access initialization a defined ordering I moved it to a separate function which is safer. This avoids problems with the linker reordering them and the less useful PCI config space access methods taking priority over the better ones. Fixes some problems with broken MMCONFIG Cc: Dave Hansen Signed-off-by: Andi Kleen Signed-off-by: Greg Kroah-Hartman --- arch/i386/pci/Makefile | 2 +- arch/i386/pci/direct.c | 15 +++++---------- arch/i386/pci/init.c | 25 +++++++++++++++++++++++++ arch/i386/pci/mmconfig.c | 11 +++-------- arch/i386/pci/pcbios.c | 4 +--- arch/i386/pci/pci.h | 3 +++ arch/x86_64/pci/Makefile | 3 ++- 7 files changed, 40 insertions(+), 23 deletions(-) create mode 100644 arch/i386/pci/init.c diff --git a/arch/i386/pci/Makefile b/arch/i386/pci/Makefile index 5461d4d5ea1e..62ad75c57e6a 100644 --- a/arch/i386/pci/Makefile +++ b/arch/i386/pci/Makefile @@ -1,4 +1,4 @@ -obj-y := i386.o +obj-y := i386.o init.o obj-$(CONFIG_PCI_BIOS) += pcbios.o obj-$(CONFIG_PCI_MMCONFIG) += mmconfig.o direct.o diff --git a/arch/i386/pci/direct.c b/arch/i386/pci/direct.c index e3ac502bf2fb..99012b93bd12 100644 --- a/arch/i386/pci/direct.c +++ b/arch/i386/pci/direct.c @@ -245,7 +245,7 @@ static int __init pci_check_type2(void) return works; } -static int __init pci_direct_init(void) +void __init pci_direct_init(void) { struct resource *region, *region2; @@ -258,16 +258,16 @@ static int __init pci_direct_init(void) if (pci_check_type1()) { printk(KERN_INFO "PCI: Using configuration type 1\n"); raw_pci_ops = &pci_direct_conf1; - return 0; + return; } release_resource(region); type2: if ((pci_probe & PCI_PROBE_CONF2) == 0) - goto out; + return; region = request_region(0xCF8, 4, "PCI conf2"); if (!region) - goto out; + return; region2 = request_region(0xC000, 0x1000, "PCI conf2"); if (!region2) goto fail2; @@ -275,15 +275,10 @@ static int __init pci_direct_init(void) if (pci_check_type2()) { printk(KERN_INFO "PCI: Using configuration type 2\n"); raw_pci_ops = &pci_direct_conf2; - return 0; + return; } release_resource(region2); fail2: release_resource(region); - - out: - return 0; } - -arch_initcall(pci_direct_init); diff --git a/arch/i386/pci/init.c b/arch/i386/pci/init.c new file mode 100644 index 000000000000..f9156d3ac723 --- /dev/null +++ b/arch/i386/pci/init.c @@ -0,0 +1,25 @@ +#include +#include +#include +#include "pci.h" + +/* arch_initcall has too random ordering, so call the initializers + in the right sequence from here. */ +static __init int pci_access_init(void) +{ +#ifdef CONFIG_PCI_MMCONFIG + pci_mmcfg_init(); +#endif + if (raw_pci_ops) + return 0; +#ifdef CONFIG_PCI_BIOS + pci_pcbios_init(); +#endif + if (raw_pci_ops) + return 0; +#ifdef CONFIG_PCI_DIRECT + pci_direct_init(); +#endif + return 0; +} +arch_initcall(pci_access_init); diff --git a/arch/i386/pci/mmconfig.c b/arch/i386/pci/mmconfig.c index 0ee8a983708c..613789071f30 100644 --- a/arch/i386/pci/mmconfig.c +++ b/arch/i386/pci/mmconfig.c @@ -172,25 +172,20 @@ static __init void unreachable_devices(void) } } -static int __init pci_mmcfg_init(void) +void __init pci_mmcfg_init(void) { if ((pci_probe & PCI_PROBE_MMCONF) == 0) - goto out; + return; acpi_table_parse(ACPI_MCFG, acpi_parse_mcfg); if ((pci_mmcfg_config_num == 0) || (pci_mmcfg_config == NULL) || (pci_mmcfg_config[0].base_address == 0)) - goto out; + return; printk(KERN_INFO "PCI: Using MMCONFIG\n"); raw_pci_ops = &pci_mmcfg; pci_probe = (pci_probe & ~PCI_PROBE_MASK) | PCI_PROBE_MMCONF; unreachable_devices(); - - out: - return 0; } - -arch_initcall(pci_mmcfg_init); diff --git a/arch/i386/pci/pcbios.c b/arch/i386/pci/pcbios.c index b9d65f0bc2d1..1eec0868f4b3 100644 --- a/arch/i386/pci/pcbios.c +++ b/arch/i386/pci/pcbios.c @@ -476,14 +476,12 @@ int pcibios_set_irq_routing(struct pci_dev *dev, int pin, int irq) } EXPORT_SYMBOL(pcibios_set_irq_routing); -static int __init pci_pcbios_init(void) +void __init pci_pcbios_init(void) { if ((pci_probe & PCI_PROBE_BIOS) && ((raw_pci_ops = pci_find_bios()))) { pci_probe |= PCI_BIOS_SORT; pci_bios_present = 1; } - return 0; } -arch_initcall(pci_pcbios_init); diff --git a/arch/i386/pci/pci.h b/arch/i386/pci/pci.h index f550781ec310..12035e29108b 100644 --- a/arch/i386/pci/pci.h +++ b/arch/i386/pci/pci.h @@ -80,4 +80,7 @@ extern int pci_conf1_write(unsigned int seg, unsigned int bus, extern int pci_conf1_read(unsigned int seg, unsigned int bus, unsigned int devfn, int reg, int len, u32 *value); +extern void pci_direct_init(void); +extern void pci_pcbios_init(void); +extern void pci_mmcfg_init(void); diff --git a/arch/x86_64/pci/Makefile b/arch/x86_64/pci/Makefile index a8f75a2a0f6f..a3f6ad570179 100644 --- a/arch/x86_64/pci/Makefile +++ b/arch/x86_64/pci/Makefile @@ -7,7 +7,7 @@ CFLAGS += -Iarch/i386/pci obj-y := i386.o obj-$(CONFIG_PCI_DIRECT)+= direct.o -obj-y += fixup.o +obj-y += fixup.o init.o obj-$(CONFIG_ACPI) += acpi.o obj-y += legacy.o irq.o common.o # mmconfig has a 64bit special @@ -22,3 +22,4 @@ irq-y += ../../i386/pci/irq.o common-y += ../../i386/pci/common.o fixup-y += ../../i386/pci/fixup.o i386-y += ../../i386/pci/i386.o +init-y += ../../i386/pci/init.o From bbe8f9a3e76c551973ee739de10b26581d78b45f Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Tue, 14 Feb 2006 16:23:57 +0000 Subject: [PATCH 18/49] [PATCH] PCI: Avoid leaving MASTER_ABORT disabled permanently when returning from pci_scan_bridge. > On Mon, Feb 13, 2006 at 05:13:21PM -0800, David S. Miller wrote: > > > > In drivers/pci/probe.c:pci_scan_bridge(), if this is not the first > > pass (pass != 0) we don't restore the PCI_BRIDGE_CONTROL_REGISTER and > > thus leave PCI_BRIDGE_CTL_MASTER_ABORT off: > > > > int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max, int pass) > > { > > ... > > /* 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) { > > unsigned int cmax, busnr; > > /* > > * Bus already configured by firmware, process it in the first > > * pass and just note the configuration. > > */ > > if (pass) > > return max; > > ... > > } > > > > pci_write_config_word(dev, PCI_BRIDGE_CONTROL, bctl); > > ... > > > > This doesn't seem intentional. Agreed, looks like an accident. The patch [1] originally came from Kip Walker (Broadcom back then) between 2.6.0-test3 and 2.6.0-test4. As I recall it was supposed to fix an issue with with PCI aborts being signalled by the PCI bridge of the Broadcom BCM1250 family of SOCs when probing behind pci_scan_bridge. It is undeseriable to disable PCI_BRIDGE_CTL_MASTER_ABORT in pci_{read,write)_config_* and the behaviour wasn't considered a bug in need of a workaround, so this was put in probe.c. I don't have an affected system at hand, so can't really test but I propose something like the below patch. [1] http://www.linux-mips.org/git?p=linux.git;a=commit;h=599457e0cb702a31a3247ea6a5d9c6c99c4cf195 [PCI] Avoid leaving MASTER_ABORT disabled permanently when returning from pci_scan_bridge. Signed-off-by: Ralf Baechle Signed-off-by: Greg Kroah-Hartman --- drivers/pci/probe.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 63751a283817..3bc0fcd71d03 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -456,7 +456,7 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max * pass and just note the configuration. */ if (pass) - return max; + goto out; busnr = (buses >> 8) & 0xFF; /* @@ -466,12 +466,12 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max if (pci_find_bus(pci_domain_nr(bus), busnr)) { printk(KERN_INFO "PCI: Bus %04x:%02x already known\n", pci_domain_nr(bus), busnr); - return max; + goto out; } child = pci_add_new_bus(bus, dev, busnr); if (!child) - return max; + goto out; child->primary = buses & 0xFF; child->subordinate = (buses >> 16) & 0xFF; child->bridge_ctl = bctl; @@ -496,7 +496,7 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max bus ranges. */ pci_write_config_dword(dev, PCI_PRIMARY_BUS, buses & ~0xffffff); - return max; + goto out; } /* Clear errors */ @@ -505,7 +505,7 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max /* Prevent assigning a bus number that already exists. * This can happen when a bridge is hot-plugged */ if (pci_find_bus(pci_domain_nr(bus), max+1)) - return max; + goto out; child = pci_add_new_bus(bus, dev, ++max); buses = (buses & 0xff000000) | ((unsigned int)(child->primary) << 0) @@ -581,8 +581,6 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max pci_write_config_byte(dev, PCI_SUBORDINATE_BUS, max); } - pci_write_config_word(dev, PCI_BRIDGE_CONTROL, bctl); - sprintf(child->name, (is_cardbus ? "PCI CardBus #%02x" : "PCI Bus #%02x"), child->number); while (bus->parent) { @@ -601,6 +599,9 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max bus = bus->parent; } +out: + pci_write_config_word(dev, PCI_BRIDGE_CONTROL, bctl); + return max; } From 09e1218eccf58f6174fa68360a7c8dcfe457fe9b Mon Sep 17 00:00:00 2001 From: Kenji Kaneshige Date: Tue, 21 Feb 2006 15:45:38 -0800 Subject: [PATCH 19/49] [PATCH] shpchp: Remove unused pci_bus member from controller structure This patch removes unused 'pci_bus' member from controller structure. This patch have no functional change. Signed-off-by: Kenji Kaneshige Signed-off-by: Kristen Carlson Accardi Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/shpchp.h | 1 - drivers/pci/hotplug/shpchp_core.c | 13 +------------ 2 files changed, 1 insertion(+), 13 deletions(-) diff --git a/drivers/pci/hotplug/shpchp.h b/drivers/pci/hotplug/shpchp.h index dc12b0dbb9b2..ce792b3cf9de 100644 --- a/drivers/pci/hotplug/shpchp.h +++ b/drivers/pci/hotplug/shpchp.h @@ -85,7 +85,6 @@ struct controller { int num_slots; /* Number of slots on ctlr */ int slot_num_inc; /* 1 or -1 */ struct pci_dev *pci_dev; - struct pci_bus *pci_bus; struct event_info event_queue[10]; struct list_head slot_list; struct hpc_ops *hpc_ops; diff --git a/drivers/pci/hotplug/shpchp_core.c b/drivers/pci/hotplug/shpchp_core.c index cb4ac43ea95c..8b21fc206712 100644 --- a/drivers/pci/hotplug/shpchp_core.c +++ b/drivers/pci/hotplug/shpchp_core.c @@ -386,14 +386,6 @@ static int shpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) pci_set_drvdata(pdev, ctrl); - ctrl->pci_bus = kmalloc(sizeof(*ctrl->pci_bus), GFP_KERNEL); - if (!ctrl->pci_bus) { - err("out of memory\n"); - rc = -ENOMEM; - goto err_out_unmap_mmio_region; - } - - memcpy (ctrl->pci_bus, pdev->bus, sizeof (*ctrl->pci_bus)); ctrl->bus = pdev->bus->number; ctrl->slot_bus = pdev->subordinate->number; ctrl->device = PCI_SLOT(pdev->devfn); @@ -408,7 +400,7 @@ static int shpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) rc = get_ctlr_slot_config(ctrl); if (rc) { err(msg_initialization_err, rc); - goto err_out_free_ctrl_bus; + goto err_out_unmap_mmio_region; } first_device_num = ctrl->slot_device_offset; num_ctlr_slots = ctrl->num_slots; @@ -446,8 +438,6 @@ static int shpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) err_out_free_ctrl_slot: cleanup_slots(ctrl); -err_out_free_ctrl_bus: - kfree(ctrl->pci_bus); err_out_unmap_mmio_region: ctrl->hpc_ops->release_ctlr(ctrl); err_out_free_ctrl: @@ -481,7 +471,6 @@ static void __exit unload_shpchpd(void) ctrl = list_entry(tmp, struct controller, ctrl_list); shpchp_remove_ctrl_files(ctrl); cleanup_slots(ctrl); - kfree (ctrl->pci_bus); ctrl->hpc_ops->release_ctlr(ctrl); kfree(ctrl); } From 68c0b671491088d79611fa965bbf94b3bc0024a4 Mon Sep 17 00:00:00 2001 From: Kenji Kaneshige Date: Tue, 21 Feb 2006 15:45:42 -0800 Subject: [PATCH 20/49] [PATCH] shpchp: Remove unused wait_for_ctrl_irq The wait_for_ctrl_irq() function in SHPCHP driver is no longer needed. This patch removes that. This patch has no functional change. Signed-off-by: Kenji Kaneshige Signed-off-by: Kristen Carlson Accardi Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/shpchp.h | 21 --------------------- drivers/pci/hotplug/shpchp_ctrl.c | 2 +- 2 files changed, 1 insertion(+), 22 deletions(-) diff --git a/drivers/pci/hotplug/shpchp.h b/drivers/pci/hotplug/shpchp.h index ce792b3cf9de..6e1fb1bdc243 100644 --- a/drivers/pci/hotplug/shpchp.h +++ b/drivers/pci/hotplug/shpchp.h @@ -325,27 +325,6 @@ static inline struct slot *shpchp_find_slot (struct controller *ctrl, u8 device) return NULL; } -static inline int wait_for_ctrl_irq (struct controller *ctrl) -{ - DECLARE_WAITQUEUE(wait, current); - int retval = 0; - - add_wait_queue(&ctrl->queue, &wait); - - if (!shpchp_poll_mode) { - /* Sleep for up to 1 second */ - msleep_interruptible(1000); - } else { - /* Sleep for up to 2 seconds */ - msleep_interruptible(2000); - } - remove_wait_queue(&ctrl->queue, &wait); - if (signal_pending(current)) - retval = -EINTR; - - return retval; -} - static inline void amd_pogo_errata_save_misc_reg(struct slot *p_slot) { u32 pcix_misc2_temp; diff --git a/drivers/pci/hotplug/shpchp_ctrl.c b/drivers/pci/hotplug/shpchp_ctrl.c index 1a7003d4ba96..b709328a4145 100644 --- a/drivers/pci/hotplug/shpchp_ctrl.c +++ b/drivers/pci/hotplug/shpchp_ctrl.c @@ -441,7 +441,7 @@ static int board_added(struct slot *p_slot) } /* Wait for ~1 second */ - wait_for_ctrl_irq (ctrl); + msleep(1000); dbg("%s: slot status = %x\n", __FUNCTION__, p_slot->status); /* Check for a power fault */ From f7391f5325ea744f0632f7ef39a90085162743ac Mon Sep 17 00:00:00 2001 From: Kenji Kaneshige Date: Tue, 21 Feb 2006 15:45:45 -0800 Subject: [PATCH 21/49] [PATCH] shpchp: event handling rework The event handler of SHPCHP driver is unnecessarily very complex. In addition, current event handler can only a fixed number of events at the same time, and some of events would be lost if several number of events happened at the same time. This patch simplify the event handler by using 'work queue', and it also fix the above-mentioned issue. Signed-off-by: Kenji Kaneshige Signed-off-by: Kristen Carlson Accardi Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/shpchp.h | 13 +- drivers/pci/hotplug/shpchp_core.c | 49 ++--- drivers/pci/hotplug/shpchp_ctrl.c | 313 +++++++++--------------------- drivers/pci/hotplug/shpchp_hpc.c | 10 + 4 files changed, 119 insertions(+), 266 deletions(-) diff --git a/drivers/pci/hotplug/shpchp.h b/drivers/pci/hotplug/shpchp.h index 6e1fb1bdc243..87db07cfebdf 100644 --- a/drivers/pci/hotplug/shpchp.h +++ b/drivers/pci/hotplug/shpchp.h @@ -46,6 +46,7 @@ extern int shpchp_poll_mode; extern int shpchp_poll_time; extern int shpchp_debug; +extern struct workqueue_struct *shpchp_wq; /*#define dbg(format, arg...) do { if (shpchp_debug) printk(KERN_DEBUG "%s: " format, MY_NAME , ## arg); } while (0)*/ #define dbg(format, arg...) do { if (shpchp_debug) printk("%s: " format, MY_NAME , ## arg); } while (0) @@ -70,11 +71,13 @@ struct slot { struct hotplug_slot *hotplug_slot; struct list_head slot_list; char name[SLOT_NAME_SIZE]; + struct work_struct work; /* work for button event */ }; struct event_info { u32 event_type; - u8 hp_slot; + struct slot *p_slot; + struct work_struct work; }; struct controller { @@ -85,11 +88,9 @@ struct controller { int num_slots; /* Number of slots on ctlr */ int slot_num_inc; /* 1 or -1 */ struct pci_dev *pci_dev; - struct event_info event_queue[10]; struct list_head slot_list; struct hpc_ops *hpc_ops; wait_queue_head_t queue; /* sleep & wake process */ - u8 next_event; u8 bus; u8 device; u8 function; @@ -180,9 +181,6 @@ struct hotplug_params { /* sysfs functions for the hotplug controller info */ extern void shpchp_create_ctrl_files (struct controller *ctrl); -/* controller functions */ -extern int shpchp_event_start_thread(void); -extern void shpchp_event_stop_thread(void); extern int shpchp_enable_slot(struct slot *slot); extern int shpchp_disable_slot(struct slot *slot); @@ -201,7 +199,8 @@ extern void get_hp_params_from_firmware(struct pci_dev *dev, extern int shpchprm_get_physical_slot_number(struct controller *ctrl, u32 *sun, u8 busnum, u8 devnum); extern void shpchp_remove_ctrl_files(struct controller *ctrl); - +extern void cleanup_slots(struct controller *ctrl); +extern void shpchp_pushbutton_thread(void *data); /* Global variables */ extern struct list_head shpchp_ctrl_list; diff --git a/drivers/pci/hotplug/shpchp_core.c b/drivers/pci/hotplug/shpchp_core.c index 8b21fc206712..5de659d23d1a 100644 --- a/drivers/pci/hotplug/shpchp_core.c +++ b/drivers/pci/hotplug/shpchp_core.c @@ -32,6 +32,7 @@ #include #include #include +#include #include "shpchp.h" /* Global variables */ @@ -39,6 +40,7 @@ int shpchp_debug; int shpchp_poll_mode; int shpchp_poll_time; LIST_HEAD(shpchp_ctrl_list); +struct workqueue_struct *shpchp_wq; #define DRIVER_VERSION "0.4" #define DRIVER_AUTHOR "Dan Zink , Greg Kroah-Hartman , Dely Sy " @@ -57,7 +59,6 @@ MODULE_PARM_DESC(shpchp_poll_time, "Polling mechanism frequency, in seconds"); #define SHPC_MODULE_NAME "shpchp" -static int shpc_start_thread (void); static int set_attention_status (struct hotplug_slot *slot, u8 value); static int enable_slot (struct hotplug_slot *slot); static int disable_slot (struct hotplug_slot *slot); @@ -141,6 +142,7 @@ static int init_slots(struct controller *ctrl) goto error_info; slot->number = sun; + INIT_WORK(&slot->work, shpchp_pushbutton_thread, slot); /* register this slot with the hotplug pci core */ hotplug_slot->private = slot; @@ -176,7 +178,7 @@ error: return retval; } -static void cleanup_slots(struct controller *ctrl) +void cleanup_slots(struct controller *ctrl) { struct list_head *tmp; struct list_head *next; @@ -185,6 +187,8 @@ static void cleanup_slots(struct controller *ctrl) list_for_each_safe(tmp, next, &ctrl->slot_list) { slot = list_entry(tmp, struct slot, slot_list); list_del(&slot->slot_list); + cancel_delayed_work(&slot->work); + flush_workqueue(shpchp_wq); pci_hp_deregister(slot->hotplug_slot); } } @@ -400,7 +404,7 @@ static int shpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) rc = get_ctlr_slot_config(ctrl); if (rc) { err(msg_initialization_err, rc); - goto err_out_unmap_mmio_region; + goto err_out_release_ctlr; } first_device_num = ctrl->slot_device_offset; num_ctlr_slots = ctrl->num_slots; @@ -411,7 +415,7 @@ static int shpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) rc = init_slots(ctrl); if (rc) { err(msg_initialization_err, 6); - goto err_out_free_ctrl_slot; + goto err_out_release_ctlr; } /* Now hpc_functions (slot->hpc_ops->functions) are ready */ @@ -427,18 +431,13 @@ static int shpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ctrl->speed = PCI_SPEED_33MHz; } - /* Finish setting up the hot plug ctrl device */ - ctrl->next_event = 0; - list_add(&ctrl->ctrl_list, &shpchp_ctrl_list); shpchp_create_ctrl_files(ctrl); return 0; -err_out_free_ctrl_slot: - cleanup_slots(ctrl); -err_out_unmap_mmio_region: +err_out_release_ctlr: ctrl->hpc_ops->release_ctlr(ctrl); err_out_free_ctrl: kfree(ctrl); @@ -446,21 +445,6 @@ err_out_none: return -ENODEV; } -static int shpc_start_thread(void) -{ - int retval = 0; - - dbg("Initialize + Start the notification/polling mechanism \n"); - - retval = shpchp_event_start_thread(); - if (retval) { - dbg("shpchp_event_start_thread() failed\n"); - return retval; - } - - return retval; -} - static void __exit unload_shpchpd(void) { struct list_head *tmp; @@ -470,14 +454,11 @@ static void __exit unload_shpchpd(void) list_for_each_safe(tmp, next, &shpchp_ctrl_list) { ctrl = list_entry(tmp, struct controller, ctrl_list); shpchp_remove_ctrl_files(ctrl); - cleanup_slots(ctrl); ctrl->hpc_ops->release_ctlr(ctrl); kfree(ctrl); } - /* Stop the notification mechanism */ - shpchp_event_stop_thread(); - + destroy_workqueue(shpchp_wq); } static struct pci_device_id shpcd_pci_tbl[] = { @@ -501,17 +482,15 @@ static int __init shpcd_init(void) shpchp_poll_mode = 1; #endif - retval = shpc_start_thread(); - if (retval) - goto error_hpc_init; + shpchp_wq = create_singlethread_workqueue("shpchpd"); + if (!shpchp_wq) + return -ENOMEM; retval = pci_register_driver(&shpc_driver); dbg("%s: pci_register_driver = %d\n", __FUNCTION__, retval); info(DRIVER_DESC " version: " DRIVER_VERSION "\n"); - -error_hpc_init: if (retval) { - shpchp_event_stop_thread(); + destroy_workqueue(shpchp_wq); } return retval; } diff --git a/drivers/pci/hotplug/shpchp_ctrl.c b/drivers/pci/hotplug/shpchp_ctrl.c index b709328a4145..2411f3bd08da 100644 --- a/drivers/pci/hotplug/shpchp_ctrl.c +++ b/drivers/pci/hotplug/shpchp_ctrl.c @@ -32,44 +32,46 @@ #include #include #include +#include #include "../pci.h" #include "shpchp.h" -static void interrupt_event_handler(struct controller *ctrl); +static void interrupt_event_handler(void *data); -static struct semaphore event_semaphore; /* mutex for process loop (up if something to process) */ -static struct semaphore event_exit; /* guard ensure thread has exited before calling it quits */ -static int event_finished; -static unsigned long pushbutton_pending; /* = 0 */ +static int queue_interrupt_event(struct slot *p_slot, u32 event_type) +{ + struct event_info *info; + + info = kmalloc(sizeof(*info), GFP_ATOMIC); + if (!info) + return -ENOMEM; + + info->event_type = event_type; + info->p_slot = p_slot; + INIT_WORK(&info->work, interrupt_event_handler, info); + + queue_work(shpchp_wq, &info->work); + + return 0; +} u8 shpchp_handle_attention_button(u8 hp_slot, void *inst_id) { struct controller *ctrl = (struct controller *) inst_id; struct slot *p_slot; - u8 rc = 0; - u8 getstatus; - struct event_info *taskInfo; + u32 event_type; /* Attention Button Change */ dbg("shpchp: Attention button interrupt received.\n"); - /* This is the structure that tells the worker thread what to do */ - taskInfo = &(ctrl->event_queue[ctrl->next_event]); p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); - p_slot->hpc_ops->get_adapter_status(p_slot, &(p_slot->presence_save)); - p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); - - ctrl->next_event = (ctrl->next_event + 1) % 10; - taskInfo->hp_slot = hp_slot; - - rc++; /* * Button pressed - See if need to TAKE ACTION!!! */ info("Button pressed on Slot(%d)\n", ctrl->first_slot + hp_slot); - taskInfo->event_type = INT_BUTTON_PRESS; + event_type = INT_BUTTON_PRESS; if ((p_slot->state == BLINKINGON_STATE) || (p_slot->state == BLINKINGOFF_STATE)) { @@ -77,7 +79,7 @@ u8 shpchp_handle_attention_button(u8 hp_slot, void *inst_id) * attention again before the 5 sec. limit expires to cancel hot-add * or hot-remove */ - taskInfo->event_type = INT_BUTTON_CANCEL; + event_type = INT_BUTTON_CANCEL; info("Button cancel on Slot(%d)\n", ctrl->first_slot + hp_slot); } else if ((p_slot->state == POWERON_STATE) || (p_slot->state == POWEROFF_STATE)) { @@ -85,12 +87,11 @@ u8 shpchp_handle_attention_button(u8 hp_slot, void *inst_id) * means that the previous attention button action to hot-add or * hot-remove is undergoing */ - taskInfo->event_type = INT_BUTTON_IGNORE; + event_type = INT_BUTTON_IGNORE; info("Button ignore on Slot(%d)\n", ctrl->first_slot + hp_slot); } - if (rc) - up(&event_semaphore); /* signal event thread that new event is posted */ + queue_interrupt_event(p_slot, event_type); return 0; @@ -100,21 +101,12 @@ u8 shpchp_handle_switch_change(u8 hp_slot, void *inst_id) { struct controller *ctrl = (struct controller *) inst_id; struct slot *p_slot; - u8 rc = 0; u8 getstatus; - struct event_info *taskInfo; + u32 event_type; /* Switch Change */ dbg("shpchp: Switch interrupt received.\n"); - /* This is the structure that tells the worker thread - * what to do - */ - taskInfo = &(ctrl->event_queue[ctrl->next_event]); - ctrl->next_event = (ctrl->next_event + 1) % 10; - taskInfo->hp_slot = hp_slot; - - rc++; p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); p_slot->hpc_ops->get_adapter_status(p_slot, &(p_slot->presence_save)); p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); @@ -126,9 +118,9 @@ u8 shpchp_handle_switch_change(u8 hp_slot, void *inst_id) * Switch opened */ info("Latch open on Slot(%d)\n", ctrl->first_slot + hp_slot); - taskInfo->event_type = INT_SWITCH_OPEN; + event_type = INT_SWITCH_OPEN; if (p_slot->pwr_save && p_slot->presence_save) { - taskInfo->event_type = INT_POWER_FAULT; + event_type = INT_POWER_FAULT; err("Surprise Removal of card\n"); } } else { @@ -136,34 +128,23 @@ u8 shpchp_handle_switch_change(u8 hp_slot, void *inst_id) * Switch closed */ info("Latch close on Slot(%d)\n", ctrl->first_slot + hp_slot); - taskInfo->event_type = INT_SWITCH_CLOSE; + event_type = INT_SWITCH_CLOSE; } - if (rc) - up(&event_semaphore); /* signal event thread that new event is posted */ + queue_interrupt_event(p_slot, event_type); - return rc; + return 1; } u8 shpchp_handle_presence_change(u8 hp_slot, void *inst_id) { struct controller *ctrl = (struct controller *) inst_id; struct slot *p_slot; - u8 rc = 0; - /*u8 temp_byte;*/ - struct event_info *taskInfo; + u32 event_type; /* Presence Change */ dbg("shpchp: Presence/Notify input change.\n"); - /* This is the structure that tells the worker thread - * what to do - */ - taskInfo = &(ctrl->event_queue[ctrl->next_event]); - ctrl->next_event = (ctrl->next_event + 1) % 10; - taskInfo->hp_slot = hp_slot; - - rc++; p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); /* @@ -175,39 +156,29 @@ u8 shpchp_handle_presence_change(u8 hp_slot, void *inst_id) * Card Present */ info("Card present on Slot(%d)\n", ctrl->first_slot + hp_slot); - taskInfo->event_type = INT_PRESENCE_ON; + event_type = INT_PRESENCE_ON; } else { /* * Not Present */ info("Card not present on Slot(%d)\n", ctrl->first_slot + hp_slot); - taskInfo->event_type = INT_PRESENCE_OFF; + event_type = INT_PRESENCE_OFF; } - if (rc) - up(&event_semaphore); /* signal event thread that new event is posted */ + queue_interrupt_event(p_slot, event_type); - return rc; + return 1; } u8 shpchp_handle_power_fault(u8 hp_slot, void *inst_id) { struct controller *ctrl = (struct controller *) inst_id; struct slot *p_slot; - u8 rc = 0; - struct event_info *taskInfo; + u32 event_type; /* Power fault */ dbg("shpchp: Power fault interrupt received.\n"); - /* This is the structure that tells the worker thread - * what to do - */ - taskInfo = &(ctrl->event_queue[ctrl->next_event]); - ctrl->next_event = (ctrl->next_event + 1) % 10; - taskInfo->hp_slot = hp_slot; - - rc++; p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); if ( !(p_slot->hpc_ops->query_power_fault(p_slot))) { @@ -216,21 +187,21 @@ u8 shpchp_handle_power_fault(u8 hp_slot, void *inst_id) */ info("Power fault cleared on Slot(%d)\n", ctrl->first_slot + hp_slot); p_slot->status = 0x00; - taskInfo->event_type = INT_POWER_FAULT_CLEAR; + event_type = INT_POWER_FAULT_CLEAR; } else { /* * Power fault */ info("Power fault on Slot(%d)\n", ctrl->first_slot + hp_slot); - taskInfo->event_type = INT_POWER_FAULT; + event_type = INT_POWER_FAULT; /* set power fault status for this board */ p_slot->status = 0xFF; info("power fault bit %x set\n", hp_slot); } - if (rc) - up(&event_semaphore); /* signal event thread that new event is posted */ - return rc; + queue_interrupt_event(p_slot, event_type); + + return 1; } /* The following routines constitute the bulk of the @@ -521,14 +492,6 @@ static int remove_board(struct slot *p_slot) } -static void pushbutton_helper_thread (unsigned long data) -{ - pushbutton_pending = data; - - up(&event_semaphore); -} - - /** * shpchp_pushbutton_thread * @@ -536,90 +499,24 @@ static void pushbutton_helper_thread (unsigned long data) * Handles all pending events and exits. * */ -static void shpchp_pushbutton_thread (unsigned long slot) +void shpchp_pushbutton_thread(void *data) { - struct slot *p_slot = (struct slot *) slot; + struct slot *p_slot = data; u8 getstatus; - - pushbutton_pending = 0; - - if (!p_slot) { - dbg("%s: Error! slot NULL\n", __FUNCTION__); - return; - } p_slot->hpc_ops->get_power_status(p_slot, &getstatus); if (getstatus) { p_slot->state = POWEROFF_STATE; - shpchp_disable_slot(p_slot); p_slot->state = STATIC_STATE; } else { p_slot->state = POWERON_STATE; - if (shpchp_enable_slot(p_slot)) p_slot->hpc_ops->green_led_off(p_slot); - p_slot->state = STATIC_STATE; } - - return; } - -/* this is the main worker thread */ -static int event_thread(void* data) -{ - struct controller *ctrl; - lock_kernel(); - daemonize("shpchpd_event"); - unlock_kernel(); - - while (1) { - dbg("!!!!event_thread sleeping\n"); - down_interruptible (&event_semaphore); - dbg("event_thread woken finished = %d\n", event_finished); - if (event_finished || signal_pending(current)) - break; - /* Do stuff here */ - if (pushbutton_pending) - shpchp_pushbutton_thread(pushbutton_pending); - else - list_for_each_entry(ctrl, &shpchp_ctrl_list, ctrl_list) - interrupt_event_handler(ctrl); - } - dbg("event_thread signals exit\n"); - up(&event_exit); - return 0; -} - -int shpchp_event_start_thread (void) -{ - int pid; - - /* initialize our semaphores */ - init_MUTEX_LOCKED(&event_exit); - event_finished=0; - - init_MUTEX_LOCKED(&event_semaphore); - pid = kernel_thread(event_thread, NULL, 0); - - if (pid < 0) { - err ("Can't start up our event thread\n"); - return -1; - } - return 0; -} - - -void shpchp_event_stop_thread (void) -{ - event_finished = 1; - up(&event_semaphore); - down(&event_exit); -} - - static int update_slot_info (struct slot *slot) { struct hotplug_slot_info *info; @@ -639,91 +536,59 @@ static int update_slot_info (struct slot *slot) return result; } -static void interrupt_event_handler(struct controller *ctrl) +static void interrupt_event_handler(void *data) { - int loop = 0; - int change = 1; - u8 hp_slot; + struct event_info *info = data; + struct slot *p_slot = info->p_slot; u8 getstatus; - struct slot *p_slot; - while (change) { - change = 0; + switch (info->event_type) { + case INT_BUTTON_CANCEL: + dbg("%s: button cancel\n", __FUNCTION__); + cancel_delayed_work(&p_slot->work); + switch (p_slot->state) { + case BLINKINGOFF_STATE: + p_slot->hpc_ops->green_led_on(p_slot); + p_slot->hpc_ops->set_attention_status(p_slot, 0); + break; + case BLINKINGON_STATE: + p_slot->hpc_ops->green_led_off(p_slot); + p_slot->hpc_ops->set_attention_status(p_slot, 0); + break; + default: + warn("Not a valid state\n"); + return; + } + info(msg_button_cancel, p_slot->number); + p_slot->state = STATIC_STATE; + break; + case INT_BUTTON_PRESS: + dbg("%s: Button pressed\n", __FUNCTION__); + p_slot->hpc_ops->get_power_status(p_slot, &getstatus); + if (getstatus) { + p_slot->state = BLINKINGOFF_STATE; + info(msg_button_off, p_slot->number); + } else { + p_slot->state = BLINKINGON_STATE; + info(msg_button_on, p_slot->number); + } + /* blink green LED and turn off amber */ + p_slot->hpc_ops->green_led_blink(p_slot); + p_slot->hpc_ops->set_attention_status(p_slot, 0); - for (loop = 0; loop < 10; loop++) { - if (ctrl->event_queue[loop].event_type != 0) { - dbg("%s:loop %x event_type %x\n", __FUNCTION__, loop, - ctrl->event_queue[loop].event_type); - hp_slot = ctrl->event_queue[loop].hp_slot; - - p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); - - if (ctrl->event_queue[loop].event_type == INT_BUTTON_CANCEL) { - dbg("%s: button cancel\n", __FUNCTION__); - del_timer(&p_slot->task_event); - - switch (p_slot->state) { - case BLINKINGOFF_STATE: - p_slot->hpc_ops->green_led_on(p_slot); - p_slot->hpc_ops->set_attention_status(p_slot, 0); - break; - case BLINKINGON_STATE: - p_slot->hpc_ops->green_led_off(p_slot); - p_slot->hpc_ops->set_attention_status(p_slot, 0); - break; - default: - warn("Not a valid state\n"); - return; - } - info(msg_button_cancel, p_slot->number); - p_slot->state = STATIC_STATE; - } else if (ctrl->event_queue[loop].event_type == INT_BUTTON_PRESS) { - /* Button Pressed (No action on 1st press...) */ - dbg("%s: Button pressed\n", __FUNCTION__); - - p_slot->hpc_ops->get_power_status(p_slot, &getstatus); - if (getstatus) { - /* slot is on */ - dbg("%s: slot is on\n", __FUNCTION__); - p_slot->state = BLINKINGOFF_STATE; - info(msg_button_off, p_slot->number); - } else { - /* slot is off */ - dbg("%s: slot is off\n", __FUNCTION__); - p_slot->state = BLINKINGON_STATE; - info(msg_button_on, p_slot->number); - } - - /* blink green LED and turn off amber */ - p_slot->hpc_ops->green_led_blink(p_slot); - p_slot->hpc_ops->set_attention_status(p_slot, 0); - - init_timer(&p_slot->task_event); - p_slot->task_event.expires = jiffies + 5 * HZ; /* 5 second delay */ - p_slot->task_event.function = (void (*)(unsigned long)) pushbutton_helper_thread; - p_slot->task_event.data = (unsigned long) p_slot; - - dbg("%s: add_timer p_slot = %p\n", __FUNCTION__,(void *) p_slot); - add_timer(&p_slot->task_event); - } else if (ctrl->event_queue[loop].event_type == INT_POWER_FAULT) { - /***********POWER FAULT********************/ - dbg("%s: power fault\n", __FUNCTION__); - p_slot->hpc_ops->set_attention_status(p_slot, 1); - p_slot->hpc_ops->green_led_off(p_slot); - } else { - /* refresh notification */ - if (p_slot) - update_slot_info(p_slot); - } - - ctrl->event_queue[loop].event_type = 0; - - change = 1; - } - } /* End of FOR loop */ + queue_delayed_work(shpchp_wq, &p_slot->work, 5*HZ); + break; + case INT_POWER_FAULT: + dbg("%s: power fault\n", __FUNCTION__); + p_slot->hpc_ops->set_attention_status(p_slot, 1); + p_slot->hpc_ops->green_led_off(p_slot); + break; + default: + update_slot_info(p_slot); + break; } - return; + kfree(info); } diff --git a/drivers/pci/hotplug/shpchp_hpc.c b/drivers/pci/hotplug/shpchp_hpc.c index 943ed2b4dabe..b392606a905a 100644 --- a/drivers/pci/hotplug/shpchp_hpc.c +++ b/drivers/pci/hotplug/shpchp_hpc.c @@ -813,6 +813,7 @@ static void hpc_release_ctlr(struct controller *ctrl) { struct php_ctlr_state_s *php_ctlr = ctrl->hpc_ctlr_handle; struct php_ctlr_state_s *p, *p_prev; + int i; DBG_ENTER_ROUTINE @@ -821,6 +822,14 @@ static void hpc_release_ctlr(struct controller *ctrl) return ; } + /* + * Mask all slot event interrupts + */ + for (i = 0; i < ctrl->num_slots; i++) + writel(0xffff3fff, php_ctlr->creg + SLOT1 + (4 * i)); + + cleanup_slots(ctrl); + if (shpchp_poll_mode) { del_timer(&php_ctlr->int_poll_timer); } else { @@ -830,6 +839,7 @@ static void hpc_release_ctlr(struct controller *ctrl) pci_disable_msi(php_ctlr->pci_dev); } } + if (php_ctlr->pci_dev) { iounmap(php_ctlr->creg); release_mem_region(ctrl->mmio_base, ctrl->mmio_size); From a246fa4e9f0f1b5096a1cad0659d22fb10fb3732 Mon Sep 17 00:00:00 2001 From: Kenji Kaneshige Date: Tue, 21 Feb 2006 15:45:48 -0800 Subject: [PATCH 22/49] [PATCH] shpchp: Fix slot state handling Current SHPCHP driver doesn't care about the confliction between hotplug operation via sysfs and hotplug operation via attention button. So if those ware conflicted, slot could be an unexpected state. This patch changes SHPCHP driver to handle slot state properly. With this patch, slot events are handled according to the current slot state as shown at the Table below. Table. Slot States and Event Handling ========================================================================= Slot State Event and Action ========================================================================= STATIC - Go to POWERON state if user initiates (Slot enabled, insertion request via sysfs Slot disabled) - Go to POWEROFF state if user initiates removal request via sysfs - Go to BLINKINGON state if user presses attention button when the slot is disabled - Go to BLINKINGOFF state if user presses attention button when the slot is enabled --- drivers/pci/hotplug/shpchp.h | 7 +- drivers/pci/hotplug/shpchp_core.c | 8 +- drivers/pci/hotplug/shpchp_ctrl.c | 227 ++++++++++++++++++++++-------- 3 files changed, 181 insertions(+), 61 deletions(-) diff --git a/drivers/pci/hotplug/shpchp.h b/drivers/pci/hotplug/shpchp.h index 87db07cfebdf..dd449512cf68 100644 --- a/drivers/pci/hotplug/shpchp.h +++ b/drivers/pci/hotplug/shpchp.h @@ -72,6 +72,7 @@ struct slot { struct list_head slot_list; char name[SLOT_NAME_SIZE]; struct work_struct work; /* work for button event */ + struct mutex lock; }; struct event_info { @@ -181,8 +182,8 @@ struct hotplug_params { /* sysfs functions for the hotplug controller info */ extern void shpchp_create_ctrl_files (struct controller *ctrl); -extern int shpchp_enable_slot(struct slot *slot); -extern int shpchp_disable_slot(struct slot *slot); +extern int shpchp_sysfs_enable_slot(struct slot *slot); +extern int shpchp_sysfs_disable_slot(struct slot *slot); extern u8 shpchp_handle_attention_button(u8 hp_slot, void *inst_id); extern u8 shpchp_handle_switch_change(u8 hp_slot, void *inst_id); @@ -200,7 +201,7 @@ extern int shpchprm_get_physical_slot_number(struct controller *ctrl, u32 *sun, u8 busnum, u8 devnum); extern void shpchp_remove_ctrl_files(struct controller *ctrl); extern void cleanup_slots(struct controller *ctrl); -extern void shpchp_pushbutton_thread(void *data); +extern void queue_pushbutton_work(void *data); /* Global variables */ extern struct list_head shpchp_ctrl_list; diff --git a/drivers/pci/hotplug/shpchp_core.c b/drivers/pci/hotplug/shpchp_core.c index 5de659d23d1a..fa60ae47d91d 100644 --- a/drivers/pci/hotplug/shpchp_core.c +++ b/drivers/pci/hotplug/shpchp_core.c @@ -136,13 +136,14 @@ static int init_slots(struct controller *ctrl) slot->bus = ctrl->slot_bus; slot->device = ctrl->slot_device_offset + i; slot->hpc_ops = ctrl->hpc_ops; + mutex_init(&slot->lock); if (shpchprm_get_physical_slot_number(ctrl, &sun, slot->bus, slot->device)) goto error_info; slot->number = sun; - INIT_WORK(&slot->work, shpchp_pushbutton_thread, slot); + INIT_WORK(&slot->work, queue_pushbutton_work, slot); /* register this slot with the hotplug pci core */ hotplug_slot->private = slot; @@ -188,6 +189,7 @@ void cleanup_slots(struct controller *ctrl) slot = list_entry(tmp, struct slot, slot_list); list_del(&slot->slot_list); cancel_delayed_work(&slot->work); + flush_scheduled_work(); flush_workqueue(shpchp_wq); pci_hp_deregister(slot->hotplug_slot); } @@ -244,7 +246,7 @@ static int enable_slot (struct hotplug_slot *hotplug_slot) dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); - return shpchp_enable_slot(slot); + return shpchp_sysfs_enable_slot(slot); } static int disable_slot (struct hotplug_slot *hotplug_slot) @@ -253,7 +255,7 @@ static int disable_slot (struct hotplug_slot *hotplug_slot) dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); - return shpchp_disable_slot(slot); + return shpchp_sysfs_disable_slot(slot); } static int get_power_status (struct hotplug_slot *hotplug_slot, u8 *value) diff --git a/drivers/pci/hotplug/shpchp_ctrl.c b/drivers/pci/hotplug/shpchp_ctrl.c index 2411f3bd08da..10f3257b18a7 100644 --- a/drivers/pci/hotplug/shpchp_ctrl.c +++ b/drivers/pci/hotplug/shpchp_ctrl.c @@ -37,6 +37,8 @@ #include "shpchp.h" static void interrupt_event_handler(void *data); +static int shpchp_enable_slot(struct slot *p_slot); +static int shpchp_disable_slot(struct slot *p_slot); static int queue_interrupt_event(struct slot *p_slot, u32 event_type) { @@ -50,7 +52,7 @@ static int queue_interrupt_event(struct slot *p_slot, u32 event_type) info->p_slot = p_slot; INIT_WORK(&info->work, interrupt_event_handler, info); - queue_work(shpchp_wq, &info->work); + schedule_work(&info->work); return 0; } @@ -73,24 +75,6 @@ u8 shpchp_handle_attention_button(u8 hp_slot, void *inst_id) info("Button pressed on Slot(%d)\n", ctrl->first_slot + hp_slot); event_type = INT_BUTTON_PRESS; - if ((p_slot->state == BLINKINGON_STATE) - || (p_slot->state == BLINKINGOFF_STATE)) { - /* Cancel if we are still blinking; this means that we press the - * attention again before the 5 sec. limit expires to cancel hot-add - * or hot-remove - */ - event_type = INT_BUTTON_CANCEL; - info("Button cancel on Slot(%d)\n", ctrl->first_slot + hp_slot); - } else if ((p_slot->state == POWERON_STATE) - || (p_slot->state == POWEROFF_STATE)) { - /* Ignore if the slot is on power-on or power-off state; this - * means that the previous attention button action to hot-add or - * hot-remove is undergoing - */ - event_type = INT_BUTTON_IGNORE; - info("Button ignore on Slot(%d)\n", ctrl->first_slot + hp_slot); - } - queue_interrupt_event(p_slot, event_type); return 0; @@ -492,6 +476,11 @@ static int remove_board(struct slot *p_slot) } +struct pushbutton_work_info { + struct slot *p_slot; + struct work_struct work; +}; + /** * shpchp_pushbutton_thread * @@ -499,22 +488,61 @@ static int remove_board(struct slot *p_slot) * Handles all pending events and exits. * */ -void shpchp_pushbutton_thread(void *data) +static void shpchp_pushbutton_thread(void *data) { - struct slot *p_slot = data; - u8 getstatus; + struct pushbutton_work_info *info = data; + struct slot *p_slot = info->p_slot; - p_slot->hpc_ops->get_power_status(p_slot, &getstatus); - if (getstatus) { - p_slot->state = POWEROFF_STATE; + mutex_lock(&p_slot->lock); + switch (p_slot->state) { + case POWEROFF_STATE: + mutex_unlock(&p_slot->lock); shpchp_disable_slot(p_slot); + mutex_lock(&p_slot->lock); p_slot->state = STATIC_STATE; - } else { - p_slot->state = POWERON_STATE; + break; + case POWERON_STATE: + mutex_unlock(&p_slot->lock); if (shpchp_enable_slot(p_slot)) p_slot->hpc_ops->green_led_off(p_slot); + mutex_lock(&p_slot->lock); p_slot->state = STATIC_STATE; + break; + default: + break; } + mutex_unlock(&p_slot->lock); + + kfree(info); +} + +void queue_pushbutton_work(void *data) +{ + struct slot *p_slot = data; + struct pushbutton_work_info *info; + + info = kmalloc(sizeof(*info), GFP_KERNEL); + if (!info) { + err("%s: Cannot allocate memory\n", __FUNCTION__); + return; + } + info->p_slot = p_slot; + INIT_WORK(&info->work, shpchp_pushbutton_thread, info); + + mutex_lock(&p_slot->lock); + switch (p_slot->state) { + case BLINKINGOFF_STATE: + p_slot->state = POWEROFF_STATE; + break; + case BLINKINGON_STATE: + p_slot->state = POWERON_STATE; + break; + default: + goto out; + } + queue_work(shpchp_wq, &info->work); + out: + mutex_unlock(&p_slot->lock); } static int update_slot_info (struct slot *slot) @@ -536,34 +564,15 @@ static int update_slot_info (struct slot *slot) return result; } -static void interrupt_event_handler(void *data) +/* + * Note: This function must be called with slot->lock held + */ +static void handle_button_press_event(struct slot *p_slot) { - struct event_info *info = data; - struct slot *p_slot = info->p_slot; u8 getstatus; - switch (info->event_type) { - case INT_BUTTON_CANCEL: - dbg("%s: button cancel\n", __FUNCTION__); - cancel_delayed_work(&p_slot->work); - switch (p_slot->state) { - case BLINKINGOFF_STATE: - p_slot->hpc_ops->green_led_on(p_slot); - p_slot->hpc_ops->set_attention_status(p_slot, 0); - break; - case BLINKINGON_STATE: - p_slot->hpc_ops->green_led_off(p_slot); - p_slot->hpc_ops->set_attention_status(p_slot, 0); - break; - default: - warn("Not a valid state\n"); - return; - } - info(msg_button_cancel, p_slot->number); - p_slot->state = STATIC_STATE; - break; - case INT_BUTTON_PRESS: - dbg("%s: Button pressed\n", __FUNCTION__); + switch (p_slot->state) { + case STATIC_STATE: p_slot->hpc_ops->get_power_status(p_slot, &getstatus); if (getstatus) { p_slot->state = BLINKINGOFF_STATE; @@ -576,7 +585,51 @@ static void interrupt_event_handler(void *data) p_slot->hpc_ops->green_led_blink(p_slot); p_slot->hpc_ops->set_attention_status(p_slot, 0); - queue_delayed_work(shpchp_wq, &p_slot->work, 5*HZ); + schedule_delayed_work(&p_slot->work, 5*HZ); + break; + case BLINKINGOFF_STATE: + case BLINKINGON_STATE: + /* + * Cancel if we are still blinking; this means that we + * 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); + dbg("%s: button cancel\n", __FUNCTION__); + cancel_delayed_work(&p_slot->work); + if (p_slot->state == BLINKINGOFF_STATE) + p_slot->hpc_ops->green_led_on(p_slot); + else + p_slot->hpc_ops->green_led_off(p_slot); + p_slot->hpc_ops->set_attention_status(p_slot, 0); + info(msg_button_cancel, p_slot->number); + p_slot->state = STATIC_STATE; + break; + case POWEROFF_STATE: + case POWERON_STATE: + /* + * Ignore if the slot is on power-on or power-off state; + * 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); + update_slot_info(p_slot); + break; + default: + warn("Not a valid state\n"); + break; + } +} + +static void interrupt_event_handler(void *data) +{ + struct event_info *info = data; + struct slot *p_slot = info->p_slot; + + mutex_lock(&p_slot->lock); + switch (info->event_type) { + case INT_BUTTON_PRESS: + handle_button_press_event(p_slot); break; case INT_POWER_FAULT: dbg("%s: power fault\n", __FUNCTION__); @@ -587,12 +640,13 @@ static void interrupt_event_handler(void *data) update_slot_info(p_slot); break; } + mutex_unlock(&p_slot->lock); kfree(info); } -int shpchp_enable_slot (struct slot *p_slot) +static int shpchp_enable_slot (struct slot *p_slot) { u8 getstatus = 0; int rc, retval = -ENODEV; @@ -647,7 +701,7 @@ int shpchp_enable_slot (struct slot *p_slot) } -int shpchp_disable_slot (struct slot *p_slot) +static int shpchp_disable_slot (struct slot *p_slot) { u8 getstatus = 0; int rc, retval = -ENODEV; @@ -681,3 +735,66 @@ int shpchp_disable_slot (struct slot *p_slot) return retval; } +int shpchp_sysfs_enable_slot(struct slot *p_slot) +{ + int retval = -ENODEV; + + mutex_lock(&p_slot->lock); + switch (p_slot->state) { + case BLINKINGON_STATE: + cancel_delayed_work(&p_slot->work); + case STATIC_STATE: + p_slot->state = POWERON_STATE; + mutex_unlock(&p_slot->lock); + retval = shpchp_enable_slot(p_slot); + mutex_lock(&p_slot->lock); + p_slot->state = STATIC_STATE; + break; + case POWERON_STATE: + info("Slot %s is already in powering on state\n", + p_slot->name); + break; + case BLINKINGOFF_STATE: + case POWEROFF_STATE: + info("Already enabled on slot %s\n", p_slot->name); + break; + default: + err("Not a valid state on slot %s\n", p_slot->name); + break; + } + mutex_unlock(&p_slot->lock); + + return retval; +} + +int shpchp_sysfs_disable_slot(struct slot *p_slot) +{ + int retval = -ENODEV; + + mutex_lock(&p_slot->lock); + switch (p_slot->state) { + case BLINKINGOFF_STATE: + cancel_delayed_work(&p_slot->work); + case STATIC_STATE: + p_slot->state = POWEROFF_STATE; + mutex_unlock(&p_slot->lock); + retval = shpchp_disable_slot(p_slot); + mutex_lock(&p_slot->lock); + p_slot->state = STATIC_STATE; + break; + case POWEROFF_STATE: + info("Slot %s is already in powering off state\n", + p_slot->name); + break; + case BLINKINGON_STATE: + case POWERON_STATE: + info("Already disabled on slot %s\n", p_slot->name); + break; + default: + err("Not a valid state on slot %s\n", p_slot->name); + break; + } + mutex_unlock(&p_slot->lock); + + return retval; +} From e6b82b13c4066ca091a4919620d6403c8a269bc3 Mon Sep 17 00:00:00 2001 From: Kenji Kaneshige Date: Tue, 21 Feb 2006 15:45:50 -0800 Subject: [PATCH 23/49] [PATCH] shpchp: adapt to pci driver model This patch adapts SHPCHP driver to the PCI device driver model. Signed-off-by: Kenji Kaneshige Signed-off-by: Kristen Carlson Accardi Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/shpchp.h | 4 ---- drivers/pci/hotplug/shpchp_core.c | 26 +++++++------------------- 2 files changed, 7 insertions(+), 23 deletions(-) diff --git a/drivers/pci/hotplug/shpchp.h b/drivers/pci/hotplug/shpchp.h index dd449512cf68..f10f1ba877af 100644 --- a/drivers/pci/hotplug/shpchp.h +++ b/drivers/pci/hotplug/shpchp.h @@ -82,7 +82,6 @@ struct event_info { }; struct controller { - struct list_head ctrl_list; struct mutex crit_sect; /* critical section mutex */ struct mutex cmd_lock; /* command lock */ struct php_ctlr_state_s *hpc_ctlr_handle; /* HPC controller handle */ @@ -203,9 +202,6 @@ extern void shpchp_remove_ctrl_files(struct controller *ctrl); extern void cleanup_slots(struct controller *ctrl); extern void queue_pushbutton_work(void *data); -/* Global variables */ -extern struct list_head shpchp_ctrl_list; - struct ctrl_reg { volatile u32 base_offset; volatile u32 slot_avail1; diff --git a/drivers/pci/hotplug/shpchp_core.c b/drivers/pci/hotplug/shpchp_core.c index fa60ae47d91d..0e83c5fbc9df 100644 --- a/drivers/pci/hotplug/shpchp_core.c +++ b/drivers/pci/hotplug/shpchp_core.c @@ -39,7 +39,6 @@ int shpchp_debug; int shpchp_poll_mode; int shpchp_poll_time; -LIST_HEAD(shpchp_ctrl_list); struct workqueue_struct *shpchp_wq; #define DRIVER_VERSION "0.4" @@ -433,8 +432,6 @@ static int shpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ctrl->speed = PCI_SPEED_33MHz; } - list_add(&ctrl->ctrl_list, &shpchp_ctrl_list); - shpchp_create_ctrl_files(ctrl); return 0; @@ -447,20 +444,13 @@ err_out_none: return -ENODEV; } -static void __exit unload_shpchpd(void) +static void shpc_remove(struct pci_dev *dev) { - struct list_head *tmp; - struct list_head *next; - struct controller *ctrl; + struct controller *ctrl = pci_get_drvdata(dev); - list_for_each_safe(tmp, next, &shpchp_ctrl_list) { - ctrl = list_entry(tmp, struct controller, ctrl_list); - shpchp_remove_ctrl_files(ctrl); - ctrl->hpc_ops->release_ctlr(ctrl); - kfree(ctrl); - } - - destroy_workqueue(shpchp_wq); + shpchp_remove_ctrl_files(ctrl); + ctrl->hpc_ops->release_ctlr(ctrl); + kfree(ctrl); } static struct pci_device_id shpcd_pci_tbl[] = { @@ -473,7 +463,7 @@ static struct pci_driver shpc_driver = { .name = SHPC_MODULE_NAME, .id_table = shpcd_pci_tbl, .probe = shpc_probe, - /* remove: shpc_remove_one, */ + .remove = shpc_remove, }; static int __init shpcd_init(void) @@ -500,10 +490,8 @@ static int __init shpcd_init(void) static void __exit shpcd_cleanup(void) { dbg("unload_shpchpd()\n"); - unload_shpchpd(); - pci_unregister_driver(&shpc_driver); - + destroy_workqueue(shpchp_wq); info(DRIVER_DESC " version: " DRIVER_VERSION " unloaded\n"); } From 50defa1ccaffc197a133d92acb48d696d5ea3539 Mon Sep 17 00:00:00 2001 From: Brian Gerst Date: Sun, 19 Feb 2006 16:05:52 -0500 Subject: [PATCH 24/49] [PATCH] PCI: Add pci_device_shutdown to pci_bus_type The extra compatability code is not necessary. Any code still using the old shutdown method will trigger the warning in driver_register() instead. Signed-off-by: Brian Gerst Signed-off-by: Greg Kroah-Hartman --- drivers/pci/pci-driver.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c index 0aa14c92b570..eb5b50c8770c 100644 --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c @@ -380,14 +380,6 @@ int __pci_register_driver(struct pci_driver *drv, struct module *owner) /* initialize common driver fields */ drv->driver.name = drv->name; drv->driver.bus = &pci_bus_type; - /* FIXME, once all of the existing PCI drivers have been fixed to set - * the pci shutdown function, this test can go away. */ - if (!drv->driver.shutdown) - drv->driver.shutdown = pci_device_shutdown; - else - printk(KERN_WARNING "Warning: PCI driver %s has a struct " - "device_driver shutdown method, please update!\n", - drv->name); drv->driver.owner = owner; drv->driver.kobj.ktype = &pci_driver_kobj_type; @@ -514,6 +506,7 @@ struct bus_type pci_bus_type = { .probe = pci_device_probe, .remove = pci_device_remove, .suspend = pci_device_suspend, + .shutdown = pci_device_shutdown, .resume = pci_device_resume, .dev_attrs = pci_dev_attrs, }; From 3c0a654e390d00fef9d8faed758f5e1e8078adb5 Mon Sep 17 00:00:00 2001 From: "tomek@koprowski.org" Date: Sun, 19 Feb 2006 18:03:24 +0100 Subject: [PATCH 25/49] [PATCH] PCI: SMBus unhide on HP Compaq nx6110 I attach a trivial patch for 2.6.15.4 that unhides SMBus controller on an HP Compaq nx6110 notebook. Signed-off-by: Tomasz Koprowski Signed-off-by: Greg Kroah-Hartman --- drivers/pci/quirks.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 7ec9fc9a9a42..af4bc8e2cf83 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -934,6 +934,12 @@ static void __init asus_hides_smbus_hostbridge(struct pci_dev *dev) case 0x12bd: /* HP D530 */ asus_hides_smbus = 1; } + if (dev->device == PCI_DEVICE_ID_INTEL_82915GM_HB) { + switch (dev->subsystem_device) { + case 0x099c: /* HP Compaq nx6110 */ + asus_hides_smbus = 1; + } + } } else if (unlikely(dev->subsystem_vendor == PCI_VENDOR_ID_TOSHIBA)) { if (dev->device == PCI_DEVICE_ID_INTEL_82855GM_HB) switch(dev->subsystem_device) { From e5548e960f38557825e50806b52cb24c9e730aa2 Mon Sep 17 00:00:00 2001 From: Bauke Jan Douma Date: Tue, 28 Feb 2006 21:44:36 +0100 Subject: [PATCH 26/49] [PATCH] PCI: quirk for asus a8v and a8v delux motherboards On ASUS A8V and A8V Deluxe boards, the onboard AC97 audio controller and MC97 modem controller are deactivated when a second PCI soundcard is present. This patch enables them. Signed-off-by: Bauke Jan Douma Signed-off-by: Greg Kroah-Hartman --- drivers/pci/quirks.c | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index af4bc8e2cf83..d71c31df7fdf 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -1074,6 +1074,37 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_651, quirk_sis_96x_ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_735, quirk_sis_96x_compatible ); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_503, quirk_sis_503 ); +/* + * On ASUS A8V and A8V Deluxe boards, the onboard AC97 audio controller + * and MC97 modem controller are disabled when a second PCI soundcard is + * present. This patch, tweaking the VT8237 ISA bridge, enables them. + * -- bjd + */ +static void __init asus_hides_ac97_lpc(struct pci_dev *dev) +{ + u8 val; + int asus_hides_ac97 = 0; + + if (likely(dev->subsystem_vendor == PCI_VENDOR_ID_ASUSTEK)) { + if (dev->device == PCI_DEVICE_ID_VIA_8237) + asus_hides_ac97 = 1; + } + + if (!asus_hides_ac97) + return; + + pci_read_config_byte(dev, 0x50, &val); + if (val & 0xc0) { + pci_write_config_byte(dev, 0x50, val & (~0xc0)); + pci_read_config_byte(dev, 0x50, &val); + if (val & 0xc0) + printk(KERN_INFO "PCI: onboard AC97/MC97 devices continue to play 'hide and seek'! 0x%x\n", val); + else + printk(KERN_INFO "PCI: enabled onboard AC97/MC97 devices\n"); + } +} +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237, asus_hides_ac97_lpc ); + DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_961, quirk_sis_96x_smbus ); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_962, quirk_sis_96x_smbus ); From 6e325a62a0a228cd0222783802b53cce04551776 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Tue, 14 Feb 2006 18:52:22 +0200 Subject: [PATCH 27/49] [PATCH] PCI: make MSI quirk inheritable from the pci bus It turns out AMD 8131 quirk only affects MSI for devices behind the 8131 bridge. Handle this by adding a flags field in pci_bus, inherited from parent to child. Signed-off-by: Michael S. Tsirkin Signed-off-by: Greg Kroah-Hartman --- drivers/pci/msi.c | 3 +++ drivers/pci/probe.c | 1 + drivers/pci/quirks.c | 7 +++++-- include/linux/pci.h | 7 ++++++- 4 files changed, 15 insertions(+), 3 deletions(-) diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index d5a67c1bcb98..4de1c17ee573 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c @@ -703,6 +703,9 @@ int pci_enable_msi(struct pci_dev* dev) if (dev->no_msi) return status; + if (dev->bus->bus_flags & PCI_BUS_FLAGS_NO_MSI) + return -EINVAL; + temp = dev->irq; status = msi_init(); diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 3bc0fcd71d03..542e7dfb371b 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -347,6 +347,7 @@ pci_alloc_child_bus(struct pci_bus *parent, struct pci_dev *bridge, int busnr) child->parent = parent; child->ops = parent->ops; child->sysdata = parent->sysdata; + child->bus_flags = parent->bus_flags; child->bridge = get_device(&bridge->dev); child->class_dev.class = &pcibus_class; diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index d71c31df7fdf..4970f47be72c 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -575,8 +575,11 @@ static void __init quirk_amd_8131_ioapic(struct pci_dev *dev) { unsigned char revid, tmp; - pci_msi_quirk = 1; - printk(KERN_WARNING "PCI: MSI quirk detected. pci_msi_quirk set.\n"); + if (dev->subordinate) { + printk(KERN_WARNING "PCI: MSI quirk detected. " + "PCI_BUS_FLAGS_NO_MSI set for subordinate bus.\n"); + dev->subordinate->bus_flags |= PCI_BUS_FLAGS_NO_MSI; + } if (nr_ioapics == 0) return; diff --git a/include/linux/pci.h b/include/linux/pci.h index 2039da1f3672..d4d533fa5d30 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -95,6 +95,11 @@ enum pci_channel_state { pci_channel_io_perm_failure = (__force pci_channel_state_t) 3, }; +typedef unsigned short __bitwise pci_bus_flags_t; +enum pci_bus_flags { + PCI_BUS_FLAGS_NO_MSI = (pci_bus_flags_t) 1, +}; + /* * The pci_dev structure is used to describe PCI devices. */ @@ -203,7 +208,7 @@ struct pci_bus { char name[48]; unsigned short bridge_ctl; /* manage NO_ISA/FBB/et al behaviors */ - unsigned short pad2; + pci_bus_flags_t bus_flags; /* Inherited by child busses */ struct device *bridge; struct class_device class_dev; struct bin_attribute *legacy_io; /* legacy I/O for this bus */ From 75cde0e25787c1af341a128b350c36df24e5397d Mon Sep 17 00:00:00 2001 From: Shaohua Li Date: Wed, 8 Feb 2006 17:11:40 +0800 Subject: [PATCH 28/49] [PATCH] PCI: remove msi save/restore code in specific driver Remove pcie port driver's msi save/restore code. Signed-off-by: Shaohua Li Signed-off-by: Greg Kroah-Hartman --- drivers/pci/pcie/portdrv.h | 1 - drivers/pci/pcie/portdrv_pci.c | 66 +++------------------------------- 2 files changed, 4 insertions(+), 63 deletions(-) diff --git a/drivers/pci/pcie/portdrv.h b/drivers/pci/pcie/portdrv.h index a63bd8f72601..1d317d22ee89 100644 --- a/drivers/pci/pcie/portdrv.h +++ b/drivers/pci/pcie/portdrv.h @@ -29,7 +29,6 @@ struct pcie_port_device_ext { int interrupt_mode; /* [0:INTx | 1:MSI | 2:MSI-X] */ - unsigned int saved_msi_config_space[5]; }; extern struct bus_type pcie_port_bus_type; diff --git a/drivers/pci/pcie/portdrv_pci.c b/drivers/pci/pcie/portdrv_pci.c index 02260141dc81..50bfc1b2f3bf 100644 --- a/drivers/pci/pcie/portdrv_pci.c +++ b/drivers/pci/pcie/portdrv_pci.c @@ -30,75 +30,16 @@ MODULE_LICENSE("GPL"); /* global data */ static const char device_name[] = "pcieport-driver"; -static void pci_save_msi_state(struct pci_dev *dev) +static int pcie_portdrv_save_config(struct pci_dev *dev) { - struct pcie_port_device_ext *p_ext = pci_get_drvdata(dev); - int i = 0, pos; - u16 control; - - if ((pos = pci_find_capability(dev, PCI_CAP_ID_MSI)) <= 0) - return; - - pci_read_config_dword(dev, pos, &p_ext->saved_msi_config_space[i++]); - control = p_ext->saved_msi_config_space[0] >> 16; - pci_read_config_dword(dev, pos + PCI_MSI_ADDRESS_LO, - &p_ext->saved_msi_config_space[i++]); - if (control & PCI_MSI_FLAGS_64BIT) { - pci_read_config_dword(dev, pos + PCI_MSI_ADDRESS_HI, - &p_ext->saved_msi_config_space[i++]); - pci_read_config_dword(dev, pos + PCI_MSI_DATA_64, - &p_ext->saved_msi_config_space[i++]); - } else - pci_read_config_dword(dev, pos + PCI_MSI_DATA_32, - &p_ext->saved_msi_config_space[i++]); - if (control & PCI_MSI_FLAGS_MASKBIT) - pci_read_config_dword(dev, pos + PCI_MSI_MASK_BIT, - &p_ext->saved_msi_config_space[i++]); -} - -static void pci_restore_msi_state(struct pci_dev *dev) -{ - struct pcie_port_device_ext *p_ext = pci_get_drvdata(dev); - int i = 0, pos; - u16 control; - - if ((pos = pci_find_capability(dev, PCI_CAP_ID_MSI)) <= 0) - return; - - control = p_ext->saved_msi_config_space[i++] >> 16; - pci_write_config_word(dev, pos + PCI_MSI_FLAGS, control); - pci_write_config_dword(dev, pos + PCI_MSI_ADDRESS_LO, - p_ext->saved_msi_config_space[i++]); - if (control & PCI_MSI_FLAGS_64BIT) { - pci_write_config_dword(dev, pos + PCI_MSI_ADDRESS_HI, - p_ext->saved_msi_config_space[i++]); - pci_write_config_dword(dev, pos + PCI_MSI_DATA_64, - p_ext->saved_msi_config_space[i++]); - } else - pci_write_config_dword(dev, pos + PCI_MSI_DATA_32, - p_ext->saved_msi_config_space[i++]); - if (control & PCI_MSI_FLAGS_MASKBIT) - pci_write_config_dword(dev, pos + PCI_MSI_MASK_BIT, - p_ext->saved_msi_config_space[i++]); -} - -static void pcie_portdrv_save_config(struct pci_dev *dev) -{ - struct pcie_port_device_ext *p_ext = pci_get_drvdata(dev); - - pci_save_state(dev); - if (p_ext->interrupt_mode == PCIE_PORT_MSI_MODE) - pci_save_msi_state(dev); + return pci_save_state(dev); } static int pcie_portdrv_restore_config(struct pci_dev *dev) { - struct pcie_port_device_ext *p_ext = pci_get_drvdata(dev); int retval; pci_restore_state(dev); - if (p_ext->interrupt_mode == PCIE_PORT_MSI_MODE) - pci_restore_msi_state(dev); retval = pci_enable_device(dev); if (retval) return retval; @@ -149,7 +90,8 @@ static int pcie_portdrv_suspend (struct pci_dev *dev, pm_message_t state) { int ret = pcie_port_device_suspend(dev, state); - pcie_portdrv_save_config(dev); + if (!ret) + ret = pcie_portdrv_save_config(dev); return ret; } From b408cbc704352eccee301e1103b23203ba1c3a0e Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Wed, 22 Feb 2006 15:50:30 -0800 Subject: [PATCH 29/49] [PATCH] PCI: resource address mismatch On Tue, 21 Feb 2006, Ivan Kokshaysky wrote: > There are two bogus entries in the BIOS memory map table which are > conflicting with a prefetchable memory range of the AGP bridge: > > BIOS-e820: 00000000fec00000 - 00000000fec01000 (reserved) > BIOS-e820: 00000000fee00000 - 00000000fee01000 (reserved) > > 0000:00:02.0 PCI bridge: Silicon Integrated Systems [SiS] Virtual PCI-to-PCI bridge (AGP) (prog-if 00 [Normal decode]) > Flags: bus master, fast devsel, latency 0 > Bus: primary=00, secondary=01, subordinate=01, sec-latency=0 > I/O behind bridge: 0000c000-0000cfff > Memory behind bridge: e7e00000-e7efffff > Prefetchable memory behind bridge: fec00000-ffcfffff > ^^^^^^^^^^^^^^^^^ Yes. However, it's pretty clear that the e820 entries are there for a reason. Probably they are a hack by the BIOS maintainers to keep Windows from stomping/moving that region, exactly because they want to keep the bridge where it is (or, it's actually for the BIOS itself - the BIOS tables are a horrid mess, and BIOS engineers are pretty hacky people: they'll add random entries to make their own broken algorithms do the "right thing"). > Starting from 2.6.13, kernel tries to resolve that sort of conflicts, > so that prefetch window of the bridge and the framebuffer memory behind > it get moved to 0x10000000. I think we could (and probably should) solve this another way: consider the ACPI "reserved regions" from the e820 map exactly the same way that we do other ACPI hints - they should restrict _new_ allocations, but not impact stuff we figure out on our own. Basically, right now we assign _unassigned_ resources at "fs_initcall" time. If we were to add in the e820 "reserved region" stuff before that (but after we've done PCI discovery), we'd probably do the right thing. Right now we do the e820 reserved regions very early indeed: we call "register_memory()" from setup_arch(). We could move at least part of it (the part that registers the resources) down a bit. Here's a test-patch. I'm not saying we should absolutely do this, but it might be interesting to try... Cc: "Antonino A. Daplas" Cc: Ivan Kokshaysky Cc: Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- arch/i386/kernel/efi.c | 2 +- arch/i386/kernel/setup.c | 22 +++++++++++++++++----- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/arch/i386/kernel/efi.c b/arch/i386/kernel/efi.c index aeabb4196861..7ec6cfa01fb3 100644 --- a/arch/i386/kernel/efi.c +++ b/arch/i386/kernel/efi.c @@ -543,7 +543,7 @@ efi_initialize_iomem_resources(struct resource *code_resource, if ((md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT)) > 0x100000000ULL) continue; - res = alloc_bootmem_low(sizeof(struct resource)); + res = kzalloc(sizeof(struct resource), GFP_ATOMIC); switch (md->type) { case EFI_RESERVED_TYPE: res->name = "Reserved Memory"; diff --git a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c index 2d8782960f41..d313a11acafa 100644 --- a/arch/i386/kernel/setup.c +++ b/arch/i386/kernel/setup.c @@ -1288,7 +1288,7 @@ legacy_init_iomem_resources(struct resource *code_resource, struct resource *dat struct resource *res; if (e820.map[i].addr + e820.map[i].size > 0x100000000ULL) continue; - res = alloc_bootmem_low(sizeof(struct resource)); + res = kzalloc(sizeof(struct resource), GFP_ATOMIC); switch (e820.map[i].type) { case E820_RAM: res->name = "System RAM"; break; case E820_ACPI: res->name = "ACPI Tables"; break; @@ -1316,13 +1316,15 @@ legacy_init_iomem_resources(struct resource *code_resource, struct resource *dat /* * Request address space for all standard resources + * + * This is called just before pcibios_assign_resources(), which is also + * an fs_initcall, but is linked in later (in arch/i386/pci/i386.c). */ -static void __init register_memory(void) +static int __init request_standard_resources(void) { - unsigned long gapstart, gapsize, round; - unsigned long long last; - int i; + int i; + printk("Setting up standard PCI resources\n"); if (efi_enabled) efi_initialize_iomem_resources(&code_resource, &data_resource); else @@ -1334,6 +1336,16 @@ static void __init register_memory(void) /* request I/O space for devices used on all i[345]86 PCs */ for (i = 0; i < STANDARD_IO_RESOURCES; i++) request_resource(&ioport_resource, &standard_io_resources[i]); + return 0; +} + +fs_initcall(request_standard_resources); + +static void __init register_memory(void) +{ + unsigned long gapstart, gapsize, round; + unsigned long long last; + int i; /* * Search for the bigest gap in the low 32 bits of the e820 From a0454b40ee8fac03194bb71f01730266506e75e1 Mon Sep 17 00:00:00 2001 From: Grant Grundler Date: Thu, 16 Feb 2006 23:58:29 -0800 Subject: [PATCH 30/49] [PATCH] PCI: fix problems with MSI-X on ia64 Use "unsigned long" when dealing with PCI resources. The BAR Indicator Register (BIR) can be a 64-bit value or the resource could be a 64-bit host physical address. Enables ib_mthca and cciss drivers to use MSI-X on ia64 HW. Problem showed up now because of new system firmware on one platform. Symptom will either be memory corruption or MCA. Second part of this patch deals with "useless" code. We walk through the steps to find the phys_addr and then don't use the result. I suspect the intent was to zero out the respective MSI-X entry but I'm not sure at the moment. Delete the code inside the #if 0/#endif if it's really not needed. Signed-off-by: Grant Grundler Signed-off-by: Greg Kroah-Hartman --- drivers/pci/msi.c | 37 ++++++++++++++++++++++++------------- 1 file changed, 24 insertions(+), 13 deletions(-) diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index 4de1c17ee573..aea8b258b9b8 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c @@ -600,7 +600,8 @@ static int msix_capability_init(struct pci_dev *dev, struct msg_address address; struct msg_data data; int vector, pos, i, j, nr_entries, temp = 0; - u32 phys_addr, table_offset; + unsigned long phys_addr; + u32 table_offset; u16 control; u8 bir; void __iomem *base; @@ -609,11 +610,11 @@ static int msix_capability_init(struct pci_dev *dev, /* Request & Map MSI-X table region */ pci_read_config_word(dev, msi_control_reg(pos), &control); nr_entries = multi_msix_capable(control); - pci_read_config_dword(dev, msix_table_offset_reg(pos), - &table_offset); + + pci_read_config_dword(dev, msix_table_offset_reg(pos), &table_offset); bir = (u8)(table_offset & PCI_MSIX_FLAGS_BIRMASK); - phys_addr = pci_resource_start (dev, bir); - phys_addr += (u32)(table_offset & ~PCI_MSIX_FLAGS_BIRMASK); + table_offset &= ~PCI_MSIX_FLAGS_BIRMASK; + phys_addr = pci_resource_start (dev, bir) + table_offset; base = ioremap_nocache(phys_addr, nr_entries * PCI_MSIX_ENTRY_SIZE); if (base == NULL) return -ENOMEM; @@ -838,8 +839,10 @@ static int msi_free_vector(struct pci_dev* dev, int vector, int reassign) * Detect last MSI-X vector to be released. * Release the MSI-X memory-mapped table. */ +#if 0 int pos, nr_entries; - u32 phys_addr, table_offset; + unsigned long phys_addr; + u32 table_offset; u16 control; u8 bir; @@ -850,9 +853,12 @@ static int msi_free_vector(struct pci_dev* dev, int vector, int reassign) pci_read_config_dword(dev, msix_table_offset_reg(pos), &table_offset); bir = (u8)(table_offset & PCI_MSIX_FLAGS_BIRMASK); - phys_addr = pci_resource_start (dev, bir); - phys_addr += (u32)(table_offset & - ~PCI_MSIX_FLAGS_BIRMASK); + table_offset &= ~PCI_MSIX_FLAGS_BIRMASK; + phys_addr = pci_resource_start(dev, bir) + table_offset; +/* + * FIXME! and what did you want to do with phys_addr? + */ +#endif iounmap(base); } } @@ -1119,7 +1125,9 @@ void msi_remove_pci_irq_vectors(struct pci_dev* dev) msi_free_vector(dev, vector, 0); if (warning) { /* Force to release the MSI-X memory-mapped table */ - u32 phys_addr, table_offset; +#if 0 + unsigned long phys_addr; + u32 table_offset; u16 control; u8 bir; @@ -1128,9 +1136,12 @@ void msi_remove_pci_irq_vectors(struct pci_dev* dev) pci_read_config_dword(dev, msix_table_offset_reg(pos), &table_offset); bir = (u8)(table_offset & PCI_MSIX_FLAGS_BIRMASK); - phys_addr = pci_resource_start (dev, bir); - phys_addr += (u32)(table_offset & - ~PCI_MSIX_FLAGS_BIRMASK); + table_offset &= ~PCI_MSIX_FLAGS_BIRMASK; + phys_addr = pci_resource_start(dev, bir) + table_offset; +/* + * FIXME! and what did you want to do with phys_addr? + */ +#endif iounmap(base); printk(KERN_WARNING "PCI: %s: msi_remove_pci_irq_vectors() " "called without free_irq() on all MSI-X vectors\n", From 8c4b2cf9af9b4ecc29d4f0ec4ecc8e94dc4432d7 Mon Sep 17 00:00:00 2001 From: Bernhard Kaindl Date: Sat, 18 Feb 2006 01:36:55 -0800 Subject: [PATCH 31/49] [PATCH] PCI: PCI/Cardbus cards hidden, needs pci=assign-busses to fix "In some cases, especially on modern laptops with a lot of PCI and cardbus bridges, we're unable to assign correct secondary/subordinate bus numbers to all cardbus bridges due to BIOS limitations unless we are using "pci=assign-busses" boot option." -- Ivan Kokshaysky (from a patch comment) Without it, Cardbus cards inserted are never seen by PCI because the parent PCI-PCI Bridge of the Cardbus bridge will not pass and translate Type 1 PCI configuration cycles correctly and the system will fail to find and initialise the PCI devices in the system. Reference: PCI-PCI Bridges: PCI Configuration Cycles and PCI Bus Numbering: http://www.science.unitn.it/~fiorella/guidelinux/tlk/node72.html The reason for this is that: ``All PCI busses located behind a PCI-PCI bridge must reside between the secondary bus number and the subordinate bus number (inclusive).'' "pci=assign-busses" makes pcibios_assign_all_busses return 1 and this turns on PCI renumbering during PCI probing. Alan suggested to use DMI automatically set assign-busses on problem systems. The only question for me was where to put it. I put it directly before scanning PCI bus into pcibios_scan_root() because it's called from legacy, acpi and numa and so it can be one place for all systems and configurations which may need it. AMD64 Laptops are also affected and fixed by assign-busses, and the code is also incuded from arch/x86_64/pci/ that place will also work for x86_64 kernels, I only ifdef'-ed the x86-only Laptop in this example. Affected and known or assumed to be fixed with it are (found by googling): * ASUS Z71V and L3s * Samsung X20 * Compaq R3140us and all Compaq R3000 series laptops with TI1620 Controller, also Compaq R4000 series (from a kernel.org bugreport) * HP zv5000z (AMD64 3700+, known that fixup_parent_subordinate_busnr fixes it) * HP zv5200z * IBM ThinkPad 240 * An IBM ThinkPad (1.8 GHz Pentium M) debugged by Pavel Machek gives the correspondig message which detects the possible problem. * MSI S260 / Medion SIM 2100 MD 95600 The patch also expands the "try pci=assign-busses" warning so testers will help us to update the DMI table. Cc: Ivan Kokshaysky Cc: Alan Cox Cc: Dominik Brodowski Cc: Russell King Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- arch/i386/pci/common.c | 32 ++++++++++++++++++++++++++++++++ drivers/pci/probe.c | 4 +++- 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/arch/i386/pci/common.c b/arch/i386/pci/common.c index f6bc48da4d2a..dbece776c5b2 100644 --- a/arch/i386/pci/common.c +++ b/arch/i386/pci/common.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include @@ -120,11 +121,42 @@ void __devinit pcibios_fixup_bus(struct pci_bus *b) pci_read_bridge_bases(b); } +/* + * Enable renumbering of PCI bus# ranges to reach all PCI busses (Cardbus) + */ +#ifdef __i386__ +static int __devinit assign_all_busses(struct dmi_system_id *d) +{ + pci_probe |= PCI_ASSIGN_ALL_BUSSES; + printk(KERN_INFO "%s detected: enabling PCI bus# renumbering" + " (pci=assign-busses)\n", d->ident); + return 0; +} +#endif + +/* + * Laptops which need pci=assign-busses to see Cardbus cards + */ +static struct dmi_system_id __devinitdata pciprobe_dmi_table[] = { +#ifdef __i386__ + { + .callback = assign_all_busses, + .ident = "Samsung X20 Laptop", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Samsung Electronics"), + DMI_MATCH(DMI_PRODUCT_NAME, "SX20S"), + }, + }, +#endif /* __i386__ */ + {} +}; struct pci_bus * __devinit pcibios_scan_root(int busnum) { struct pci_bus *bus = NULL; + dmi_check_system(pciprobe_dmi_table); + while ((bus = pci_find_next_bus(bus)) != NULL) { if (bus->number == busnum) { /* Already scanned */ diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 542e7dfb371b..e3dc3063e05b 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -589,13 +589,15 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max (child->number > bus->subordinate) || (child->number < bus->number) || (child->subordinate < bus->number)) { - printk(KERN_WARNING "PCI: Bus #%02x (-#%02x) may be " + printk(KERN_WARNING "PCI: Bus #%02x (-#%02x) is " "hidden behind%s bridge #%02x (-#%02x)%s\n", child->number, child->subordinate, bus->self->transparent ? " transparent" : " ", bus->number, bus->subordinate, pcibios_assign_all_busses() ? " " : " (try 'pci=assign-busses')"); + printk(KERN_WARNING "Please report the result to " + "linux-kernel to fix this permanently\n"); } bus = bus->parent; } From b89b7ea05a8f71426bd36ed12e6cd73179d0f720 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Thu, 23 Feb 2006 17:12:51 -0500 Subject: [PATCH 32/49] [PATCH] PCI: Move pci_dev_put outside a spinlock This patch (as659) fixes a might_sleep problem in the PCI core, by moving a call to pci_dev_put() outside the scope of a spinlock. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/pci/search.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/pci/search.c b/drivers/pci/search.c index 05fa91a31c62..ce7dd6e7be60 100644 --- a/drivers/pci/search.c +++ b/drivers/pci/search.c @@ -246,9 +246,9 @@ pci_get_subsys(unsigned int vendor, unsigned int device, } dev = NULL; exit: - pci_dev_put(from); dev = pci_dev_get(dev); spin_unlock(&pci_bus_lock); + pci_dev_put(from); return dev; } @@ -339,9 +339,9 @@ struct pci_dev *pci_get_class(unsigned int class, struct pci_dev *from) } dev = NULL; exit: - pci_dev_put(from); dev = pci_dev_get(dev); spin_unlock(&pci_bus_lock); + pci_dev_put(from); return dev; } From 15a1ae74879925d0d3f71ebc3f56d0a2c5db393a Mon Sep 17 00:00:00 2001 From: Kristen Accardi Date: Thu, 23 Feb 2006 17:55:58 -0800 Subject: [PATCH 33/49] [PATCH] acpiphp: add new bus to acpi If we add a new bridge with subordinate busses, we should call make sure that acpi is notified so that the PRT (if present) can be read and drivers who have registered on this bus will be notified when it is started. Also make sure to use the max reserved bus number for the starting the bus scan. Signed-off-by: Kristen Carlson Accardi Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/acpiphp_glue.c | 111 ++++++++++++++++++++++++++++- 1 file changed, 109 insertions(+), 2 deletions(-) diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index 4e25d9c7cc39..fe0a6b7662f7 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c @@ -751,6 +751,106 @@ static int power_off_slot(struct acpiphp_slot *slot) } + +/** + * acpiphp_max_busnr - return the highest reserved bus number under + * the given bus. + * @bus: bus to start search with + * + */ +static unsigned char acpiphp_max_busnr(struct pci_bus *bus) +{ + struct list_head *tmp; + unsigned char max, n; + + /* + * pci_bus_max_busnr will return the highest + * reserved busnr for all these children. + * that is equivalent to the bus->subordinate + * value. We don't want to use the parent's + * bus->subordinate value because it could have + * padding in it. + */ + max = bus->secondary; + + list_for_each(tmp, &bus->children) { + n = pci_bus_max_busnr(pci_bus_b(tmp)); + if (n > max) + max = n; + } + return max; +} + + + +/** + * get_func - get a pointer to acpiphp_func given a slot, device + * @slot: slot to search + * @dev: pci_dev struct to match. + * + * This function will increase the reference count of pci_dev, + * so callers should call pci_dev_put when complete. + * + */ +static struct acpiphp_func * +get_func(struct acpiphp_slot *slot, struct pci_dev *dev) +{ + struct acpiphp_func *func = NULL; + struct pci_bus *bus = slot->bridge->pci_bus; + struct pci_dev *pdev; + + list_for_each_entry(func, &slot->funcs, sibling) { + pdev = pci_get_slot(bus, PCI_DEVFN(slot->device, + func->function)); + if (pdev) { + if (pdev == dev) + break; + pci_dev_put(pdev); + } + } + return func; +} + + +/** + * acpiphp_bus_add - add a new bus to acpi subsystem + * @func: acpiphp_func of the bridge + * + */ +static int acpiphp_bus_add(struct acpiphp_func *func) +{ + acpi_handle phandle; + struct acpi_device *device, *pdevice; + int ret_val; + + acpi_get_parent(func->handle, &phandle); + if (acpi_bus_get_device(phandle, &pdevice)) { + dbg("no parent device, assuming NULL\n"); + pdevice = NULL; + } + if (acpi_bus_get_device(func->handle, &device)) { + ret_val = acpi_bus_add(&device, pdevice, func->handle, + ACPI_BUS_TYPE_DEVICE); + if (ret_val) { + dbg("error adding bus, %x\n", + -ret_val); + goto acpiphp_bus_add_out; + } + } + /* + * try to start anyway. We could have failed to add + * simply because this bus had previously been added + * on another add. Don't bother with the return value + * we just keep going. + */ + ret_val = acpi_bus_start(device); + +acpiphp_bus_add_out: + return ret_val; +} + + + /** * enable_device - enable, configure a slot * @slot: slot to be enabled @@ -788,7 +888,7 @@ static int enable_device(struct acpiphp_slot *slot) goto err_exit; } - max = bus->secondary; + max = acpiphp_max_busnr(bus); for (pass = 0; pass < 2; pass++) { list_for_each_entry(dev, &bus->devices, bus_list) { if (PCI_SLOT(dev->devfn) != slot->device) @@ -796,8 +896,15 @@ static int enable_device(struct acpiphp_slot *slot) if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE || dev->hdr_type == PCI_HEADER_TYPE_CARDBUS) { max = pci_scan_bridge(bus, dev, max, pass); - if (pass && dev->subordinate) + if (pass && dev->subordinate) { pci_bus_size_bridges(dev->subordinate); + func = get_func(slot, dev); + if (func) { + acpiphp_bus_add(func); + /* side effect of get_func */ + pci_dev_put(dev); + } + } } } } From ceaba663055e38226a070a9668eac5881d65a2cc Mon Sep 17 00:00:00 2001 From: Kristen Accardi Date: Thu, 23 Feb 2006 17:56:01 -0800 Subject: [PATCH 34/49] [PATCH] acpi: export acpi_bus_trim Export the acpi_bus_trim function so that the pci hotplug driver can use it. Signed-off-by: Kristen Carlson Accardi Signed-off-by: Greg Kroah-Hartman --- drivers/acpi/scan.c | 5 +++-- include/acpi/acpi_bus.h | 1 + 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 9271e5209ac1..a0ab828b2cc5 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -23,7 +23,6 @@ static LIST_HEAD(acpi_device_list); DEFINE_SPINLOCK(acpi_device_lock); LIST_HEAD(acpi_wakeup_device_list); -static int acpi_bus_trim(struct acpi_device *start, int rmdevice); static void acpi_device_release(struct kobject *kobj) { @@ -1284,7 +1283,7 @@ int acpi_bus_start(struct acpi_device *device) EXPORT_SYMBOL(acpi_bus_start); -static int acpi_bus_trim(struct acpi_device *start, int rmdevice) +int acpi_bus_trim(struct acpi_device *start, int rmdevice) { acpi_status status; struct acpi_device *parent, *child; @@ -1337,6 +1336,8 @@ static int acpi_bus_trim(struct acpi_device *start, int rmdevice) } return err; } +EXPORT_SYMBOL_GPL(acpi_bus_trim); + static int acpi_bus_scan_fixed(struct acpi_device *root) { diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index 0b54e9a4a8a1..e496fac860ac 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -330,6 +330,7 @@ int acpi_bus_register_driver(struct acpi_driver *driver); int acpi_bus_unregister_driver(struct acpi_driver *driver); int acpi_bus_add(struct acpi_device **child, struct acpi_device *parent, acpi_handle handle, int type); +int acpi_bus_trim(struct acpi_device *start, int rmdevice); int acpi_bus_start(struct acpi_device *device); int acpi_match_ids(struct acpi_device *device, char *ids); From 20416ea54087c25502d6fb973b8e119973e16341 Mon Sep 17 00:00:00 2001 From: Kristen Accardi Date: Thu, 23 Feb 2006 17:56:03 -0800 Subject: [PATCH 35/49] [PATCH] acpiphp: add dock event handling These patches add generic dock event handling to acpiphp. If there are pci devices that need to be inserted/removed after the dock event, the event notification will be handed down to the normal pci hotplug event handler in acpiphp so that new bridges/devices can be enumerated. Because some dock stations do not have pci bridges or pci devices that need to be inserted after a dock, acpiphp will remain loaded to handle dock events even if no hotpluggable pci slots are discovered. You probably need to have the pci=assign-busses kernel parameter enabled to use these patches, and you may not allow ibm_acpi to handle docking notifications and use this patch. This patch incorporates feedback provided by many. Signed-off-by: Kristen Carlson Accardi Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/Makefile | 3 +- drivers/pci/hotplug/acpiphp.h | 36 +++ drivers/pci/hotplug/acpiphp_core.c | 7 +- drivers/pci/hotplug/acpiphp_dock.c | 438 +++++++++++++++++++++++++++++ drivers/pci/hotplug/acpiphp_glue.c | 85 ++++-- 5 files changed, 545 insertions(+), 24 deletions(-) create mode 100644 drivers/pci/hotplug/acpiphp_dock.c diff --git a/drivers/pci/hotplug/Makefile b/drivers/pci/hotplug/Makefile index 3c71e3077ff1..1c0ed377ed91 100644 --- a/drivers/pci/hotplug/Makefile +++ b/drivers/pci/hotplug/Makefile @@ -37,7 +37,8 @@ ibmphp-objs := ibmphp_core.o \ ibmphp_hpc.o acpiphp-objs := acpiphp_core.o \ - acpiphp_glue.o + acpiphp_glue.o \ + acpiphp_dock.o rpaphp-objs := rpaphp_core.o \ rpaphp_pci.o \ diff --git a/drivers/pci/hotplug/acpiphp.h b/drivers/pci/hotplug/acpiphp.h index 6a91cfb0f688..885838a2e93f 100644 --- a/drivers/pci/hotplug/acpiphp.h +++ b/drivers/pci/hotplug/acpiphp.h @@ -161,6 +161,25 @@ struct acpiphp_attention_info struct module *owner; }; + +struct dependent_device { + struct list_head device_list; + struct list_head pci_list; + acpi_handle handle; + struct acpiphp_func *func; +}; + + +struct acpiphp_dock_station { + acpi_handle handle; + u32 last_dock_time; + u32 flags; + struct acpiphp_func *dock_bridge; + struct list_head dependent_devices; + struct list_head pci_dependent_devices; +}; + + /* PCI bus bridge HID */ #define ACPI_PCI_HOST_HID "PNP0A03" @@ -198,6 +217,12 @@ struct acpiphp_attention_info #define FUNC_HAS_PS1 (0x00000020) #define FUNC_HAS_PS2 (0x00000040) #define FUNC_HAS_PS3 (0x00000080) +#define FUNC_HAS_DCK (0x00000100) +#define FUNC_IS_DD (0x00000200) + +/* dock station flags */ +#define DOCK_DOCKING (0x00000001) +#define DOCK_HAS_BRIDGE (0x00000002) /* function prototypes */ @@ -211,6 +236,7 @@ extern void acpiphp_glue_exit (void); extern int acpiphp_get_num_slots (void); extern struct acpiphp_slot *get_slot_from_id (int id); typedef int (*acpiphp_callback)(struct acpiphp_slot *slot, void *data); +void handle_hotplug_event_func(acpi_handle, u32, void*); extern int acpiphp_enable_slot (struct acpiphp_slot *slot); extern int acpiphp_disable_slot (struct acpiphp_slot *slot); @@ -220,6 +246,16 @@ extern u8 acpiphp_get_latch_status (struct acpiphp_slot *slot); extern u8 acpiphp_get_adapter_status (struct acpiphp_slot *slot); extern u32 acpiphp_get_address (struct acpiphp_slot *slot); +/* acpiphp_dock.c */ +extern int find_dock_station(void); +extern void remove_dock_station(void); +extern void add_dependent_device(struct dependent_device *new_dd); +extern void add_pci_dependent_device(struct dependent_device *new_dd); +extern struct dependent_device *get_dependent_device(acpi_handle handle); +extern int is_dependent_device(acpi_handle handle); +extern int detect_dependent_devices(acpi_handle *bridge_handle); +extern struct dependent_device *alloc_dependent_device(acpi_handle handle); + /* variables */ extern int acpiphp_debug; diff --git a/drivers/pci/hotplug/acpiphp_core.c b/drivers/pci/hotplug/acpiphp_core.c index 60c4c38047a3..bce71c933478 100644 --- a/drivers/pci/hotplug/acpiphp_core.c +++ b/drivers/pci/hotplug/acpiphp_core.c @@ -429,14 +429,17 @@ static void __exit cleanup_slots (void) static int __init acpiphp_init(void) { int retval; + int docking_station; info(DRIVER_DESC " version: " DRIVER_VERSION "\n"); acpiphp_debug = debug; + docking_station = find_dock_station(); + /* read all the ACPI info from the system */ retval = init_acpi(); - if (retval) + if (retval && !(docking_station)) return retval; return init_slots(); @@ -448,6 +451,8 @@ static void __exit acpiphp_exit(void) cleanup_slots(); /* deallocate internal data structures etc. */ acpiphp_glue_exit(); + + remove_dock_station(); } module_init(acpiphp_init); diff --git a/drivers/pci/hotplug/acpiphp_dock.c b/drivers/pci/hotplug/acpiphp_dock.c new file mode 100644 index 000000000000..4f1aaf128312 --- /dev/null +++ b/drivers/pci/hotplug/acpiphp_dock.c @@ -0,0 +1,438 @@ +/* + * ACPI PCI HotPlug dock functions to ACPI CA subsystem + * + * Copyright (C) 2006 Kristen Carlson Accardi (kristen.c.accardi@intel.com) + * Copyright (C) 2006 Intel Corporation + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Send feedback to + * + */ +#include +#include + +#include +#include +#include +#include + +#include "../pci.h" +#include "pci_hotplug.h" +#include "acpiphp.h" + +static struct acpiphp_dock_station *ds; +#define MY_NAME "acpiphp_dock" + + +int is_dependent_device(acpi_handle handle) +{ + return (get_dependent_device(handle) ? 1 : 0); +} + + +static acpi_status +find_dependent_device(acpi_handle handle, u32 lvl, void *context, void **rv) +{ + int *count = (int *)context; + + if (is_dependent_device(handle)) { + (*count)++; + return AE_CTRL_TERMINATE; + } else { + return AE_OK; + } +} + + + + +void add_dependent_device(struct dependent_device *new_dd) +{ + list_add_tail(&new_dd->device_list, &ds->dependent_devices); +} + + +void add_pci_dependent_device(struct dependent_device *new_dd) +{ + list_add_tail(&new_dd->pci_list, &ds->pci_dependent_devices); +} + + + +struct dependent_device * get_dependent_device(acpi_handle handle) +{ + struct dependent_device *dd; + + if (!ds) + return NULL; + + list_for_each_entry(dd, &ds->dependent_devices, device_list) { + if (handle == dd->handle) + return dd; + } + return NULL; +} + + + +struct dependent_device *alloc_dependent_device(acpi_handle handle) +{ + struct dependent_device *dd; + + dd = kzalloc(sizeof(*dd), GFP_KERNEL); + if (dd) { + INIT_LIST_HEAD(&dd->pci_list); + INIT_LIST_HEAD(&dd->device_list); + dd->handle = handle; + } + return dd; +} + + + +static int is_dock(acpi_handle handle) +{ + acpi_status status; + acpi_handle tmp; + + status = acpi_get_handle(handle, "_DCK", &tmp); + if (ACPI_FAILURE(status)) { + return 0; + } + return 1; +} + + + +static int dock_present(void) +{ + unsigned long sta; + acpi_status status; + + if (ds) { + status = acpi_evaluate_integer(ds->handle, "_STA", NULL, &sta); + if (ACPI_SUCCESS(status) && sta) + return 1; + } + return 0; +} + + + +static void eject_dock(void) +{ + struct acpi_object_list arg_list; + union acpi_object arg; + + arg_list.count = 1; + arg_list.pointer = &arg; + arg.type = ACPI_TYPE_INTEGER; + arg.integer.value = 1; + + if (ACPI_FAILURE(acpi_evaluate_object(ds->handle, "_EJ0", + &arg_list, NULL)) || dock_present()) + warn("%s: failed to eject dock!\n", __FUNCTION__); + + return; +} + + + + +static acpi_status handle_dock(int dock) +{ + acpi_status status; + struct acpi_object_list arg_list; + union acpi_object arg; + struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; + + dbg("%s: %s\n", __FUNCTION__, dock ? "docking" : "undocking"); + + /* _DCK method has one argument */ + arg_list.count = 1; + arg_list.pointer = &arg; + arg.type = ACPI_TYPE_INTEGER; + arg.integer.value = dock; + status = acpi_evaluate_object(ds->handle, "_DCK", + &arg_list, &buffer); + if (ACPI_FAILURE(status)) + err("%s: failed to execute _DCK\n", __FUNCTION__); + acpi_os_free(buffer.pointer); + + return status; +} + + + +static inline void dock(void) +{ + handle_dock(1); +} + + + +static inline void undock(void) +{ + handle_dock(0); +} + + + +/* + * the _DCK method can do funny things... and sometimes not + * hah-hah funny. + * + * TBD - figure out a way to only call fixups for + * systems that require them. + */ +static void post_dock_fixups(void) +{ + struct pci_bus *bus; + u32 buses; + struct dependent_device *dd; + + list_for_each_entry(dd, &ds->pci_dependent_devices, pci_list) { + bus = dd->func->slot->bridge->pci_bus; + + /* fixup bad _DCK function that rewrites + * secondary bridge on slot + */ + pci_read_config_dword(bus->self, + PCI_PRIMARY_BUS, + &buses); + + if (((buses >> 8) & 0xff) != bus->secondary) { + buses = (buses & 0xff000000) + | ((unsigned int)(bus->primary) << 0) + | ((unsigned int)(bus->secondary) << 8) + | ((unsigned int)(bus->subordinate) << 16); + pci_write_config_dword(bus->self, + PCI_PRIMARY_BUS, + buses); + } + } +} + + + +static void hotplug_pci(u32 type) +{ + struct dependent_device *dd; + + list_for_each_entry(dd, &ds->pci_dependent_devices, pci_list) + handle_hotplug_event_func(dd->handle, type, dd->func); +} + + + +static inline void begin_dock(void) +{ + ds->flags |= DOCK_DOCKING; +} + + +static inline void complete_dock(void) +{ + ds->flags &= ~(DOCK_DOCKING); + ds->last_dock_time = jiffies; +} + + +static int dock_in_progress(void) +{ + if (ds->flags & DOCK_DOCKING || + ds->last_dock_time == jiffies) { + dbg("dock in progress\n"); + return 1; + } + return 0; +} + + + +static void +handle_hotplug_event_dock(acpi_handle handle, u32 type, void *context) +{ + dbg("%s: enter\n", __FUNCTION__); + + switch (type) { + case ACPI_NOTIFY_BUS_CHECK: + dbg("BUS Check\n"); + if (!dock_in_progress() && dock_present()) { + begin_dock(); + dock(); + if (!dock_present()) { + err("Unable to dock!\n"); + break; + } + post_dock_fixups(); + hotplug_pci(type); + complete_dock(); + } + break; + case ACPI_NOTIFY_EJECT_REQUEST: + dbg("EJECT request\n"); + if (!dock_in_progress() && dock_present()) { + hotplug_pci(type); + undock(); + eject_dock(); + if (dock_present()) + err("Unable to undock!\n"); + } + break; + } +} + + + + +static acpi_status +find_dock_ejd(acpi_handle handle, u32 lvl, void *context, void **rv) +{ + acpi_status status; + acpi_handle tmp; + acpi_handle dck_handle = (acpi_handle) context; + char objname[64]; + struct acpi_buffer buffer = { .length = sizeof(objname), + .pointer = objname }; + struct acpi_buffer ejd_buffer = {ACPI_ALLOCATE_BUFFER, NULL}; + union acpi_object *ejd_obj; + + status = acpi_get_handle(handle, "_EJD", &tmp); + if (ACPI_FAILURE(status)) + return AE_OK; + + /* make sure we are dependent on the dock device, + * by executing the _EJD method, then getting a handle + * to the device referenced by that name. If that + * device handle is the same handle as the dock station + * handle, then we are a device dependent on the dock station + */ + acpi_get_name(dck_handle, ACPI_FULL_PATHNAME, &buffer); + status = acpi_evaluate_object(handle, "_EJD", NULL, &ejd_buffer); + if (ACPI_FAILURE(status)) { + err("Unable to execute _EJD!\n"); + goto find_ejd_out; + } + ejd_obj = ejd_buffer.pointer; + status = acpi_get_handle(NULL, ejd_obj->string.pointer, &tmp); + if (ACPI_FAILURE(status)) + goto find_ejd_out; + + if (tmp == dck_handle) { + struct dependent_device *dd; + dbg("%s: found device dependent on dock\n", __FUNCTION__); + dd = alloc_dependent_device(handle); + if (!dd) { + err("Can't allocate memory for dependent device!\n"); + goto find_ejd_out; + } + add_dependent_device(dd); + } + +find_ejd_out: + acpi_os_free(ejd_buffer.pointer); + return AE_OK; +} + + + +int detect_dependent_devices(acpi_handle *bridge_handle) +{ + acpi_status status; + int count; + + count = 0; + + status = acpi_walk_namespace(ACPI_TYPE_DEVICE, bridge_handle, + (u32)1, find_dependent_device, + (void *)&count, NULL); + + return count; +} + + + + + +static acpi_status +find_dock(acpi_handle handle, u32 lvl, void *context, void **rv) +{ + int *count = (int *)context; + + if (is_dock(handle)) { + dbg("%s: found dock\n", __FUNCTION__); + ds = kzalloc(sizeof(*ds), GFP_KERNEL); + ds->handle = handle; + INIT_LIST_HEAD(&ds->dependent_devices); + INIT_LIST_HEAD(&ds->pci_dependent_devices); + + /* look for devices dependent on dock station */ + acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, + ACPI_UINT32_MAX, find_dock_ejd, handle, NULL); + + acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY, + handle_hotplug_event_dock, ds); + (*count)++; + } + + return AE_OK; +} + + + + +int find_dock_station(void) +{ + int num = 0; + + ds = NULL; + + /* start from the root object, because some laptops define + * _DCK methods outside the scope of PCI (IBM x-series laptop) + */ + acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, + ACPI_UINT32_MAX, find_dock, &num, NULL); + + return num; +} + + + +void remove_dock_station(void) +{ + struct dependent_device *dd, *tmp; + if (ds) { + if (ACPI_FAILURE(acpi_remove_notify_handler(ds->handle, + ACPI_SYSTEM_NOTIFY, handle_hotplug_event_dock))) + err("failed to remove dock notify handler\n"); + + /* free all dependent devices */ + list_for_each_entry_safe(dd, tmp, &ds->dependent_devices, + device_list) + kfree(dd); + + /* no need to touch the pci_dependent_device list, + * cause all memory was freed above + */ + kfree(ds); + } +} + + diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index fe0a6b7662f7..22d0f1cf1362 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c @@ -57,7 +57,6 @@ static LIST_HEAD(bridge_list); #define MY_NAME "acpiphp_glue" static void handle_hotplug_event_bridge (acpi_handle, u32, void *); -static void handle_hotplug_event_func (acpi_handle, u32, void *); static void acpiphp_sanitize_bus(struct pci_bus *bus); static void acpiphp_set_hpp_values(acpi_handle handle, struct pci_bus *bus); @@ -125,6 +124,7 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) struct acpiphp_bridge *bridge = (struct acpiphp_bridge *)context; struct acpiphp_slot *slot; struct acpiphp_func *newfunc; + struct dependent_device *dd; acpi_handle tmp; acpi_status status = AE_OK; unsigned long adr, sun; @@ -138,7 +138,7 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) status = acpi_get_handle(handle, "_EJ0", &tmp); - if (ACPI_FAILURE(status)) + if (ACPI_FAILURE(status) && !(is_dependent_device(handle))) return AE_OK; device = (adr >> 16) & 0xffff; @@ -152,7 +152,8 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) INIT_LIST_HEAD(&newfunc->sibling); newfunc->handle = handle; newfunc->function = function; - newfunc->flags = FUNC_HAS_EJ0; + if (ACPI_SUCCESS(status)) + newfunc->flags = FUNC_HAS_EJ0; if (ACPI_SUCCESS(acpi_get_handle(handle, "_STA", &tmp))) newfunc->flags |= FUNC_HAS_STA; @@ -163,6 +164,19 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) if (ACPI_SUCCESS(acpi_get_handle(handle, "_PS3", &tmp))) newfunc->flags |= FUNC_HAS_PS3; + if (ACPI_SUCCESS(acpi_get_handle(handle, "_DCK", &tmp))) { + newfunc->flags |= FUNC_HAS_DCK; + /* add to devices dependent on dock station, + * because this may actually be the dock bridge + */ + dd = alloc_dependent_device(handle); + if (!dd) + err("Can't allocate memory for " + "new dependent device!\n"); + else + add_dependent_device(dd); + } + status = acpi_evaluate_integer(handle, "_SUN", NULL, &sun); if (ACPI_FAILURE(status)) sun = -1; @@ -210,18 +224,35 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) slot->flags |= (SLOT_ENABLED | SLOT_POWEREDON); } + /* if this is a device dependent on a dock station, + * associate the acpiphp_func to the dependent_device + * struct. + */ + if ((dd = get_dependent_device(handle))) { + newfunc->flags |= FUNC_IS_DD; + /* + * we don't want any devices which is dependent + * on the dock to have it's _EJ0 method executed. + * because we need to run _DCK first. + */ + newfunc->flags &= ~FUNC_HAS_EJ0; + dd->func = newfunc; + add_pci_dependent_device(dd); + } + /* install notify handler */ - status = acpi_install_notify_handler(handle, + if (!(newfunc->flags & FUNC_HAS_DCK)) { + status = acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY, handle_hotplug_event_func, newfunc); - if (ACPI_FAILURE(status)) { - err("failed to register interrupt notify handler\n"); - return status; - } + if (ACPI_FAILURE(status)) + err("failed to register interrupt notify handler\n"); + } else + status = AE_OK; - return AE_OK; + return status; } @@ -410,7 +441,8 @@ find_p2p_bridge(acpi_handle handle, u32 lvl, void *context, void **rv) goto out; /* check if this bridge has ejectable slots */ - if (detect_ejectable_slots(handle) > 0) { + if ((detect_ejectable_slots(handle) > 0) || + (detect_dependent_devices(handle) > 0)) { dbg("found PCI-to-PCI bridge at PCI %s\n", pci_name(dev)); add_p2p_bridge(handle, dev); } @@ -512,11 +544,13 @@ static void cleanup_bridge(struct acpiphp_bridge *bridge) list_for_each_safe (list, tmp, &slot->funcs) { struct acpiphp_func *func; func = list_entry(list, struct acpiphp_func, sibling); - status = acpi_remove_notify_handler(func->handle, + if (!(func->flags & FUNC_HAS_DCK)) { + status = acpi_remove_notify_handler(func->handle, ACPI_SYSTEM_NOTIFY, handle_hotplug_event_func); - if (ACPI_FAILURE(status)) - err("failed to remove notify handler\n"); + if (ACPI_FAILURE(status)) + err("failed to remove notify handler\n"); + } pci_dev_put(func->pci_dev); list_del(list); kfree(func); @@ -828,14 +862,21 @@ static int acpiphp_bus_add(struct acpiphp_func *func) dbg("no parent device, assuming NULL\n"); pdevice = NULL; } - if (acpi_bus_get_device(func->handle, &device)) { - ret_val = acpi_bus_add(&device, pdevice, func->handle, - ACPI_BUS_TYPE_DEVICE); - if (ret_val) { - dbg("error adding bus, %x\n", - -ret_val); - goto acpiphp_bus_add_out; - } + if (!acpi_bus_get_device(func->handle, &device)) { + dbg("bus exists... trim\n"); + /* this shouldn't be in here, so remove + * the bus then re-add it... + */ + ret_val = acpi_bus_trim(device, 1); + dbg("acpi_bus_trim return %x\n", ret_val); + } + + ret_val = acpi_bus_add(&device, pdevice, func->handle, + ACPI_BUS_TYPE_DEVICE); + if (ret_val) { + dbg("error adding bus, %x\n", + -ret_val); + goto acpiphp_bus_add_out; } /* * try to start anyway. We could have failed to add @@ -1307,7 +1348,7 @@ static void handle_hotplug_event_bridge(acpi_handle handle, u32 type, void *cont * handles ACPI event notification on slots * */ -static void handle_hotplug_event_func(acpi_handle handle, u32 type, void *context) +void handle_hotplug_event_func(acpi_handle handle, u32 type, void *context) { struct acpiphp_func *func; char objname[64]; From 63e5f248c4b748690b5180aa1b4b10eac51bb0e1 Mon Sep 17 00:00:00 2001 From: Kristen Accardi Date: Thu, 23 Feb 2006 17:56:06 -0800 Subject: [PATCH 36/49] [PATCH] acpi: remove dock event handling from ibm_acpi Remove dock station support from ibm_acpi by default. This support has been put into acpiphp instead. Allow ibm_acpi to continue to provide docking station support via config option for laptops/docking stations that are not supported by acpiphp. Signed-off-by: Kristen Carlson Accardi Signed-off-by: Greg Kroah-Hartman --- drivers/acpi/Kconfig | 12 ++++++++++++ drivers/acpi/ibm_acpi.c | 13 ++++++++++--- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index 33e2ca847a26..82710ae39228 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -205,6 +205,18 @@ config ACPI_IBM If you have an IBM ThinkPad laptop, say Y or M here. +config ACPI_IBM_DOCK + bool "Legacy Docking Station Support" + depends on ACPI_IBM + default n + ---help--- + Allows the ibm_acpi driver to handle docking station events. + This support is obsoleted by CONFIG_HOTPLUG_PCI_ACPI. It will + allow locking and removing the laptop from the docking station, + but will not properly connect PCI devices. + + If you are not sure, say N here. + config ACPI_TOSHIBA tristate "Toshiba Laptop Extras" depends on X86 diff --git a/drivers/acpi/ibm_acpi.c b/drivers/acpi/ibm_acpi.c index 5cc090326ddc..262b1f41335a 100644 --- a/drivers/acpi/ibm_acpi.c +++ b/drivers/acpi/ibm_acpi.c @@ -160,13 +160,13 @@ IBM_HANDLE(cmos, root, "\\UCMS", /* R50, R50e, R50p, R51, T4x, X31, X40 */ "\\CMOS", /* A3x, G4x, R32, T23, T30, X22-24, X30 */ "\\CMS", /* R40, R40e */ ); /* all others */ - +#ifdef CONFIG_ACPI_IBM_DOCK IBM_HANDLE(dock, root, "\\_SB.GDCK", /* X30, X31, X40 */ "\\_SB.PCI0.DOCK", /* 600e/x,770e,770x,A2xm/p,T20-22,X20-21 */ "\\_SB.PCI0.PCI1.DOCK", /* all others */ "\\_SB.PCI.ISA.SLCE", /* 570 */ ); /* A21e,G4x,R30,R31,R32,R40,R40e,R50e */ - +#endif IBM_HANDLE(bay, root, "\\_SB.PCI.IDE.SECN.MAST", /* 570 */ "\\_SB.PCI0.IDE0.IDES.IDSM", /* 600e/x, 770e, 770x */ "\\_SB.PCI0.IDE0.SCND.MSTR", /* all others */ @@ -844,7 +844,7 @@ static int _sta(acpi_handle handle) return status; } - +#ifdef CONFIG_ACPI_IBM_DOCK #define dock_docked() (_sta(dock_handle) & 1) static int dock_read(char *p) @@ -907,6 +907,7 @@ static void dock_notify(struct ibm_struct *ibm, u32 event) acpi_bus_generate_event(ibm->device, event, 0); /* unknown */ } } +#endif static int bay_status_supported; static int bay_status2_supported; @@ -1574,6 +1575,7 @@ static struct ibm_struct ibms[] = { .read = light_read, .write = light_write, }, +#ifdef CONFIG_ACPI_IBM_DOCK { .name = "dock", .read = dock_read, @@ -1589,6 +1591,7 @@ static struct ibm_struct ibms[] = { .handle = &pci_handle, .type = ACPI_SYSTEM_NOTIFY, }, +#endif { .name = "bay", .init = bay_init, @@ -1880,7 +1883,9 @@ IBM_PARAM(hotkey); IBM_PARAM(bluetooth); IBM_PARAM(video); IBM_PARAM(light); +#ifdef CONFIG_ACPI_IBM_DOCK IBM_PARAM(dock); +#endif IBM_PARAM(bay); IBM_PARAM(cmos); IBM_PARAM(led); @@ -1927,7 +1932,9 @@ static int __init acpi_ibm_init(void) IBM_HANDLE_INIT(hkey); IBM_HANDLE_INIT(lght); IBM_HANDLE_INIT(cmos); +#ifdef CONFIG_ACPI_IBM_DOCK IBM_HANDLE_INIT(dock); +#endif IBM_HANDLE_INIT(pci); IBM_HANDLE_INIT(bay); if (bay_handle) From e27da3814170385a4d2797397d706e554635812d Mon Sep 17 00:00:00 2001 From: MUNEDA Takahiro Date: Thu, 23 Feb 2006 17:56:08 -0800 Subject: [PATCH 37/49] [PATCH] acpiphp - slot management fix - V4 o This patch removes IDs (for slots management). o This patch removes the slot register/unregister processes from the init/exit phases. Instead, adds these processes in the bridge add/cleanup phases. o Currently, this change doesn't have any meanings. But these changes are needed to support p2p bridge(with hotplug slot) Signed-off-by: MUNEDA Takahiro Signed-off-by: Kristen Carlson Accardi Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/acpiphp.h | 8 +-- drivers/pci/hotplug/acpiphp_core.c | 111 ++++++++++++++--------------- drivers/pci/hotplug/acpiphp_glue.c | 48 ++++++------- 3 files changed, 78 insertions(+), 89 deletions(-) diff --git a/drivers/pci/hotplug/acpiphp.h b/drivers/pci/hotplug/acpiphp.h index 885838a2e93f..de9df80ffb50 100644 --- a/drivers/pci/hotplug/acpiphp.h +++ b/drivers/pci/hotplug/acpiphp.h @@ -60,10 +60,7 @@ struct acpiphp_slot; * struct slot - slot information for each *physical* slot */ struct slot { - u8 number; struct hotplug_slot *hotplug_slot; - struct list_head slot_list; - struct acpiphp_slot *acpi_slot; }; @@ -119,9 +116,9 @@ struct acpiphp_slot { struct acpiphp_bridge *bridge; /* parent */ struct list_head funcs; /* one slot may have different objects (i.e. for each function) */ + struct slot *slot; struct mutex crit_sect; - u32 id; /* slot id (serial #) for hotplug core */ u8 device; /* pci device# */ u32 sun; /* ACPI _SUN (slot unique number) */ @@ -229,12 +226,13 @@ struct acpiphp_dock_station { /* acpiphp_core.c */ extern int acpiphp_register_attention(struct acpiphp_attention_info*info); extern int acpiphp_unregister_attention(struct acpiphp_attention_info *info); +extern int acpiphp_register_hotplug_slot(struct acpiphp_slot *slot); +extern void acpiphp_unregister_hotplug_slot(struct acpiphp_slot *slot); /* acpiphp_glue.c */ extern int acpiphp_glue_init (void); extern void acpiphp_glue_exit (void); extern int acpiphp_get_num_slots (void); -extern struct acpiphp_slot *get_slot_from_id (int id); typedef int (*acpiphp_callback)(struct acpiphp_slot *slot, void *data); void handle_hotplug_event_func(acpi_handle, u32, void*); diff --git a/drivers/pci/hotplug/acpiphp_core.c b/drivers/pci/hotplug/acpiphp_core.c index bce71c933478..4f1b0da8e47e 100644 --- a/drivers/pci/hotplug/acpiphp_core.c +++ b/drivers/pci/hotplug/acpiphp_core.c @@ -44,8 +44,6 @@ #include "pci_hotplug.h" #include "acpiphp.h" -static LIST_HEAD(slot_list); - #define MY_NAME "acpiphp" static int debug; @@ -341,62 +339,53 @@ static void release_slot(struct hotplug_slot *hotplug_slot) kfree(slot); } -/** - * init_slots - initialize 'struct slot' structures for each slot - * - */ -static int __init init_slots(void) +/* callback routine to initialize 'struct slot' for each slot */ +int acpiphp_register_hotplug_slot(struct acpiphp_slot *acpiphp_slot) { struct slot *slot; + struct hotplug_slot *hotplug_slot; + struct hotplug_slot_info *hotplug_slot_info; int retval = -ENOMEM; - int i; - for (i = 0; i < num_slots; ++i) { - slot = kmalloc(sizeof(struct slot), GFP_KERNEL); - if (!slot) - goto error; - memset(slot, 0, sizeof(struct slot)); + slot = kzalloc(sizeof(*slot), GFP_KERNEL); + if (!slot) + goto error; - slot->hotplug_slot = kmalloc(sizeof(struct hotplug_slot), GFP_KERNEL); - if (!slot->hotplug_slot) - goto error_slot; - memset(slot->hotplug_slot, 0, sizeof(struct hotplug_slot)); + slot->hotplug_slot = kzalloc(sizeof(*hotplug_slot), GFP_KERNEL); + if (!slot->hotplug_slot) + goto error_slot; - slot->hotplug_slot->info = kmalloc(sizeof(struct hotplug_slot_info), GFP_KERNEL); - if (!slot->hotplug_slot->info) - goto error_hpslot; - memset(slot->hotplug_slot->info, 0, sizeof(struct hotplug_slot_info)); + slot->hotplug_slot->info = kzalloc(sizeof(*hotplug_slot_info), + GFP_KERNEL); + if (!slot->hotplug_slot->info) + goto error_hpslot; - slot->hotplug_slot->name = kmalloc(SLOT_NAME_SIZE, GFP_KERNEL); - if (!slot->hotplug_slot->name) - goto error_info; + slot->hotplug_slot->name = kzalloc(SLOT_NAME_SIZE, GFP_KERNEL); + if (!slot->hotplug_slot->name) + goto error_info; - slot->number = i; + slot->hotplug_slot->private = slot; + slot->hotplug_slot->release = &release_slot; + slot->hotplug_slot->ops = &acpi_hotplug_slot_ops; - slot->hotplug_slot->private = slot; - slot->hotplug_slot->release = &release_slot; - slot->hotplug_slot->ops = &acpi_hotplug_slot_ops; + slot->acpi_slot = acpiphp_slot; + slot->hotplug_slot->info->power_status = acpiphp_get_power_status(slot->acpi_slot); + slot->hotplug_slot->info->attention_status = 0; + slot->hotplug_slot->info->latch_status = acpiphp_get_latch_status(slot->acpi_slot); + slot->hotplug_slot->info->adapter_status = acpiphp_get_adapter_status(slot->acpi_slot); + slot->hotplug_slot->info->max_bus_speed = PCI_SPEED_UNKNOWN; + slot->hotplug_slot->info->cur_bus_speed = PCI_SPEED_UNKNOWN; - slot->acpi_slot = get_slot_from_id(i); - slot->hotplug_slot->info->power_status = acpiphp_get_power_status(slot->acpi_slot); - slot->hotplug_slot->info->attention_status = 0; - slot->hotplug_slot->info->latch_status = acpiphp_get_latch_status(slot->acpi_slot); - slot->hotplug_slot->info->adapter_status = acpiphp_get_adapter_status(slot->acpi_slot); - slot->hotplug_slot->info->max_bus_speed = PCI_SPEED_UNKNOWN; - slot->hotplug_slot->info->cur_bus_speed = PCI_SPEED_UNKNOWN; + acpiphp_slot->slot = slot; + make_slot_name(slot); - make_slot_name(slot); + retval = pci_hp_register(slot->hotplug_slot); + if (retval) { + err("pci_hp_register failed with error %d\n", retval); + goto error_name; + } - retval = pci_hp_register(slot->hotplug_slot); - if (retval) { - err("pci_hp_register failed with error %d\n", retval); - goto error_name; - } - - /* add slot to our internal list */ - list_add(&slot->slot_list, &slot_list); - info("Slot [%s] registered\n", slot->hotplug_slot->name); - } + info("Slot [%s] registered\n", slot->hotplug_slot->name); return 0; error_name: @@ -412,17 +401,16 @@ error: } -static void __exit cleanup_slots (void) +void acpiphp_unregister_hotplug_slot(struct acpiphp_slot *acpiphp_slot) { - struct list_head *tmp, *n; - struct slot *slot; + struct slot *slot = acpiphp_slot->slot; + int retval = 0; - list_for_each_safe (tmp, n, &slot_list) { - /* memory will be freed in release_slot callback */ - slot = list_entry(tmp, struct slot, slot_list); - list_del(&slot->slot_list); - pci_hp_deregister(slot->hotplug_slot); - } + info ("Slot [%s] unregistered\n", slot->hotplug_slot->name); + + retval = pci_hp_deregister(slot->hotplug_slot); + if (retval) + err("pci_hp_deregister failed with error %d\n", retval); } @@ -439,16 +427,21 @@ static int __init acpiphp_init(void) /* read all the ACPI info from the system */ retval = init_acpi(); - if (retval && !(docking_station)) - return retval; - return init_slots(); + /* if we have found a docking station, we should + * go ahead and load even if init_acpi has found + * no slots. This handles the case when the _DCK + * method not defined under the actual dock bridge + */ + if (docking_station) + return 0; + else + return retval; } static void __exit acpiphp_exit(void) { - cleanup_slots(); /* deallocate internal data structures etc. */ acpiphp_glue_exit(); diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index 22d0f1cf1362..dbfdac63cb49 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c @@ -128,8 +128,7 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) acpi_handle tmp; acpi_status status = AE_OK; unsigned long adr, sun; - int device, function; - static int num_slots = 0; /* XXX if we support I/O node hotplug... */ + int device, function, retval; status = acpi_evaluate_integer(handle, "_ADR", NULL, &adr); @@ -198,7 +197,6 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) memset(slot, 0, sizeof(struct acpiphp_slot)); slot->bridge = bridge; - slot->id = num_slots++; slot->device = device; slot->sun = sun; INIT_LIST_HEAD(&slot->funcs); @@ -212,6 +210,11 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) dbg("found ACPI PCI Hotplug slot %d at PCI %04x:%02x:%02x\n", slot->sun, pci_domain_nr(bridge->pci_bus), bridge->pci_bus->number, slot->device); + retval = acpiphp_register_hotplug_slot(slot); + if (retval) { + warn("acpiphp_register_hotplug_slot failed(err code = 0x%x)\n", retval); + goto err_exit; + } } newfunc->slot = slot; @@ -253,6 +256,14 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) status = AE_OK; return status; + + err_exit: + bridge->nr_slots--; + bridge->slots = slot->next; + kfree(slot); + kfree(newfunc); + + return AE_OK; } @@ -335,9 +346,16 @@ static void init_bridge_misc(struct acpiphp_bridge *bridge) /* decode ACPI 2.0 _HPP (hot plug parameters) */ decode_hpp(bridge); + /* must be added to the list prior to calling register_slot */ + list_add(&bridge->list, &bridge_list); + /* register all slot objects under this bridge */ status = acpi_walk_namespace(ACPI_TYPE_DEVICE, bridge->handle, (u32)1, register_slot, bridge, NULL); + if (ACPI_FAILURE(status)) { + list_del(&bridge->list); + return; + } /* install notify handler */ if (bridge->type != BRIDGE_TYPE_HOST) { @@ -350,8 +368,6 @@ static void init_bridge_misc(struct acpiphp_bridge *bridge) err("failed to register interrupt notify handler\n"); } } - - list_add(&bridge->list, &bridge_list); } @@ -555,6 +571,8 @@ static void cleanup_bridge(struct acpiphp_bridge *bridge) list_del(list); kfree(func); } + acpiphp_unregister_hotplug_slot(slot); + list_del(&slot->funcs); kfree(slot); slot = next; } @@ -1521,26 +1539,6 @@ static int acpiphp_for_each_slot(acpiphp_callback fn, void *data) } #endif -/* search matching slot from id */ -struct acpiphp_slot *get_slot_from_id(int id) -{ - struct list_head *node; - struct acpiphp_bridge *bridge; - struct acpiphp_slot *slot; - - list_for_each (node, &bridge_list) { - bridge = (struct acpiphp_bridge *)node; - for (slot = bridge->slots; slot; slot = slot->next) - if (slot->id == id) - return slot; - } - - /* should never happen! */ - err("%s: no object for id %d\n", __FUNCTION__, id); - WARN_ON(1); - return NULL; -} - /** * acpiphp_enable_slot - power on slot From 0cccd0c20677e8a9da40018632f1b6c487ba2bd5 Mon Sep 17 00:00:00 2001 From: MUNEDA Takahiro Date: Fri, 24 Feb 2006 17:46:04 +0900 Subject: [PATCH 38/49] [PATCH] acpiphp: fix bridge handle When hotplug slot is under the host bridge, DEVICE_ACPI_HANDLE(&bus->self->dev) fails since '&bus->self' was not set. This patch fixes it. This patch is based on kristen's latest patches. I tested this patch on my Tiger4. Signed-off-by: MUNEDA Takahiro Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/acpiphp_glue.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index dbfdac63cb49..21fa13e84470 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c @@ -972,8 +972,8 @@ static int enable_device(struct acpiphp_slot *slot) acpiphp_sanitize_bus(bus); pci_enable_bridges(bus); pci_bus_add_devices(bus); - acpiphp_set_hpp_values(DEVICE_ACPI_HANDLE(&bus->self->dev), bus); - acpiphp_configure_ioapics(DEVICE_ACPI_HANDLE(&bus->self->dev)); + acpiphp_set_hpp_values(slot->bridge->handle, bus); + acpiphp_configure_ioapics(slot->bridge->handle); /* associate pci_dev to our representation */ list_for_each (l, &slot->funcs) { From 1305e9184a3de84f78dca102b293d21007bb6c49 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Sun, 26 Feb 2006 22:16:51 +0100 Subject: [PATCH 39/49] [PATCH] PCI: cpqphp_ctrl.c: board_replaced(): remove dead code The Coverity checker correctly noted, that in function board_replaced in drivers/pci/hotplug/cpqphp_ctrl.c, the variable src always has the value 8, and therefore much code after the ... if (rc || src) { ... if (rc) return rc; else return 1; } ... can never be called. This patch removes the unreachable code in this function fixing kernel Bugzilla #6073. Signed-off-by: Adrian Bunk Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/cpqphp_ctrl.c | 76 ++++++------------------------- 1 file changed, 14 insertions(+), 62 deletions(-) diff --git a/drivers/pci/hotplug/cpqphp_ctrl.c b/drivers/pci/hotplug/cpqphp_ctrl.c index 72eb8e2d2065..55d2dc7e39ca 100644 --- a/drivers/pci/hotplug/cpqphp_ctrl.c +++ b/drivers/pci/hotplug/cpqphp_ctrl.c @@ -1282,9 +1282,7 @@ static u32 board_replaced(struct pci_func *func, struct controller *ctrl) u8 hp_slot; u8 temp_byte; u8 adapter_speed; - u32 index; u32 rc = 0; - u32 src = 8; hp_slot = func->device - ctrl->slot_device_offset; @@ -1368,68 +1366,17 @@ static u32 board_replaced(struct pci_func *func, struct controller *ctrl) rc = cpqhp_configure_board(ctrl, func); - if (rc || src) { - /* If configuration fails, turn it off - * Get slot won't work for devices behind - * bridges, but in this case it will always be - * called for the "base" bus/dev/func of an - * adapter. */ - - mutex_lock(&ctrl->crit_sect); - - amber_LED_on (ctrl, hp_slot); - green_LED_off (ctrl, hp_slot); - slot_disable (ctrl, hp_slot); - - set_SOGO(ctrl); - - /* Wait for SOBS to be unset */ - wait_for_ctrl_irq (ctrl); - - mutex_unlock(&ctrl->crit_sect); - - if (rc) - return rc; - else - return 1; - } - - func->status = 0; - func->switch_save = 0x10; - - index = 1; - while (((func = cpqhp_slot_find(func->bus, func->device, index)) != NULL) && !rc) { - rc |= cpqhp_configure_board(ctrl, func); - index++; - } - - if (rc) { - /* If configuration fails, turn it off - * Get slot won't work for devices behind - * bridges, but in this case it will always be - * called for the "base" bus/dev/func of an - * adapter. */ - - mutex_lock(&ctrl->crit_sect); - - amber_LED_on (ctrl, hp_slot); - green_LED_off (ctrl, hp_slot); - slot_disable (ctrl, hp_slot); - - set_SOGO(ctrl); - - /* Wait for SOBS to be unset */ - wait_for_ctrl_irq (ctrl); - - mutex_unlock(&ctrl->crit_sect); - - return rc; - } - /* Done configuring so turn LED on full time */ + /* If configuration fails, turn it off + * Get slot won't work for devices behind + * bridges, but in this case it will always be + * called for the "base" bus/dev/func of an + * adapter. */ mutex_lock(&ctrl->crit_sect); - green_LED_on (ctrl, hp_slot); + amber_LED_on (ctrl, hp_slot); + green_LED_off (ctrl, hp_slot); + slot_disable (ctrl, hp_slot); set_SOGO(ctrl); @@ -1437,7 +1384,12 @@ static u32 board_replaced(struct pci_func *func, struct controller *ctrl) wait_for_ctrl_irq (ctrl); mutex_unlock(&ctrl->crit_sect); - rc = 0; + + if (rc) + return rc; + else + return 1; + } else { /* Something is wrong From 5eeca8e688b6affba4cd85262152fdd1b274ad33 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Sun, 5 Mar 2006 16:49:48 +0100 Subject: [PATCH 40/49] [PATCH] PCI: the scheduled removal of PCI_LEGACY_PROC This patch contains the scheduled removal of PCI_LEGACY_PROC. Signed-off-by: Adrian Bunk Signed-off-by: Greg Kroah-Hartman --- Documentation/feature-removal-schedule.txt | 7 -- drivers/pci/Kconfig | 17 --- drivers/pci/proc.c | 126 --------------------- 3 files changed, 150 deletions(-) diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt index afeaf6218ea2..c7a4d0faab22 100644 --- a/Documentation/feature-removal-schedule.txt +++ b/Documentation/feature-removal-schedule.txt @@ -158,13 +158,6 @@ Who: Adrian Bunk --------------------------- -What: Legacy /proc/pci interface (PCI_LEGACY_PROC) -When: March 2006 -Why: deprecated since 2.5.53 in favor of lspci(8) -Who: Adrian Bunk - ---------------------------- - What: pci_module_init(driver) When: January 2007 Why: Is replaced by pci_register_driver(pci_driver). diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig index f187fd8aeed6..d3dcce815d15 100644 --- a/drivers/pci/Kconfig +++ b/drivers/pci/Kconfig @@ -13,23 +13,6 @@ config PCI_MSI If you don't know what to do here, say N. -config PCI_LEGACY_PROC - bool "Legacy /proc/pci interface" - depends on PCI - ---help--- - This feature enables a procfs file -- /proc/pci -- that provides a - summary of PCI devices in the system. - - This feature has been deprecated as of v2.5.53, in favor of using the - tool lspci(8). This feature may be removed at a future date. - - lspci can provide the same data, as well as much more. lspci is a part of - the pci-utils package, which should be installed by your distribution. - See for information on where to get the latest - version. - - When in doubt, say N. - config PCI_DEBUG bool "PCI Debugging" depends on PCI && DEBUG_KERNEL diff --git a/drivers/pci/proc.c b/drivers/pci/proc.c index 92a885760832..54b2ebc9c91a 100644 --- a/drivers/pci/proc.c +++ b/drivers/pci/proc.c @@ -458,131 +458,6 @@ int pci_proc_detach_bus(struct pci_bus* bus) return 0; } -#ifdef CONFIG_PCI_LEGACY_PROC - -/* - * Backward compatible /proc/pci interface. - */ - -/* - * Convert some of the configuration space registers of the device at - * address (bus,devfn) into a string (possibly several lines each). - * The configuration string is stored starting at buf[len]. If the - * string would exceed the size of the buffer (SIZE), 0 is returned. - */ -static int show_dev_config(struct seq_file *m, void *v) -{ - struct pci_dev *dev = v; - struct pci_dev *first_dev; - struct pci_driver *drv; - u32 class_rev; - unsigned char latency, min_gnt, max_lat; - int reg; - - first_dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL); - if (dev == first_dev) - seq_puts(m, "PCI devices found:\n"); - pci_dev_put(first_dev); - - drv = pci_dev_driver(dev); - - pci_user_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev); - pci_user_read_config_byte (dev, PCI_LATENCY_TIMER, &latency); - pci_user_read_config_byte (dev, PCI_MIN_GNT, &min_gnt); - pci_user_read_config_byte (dev, PCI_MAX_LAT, &max_lat); - seq_printf(m, " Bus %2d, device %3d, function %2d:\n", - dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn)); - seq_printf(m, " Class %04x", class_rev >> 16); - seq_printf(m, ": PCI device %04x:%04x", dev->vendor, dev->device); - seq_printf(m, " (rev %d).\n", class_rev & 0xff); - - if (dev->irq) - seq_printf(m, " IRQ %d.\n", dev->irq); - - if (latency || min_gnt || max_lat) { - seq_printf(m, " Master Capable. "); - if (latency) - seq_printf(m, "Latency=%d. ", latency); - else - seq_puts(m, "No bursts. "); - if (min_gnt) - seq_printf(m, "Min Gnt=%d.", min_gnt); - if (max_lat) - seq_printf(m, "Max Lat=%d.", max_lat); - seq_putc(m, '\n'); - } - - for (reg = 0; reg < 6; reg++) { - struct resource *res = dev->resource + reg; - unsigned long base, end, flags; - - base = res->start; - end = res->end; - flags = res->flags; - if (!end) - continue; - - if (flags & PCI_BASE_ADDRESS_SPACE_IO) { - seq_printf(m, " I/O at 0x%lx [0x%lx].\n", - base, end); - } else { - const char *pref, *type = "unknown"; - - if (flags & PCI_BASE_ADDRESS_MEM_PREFETCH) - pref = "P"; - else - pref = "Non-p"; - switch (flags & PCI_BASE_ADDRESS_MEM_TYPE_MASK) { - case PCI_BASE_ADDRESS_MEM_TYPE_32: - type = "32 bit"; break; - case PCI_BASE_ADDRESS_MEM_TYPE_1M: - type = "20 bit"; break; - case PCI_BASE_ADDRESS_MEM_TYPE_64: - type = "64 bit"; break; - } - seq_printf(m, " %srefetchable %s memory at " - "0x%lx [0x%lx].\n", pref, type, - base, - end); - } - } - return 0; -} - -static struct seq_operations proc_pci_op = { - .start = pci_seq_start, - .next = pci_seq_next, - .stop = pci_seq_stop, - .show = show_dev_config -}; - -static int proc_pci_open(struct inode *inode, struct file *file) -{ - return seq_open(file, &proc_pci_op); -} -static struct file_operations proc_pci_operations = { - .open = proc_pci_open, - .read = seq_read, - .llseek = seq_lseek, - .release = seq_release, -}; - -static void legacy_proc_init(void) -{ - struct proc_dir_entry * entry = create_proc_entry("pci", 0, NULL); - if (entry) - entry->proc_fops = &proc_pci_operations; -} - -#else - -static void legacy_proc_init(void) -{ - -} - -#endif /* CONFIG_PCI_LEGACY_PROC */ - static int proc_bus_pci_dev_open(struct inode *inode, struct file *file) { return seq_open(file, &proc_bus_pci_devices_op); @@ -606,7 +481,6 @@ static int __init pci_proc_init(void) while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { pci_proc_attach_device(dev); } - legacy_proc_init(); return 0; } From 309e57df7b766172ba137a8cbd909f88dd76e8e9 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Sun, 5 Mar 2006 22:33:34 -0700 Subject: [PATCH 41/49] [PATCH] PCI: Provide a boot parameter to disable MSI Several drivers are starting to grow options to disable MSI. However, it's often a host chipset issue, not something which individual drivers should handle. So we add the pci=nomsi kernel parameter to allow the user to disable MSI modes for systems we haven't added to the quirk list yet. Signed-off-by: Matthew Wilcox Signed-off-by: Randy Dunlap Acked-by: Jeff Garzik Signed-off-by: Greg Kroah-Hartman --- Documentation/kernel-parameters.txt | 4 ++++ drivers/pci/Kconfig | 4 ++++ drivers/pci/msi.c | 10 ++++++++++ drivers/pci/pci.c | 8 ++++++-- drivers/pci/pci.h | 2 ++ 5 files changed, 26 insertions(+), 2 deletions(-) diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 7b7382d0f758..44a25f3f51d1 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -49,6 +49,7 @@ restrictions referred to are that the relevant option is valid if: MCA MCA bus support is enabled. MDA MDA console support is enabled. MOUSE Appropriate mouse support is enabled. + MSI Message Signaled Interrupts (PCI). MTD MTD support is enabled. NET Appropriate network support is enabled. NUMA NUMA support is enabled. @@ -1152,6 +1153,9 @@ running once the system is up. Mechanism 2. nommconf [IA-32,X86_64] Disable use of MMCONFIG for PCI Configuration + nomsi [MSI] If the PCI_MSI kernel config parameter is + enabled, this kernel boot option can be used to + disable the use of MSI interrupts system-wide. nosort [IA-32] Don't sort PCI devices according to order given by the PCI BIOS. This sorting is done to get a device order compatible with diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig index d3dcce815d15..4d762fc4878c 100644 --- a/drivers/pci/Kconfig +++ b/drivers/pci/Kconfig @@ -11,6 +11,10 @@ config PCI_MSI generate an interrupt using an inbound Memory Write on its PCI bus instead of asserting a device IRQ pin. + Use of PCI MSI interrupts can be disabled at kernel boot time + by using the 'pci=nomsi' option. This disables MSI for the + entire system. + If you don't know what to do here, say N. config PCI_DEBUG diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index aea8b258b9b8..a77e79c8c82e 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c @@ -765,8 +765,11 @@ void pci_disable_msi(struct pci_dev* dev) u16 control; unsigned long flags; + if (!pci_msi_enable) + return; if (!dev) return; + pos = pci_find_capability(dev, PCI_CAP_ID_MSI); if (!pos) return; @@ -1026,6 +1029,8 @@ void pci_disable_msix(struct pci_dev* dev) int pos, temp; u16 control; + if (!pci_msi_enable) + return; if (!dev) return; @@ -1152,6 +1157,11 @@ void msi_remove_pci_irq_vectors(struct pci_dev* dev) } } +void pci_no_msi(void) +{ + pci_msi_enable = 0; +} + EXPORT_SYMBOL(pci_enable_msi); EXPORT_SYMBOL(pci_disable_msi); EXPORT_SYMBOL(pci_enable_msix); diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 0bf6d254426b..03af23238939 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -900,8 +900,12 @@ static int __devinit pci_setup(char *str) if (k) *k++ = 0; if (*str && (str = pcibios_setup(str)) && *str) { - /* PCI layer options should be handled here */ - printk(KERN_ERR "PCI: Unknown option `%s'\n", str); + if (!strcmp(str, "nomsi")) { + pci_no_msi(); + } else { + printk(KERN_ERR "PCI: Unknown option `%s'\n", + str); + } } str = k; } diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index a6dfee2f6d2b..8f3fb47ea671 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h @@ -50,8 +50,10 @@ extern int pci_msi_quirk; #ifdef CONFIG_PCI_MSI void disable_msi_mode(struct pci_dev *dev, int pos, int type); +void pci_no_msi(void); #else static inline void disable_msi_mode(struct pci_dev *dev, int pos, int type) { } +static inline void pci_no_msi(void) { } #endif extern int pcie_mch_quirk; From 3c990e9219ea0b0aee588473ce6c8a66cdee3ff5 Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Sat, 4 Mar 2006 21:52:42 -0500 Subject: [PATCH 42/49] [PATCH] PCI: fix pci_request_region[s] arg Add missing 'const' to pci_request_region[s] 'res_name' arg, since we pass it directly to __request_region(), whose 'name' arg is also const. Signed-off-by: Greg Kroah-Hartman --- drivers/pci/pci.c | 4 ++-- include/linux/pci.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 03af23238939..bea1ad1ad5ba 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -639,7 +639,7 @@ void pci_release_region(struct pci_dev *pdev, int bar) * Returns 0 on success, or %EBUSY on error. A warning * message is also printed on failure. */ -int pci_request_region(struct pci_dev *pdev, int bar, char *res_name) +int pci_request_region(struct pci_dev *pdev, int bar, const char *res_name) { if (pci_resource_len(pdev, bar) == 0) return 0; @@ -697,7 +697,7 @@ void pci_release_regions(struct pci_dev *pdev) * Returns 0 on success, or %EBUSY on error. A warning * message is also printed on failure. */ -int pci_request_regions(struct pci_dev *pdev, char *res_name) +int pci_request_regions(struct pci_dev *pdev, const char *res_name) { int i; diff --git a/include/linux/pci.h b/include/linux/pci.h index d4d533fa5d30..0aad5a378e95 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -490,9 +490,9 @@ void pdev_sort_resources(struct pci_dev *, struct resource_list *); void pci_fixup_irqs(u8 (*)(struct pci_dev *, u8 *), int (*)(struct pci_dev *, u8, u8)); #define HAVE_PCI_REQ_REGIONS 2 -int pci_request_regions(struct pci_dev *, char *); +int pci_request_regions(struct pci_dev *, const char *); void pci_release_regions(struct pci_dev *); -int pci_request_region(struct pci_dev *, int, char *); +int pci_request_region(struct pci_dev *, int, const char *); void pci_release_region(struct pci_dev *, int); /* drivers/pci/bus.c */ From 0afabe906539b4e8b9e895f19ea31aabdf12f30b Mon Sep 17 00:00:00 2001 From: Kenji Kaneshige Date: Wed, 1 Mar 2006 14:55:11 +0900 Subject: [PATCH 43/49] [PATCH] shpchp: cleanup bus speed handling The code related to handling bus speed in SHPCHP driver is unnecessarily complex. This patch cleans up and simplify that. Signed-off-by: Kenji Kaneshige Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/shpchp_ctrl.c | 152 +++------- drivers/pci/hotplug/shpchp_hpc.c | 466 ++++++++++-------------------- 2 files changed, 189 insertions(+), 429 deletions(-) diff --git a/drivers/pci/hotplug/shpchp_ctrl.c b/drivers/pci/hotplug/shpchp_ctrl.c index 10f3257b18a7..4e6381481c55 100644 --- a/drivers/pci/hotplug/shpchp_ctrl.c +++ b/drivers/pci/hotplug/shpchp_ctrl.c @@ -198,7 +198,8 @@ static int change_bus_speed(struct controller *ctrl, struct slot *p_slot, dbg("%s: change to speed %d\n", __FUNCTION__, speed); if ((rc = p_slot->hpc_ops->set_bus_speed_mode(p_slot, speed))) { - err("%s: Issue of set bus speed mode command failed\n", __FUNCTION__); + err("%s: Issue of set bus speed mode command failed\n", + __FUNCTION__); return WRONG_BUS_FREQUENCY; } return rc; @@ -209,33 +210,26 @@ static int fix_bus_speed(struct controller *ctrl, struct slot *pslot, enum pci_bus_speed msp) { int rc = 0; - - if (flag != 0) { /* Other slots on the same bus are occupied */ - if ( asp < bsp ) { - err("%s: speed of bus %x and adapter %x mismatch\n", __FUNCTION__, bsp, asp); - return WRONG_BUS_FREQUENCY; + + /* + * If other slots on the same bus are occupied, we cannot + * change the bus speed. + */ + if (flag) { + if (asp < bsp) { + err("%s: speed of bus %x and adapter %x mismatch\n", + __FUNCTION__, bsp, asp); + rc = WRONG_BUS_FREQUENCY; } + return rc; + } + + if (asp < msp) { + if (bsp != asp) + rc = change_bus_speed(ctrl, pslot, asp); } else { - /* Other slots on the same bus are empty */ - if (msp == bsp) { - /* if adapter_speed >= bus_speed, do nothing */ - if (asp < bsp) { - /* - * Try to lower bus speed to accommodate the adapter if other slots - * on the same controller are empty - */ - if ((rc = change_bus_speed(ctrl, pslot, asp))) - return rc; - } - } else { - if (asp < msp) { - if ((rc = change_bus_speed(ctrl, pslot, asp))) - return rc; - } else { - if ((rc = change_bus_speed(ctrl, pslot, msp))) - return rc; - } - } + if (bsp != msp) + rc = change_bus_speed(ctrl, pslot, msp); } return rc; } @@ -252,8 +246,7 @@ static int board_added(struct slot *p_slot) u8 hp_slot; u8 slots_not_empty = 0; int rc = 0; - enum pci_bus_speed adapter_speed, bus_speed, max_bus_speed; - u8 pi, mode; + enum pci_bus_speed asp, bsp, msp; struct controller *ctrl = p_slot->ctrl; hp_slot = p_slot->device - ctrl->slot_device_offset; @@ -285,109 +278,36 @@ static int board_added(struct slot *p_slot) } } - rc = p_slot->hpc_ops->get_adapter_speed(p_slot, &adapter_speed); - /* 0 = PCI 33Mhz, 1 = PCI 66 Mhz, 2 = PCI-X 66 PA, 4 = PCI-X 66 ECC, */ - /* 5 = PCI-X 133 PA, 7 = PCI-X 133 ECC, 0xa = PCI-X 133 Mhz 266, */ - /* 0xd = PCI-X 133 Mhz 533 */ - /* This encoding is different from the one used in cur_bus_speed & */ - /* max_bus_speed */ - - if (rc || adapter_speed == PCI_SPEED_UNKNOWN) { - err("%s: Can't get adapter speed or bus mode mismatch\n", __FUNCTION__); + rc = p_slot->hpc_ops->get_adapter_speed(p_slot, &asp); + if (rc) { + err("%s: Can't get adapter speed or bus mode mismatch\n", + __FUNCTION__); return WRONG_BUS_FREQUENCY; } - rc = p_slot->hpc_ops->get_cur_bus_speed(p_slot, &bus_speed); - if (rc || bus_speed == PCI_SPEED_UNKNOWN) { + rc = p_slot->hpc_ops->get_cur_bus_speed(p_slot, &bsp); + if (rc) { err("%s: Can't get bus operation speed\n", __FUNCTION__); return WRONG_BUS_FREQUENCY; } - rc = p_slot->hpc_ops->get_max_bus_speed(p_slot, &max_bus_speed); - if (rc || max_bus_speed == PCI_SPEED_UNKNOWN) { + rc = p_slot->hpc_ops->get_max_bus_speed(p_slot, &msp); + if (rc) { err("%s: Can't get max bus operation speed\n", __FUNCTION__); - max_bus_speed = bus_speed; - } - - if ((rc = p_slot->hpc_ops->get_prog_int(p_slot, &pi))) { - err("%s: Can't get controller programming interface, set it to 1\n", __FUNCTION__); - pi = 1; + msp = bsp; } /* Check if there are other slots or devices on the same bus */ if (!list_empty(&ctrl->pci_dev->subordinate->devices)) slots_not_empty = 1; - dbg("%s: slots_not_empty %d, pi %d\n", __FUNCTION__, - slots_not_empty, pi); - dbg("adapter_speed %d, bus_speed %d, max_bus_speed %d\n", - adapter_speed, bus_speed, max_bus_speed); + dbg("%s: slots_not_empty %d, adapter_speed %d, bus_speed %d, " + "max_bus_speed %d\n", __FUNCTION__, slots_not_empty, asp, + bsp, msp); - if (pi == 2) { - dbg("%s: In PI = %d\n", __FUNCTION__, pi); - if ((rc = p_slot->hpc_ops->get_mode1_ECC_cap(p_slot, &mode))) { - err("%s: Can't get Mode1_ECC, set mode to 0\n", __FUNCTION__); - mode = 0; - } - - switch (adapter_speed) { - case PCI_SPEED_133MHz_PCIX_533: - case PCI_SPEED_133MHz_PCIX_266: - if ((bus_speed != adapter_speed) && - ((rc = fix_bus_speed(ctrl, p_slot, slots_not_empty, adapter_speed, bus_speed, max_bus_speed)))) - return rc; - break; - case PCI_SPEED_133MHz_PCIX_ECC: - case PCI_SPEED_133MHz_PCIX: - if (mode) { /* Bus - Mode 1 ECC */ - if ((bus_speed != 0x7) && - ((rc = fix_bus_speed(ctrl, p_slot, slots_not_empty, adapter_speed, bus_speed, max_bus_speed)))) - return rc; - } else { - if ((bus_speed != 0x4) && - ((rc = fix_bus_speed(ctrl, p_slot, slots_not_empty, adapter_speed, bus_speed, max_bus_speed)))) - return rc; - } - break; - case PCI_SPEED_66MHz_PCIX_ECC: - case PCI_SPEED_66MHz_PCIX: - if (mode) { /* Bus - Mode 1 ECC */ - if ((bus_speed != 0x5) && - ((rc = fix_bus_speed(ctrl, p_slot, slots_not_empty, adapter_speed, bus_speed, max_bus_speed)))) - return rc; - } else { - if ((bus_speed != 0x2) && - ((rc = fix_bus_speed(ctrl, p_slot, slots_not_empty, adapter_speed, bus_speed, max_bus_speed)))) - return rc; - } - break; - case PCI_SPEED_66MHz: - if ((bus_speed != 0x1) && - ((rc = fix_bus_speed(ctrl, p_slot, slots_not_empty, adapter_speed, bus_speed, max_bus_speed)))) - return rc; - break; - case PCI_SPEED_33MHz: - if (bus_speed > 0x0) { - if (slots_not_empty == 0) { - if ((rc = change_bus_speed(ctrl, p_slot, adapter_speed))) - return rc; - } else { - err("%s: speed of bus %x and adapter %x mismatch\n", __FUNCTION__, bus_speed, adapter_speed); - return WRONG_BUS_FREQUENCY; - } - } - break; - default: - err("%s: speed of bus %x and adapter %x mismatch\n", __FUNCTION__, bus_speed, adapter_speed); - return WRONG_BUS_FREQUENCY; - } - } else { - /* If adpater_speed == bus_speed, nothing to do here */ - dbg("%s: In PI = %d\n", __FUNCTION__, pi); - if ((adapter_speed != bus_speed) && - ((rc = fix_bus_speed(ctrl, p_slot, slots_not_empty, adapter_speed, bus_speed, max_bus_speed)))) - return rc; - } + rc = fix_bus_speed(ctrl, p_slot, slots_not_empty, asp, bsp, msp); + if (rc) + return rc; /* turn on board, blink green LED, turn off Amber LED */ if ((rc = p_slot->hpc_ops->slot_enable(p_slot))) { diff --git a/drivers/pci/hotplug/shpchp_hpc.c b/drivers/pci/hotplug/shpchp_hpc.c index b392606a905a..66123cf4deaa 100644 --- a/drivers/pci/hotplug/shpchp_hpc.c +++ b/drivers/pci/hotplug/shpchp_hpc.c @@ -82,31 +82,6 @@ #define SLOT_100MHZ_PCIX_533 0x0f000000 #define SLOT_133MHZ_PCIX_533 0xf0000000 - -/* Secondary Bus Configuration Register */ -/* For PI = 1, Bits 0 to 2 have been encoded as follows to show current bus speed/mode */ -#define PCI_33MHZ 0x0 -#define PCI_66MHZ 0x1 -#define PCIX_66MHZ 0x2 -#define PCIX_100MHZ 0x3 -#define PCIX_133MHZ 0x4 - -/* For PI = 2, Bits 0 to 3 have been encoded as follows to show current bus speed/mode */ -#define PCI_33MHZ 0x0 -#define PCI_66MHZ 0x1 -#define PCIX_66MHZ 0x2 -#define PCIX_100MHZ 0x3 -#define PCIX_133MHZ 0x4 -#define PCIX_66MHZ_ECC 0x5 -#define PCIX_100MHZ_ECC 0x6 -#define PCIX_133MHZ_ECC 0x7 -#define PCIX_66MHZ_266 0x9 -#define PCIX_100MHZ_266 0xa -#define PCIX_133MHZ_266 0xb -#define PCIX_66MHZ_533 0x11 -#define PCIX_100MHZ_533 0x12 -#define PCIX_133MHZ_533 0x13 - /* Slot Configuration */ #define SLOT_NUM 0x0000001F #define FIRST_DEV_NUM 0x00001F00 @@ -548,81 +523,41 @@ static int hpc_get_prog_int(struct slot *slot, u8 *prog_int) static int hpc_get_adapter_speed(struct slot *slot, enum pci_bus_speed *value) { - struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; - u32 slot_reg; - u16 slot_status, sec_bus_status; - u8 m66_cap, pcix_cap, pi; int retval = 0; + struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; + u32 slot_reg = readl(php_ctlr->creg + SLOT1 + 4 * slot->hp_slot); + u8 pcix_cap = (slot_reg >> 12) & 7; + u8 m66_cap = (slot_reg >> 9) & 1; DBG_ENTER_ROUTINE - if (!slot->ctrl->hpc_ctlr_handle) { - err("%s: Invalid HPC controller handle!\n", __FUNCTION__); - return -1; - } + dbg("%s: slot_reg = %x, pcix_cap = %x, m66_cap = %x\n", + __FUNCTION__, slot_reg, pcix_cap, m66_cap); - if (slot->hp_slot >= php_ctlr->num_slots) { - err("%s: Invalid HPC slot number!\n", __FUNCTION__); - return -1; - } - - pi = readb(php_ctlr->creg + PROG_INTERFACE); - slot_reg = readl(php_ctlr->creg + SLOT1 + 4*(slot->hp_slot)); - dbg("%s: pi = %d, slot_reg = %x\n", __FUNCTION__, pi, slot_reg); - slot_status = (u16) slot_reg; - dbg("%s: slot_status = %x\n", __FUNCTION__, slot_status); - sec_bus_status = readw(php_ctlr->creg + SEC_BUS_CONFIG); - - pcix_cap = (u8) ((slot_status & 0x3000) >> 12); - dbg("%s: pcix_cap = %x\n", __FUNCTION__, pcix_cap); - m66_cap = (u8) ((slot_status & 0x0200) >> 9); - dbg("%s: m66_cap = %x\n", __FUNCTION__, m66_cap); - - - if (pi == 2) { - switch (pcix_cap) { - case 0: - *value = m66_cap ? PCI_SPEED_66MHz : PCI_SPEED_33MHz; - break; - case 1: - *value = PCI_SPEED_66MHz_PCIX; - break; - case 3: - *value = PCI_SPEED_133MHz_PCIX; - break; - case 4: - *value = PCI_SPEED_133MHz_PCIX_266; - break; - case 5: - *value = PCI_SPEED_133MHz_PCIX_533; - break; - case 2: /* Reserved */ - default: - *value = PCI_SPEED_UNKNOWN; - retval = -ENODEV; - break; - } - } else { - switch (pcix_cap) { - case 0: - *value = m66_cap ? PCI_SPEED_66MHz : PCI_SPEED_33MHz; - break; - case 1: - *value = PCI_SPEED_66MHz_PCIX; - break; - case 3: - *value = PCI_SPEED_133MHz_PCIX; - break; - case 2: /* Reserved */ - default: - *value = PCI_SPEED_UNKNOWN; - retval = -ENODEV; - break; - } + switch (pcix_cap) { + case 0x0: + *value = m66_cap ? PCI_SPEED_66MHz : PCI_SPEED_33MHz; + break; + case 0x1: + *value = PCI_SPEED_66MHz_PCIX; + break; + case 0x3: + *value = PCI_SPEED_133MHz_PCIX; + break; + case 0x4: + *value = PCI_SPEED_133MHz_PCIX_266; + break; + case 0x5: + *value = PCI_SPEED_133MHz_PCIX_533; + break; + case 0x2: + default: + *value = PCI_SPEED_UNKNOWN; + retval = -ENODEV; + break; } dbg("Adapter speed = %d\n", *value); - DBG_LEAVE_ROUTINE return retval; } @@ -965,98 +900,66 @@ static int hpc_slot_disable(struct slot * slot) static int hpc_set_bus_speed_mode(struct slot * slot, enum pci_bus_speed value) { - u8 slot_cmd; - u8 pi; - int retval = 0; + int retval; struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; + u8 pi, cmd; DBG_ENTER_ROUTINE - - if (!slot->ctrl->hpc_ctlr_handle) { - err("%s: Invalid HPC controller handle!\n", __FUNCTION__); - return -1; - } pi = readb(php_ctlr->creg + PROG_INTERFACE); - - if (pi == 1) { - switch (value) { - case 0: - slot_cmd = SETA_PCI_33MHZ; - break; - case 1: - slot_cmd = SETA_PCI_66MHZ; - break; - case 2: - slot_cmd = SETA_PCIX_66MHZ; - break; - case 3: - slot_cmd = SETA_PCIX_100MHZ; - break; - case 4: - slot_cmd = SETA_PCIX_133MHZ; - break; - default: - slot_cmd = PCI_SPEED_UNKNOWN; - retval = -ENODEV; - return retval; - } - } else { - switch (value) { - case 0: - slot_cmd = SETB_PCI_33MHZ; - break; - case 1: - slot_cmd = SETB_PCI_66MHZ; - break; - case 2: - slot_cmd = SETB_PCIX_66MHZ_PM; - break; - case 3: - slot_cmd = SETB_PCIX_100MHZ_PM; - break; - case 4: - slot_cmd = SETB_PCIX_133MHZ_PM; - break; - case 5: - slot_cmd = SETB_PCIX_66MHZ_EM; - break; - case 6: - slot_cmd = SETB_PCIX_100MHZ_EM; - break; - case 7: - slot_cmd = SETB_PCIX_133MHZ_EM; - break; - case 8: - slot_cmd = SETB_PCIX_66MHZ_266; - break; - case 0x9: - slot_cmd = SETB_PCIX_100MHZ_266; - break; - case 0xa: - slot_cmd = SETB_PCIX_133MHZ_266; - break; - case 0xb: - slot_cmd = SETB_PCIX_66MHZ_533; - break; - case 0xc: - slot_cmd = SETB_PCIX_100MHZ_533; - break; - case 0xd: - slot_cmd = SETB_PCIX_133MHZ_533; - break; - default: - slot_cmd = PCI_SPEED_UNKNOWN; - retval = -ENODEV; - return retval; - } + if ((pi == 1) && (value > PCI_SPEED_133MHz_PCIX)) + return -EINVAL; + switch (value) { + case PCI_SPEED_33MHz: + cmd = SETA_PCI_33MHZ; + break; + case PCI_SPEED_66MHz: + cmd = SETA_PCI_66MHZ; + break; + case PCI_SPEED_66MHz_PCIX: + cmd = SETA_PCIX_66MHZ; + break; + case PCI_SPEED_100MHz_PCIX: + cmd = SETA_PCIX_100MHZ; + break; + case PCI_SPEED_133MHz_PCIX: + cmd = SETA_PCIX_133MHZ; + break; + case PCI_SPEED_66MHz_PCIX_ECC: + cmd = SETB_PCIX_66MHZ_EM; + break; + case PCI_SPEED_100MHz_PCIX_ECC: + cmd = SETB_PCIX_100MHZ_EM; + break; + case PCI_SPEED_133MHz_PCIX_ECC: + cmd = SETB_PCIX_133MHZ_EM; + break; + case PCI_SPEED_66MHz_PCIX_266: + cmd = SETB_PCIX_66MHZ_266; + break; + case PCI_SPEED_100MHz_PCIX_266: + cmd = SETB_PCIX_100MHZ_266; + break; + case PCI_SPEED_133MHz_PCIX_266: + cmd = SETB_PCIX_133MHZ_266; + break; + case PCI_SPEED_66MHz_PCIX_533: + cmd = SETB_PCIX_66MHZ_533; + break; + case PCI_SPEED_100MHz_PCIX_533: + cmd = SETB_PCIX_100MHZ_533; + break; + case PCI_SPEED_133MHz_PCIX_533: + cmd = SETB_PCIX_133MHZ_533; + break; + default: + return -EINVAL; } - retval = shpc_write_cmd(slot, 0, slot_cmd); - if (retval) { + + retval = shpc_write_cmd(slot, 0, cmd); + if (retval) err("%s: Write command failed!\n", __FUNCTION__); - return -1; - } DBG_LEAVE_ROUTINE return retval; @@ -1163,64 +1066,43 @@ static irqreturn_t shpc_isr(int IRQ, void *dev_id, struct pt_regs *regs) static int hpc_get_max_bus_speed (struct slot *slot, enum pci_bus_speed *value) { + int retval = 0; struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; enum pci_bus_speed bus_speed = PCI_SPEED_UNKNOWN; - int retval = 0; - u8 pi; - u32 slot_avail1, slot_avail2; + u8 pi = readb(php_ctlr->creg + PROG_INTERFACE); + u32 slot_avail1 = readl(php_ctlr->creg + SLOT_AVAIL1); + u32 slot_avail2 = readl(php_ctlr->creg + SLOT_AVAIL2); DBG_ENTER_ROUTINE - if (!slot->ctrl->hpc_ctlr_handle) { - err("%s: Invalid HPC controller handle!\n", __FUNCTION__); - return -1; - } - - if (slot->hp_slot >= php_ctlr->num_slots) { - err("%s: Invalid HPC slot number!\n", __FUNCTION__); - return -1; - } - - pi = readb(php_ctlr->creg + PROG_INTERFACE); - slot_avail1 = readl(php_ctlr->creg + SLOT_AVAIL1); - slot_avail2 = readl(php_ctlr->creg + SLOT_AVAIL2); - if (pi == 2) { if (slot_avail2 & SLOT_133MHZ_PCIX_533) - bus_speed = PCIX_133MHZ_533; + bus_speed = PCI_SPEED_133MHz_PCIX_533; else if (slot_avail2 & SLOT_100MHZ_PCIX_533) - bus_speed = PCIX_100MHZ_533; + bus_speed = PCI_SPEED_100MHz_PCIX_533; else if (slot_avail2 & SLOT_66MHZ_PCIX_533) - bus_speed = PCIX_66MHZ_533; + bus_speed = PCI_SPEED_66MHz_PCIX_533; else if (slot_avail2 & SLOT_133MHZ_PCIX_266) - bus_speed = PCIX_133MHZ_266; + bus_speed = PCI_SPEED_133MHz_PCIX_266; else if (slot_avail2 & SLOT_100MHZ_PCIX_266) - bus_speed = PCIX_100MHZ_266; + bus_speed = PCI_SPEED_100MHz_PCIX_266; else if (slot_avail2 & SLOT_66MHZ_PCIX_266) - bus_speed = PCIX_66MHZ_266; - else if (slot_avail1 & SLOT_133MHZ_PCIX) - bus_speed = PCIX_133MHZ; - else if (slot_avail1 & SLOT_100MHZ_PCIX) - bus_speed = PCIX_100MHZ; - else if (slot_avail1 & SLOT_66MHZ_PCIX) - bus_speed = PCIX_66MHZ; - else if (slot_avail2 & SLOT_66MHZ) - bus_speed = PCI_66MHZ; - else if (slot_avail1 & SLOT_33MHZ) - bus_speed = PCI_33MHZ; - else bus_speed = PCI_SPEED_UNKNOWN; - } else { + bus_speed = PCI_SPEED_66MHz_PCIX_266; + } + + if (bus_speed == PCI_SPEED_UNKNOWN) { if (slot_avail1 & SLOT_133MHZ_PCIX) - bus_speed = PCIX_133MHZ; + bus_speed = PCI_SPEED_133MHz_PCIX; else if (slot_avail1 & SLOT_100MHZ_PCIX) - bus_speed = PCIX_100MHZ; + bus_speed = PCI_SPEED_100MHz_PCIX; else if (slot_avail1 & SLOT_66MHZ_PCIX) - bus_speed = PCIX_66MHZ; + bus_speed = PCI_SPEED_66MHz_PCIX; else if (slot_avail2 & SLOT_66MHZ) - bus_speed = PCI_66MHZ; + bus_speed = PCI_SPEED_66MHz; else if (slot_avail1 & SLOT_33MHZ) - bus_speed = PCI_33MHZ; - else bus_speed = PCI_SPEED_UNKNOWN; + bus_speed = PCI_SPEED_33MHz; + else + retval = -ENODEV; } *value = bus_speed; @@ -1231,111 +1113,69 @@ static int hpc_get_max_bus_speed (struct slot *slot, enum pci_bus_speed *value) static int hpc_get_cur_bus_speed (struct slot *slot, enum pci_bus_speed *value) { + int retval = 0; struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; enum pci_bus_speed bus_speed = PCI_SPEED_UNKNOWN; - u16 sec_bus_status; - int retval = 0; - u8 pi; + u16 sec_bus_reg = readw(php_ctlr->creg + SEC_BUS_CONFIG); + u8 pi = readb(php_ctlr->creg + PROG_INTERFACE); + u8 speed_mode = (pi == 2) ? (sec_bus_reg & 0xF) : (sec_bus_reg & 0x7); DBG_ENTER_ROUTINE - if (!slot->ctrl->hpc_ctlr_handle) { - err("%s: Invalid HPC controller handle!\n", __FUNCTION__); - return -1; + if ((pi == 1) && (speed_mode > 4)) { + *value = PCI_SPEED_UNKNOWN; + return -ENODEV; } - if (slot->hp_slot >= php_ctlr->num_slots) { - err("%s: Invalid HPC slot number!\n", __FUNCTION__); - return -1; + switch (speed_mode) { + case 0x0: + *value = PCI_SPEED_33MHz; + break; + case 0x1: + *value = PCI_SPEED_66MHz; + break; + case 0x2: + *value = PCI_SPEED_66MHz_PCIX; + break; + case 0x3: + *value = PCI_SPEED_100MHz_PCIX; + break; + case 0x4: + *value = PCI_SPEED_133MHz_PCIX; + break; + case 0x5: + *value = PCI_SPEED_66MHz_PCIX_ECC; + break; + case 0x6: + *value = PCI_SPEED_100MHz_PCIX_ECC; + break; + case 0x7: + *value = PCI_SPEED_133MHz_PCIX_ECC; + break; + case 0x8: + *value = PCI_SPEED_66MHz_PCIX_266; + break; + case 0x9: + *value = PCI_SPEED_100MHz_PCIX_266; + break; + case 0xa: + *value = PCI_SPEED_133MHz_PCIX_266; + break; + case 0xb: + *value = PCI_SPEED_66MHz_PCIX_533; + break; + case 0xc: + *value = PCI_SPEED_100MHz_PCIX_533; + break; + case 0xd: + *value = PCI_SPEED_133MHz_PCIX_533; + break; + default: + *value = PCI_SPEED_UNKNOWN; + retval = -ENODEV; + break; } - pi = readb(php_ctlr->creg + PROG_INTERFACE); - sec_bus_status = readw(php_ctlr->creg + SEC_BUS_CONFIG); - - if (pi == 2) { - switch (sec_bus_status & 0x000f) { - case 0: - bus_speed = PCI_SPEED_33MHz; - break; - case 1: - bus_speed = PCI_SPEED_66MHz; - break; - case 2: - bus_speed = PCI_SPEED_66MHz_PCIX; - break; - case 3: - bus_speed = PCI_SPEED_100MHz_PCIX; - break; - case 4: - bus_speed = PCI_SPEED_133MHz_PCIX; - break; - case 5: - bus_speed = PCI_SPEED_66MHz_PCIX_ECC; - break; - case 6: - bus_speed = PCI_SPEED_100MHz_PCIX_ECC; - break; - case 7: - bus_speed = PCI_SPEED_133MHz_PCIX_ECC; - break; - case 8: - bus_speed = PCI_SPEED_66MHz_PCIX_266; - break; - case 9: - bus_speed = PCI_SPEED_100MHz_PCIX_266; - break; - case 0xa: - bus_speed = PCI_SPEED_133MHz_PCIX_266; - break; - case 0xb: - bus_speed = PCI_SPEED_66MHz_PCIX_533; - break; - case 0xc: - bus_speed = PCI_SPEED_100MHz_PCIX_533; - break; - case 0xd: - bus_speed = PCI_SPEED_133MHz_PCIX_533; - break; - case 0xe: - case 0xf: - default: - bus_speed = PCI_SPEED_UNKNOWN; - break; - } - } else { - /* In the case where pi is undefined, default it to 1 */ - switch (sec_bus_status & 0x0007) { - case 0: - bus_speed = PCI_SPEED_33MHz; - break; - case 1: - bus_speed = PCI_SPEED_66MHz; - break; - case 2: - bus_speed = PCI_SPEED_66MHz_PCIX; - break; - case 3: - bus_speed = PCI_SPEED_100MHz_PCIX; - break; - case 4: - bus_speed = PCI_SPEED_133MHz_PCIX; - break; - case 5: - bus_speed = PCI_SPEED_UNKNOWN; /* Reserved */ - break; - case 6: - bus_speed = PCI_SPEED_UNKNOWN; /* Reserved */ - break; - case 7: - bus_speed = PCI_SPEED_UNKNOWN; /* Reserved */ - break; - default: - bus_speed = PCI_SPEED_UNKNOWN; - break; - } - } - - *value = bus_speed; dbg("Current bus speed = %d\n", bus_speed); DBG_LEAVE_ROUTINE return retval; From 8e77af6a9a9b1eefdb538894b20ed41f65b65ab7 Mon Sep 17 00:00:00 2001 From: John Keller Date: Wed, 8 Mar 2006 13:21:34 -0600 Subject: [PATCH 44/49] [PATCH] PCI Hotplug: SN: Fix cleanup on hotplug removal of PPB When doing a hotplug removal of a PPB, sn_bus_store_sysdata() needs to be called for the PPB and all of its children. Acked-by: Prarit Bhargava Signed-off-by: John Keller Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/sgi_hotplug.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/pci/hotplug/sgi_hotplug.c b/drivers/pci/hotplug/sgi_hotplug.c index a32ae82e5922..c402da8e78ae 100644 --- a/drivers/pci/hotplug/sgi_hotplug.c +++ b/drivers/pci/hotplug/sgi_hotplug.c @@ -3,7 +3,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 2005 Silicon Graphics, Inc. All rights reserved. + * Copyright (C) 2005-2006 Silicon Graphics, Inc. All rights reserved. * * This work was based on the 2.4/2.6 kernel development by Dick Reigner. * Work to add BIOS PROM support was completed by Mike Habeck. @@ -230,6 +230,13 @@ static void sn_bus_free_data(struct pci_dev *dev) list_for_each_entry(child, &subordinate_bus->devices, bus_list) sn_bus_free_data(child); } + /* + * Some drivers may use dma accesses during the + * driver remove function. We release the sysdata + * areas after the driver remove functions have + * been called. + */ + sn_bus_store_sysdata(dev); sn_pci_unfixup_slot(dev); } @@ -429,13 +436,6 @@ static int disable_slot(struct hotplug_slot *bss_hotplug_slot) PCI_DEVFN(slot->device_num + 1, PCI_FUNC(func))); if (dev) { - /* - * Some drivers may use dma accesses during the - * driver remove function. We release the sysdata - * areas after the driver remove functions have - * been called. - */ - sn_bus_store_sysdata(dev); sn_bus_free_data(dev); pci_remove_bus_device(dev); pci_dev_put(dev); From 7c8f25da12a3dda46fb730699582895d5fc51287 Mon Sep 17 00:00:00 2001 From: Kenji Kaneshige Date: Mon, 27 Feb 2006 22:15:49 +0900 Subject: [PATCH 45/49] [PATCH] acpiphp: Scan slots under the nested P2P bridge Current ACPIPHP driver scans only slots under the top level PCI-to-PCI bridge. So hotplug PCI slots under the nested PCI-to-PCI bridge would not be detected. For example, if the system has the ACPI namespace like below, hotplug slots woule not be detected. Device (PCI0) { /* Root bridge */ Name (_HID, "PNP0A03") Device (P2PA) { /* PCI-to-PCI bridge */ Name (_ADR, ...) Device (P2PB) { /* PCI-to-PCI bridge */ Name (_ADR, ...) Device (S0F0) { /* hotplug slot */ Name (_ADR, ...) Name (_SUN, ...) Method (_EJ0, ...) { ... } } ... Device (S0F7) { /* hotplug slot */ Name (_ADR, ...) Name (_SUN, ...) Method (_EJ0, ...) { ... } } Device (S1F0) { /* hotplug slot */ Name (_ADR, ...) Name (_SUN, ...) Method (_EJ0, ...) { ... } } ... } } } This patch fixes this issue. Signed-off-by: Kenji Kaneshige Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/acpiphp_glue.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index 21fa13e84470..cbd5893d198e 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c @@ -463,6 +463,12 @@ find_p2p_bridge(acpi_handle handle, u32 lvl, void *context, void **rv) add_p2p_bridge(handle, dev); } + /* search P2P bridges under this p2p bridge */ + status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1, + find_p2p_bridge, dev->subordinate, NULL); + if (ACPI_FAILURE(status)) + warn("find_p2p_bridge faied (error code = 0x%x)\n", status); + out: pci_dev_put(dev); return AE_OK; @@ -603,7 +609,8 @@ static void remove_bridge(acpi_handle handle) } else { /* clean-up p2p bridges under this host bridge */ acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, - (u32)1, cleanup_p2p_bridge, NULL, NULL); + ACPI_UINT32_MAX, cleanup_p2p_bridge, + NULL, NULL); } } From f5afe8064f3087bead8fea7e32547c2a3ada5fd0 Mon Sep 17 00:00:00 2001 From: Eric Sesterhenn Date: Tue, 28 Feb 2006 15:34:49 +0100 Subject: [PATCH 46/49] [PATCH] PCI: kzalloc() conversion in drivers/pci this patch converts drivers/pci to kzalloc usage. Compile tested with allyes config. Signed-off-by: Eric Sesterhenn Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/acpiphp_glue.c | 14 ++---- drivers/pci/hotplug/cpci_hotplug_core.c | 9 ++-- drivers/pci/hotplug/cpqphp_core.c | 13 ++--- drivers/pci/hotplug/fakephp.c | 9 ++-- drivers/pci/hotplug/ibmphp_core.c | 6 +-- drivers/pci/hotplug/ibmphp_ebda.c | 57 ++++++---------------- drivers/pci/hotplug/ibmphp_pci.c | 63 +++++++++---------------- drivers/pci/hotplug/ibmphp_res.c | 33 +++++-------- drivers/pci/hotplug/pciehp_core.c | 13 ++--- drivers/pci/hotplug/rpaphp_slot.c | 9 ++-- drivers/pci/pci-driver.c | 3 +- drivers/pci/pci-sysfs.c | 3 +- drivers/pci/pcie/portdrv_core.c | 3 +- drivers/pci/probe.c | 9 ++-- 14 files changed, 75 insertions(+), 169 deletions(-) diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index cbd5893d198e..c7e6387983df 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c @@ -143,10 +143,9 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) device = (adr >> 16) & 0xffff; function = adr & 0xffff; - newfunc = kmalloc(sizeof(struct acpiphp_func), GFP_KERNEL); + newfunc = kzalloc(sizeof(struct acpiphp_func), GFP_KERNEL); if (!newfunc) return AE_NO_MEMORY; - memset(newfunc, 0, sizeof(struct acpiphp_func)); INIT_LIST_HEAD(&newfunc->sibling); newfunc->handle = handle; @@ -189,13 +188,12 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) } if (!slot) { - slot = kmalloc(sizeof(struct acpiphp_slot), GFP_KERNEL); + slot = kzalloc(sizeof(struct acpiphp_slot), GFP_KERNEL); if (!slot) { kfree(newfunc); return AE_NO_MEMORY; } - memset(slot, 0, sizeof(struct acpiphp_slot)); slot->bridge = bridge; slot->device = device; slot->sun = sun; @@ -376,12 +374,10 @@ static void add_host_bridge(acpi_handle *handle, struct pci_bus *pci_bus) { struct acpiphp_bridge *bridge; - bridge = kmalloc(sizeof(struct acpiphp_bridge), GFP_KERNEL); + bridge = kzalloc(sizeof(struct acpiphp_bridge), GFP_KERNEL); if (bridge == NULL) return; - memset(bridge, 0, sizeof(struct acpiphp_bridge)); - bridge->type = BRIDGE_TYPE_HOST; bridge->handle = handle; @@ -398,14 +394,12 @@ static void add_p2p_bridge(acpi_handle *handle, struct pci_dev *pci_dev) { struct acpiphp_bridge *bridge; - bridge = kmalloc(sizeof(struct acpiphp_bridge), GFP_KERNEL); + bridge = kzalloc(sizeof(struct acpiphp_bridge), GFP_KERNEL); if (bridge == NULL) { err("out of memory\n"); return; } - memset(bridge, 0, sizeof(struct acpiphp_bridge)); - bridge->type = BRIDGE_TYPE_P2P; bridge->handle = handle; diff --git a/drivers/pci/hotplug/cpci_hotplug_core.c b/drivers/pci/hotplug/cpci_hotplug_core.c index 30af105271a2..037ce4c91687 100644 --- a/drivers/pci/hotplug/cpci_hotplug_core.c +++ b/drivers/pci/hotplug/cpci_hotplug_core.c @@ -248,22 +248,19 @@ cpci_hp_register_bus(struct pci_bus *bus, u8 first, u8 last) * with the pci_hotplug subsystem. */ for (i = first; i <= last; ++i) { - slot = kmalloc(sizeof (struct slot), GFP_KERNEL); + slot = kzalloc(sizeof (struct slot), GFP_KERNEL); if (!slot) goto error; - memset(slot, 0, sizeof (struct slot)); hotplug_slot = - kmalloc(sizeof (struct hotplug_slot), GFP_KERNEL); + kzalloc(sizeof (struct hotplug_slot), GFP_KERNEL); if (!hotplug_slot) goto error_slot; - memset(hotplug_slot, 0, sizeof (struct hotplug_slot)); slot->hotplug_slot = hotplug_slot; - info = kmalloc(sizeof (struct hotplug_slot_info), GFP_KERNEL); + info = kzalloc(sizeof (struct hotplug_slot_info), GFP_KERNEL); if (!info) goto error_hpslot; - memset(info, 0, sizeof (struct hotplug_slot_info)); hotplug_slot->info = info; name = kmalloc(SLOT_NAME_SIZE, GFP_KERNEL); diff --git a/drivers/pci/hotplug/cpqphp_core.c b/drivers/pci/hotplug/cpqphp_core.c index 8626901daeb8..9bc1deb8df52 100644 --- a/drivers/pci/hotplug/cpqphp_core.c +++ b/drivers/pci/hotplug/cpqphp_core.c @@ -347,26 +347,22 @@ static int ctrl_slot_setup(struct controller *ctrl, slot_number = ctrl->first_slot; while (number_of_slots) { - slot = kmalloc(sizeof(*slot), GFP_KERNEL); + slot = kzalloc(sizeof(*slot), GFP_KERNEL); if (!slot) goto error; - memset(slot, 0, sizeof(struct slot)); - slot->hotplug_slot = kmalloc(sizeof(*(slot->hotplug_slot)), + slot->hotplug_slot = kzalloc(sizeof(*(slot->hotplug_slot)), GFP_KERNEL); if (!slot->hotplug_slot) goto error_slot; hotplug_slot = slot->hotplug_slot; - memset(hotplug_slot, 0, sizeof(struct hotplug_slot)); hotplug_slot->info = - kmalloc(sizeof(*(hotplug_slot->info)), + kzalloc(sizeof(*(hotplug_slot->info)), GFP_KERNEL); if (!hotplug_slot->info) goto error_hpslot; hotplug_slot_info = hotplug_slot->info; - memset(hotplug_slot_info, 0, - sizeof(struct hotplug_slot_info)); hotplug_slot->name = kmalloc(SLOT_NAME_SIZE, GFP_KERNEL); if (!hotplug_slot->name) @@ -854,13 +850,12 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) goto err_disable_device; } - ctrl = (struct controller *) kmalloc(sizeof(struct controller), GFP_KERNEL); + ctrl = kzalloc(sizeof(struct controller), GFP_KERNEL); if (!ctrl) { err("%s : out of memory\n", __FUNCTION__); rc = -ENOMEM; goto err_disable_device; } - memset(ctrl, 0, sizeof(struct controller)); rc = pci_read_config_word(pdev, PCI_SUBSYSTEM_ID, &subsystem_deviceid); if (rc) { diff --git a/drivers/pci/hotplug/fakephp.c b/drivers/pci/hotplug/fakephp.c index 060d74775d7b..71b80c23e8ce 100644 --- a/drivers/pci/hotplug/fakephp.c +++ b/drivers/pci/hotplug/fakephp.c @@ -95,15 +95,13 @@ static int add_slot(struct pci_dev *dev) struct hotplug_slot *slot; int retval = -ENOMEM; - slot = kmalloc(sizeof(struct hotplug_slot), GFP_KERNEL); + slot = kzalloc(sizeof(struct hotplug_slot), GFP_KERNEL); if (!slot) goto error; - memset(slot, 0, sizeof(*slot)); - slot->info = kmalloc(sizeof(struct hotplug_slot_info), GFP_KERNEL); + slot->info = kzalloc(sizeof(struct hotplug_slot_info), GFP_KERNEL); if (!slot->info) goto error_slot; - memset(slot->info, 0, sizeof(struct hotplug_slot_info)); slot->info->power_status = 1; slot->info->max_bus_speed = PCI_SPEED_UNKNOWN; @@ -227,11 +225,10 @@ static void pci_rescan_bus(const struct pci_bus *bus) { unsigned int devfn; struct pci_dev *dev; - dev = kmalloc(sizeof(struct pci_dev), GFP_KERNEL); + dev = kzalloc(sizeof(struct pci_dev), GFP_KERNEL); if (!dev) return; - memset(dev, 0, sizeof(dev)); dev->bus = (struct pci_bus*)bus; dev->sysdata = bus->sysdata; for (devfn = 0; devfn < 0x100; devfn += 8) { diff --git a/drivers/pci/hotplug/ibmphp_core.c b/drivers/pci/hotplug/ibmphp_core.c index dc59da675c08..45e2a0d9b596 100644 --- a/drivers/pci/hotplug/ibmphp_core.c +++ b/drivers/pci/hotplug/ibmphp_core.c @@ -1141,7 +1141,7 @@ static int enable_slot(struct hotplug_slot *hs) goto error_power; } - slot_cur->func = kmalloc(sizeof(struct pci_func), GFP_KERNEL); + slot_cur->func = kzalloc(sizeof(struct pci_func), GFP_KERNEL); if (!slot_cur->func) { /* We cannot do update_slot_info here, since no memory for * kmalloc n.e.ways, and update_slot_info allocates some */ @@ -1149,7 +1149,6 @@ static int enable_slot(struct hotplug_slot *hs) rc = -ENOMEM; goto error_power; } - memset(slot_cur->func, 0, sizeof(struct pci_func)); slot_cur->func->busno = slot_cur->bus; slot_cur->func->device = slot_cur->device; for (i = 0; i < 4; i++) @@ -1252,13 +1251,12 @@ int ibmphp_do_disable_slot(struct slot *slot_cur) if (slot_cur->func == NULL) { /* We need this for fncs's that were there on bootup */ - slot_cur->func = kmalloc(sizeof(struct pci_func), GFP_KERNEL); + slot_cur->func = kzalloc(sizeof(struct pci_func), GFP_KERNEL); if (!slot_cur->func) { err("out of system memory\n"); rc = -ENOMEM; goto error; } - memset(slot_cur->func, 0, sizeof(struct pci_func)); slot_cur->func->busno = slot_cur->bus; slot_cur->func->device = slot_cur->device; } diff --git a/drivers/pci/hotplug/ibmphp_ebda.c b/drivers/pci/hotplug/ibmphp_ebda.c index aea1187c73ad..ba12034c5d3a 100644 --- a/drivers/pci/hotplug/ibmphp_ebda.c +++ b/drivers/pci/hotplug/ibmphp_ebda.c @@ -72,13 +72,7 @@ static int ebda_rio_table (void); static struct ebda_hpc_list * __init alloc_ebda_hpc_list (void) { - struct ebda_hpc_list *list; - - list = kmalloc (sizeof (struct ebda_hpc_list), GFP_KERNEL); - if (!list) - return NULL; - memset (list, 0, sizeof (*list)); - return list; + return kzalloc(sizeof(struct ebda_hpc_list), GFP_KERNEL); } static struct controller *alloc_ebda_hpc (u32 slot_count, u32 bus_count) @@ -87,21 +81,18 @@ static struct controller *alloc_ebda_hpc (u32 slot_count, u32 bus_count) struct ebda_hpc_slot *slots; struct ebda_hpc_bus *buses; - controller = kmalloc (sizeof (struct controller), GFP_KERNEL); + controller = kzalloc(sizeof(struct controller), GFP_KERNEL); if (!controller) goto error; - memset (controller, 0, sizeof (*controller)); - slots = kmalloc (sizeof (struct ebda_hpc_slot) * slot_count, GFP_KERNEL); + slots = kcalloc(slot_count, sizeof(struct ebda_hpc_slot), GFP_KERNEL); if (!slots) goto error_contr; - memset (slots, 0, sizeof (*slots) * slot_count); controller->slots = slots; - buses = kmalloc (sizeof (struct ebda_hpc_bus) * bus_count, GFP_KERNEL); + buses = kcalloc(bus_count, sizeof(struct ebda_hpc_bus), GFP_KERNEL); if (!buses) goto error_slots; - memset (buses, 0, sizeof (*buses) * bus_count); controller->buses = buses; return controller; @@ -122,24 +113,12 @@ static void free_ebda_hpc (struct controller *controller) static struct ebda_rsrc_list * __init alloc_ebda_rsrc_list (void) { - struct ebda_rsrc_list *list; - - list = kmalloc (sizeof (struct ebda_rsrc_list), GFP_KERNEL); - if (!list) - return NULL; - memset (list, 0, sizeof (*list)); - return list; + return kzalloc(sizeof(struct ebda_rsrc_list), GFP_KERNEL); } static struct ebda_pci_rsrc *alloc_ebda_pci_rsrc (void) { - struct ebda_pci_rsrc *resource; - - resource = kmalloc (sizeof (struct ebda_pci_rsrc), GFP_KERNEL); - if (!resource) - return NULL; - memset (resource, 0, sizeof (*resource)); - return resource; + return kzalloc(sizeof(struct ebda_pci_rsrc), GFP_KERNEL); } static void __init print_bus_info (void) @@ -390,10 +369,9 @@ int __init ibmphp_access_ebda (void) debug ("now enter io table ---\n"); debug ("rio blk id: %x\n", blk_id); - rio_table_ptr = kmalloc (sizeof (struct rio_table_hdr), GFP_KERNEL); + rio_table_ptr = kzalloc(sizeof(struct rio_table_hdr), GFP_KERNEL); if (!rio_table_ptr) return -ENOMEM; - memset (rio_table_ptr, 0, sizeof (struct rio_table_hdr) ); rio_table_ptr->ver_num = readb (io_mem + offset); rio_table_ptr->scal_count = readb (io_mem + offset + 1); rio_table_ptr->riodev_count = readb (io_mem + offset + 2); @@ -445,10 +423,9 @@ static int __init ebda_rio_table (void) // we do concern about rio details for (i = 0; i < rio_table_ptr->riodev_count; i++) { - rio_detail_ptr = kmalloc (sizeof (struct rio_detail), GFP_KERNEL); + rio_detail_ptr = kzalloc(sizeof(struct rio_detail), GFP_KERNEL); if (!rio_detail_ptr) return -ENOMEM; - memset (rio_detail_ptr, 0, sizeof (struct rio_detail)); rio_detail_ptr->rio_node_id = readb (io_mem + offset); rio_detail_ptr->bbar = readl (io_mem + offset + 1); rio_detail_ptr->rio_type = readb (io_mem + offset + 5); @@ -503,10 +480,9 @@ static int __init combine_wpg_for_chassis (void) rio_detail_ptr = list_entry (list_head_ptr, struct rio_detail, rio_detail_list); opt_rio_ptr = search_opt_vg (rio_detail_ptr->chassis_num); if (!opt_rio_ptr) { - opt_rio_ptr = (struct opt_rio *) kmalloc (sizeof (struct opt_rio), GFP_KERNEL); + opt_rio_ptr = kzalloc(sizeof(struct opt_rio), GFP_KERNEL); if (!opt_rio_ptr) return -ENOMEM; - memset (opt_rio_ptr, 0, sizeof (struct opt_rio)); opt_rio_ptr->rio_type = rio_detail_ptr->rio_type; opt_rio_ptr->chassis_num = rio_detail_ptr->chassis_num; opt_rio_ptr->first_slot_num = rio_detail_ptr->first_slot_num; @@ -546,10 +522,9 @@ static int combine_wpg_for_expansion (void) rio_detail_ptr = list_entry (list_head_ptr, struct rio_detail, rio_detail_list); opt_rio_lo_ptr = search_opt_lo (rio_detail_ptr->chassis_num); if (!opt_rio_lo_ptr) { - opt_rio_lo_ptr = (struct opt_rio_lo *) kmalloc (sizeof (struct opt_rio_lo), GFP_KERNEL); + opt_rio_lo_ptr = kzalloc(sizeof(struct opt_rio_lo), GFP_KERNEL); if (!opt_rio_lo_ptr) return -ENOMEM; - memset (opt_rio_lo_ptr, 0, sizeof (struct opt_rio_lo)); opt_rio_lo_ptr->rio_type = rio_detail_ptr->rio_type; opt_rio_lo_ptr->chassis_num = rio_detail_ptr->chassis_num; opt_rio_lo_ptr->first_slot_num = rio_detail_ptr->first_slot_num; @@ -842,12 +817,11 @@ static int __init ebda_rsrc_controller (void) bus_info_ptr2 = ibmphp_find_same_bus_num (slot_ptr->slot_bus_num); if (!bus_info_ptr2) { - bus_info_ptr1 = (struct bus_info *) kmalloc (sizeof (struct bus_info), GFP_KERNEL); + bus_info_ptr1 = kzalloc(sizeof(struct bus_info), GFP_KERNEL); if (!bus_info_ptr1) { rc = -ENOMEM; goto error_no_hp_slot; } - memset (bus_info_ptr1, 0, sizeof (struct bus_info)); bus_info_ptr1->slot_min = slot_ptr->slot_num; bus_info_ptr1->slot_max = slot_ptr->slot_num; bus_info_ptr1->slot_count += 1; @@ -946,19 +920,17 @@ static int __init ebda_rsrc_controller (void) // register slots with hpc core as well as create linked list of ibm slot for (index = 0; index < hpc_ptr->slot_count; index++) { - hp_slot_ptr = kmalloc(sizeof(*hp_slot_ptr), GFP_KERNEL); + hp_slot_ptr = kzalloc(sizeof(*hp_slot_ptr), GFP_KERNEL); if (!hp_slot_ptr) { rc = -ENOMEM; goto error_no_hp_slot; } - memset(hp_slot_ptr, 0, sizeof(*hp_slot_ptr)); - hp_slot_ptr->info = kmalloc (sizeof(struct hotplug_slot_info), GFP_KERNEL); + hp_slot_ptr->info = kzalloc(sizeof(struct hotplug_slot_info), GFP_KERNEL); if (!hp_slot_ptr->info) { rc = -ENOMEM; goto error_no_hp_info; } - memset(hp_slot_ptr->info, 0, sizeof(struct hotplug_slot_info)); hp_slot_ptr->name = kmalloc(30, GFP_KERNEL); if (!hp_slot_ptr->name) { @@ -966,12 +938,11 @@ static int __init ebda_rsrc_controller (void) goto error_no_hp_name; } - tmp_slot = kmalloc(sizeof(*tmp_slot), GFP_KERNEL); + tmp_slot = kzalloc(sizeof(*tmp_slot), GFP_KERNEL); if (!tmp_slot) { rc = -ENOMEM; goto error_no_slot; } - memset(tmp_slot, 0, sizeof(*tmp_slot)); tmp_slot->flag = TRUE; diff --git a/drivers/pci/hotplug/ibmphp_pci.c b/drivers/pci/hotplug/ibmphp_pci.c index 155133fe5c12..97753ddcd856 100644 --- a/drivers/pci/hotplug/ibmphp_pci.c +++ b/drivers/pci/hotplug/ibmphp_pci.c @@ -164,12 +164,11 @@ int ibmphp_configure_card (struct pci_func *func, u8 slotno) cleanup_count = 6; goto error; } - newfunc = kmalloc(sizeof(*newfunc), GFP_KERNEL); + newfunc = kzalloc(sizeof(*newfunc), GFP_KERNEL); if (!newfunc) { err ("out of system memory\n"); return -ENOMEM; } - memset (newfunc, 0, sizeof (struct pci_func)); newfunc->busno = cur_func->busno; newfunc->device = device; cur_func->next = newfunc; @@ -203,12 +202,11 @@ int ibmphp_configure_card (struct pci_func *func, u8 slotno) flag = FALSE; for (i = 0; i < 32; i++) { if (func->devices[i]) { - newfunc = kmalloc(sizeof(*newfunc), GFP_KERNEL); + newfunc = kzalloc(sizeof(*newfunc), GFP_KERNEL); if (!newfunc) { err ("out of system memory\n"); return -ENOMEM; } - memset (newfunc, 0, sizeof (struct pci_func)); newfunc->busno = sec_number; newfunc->device = (u8) i; for (j = 0; j < 4; j++) @@ -232,12 +230,11 @@ int ibmphp_configure_card (struct pci_func *func, u8 slotno) } } - newfunc = kmalloc(sizeof(*newfunc), GFP_KERNEL); + newfunc = kzalloc(sizeof(*newfunc), GFP_KERNEL); if (!newfunc) { err ("out of system memory\n"); return -ENOMEM; } - memset (newfunc, 0, sizeof (struct pci_func)); newfunc->busno = cur_func->busno; newfunc->device = device; for (j = 0; j < 4; j++) @@ -279,12 +276,11 @@ int ibmphp_configure_card (struct pci_func *func, u8 slotno) for (i = 0; i < 32; i++) { if (func->devices[i]) { debug ("inside for loop, device is %x\n", i); - newfunc = kmalloc(sizeof(*newfunc), GFP_KERNEL); + newfunc = kzalloc(sizeof(*newfunc), GFP_KERNEL); if (!newfunc) { err (" out of system memory\n"); return -ENOMEM; } - memset (newfunc, 0, sizeof (struct pci_func)); newfunc->busno = sec_number; newfunc->device = (u8) i; for (j = 0; j < 4; j++) @@ -405,13 +401,12 @@ static int configure_device (struct pci_func *func) debug ("len[count] in IO %x, count %d\n", len[count], count); - io[count] = kmalloc (sizeof (struct resource_node), GFP_KERNEL); + io[count] = kzalloc(sizeof(struct resource_node), GFP_KERNEL); if (!io[count]) { err ("out of system memory\n"); return -ENOMEM; } - memset (io[count], 0, sizeof (struct resource_node)); io[count]->type = IO; io[count]->busno = func->busno; io[count]->devfunc = PCI_DEVFN(func->device, func->function); @@ -444,12 +439,11 @@ static int configure_device (struct pci_func *func) debug ("len[count] in PFMEM %x, count %d\n", len[count], count); - pfmem[count] = kmalloc (sizeof (struct resource_node), GFP_KERNEL); + pfmem[count] = kzalloc(sizeof(struct resource_node), GFP_KERNEL); if (!pfmem[count]) { err ("out of system memory\n"); return -ENOMEM; } - memset (pfmem[count], 0, sizeof (struct resource_node)); pfmem[count]->type = PFMEM; pfmem[count]->busno = func->busno; pfmem[count]->devfunc = PCI_DEVFN(func->device, @@ -460,13 +454,12 @@ static int configure_device (struct pci_func *func) ibmphp_add_resource (pfmem[count]); func->pfmem[count] = pfmem[count]; } else { - mem_tmp = kmalloc(sizeof(*mem_tmp), GFP_KERNEL); + mem_tmp = kzalloc(sizeof(*mem_tmp), GFP_KERNEL); if (!mem_tmp) { err ("out of system memory\n"); kfree (pfmem[count]); return -ENOMEM; } - memset (mem_tmp, 0, sizeof (struct resource_node)); mem_tmp->type = MEM; mem_tmp->busno = pfmem[count]->busno; mem_tmp->devfunc = pfmem[count]->devfunc; @@ -512,12 +505,11 @@ static int configure_device (struct pci_func *func) debug ("len[count] in Mem %x, count %d\n", len[count], count); - mem[count] = kmalloc (sizeof (struct resource_node), GFP_KERNEL); + mem[count] = kzalloc(sizeof(struct resource_node), GFP_KERNEL); if (!mem[count]) { err ("out of system memory\n"); return -ENOMEM; } - memset (mem[count], 0, sizeof (struct resource_node)); mem[count]->type = MEM; mem[count]->busno = func->busno; mem[count]->devfunc = PCI_DEVFN(func->device, @@ -677,14 +669,13 @@ static int configure_bridge (struct pci_func **func_passed, u8 slotno) debug ("len[count] in IO = %x\n", len[count]); - bus_io[count] = kmalloc (sizeof (struct resource_node), GFP_KERNEL); + bus_io[count] = kzalloc(sizeof(struct resource_node), GFP_KERNEL); if (!bus_io[count]) { err ("out of system memory\n"); retval = -ENOMEM; goto error; } - memset (bus_io[count], 0, sizeof (struct resource_node)); bus_io[count]->type = IO; bus_io[count]->busno = func->busno; bus_io[count]->devfunc = PCI_DEVFN(func->device, @@ -711,13 +702,12 @@ static int configure_bridge (struct pci_func **func_passed, u8 slotno) debug ("len[count] in PFMEM = %x\n", len[count]); - bus_pfmem[count] = kmalloc (sizeof (struct resource_node), GFP_KERNEL); + bus_pfmem[count] = kzalloc(sizeof(struct resource_node), GFP_KERNEL); if (!bus_pfmem[count]) { err ("out of system memory\n"); retval = -ENOMEM; goto error; } - memset (bus_pfmem[count], 0, sizeof (struct resource_node)); bus_pfmem[count]->type = PFMEM; bus_pfmem[count]->busno = func->busno; bus_pfmem[count]->devfunc = PCI_DEVFN(func->device, @@ -728,13 +718,12 @@ static int configure_bridge (struct pci_func **func_passed, u8 slotno) ibmphp_add_resource (bus_pfmem[count]); func->pfmem[count] = bus_pfmem[count]; } else { - mem_tmp = kmalloc(sizeof(*mem_tmp), GFP_KERNEL); + mem_tmp = kzalloc(sizeof(*mem_tmp), GFP_KERNEL); if (!mem_tmp) { err ("out of system memory\n"); retval = -ENOMEM; goto error; } - memset (mem_tmp, 0, sizeof (struct resource_node)); mem_tmp->type = MEM; mem_tmp->busno = bus_pfmem[count]->busno; mem_tmp->devfunc = bus_pfmem[count]->devfunc; @@ -770,13 +759,12 @@ static int configure_bridge (struct pci_func **func_passed, u8 slotno) debug ("len[count] in Memory is %x\n", len[count]); - bus_mem[count] = kmalloc (sizeof (struct resource_node), GFP_KERNEL); + bus_mem[count] = kzalloc(sizeof(struct resource_node), GFP_KERNEL); if (!bus_mem[count]) { err ("out of system memory\n"); retval = -ENOMEM; goto error; } - memset (bus_mem[count], 0, sizeof (struct resource_node)); bus_mem[count]->type = MEM; bus_mem[count]->busno = func->busno; bus_mem[count]->devfunc = PCI_DEVFN(func->device, @@ -841,14 +829,13 @@ static int configure_bridge (struct pci_func **func_passed, u8 slotno) flag_io = TRUE; } else { debug ("it wants %x IO behind the bridge\n", amount_needed->io); - io = kmalloc(sizeof(*io), GFP_KERNEL); + io = kzalloc(sizeof(*io), GFP_KERNEL); if (!io) { err ("out of system memory\n"); retval = -ENOMEM; goto error; } - memset (io, 0, sizeof (struct resource_node)); io->type = IO; io->busno = func->busno; io->devfunc = PCI_DEVFN(func->device, func->function); @@ -865,13 +852,12 @@ static int configure_bridge (struct pci_func **func_passed, u8 slotno) flag_mem = TRUE; } else { debug ("it wants %x memory behind the bridge\n", amount_needed->mem); - mem = kmalloc(sizeof(*mem), GFP_KERNEL); + mem = kzalloc(sizeof(*mem), GFP_KERNEL); if (!mem) { err ("out of system memory\n"); retval = -ENOMEM; goto error; } - memset (mem, 0, sizeof (struct resource_node)); mem->type = MEM; mem->busno = func->busno; mem->devfunc = PCI_DEVFN(func->device, func->function); @@ -888,13 +874,12 @@ static int configure_bridge (struct pci_func **func_passed, u8 slotno) flag_pfmem = TRUE; } else { debug ("it wants %x pfmemory behind the bridge\n", amount_needed->pfmem); - pfmem = kmalloc(sizeof(*pfmem), GFP_KERNEL); + pfmem = kzalloc(sizeof(*pfmem), GFP_KERNEL); if (!pfmem) { err ("out of system memory\n"); retval = -ENOMEM; goto error; } - memset (pfmem, 0, sizeof (struct resource_node)); pfmem->type = PFMEM; pfmem->busno = func->busno; pfmem->devfunc = PCI_DEVFN(func->device, func->function); @@ -904,13 +889,12 @@ static int configure_bridge (struct pci_func **func_passed, u8 slotno) ibmphp_add_resource (pfmem); flag_pfmem = TRUE; } else { - mem_tmp = kmalloc(sizeof(*mem_tmp), GFP_KERNEL); + mem_tmp = kzalloc(sizeof(*mem_tmp), GFP_KERNEL); if (!mem_tmp) { err ("out of system memory\n"); retval = -ENOMEM; goto error; } - memset (mem_tmp, 0, sizeof (struct resource_node)); mem_tmp->type = MEM; mem_tmp->busno = pfmem->busno; mem_tmp->devfunc = pfmem->devfunc; @@ -936,13 +920,12 @@ static int configure_bridge (struct pci_func **func_passed, u8 slotno) */ bus = ibmphp_find_res_bus (sec_number); if (!bus) { - bus = kmalloc(sizeof(*bus), GFP_KERNEL); + bus = kzalloc(sizeof(*bus), GFP_KERNEL); if (!bus) { err ("out of system memory\n"); retval = -ENOMEM; goto error; } - memset (bus, 0, sizeof (struct bus_node)); bus->busno = sec_number; debug ("b4 adding new bus\n"); rc = add_new_bus (bus, io, mem, pfmem, func->busno); @@ -1111,10 +1094,9 @@ static struct res_needed *scan_behind_bridge (struct pci_func * func, u8 busno) }; struct res_needed *amount; - amount = kmalloc(sizeof(*amount), GFP_KERNEL); + amount = kzalloc(sizeof(*amount), GFP_KERNEL); if (amount == NULL) return NULL; - memset (amount, 0, sizeof (struct res_needed)); ibmphp_pci_bus->number = busno; @@ -1672,12 +1654,11 @@ static int add_new_bus (struct bus_node *bus, struct resource_node *io, struct r list_add (&bus->bus_list, &cur_bus->bus_list); } if (io) { - io_range = kmalloc(sizeof(*io_range), GFP_KERNEL); + io_range = kzalloc(sizeof(*io_range), GFP_KERNEL); if (!io_range) { err ("out of system memory\n"); return -ENOMEM; } - memset (io_range, 0, sizeof (struct range_node)); io_range->start = io->start; io_range->end = io->end; io_range->rangeno = 1; @@ -1685,12 +1666,11 @@ static int add_new_bus (struct bus_node *bus, struct resource_node *io, struct r bus->rangeIO = io_range; } if (mem) { - mem_range = kmalloc(sizeof(*mem_range), GFP_KERNEL); + mem_range = kzalloc(sizeof(*mem_range), GFP_KERNEL); if (!mem_range) { err ("out of system memory\n"); return -ENOMEM; } - memset (mem_range, 0, sizeof (struct range_node)); mem_range->start = mem->start; mem_range->end = mem->end; mem_range->rangeno = 1; @@ -1698,12 +1678,11 @@ static int add_new_bus (struct bus_node *bus, struct resource_node *io, struct r bus->rangeMem = mem_range; } if (pfmem) { - pfmem_range = kmalloc(sizeof(*pfmem_range), GFP_KERNEL); + pfmem_range = kzalloc(sizeof(*pfmem_range), GFP_KERNEL); if (!pfmem_range) { err ("out of system memory\n"); return -ENOMEM; } - memset (pfmem_range, 0, sizeof (struct range_node)); pfmem_range->start = pfmem->start; pfmem_range->end = pfmem->end; pfmem_range->rangeno = 1; diff --git a/drivers/pci/hotplug/ibmphp_res.c b/drivers/pci/hotplug/ibmphp_res.c index 9c224c94d698..852a98bf07d3 100644 --- a/drivers/pci/hotplug/ibmphp_res.c +++ b/drivers/pci/hotplug/ibmphp_res.c @@ -55,13 +55,12 @@ static struct bus_node * __init alloc_error_bus (struct ebda_pci_rsrc * curr, u8 return NULL; } - newbus = kmalloc (sizeof (struct bus_node), GFP_KERNEL); + newbus = kzalloc(sizeof(struct bus_node), GFP_KERNEL); if (!newbus) { err ("out of system memory\n"); return NULL; } - memset (newbus, 0, sizeof (struct bus_node)); if (flag) newbus->busno = busno; else @@ -79,12 +78,11 @@ static struct resource_node * __init alloc_resources (struct ebda_pci_rsrc * cur return NULL; } - rs = kmalloc (sizeof (struct resource_node), GFP_KERNEL); + rs = kzalloc(sizeof(struct resource_node), GFP_KERNEL); if (!rs) { err ("out of system memory\n"); return NULL; } - memset (rs, 0, sizeof (struct resource_node)); rs->busno = curr->bus_num; rs->devfunc = curr->dev_fun; rs->start = curr->start_addr; @@ -100,12 +98,11 @@ static int __init alloc_bus_range (struct bus_node **new_bus, struct range_node u8 num_ranges = 0; if (first_bus) { - newbus = kmalloc (sizeof (struct bus_node), GFP_KERNEL); + newbus = kzalloc(sizeof(struct bus_node), GFP_KERNEL); if (!newbus) { err ("out of system memory.\n"); return -ENOMEM; } - memset (newbus, 0, sizeof (struct bus_node)); newbus->busno = curr->bus_num; } else { newbus = *new_bus; @@ -122,14 +119,13 @@ static int __init alloc_bus_range (struct bus_node **new_bus, struct range_node } } - newrange = kmalloc (sizeof (struct range_node), GFP_KERNEL); + newrange = kzalloc(sizeof(struct range_node), GFP_KERNEL); if (!newrange) { if (first_bus) kfree (newbus); err ("out of system memory\n"); return -ENOMEM; } - memset (newrange, 0, sizeof (struct range_node)); newrange->start = curr->start_addr; newrange->end = curr->end_addr; @@ -1705,12 +1701,11 @@ static int __init once_over (void) bus_cur->firstPFMemFromMem = pfmem_cur; - mem = kmalloc (sizeof (struct resource_node), GFP_KERNEL); + mem = kzalloc(sizeof(struct resource_node), GFP_KERNEL); if (!mem) { err ("out of system memory\n"); return -ENOMEM; } - memset (mem, 0, sizeof (struct resource_node)); mem->type = MEM; mem->busno = pfmem_cur->busno; mem->devfunc = pfmem_cur->devfunc; @@ -1994,12 +1989,11 @@ static int __init update_bridge_ranges (struct bus_node **bus) end_address |= (upper_io_end << 16); if ((start_address) && (start_address <= end_address)) { - range = kmalloc (sizeof (struct range_node), GFP_KERNEL); + range = kzalloc(sizeof(struct range_node), GFP_KERNEL); if (!range) { err ("out of system memory\n"); return -ENOMEM; } - memset (range, 0, sizeof (struct range_node)); range->start = start_address; range->end = end_address + 0xfff; @@ -2020,13 +2014,12 @@ static int __init update_bridge_ranges (struct bus_node **bus) fix_resources (bus_sec); if (ibmphp_find_resource (bus_cur, start_address, &io, IO)) { - io = kmalloc (sizeof (struct resource_node), GFP_KERNEL); + io = kzalloc(sizeof(struct resource_node), GFP_KERNEL); if (!io) { kfree (range); err ("out of system memory\n"); return -ENOMEM; } - memset (io, 0, sizeof (struct resource_node)); io->type = IO; io->busno = bus_cur->busno; io->devfunc = ((device << 3) | (function & 0x7)); @@ -2045,12 +2038,11 @@ static int __init update_bridge_ranges (struct bus_node **bus) if ((start_address) && (start_address <= end_address)) { - range = kmalloc (sizeof (struct range_node), GFP_KERNEL); + range = kzalloc(sizeof(struct range_node), GFP_KERNEL); if (!range) { err ("out of system memory\n"); return -ENOMEM; } - memset (range, 0, sizeof (struct range_node)); range->start = start_address; range->end = end_address + 0xfffff; @@ -2072,13 +2064,12 @@ static int __init update_bridge_ranges (struct bus_node **bus) fix_resources (bus_sec); if (ibmphp_find_resource (bus_cur, start_address, &mem, MEM)) { - mem = kmalloc (sizeof (struct resource_node), GFP_KERNEL); + mem = kzalloc(sizeof(struct resource_node), GFP_KERNEL); if (!mem) { kfree (range); err ("out of system memory\n"); return -ENOMEM; } - memset (mem, 0, sizeof (struct resource_node)); mem->type = MEM; mem->busno = bus_cur->busno; mem->devfunc = ((device << 3) | (function & 0x7)); @@ -2101,12 +2092,11 @@ static int __init update_bridge_ranges (struct bus_node **bus) if ((start_address) && (start_address <= end_address)) { - range = kmalloc (sizeof (struct range_node), GFP_KERNEL); + range = kzalloc(sizeof(struct range_node), GFP_KERNEL); if (!range) { err ("out of system memory\n"); return -ENOMEM; } - memset (range, 0, sizeof (struct range_node)); range->start = start_address; range->end = end_address + 0xfffff; @@ -2127,13 +2117,12 @@ static int __init update_bridge_ranges (struct bus_node **bus) fix_resources (bus_sec); if (ibmphp_find_resource (bus_cur, start_address, &pfmem, PFMEM)) { - pfmem = kmalloc (sizeof (struct resource_node), GFP_KERNEL); + pfmem = kzalloc(sizeof(struct resource_node), GFP_KERNEL); if (!pfmem) { kfree (range); err ("out of system memory\n"); return -ENOMEM; } - memset (pfmem, 0, sizeof (struct resource_node)); pfmem->type = PFMEM; pfmem->busno = bus_cur->busno; pfmem->devfunc = ((device << 3) | (function & 0x7)); diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c index 1e8506e0fd87..601cf9045b20 100644 --- a/drivers/pci/hotplug/pciehp_core.c +++ b/drivers/pci/hotplug/pciehp_core.c @@ -117,27 +117,23 @@ static int init_slots(struct controller *ctrl) slot_number = ctrl->first_slot; while (number_of_slots) { - slot = kmalloc(sizeof(*slot), GFP_KERNEL); + slot = kzalloc(sizeof(*slot), GFP_KERNEL); if (!slot) goto error; - memset(slot, 0, sizeof(struct slot)); slot->hotplug_slot = - kmalloc(sizeof(*(slot->hotplug_slot)), + kzalloc(sizeof(*(slot->hotplug_slot)), GFP_KERNEL); if (!slot->hotplug_slot) goto error_slot; hotplug_slot = slot->hotplug_slot; - memset(hotplug_slot, 0, sizeof(struct hotplug_slot)); hotplug_slot->info = - kmalloc(sizeof(*(hotplug_slot->info)), + kzalloc(sizeof(*(hotplug_slot->info)), GFP_KERNEL); if (!hotplug_slot->info) goto error_hpslot; hotplug_slot_info = hotplug_slot->info; - memset(hotplug_slot_info, 0, - sizeof(struct hotplug_slot_info)); hotplug_slot->name = kmalloc(SLOT_NAME_SIZE, GFP_KERNEL); if (!hotplug_slot->name) goto error_info; @@ -373,12 +369,11 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_ u8 value; struct pci_dev *pdev; - ctrl = kmalloc(sizeof(*ctrl), GFP_KERNEL); + ctrl = kzalloc(sizeof(*ctrl), GFP_KERNEL); if (!ctrl) { err("%s : out of memory\n", __FUNCTION__); goto err_out_none; } - memset(ctrl, 0, sizeof(struct controller)); pdev = dev->port; ctrl->pci_dev = pdev; diff --git a/drivers/pci/hotplug/rpaphp_slot.c b/drivers/pci/hotplug/rpaphp_slot.c index 78943e064b59..b771196a654e 100644 --- a/drivers/pci/hotplug/rpaphp_slot.c +++ b/drivers/pci/hotplug/rpaphp_slot.c @@ -84,19 +84,16 @@ struct slot *alloc_slot_struct(struct device_node *dn, int drc_index, char *drc_ { struct slot *slot; - slot = kmalloc(sizeof (struct slot), GFP_KERNEL); + slot = kzalloc(sizeof(struct slot), GFP_KERNEL); if (!slot) goto error_nomem; - memset(slot, 0, sizeof (struct slot)); - slot->hotplug_slot = kmalloc(sizeof (struct hotplug_slot), GFP_KERNEL); + slot->hotplug_slot = kzalloc(sizeof(struct hotplug_slot), GFP_KERNEL); if (!slot->hotplug_slot) goto error_slot; - memset(slot->hotplug_slot, 0, sizeof (struct hotplug_slot)); - slot->hotplug_slot->info = kmalloc(sizeof (struct hotplug_slot_info), + slot->hotplug_slot->info = kzalloc(sizeof(struct hotplug_slot_info), GFP_KERNEL); if (!slot->hotplug_slot->info) goto error_hpslot; - memset(slot->hotplug_slot->info, 0, sizeof (struct hotplug_slot_info)); slot->hotplug_slot->name = kmalloc(BUS_ID_SIZE + 1, GFP_KERNEL); if (!slot->hotplug_slot->name) goto error_info; diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c index eb5b50c8770c..f22f69ac6445 100644 --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c @@ -53,11 +53,10 @@ store_new_id(struct device_driver *driver, const char *buf, size_t count) if (fields < 0) return -EINVAL; - dynid = kmalloc(sizeof(*dynid), GFP_KERNEL); + dynid = kzalloc(sizeof(*dynid), GFP_KERNEL); if (!dynid) return -ENOMEM; - memset(dynid, 0, sizeof(*dynid)); INIT_LIST_HEAD(&dynid->node); dynid->id.vendor = vendor; dynid->id.device = device; diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c index 965a5934623a..56ac2bc003c7 100644 --- a/drivers/pci/pci-sysfs.c +++ b/drivers/pci/pci-sysfs.c @@ -501,9 +501,8 @@ int pci_create_sysfs_dev_files (struct pci_dev *pdev) if (pci_resource_len(pdev, PCI_ROM_RESOURCE)) { struct bin_attribute *rom_attr; - rom_attr = kmalloc(sizeof(*rom_attr), GFP_ATOMIC); + rom_attr = kzalloc(sizeof(*rom_attr), GFP_ATOMIC); if (rom_attr) { - memset(rom_attr, 0x00, sizeof(*rom_attr)); pdev->rom_attr = rom_attr; rom_attr->size = pci_resource_len(pdev, PCI_ROM_RESOURCE); rom_attr->attr.name = "rom"; diff --git a/drivers/pci/pcie/portdrv_core.c b/drivers/pci/pcie/portdrv_core.c index e4e5f1e8d816..55c662267868 100644 --- a/drivers/pci/pcie/portdrv_core.c +++ b/drivers/pci/pcie/portdrv_core.c @@ -248,11 +248,10 @@ static struct pcie_device* alloc_pcie_device(struct pci_dev *parent, { struct pcie_device *device; - device = kmalloc(sizeof(struct pcie_device), GFP_KERNEL); + device = kzalloc(sizeof(struct pcie_device), GFP_KERNEL); if (!device) return NULL; - memset(device, 0, sizeof(struct pcie_device)); pcie_device_init(parent, device, port_type, service_type, irq,irq_mode); printk(KERN_DEBUG "Allocate Port Service[%s]\n", device->device.bus_id); return device; diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index e3dc3063e05b..a10ed9dab2c2 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -33,10 +33,9 @@ LIST_HEAD(pci_devices); */ static void pci_create_legacy_files(struct pci_bus *b) { - b->legacy_io = kmalloc(sizeof(struct bin_attribute) * 2, + b->legacy_io = kzalloc(sizeof(struct bin_attribute) * 2, GFP_ATOMIC); if (b->legacy_io) { - memset(b->legacy_io, 0, sizeof(struct bin_attribute) * 2); b->legacy_io->attr.name = "legacy_io"; b->legacy_io->size = 0xffff; b->legacy_io->attr.mode = S_IRUSR | S_IWUSR; @@ -320,9 +319,8 @@ static struct pci_bus * __devinit pci_alloc_bus(void) { struct pci_bus *b; - b = kmalloc(sizeof(*b), GFP_KERNEL); + b = kzalloc(sizeof(*b), GFP_KERNEL); if (b) { - memset(b, 0, sizeof(*b)); INIT_LIST_HEAD(&b->node); INIT_LIST_HEAD(&b->children); INIT_LIST_HEAD(&b->devices); @@ -797,11 +795,10 @@ pci_scan_device(struct pci_bus *bus, int devfn) if (pci_bus_read_config_byte(bus, devfn, PCI_HEADER_TYPE, &hdr_type)) return NULL; - dev = kmalloc(sizeof(struct pci_dev), GFP_KERNEL); + dev = kzalloc(sizeof(struct pci_dev), GFP_KERNEL); if (!dev) return NULL; - memset(dev, 0, sizeof(struct pci_dev)); dev->bus = bus; dev->sysdata = bus->sysdata; dev->dev.parent = bus->bridge; From 783c49fc506d9afe4784390b556fa25ede5d6d1f Mon Sep 17 00:00:00 2001 From: Kristen Accardi Date: Fri, 3 Mar 2006 10:16:05 -0800 Subject: [PATCH 47/49] [PATCH] PCI Hotplug: add common acpi functions to core shpchprm_acpi.c and pciehprm_acpi.c are nearly identical. In addition, there are functions in both these files that are also in acpiphp_glue.c. This patch will remove duplicate functions from shpchp, pciehp, and acpiphp and move this functionality to pci_hotplug, as it is not hardware specific. Get rid of shpchprm* and pciehprm* files since they are no longer needed. shpchprm_nonacpi.c and pciehprm_nonacpi.c are identical, as well as shpchprm_legacy.c and can be replaced with a macro. This patch also changes acpiphp to use the common hpp code. Signed-off-by: Kristen Carlson Accardi Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/Makefile | 17 +- .../hotplug/{pciehprm_acpi.c => acpi_pcihp.c} | 206 ++++++++---------- drivers/pci/hotplug/acpiphp.h | 15 +- drivers/pci/hotplug/acpiphp_glue.c | 91 ++------ drivers/pci/hotplug/pci_hotplug.h | 17 ++ drivers/pci/hotplug/pciehp.h | 24 +- drivers/pci/hotplug/pciehp_hpc.c | 74 ++++++- drivers/pci/hotplug/pciehprm_nonacpi.c | 47 ---- drivers/pci/hotplug/shpchp.h | 30 ++- drivers/pci/hotplug/shpchp_core.c | 17 ++ drivers/pci/hotplug/shpchp_pci.c | 10 +- drivers/pci/hotplug/shpchprm_acpi.c | 186 ---------------- drivers/pci/hotplug/shpchprm_legacy.c | 54 ----- drivers/pci/hotplug/shpchprm_nonacpi.c | 57 ----- 14 files changed, 254 insertions(+), 591 deletions(-) rename drivers/pci/hotplug/{pciehprm_acpi.c => acpi_pcihp.c} (58%) delete mode 100644 drivers/pci/hotplug/pciehprm_nonacpi.c delete mode 100644 drivers/pci/hotplug/shpchprm_acpi.c delete mode 100644 drivers/pci/hotplug/shpchprm_legacy.c delete mode 100644 drivers/pci/hotplug/shpchprm_nonacpi.c diff --git a/drivers/pci/hotplug/Makefile b/drivers/pci/hotplug/Makefile index 1c0ed377ed91..421cfffb1756 100644 --- a/drivers/pci/hotplug/Makefile +++ b/drivers/pci/hotplug/Makefile @@ -22,6 +22,9 @@ ifdef CONFIG_HOTPLUG_PCI_CPCI pci_hotplug-objs += cpci_hotplug_core.o \ cpci_hotplug_pci.o endif +ifdef CONFIG_ACPI +pci_hotplug-objs += acpi_pcihp.o +endif cpqphp-objs := cpqphp_core.o \ cpqphp_ctrl.o \ @@ -51,23 +54,9 @@ pciehp-objs := pciehp_core.o \ pciehp_ctrl.o \ pciehp_pci.o \ pciehp_hpc.o -ifdef CONFIG_ACPI - pciehp-objs += pciehprm_acpi.o -else - pciehp-objs += pciehprm_nonacpi.o -endif shpchp-objs := shpchp_core.o \ shpchp_ctrl.o \ shpchp_pci.o \ shpchp_sysfs.o \ shpchp_hpc.o -ifdef CONFIG_ACPI - shpchp-objs += shpchprm_acpi.o -else - ifdef CONFIG_HOTPLUG_PCI_SHPC_PHPRM_LEGACY - shpchp-objs += shpchprm_legacy.o - else - shpchp-objs += shpchprm_nonacpi.o - endif -endif diff --git a/drivers/pci/hotplug/pciehprm_acpi.c b/drivers/pci/hotplug/acpi_pcihp.c similarity index 58% rename from drivers/pci/hotplug/pciehprm_acpi.c rename to drivers/pci/hotplug/acpi_pcihp.c index 2bdb30f68bf8..0f7135317542 100644 --- a/drivers/pci/hotplug/pciehprm_acpi.c +++ b/drivers/pci/hotplug/acpi_pcihp.c @@ -1,7 +1,7 @@ /* - * PCIEHPRM ACPI: PHP Resource Manager for ACPI platform + * Common ACPI functions for hot plug platforms * - * Copyright (C) 2003-2004 Intel Corporation + * Copyright (C) 2006 Intel Corporation * * All rights reserved. * @@ -28,30 +28,37 @@ #include #include #include -#include -#include +#include #include #include -#include "pciehp.h" +#include "pci_hotplug.h" #define METHOD_NAME__SUN "_SUN" #define METHOD_NAME__HPP "_HPP" #define METHOD_NAME_OSHP "OSHP" -static u8 * acpi_path_name( acpi_handle handle) +/* acpi_path_name + * + * @handle - the acpi_handle of the object who's name you want. + * + * Caller must free buffer. + */ +u8 * acpi_path_name(acpi_handle handle) { - acpi_status status; - static u8 path_name[ACPI_PATHNAME_MAX]; - struct acpi_buffer ret_buf = { ACPI_PATHNAME_MAX, path_name }; + acpi_status status; + struct acpi_buffer ret_buf = {ACPI_ALLOCATE_BUFFER, NULL}; + union acpi_object *obj; - memset(path_name, 0, sizeof (path_name)); status = acpi_get_name(handle, ACPI_FULL_PATHNAME, &ret_buf); - - if (ACPI_FAILURE(status)) + if (ACPI_FAILURE(status)) { return NULL; - else - return path_name; + } + obj = ret_buf.pointer; + return obj->string.pointer; } +EXPORT_SYMBOL_GPL(acpi_path_name); + + static acpi_status acpi_run_hpp(acpi_handle handle, struct hotplug_params *hpp) @@ -69,8 +76,9 @@ acpi_run_hpp(acpi_handle handle, struct hotplug_params *hpp) case AE_BUFFER_OVERFLOW: ret_buf.pointer = kmalloc (ret_buf.length, GFP_KERNEL); if (!ret_buf.pointer) { - err ("%s:%s alloc for _HPP fail\n", __FUNCTION__, - path_name); + printk(KERN_ERR "%s:%s alloc for _HPP fail\n", + __FUNCTION__, path_name); + acpi_os_free(path_name); return AE_NO_MEMORY; } status = acpi_evaluate_object(handle, METHOD_NAME__HPP, @@ -79,15 +87,16 @@ acpi_run_hpp(acpi_handle handle, struct hotplug_params *hpp) break; default: if (ACPI_FAILURE(status)) { - dbg("%s:%s _HPP fail=0x%x\n", __FUNCTION__, + pr_debug("%s:%s _HPP fail=0x%x\n", __FUNCTION__, path_name, status); + acpi_os_free(path_name); return status; } } ext_obj = (union acpi_object *) ret_buf.pointer; if (ext_obj->type != ACPI_TYPE_PACKAGE) { - err ("%s:%s _HPP obj not a package\n", __FUNCTION__, + printk(KERN_ERR "%s:%s _HPP obj not a package\n", __FUNCTION__, path_name); status = AE_ERROR; goto free_and_return; @@ -102,8 +111,8 @@ acpi_run_hpp(acpi_handle handle, struct hotplug_params *hpp) nui[i] = (u8)ext_obj->integer.value; break; default: - err ("%s:%s _HPP obj type incorrect\n", __FUNCTION__, - path_name); + printk(KERN_ERR "%s:%s _HPP obj type incorrect\n", + __FUNCTION__, path_name); status = AE_ERROR; goto free_and_return; } @@ -114,33 +123,79 @@ acpi_run_hpp(acpi_handle handle, struct hotplug_params *hpp) hpp->enable_serr = nui[2]; hpp->enable_perr = nui[3]; - dbg(" _HPP: cache_line_size=0x%x\n", hpp->cache_line_size); - dbg(" _HPP: latency timer =0x%x\n", hpp->latency_timer); - dbg(" _HPP: enable SERR =0x%x\n", hpp->enable_serr); - dbg(" _HPP: enable PERR =0x%x\n", hpp->enable_perr); + pr_debug(" _HPP: cache_line_size=0x%x\n", hpp->cache_line_size); + pr_debug(" _HPP: latency timer =0x%x\n", hpp->latency_timer); + pr_debug(" _HPP: enable SERR =0x%x\n", hpp->enable_serr); + pr_debug(" _HPP: enable PERR =0x%x\n", hpp->enable_perr); free_and_return: + acpi_os_free(path_name); kfree(ret_buf.pointer); return status; } -static acpi_status acpi_run_oshp(acpi_handle handle) + + +/* acpi_run_oshp - get control of hotplug from the firmware + * + * @handle - the handle of the hotplug controller. + */ +acpi_status acpi_run_oshp(acpi_handle handle) { acpi_status status; u8 *path_name = acpi_path_name(handle); /* run OSHP */ status = acpi_evaluate_object(handle, METHOD_NAME_OSHP, NULL, NULL); - if (ACPI_FAILURE(status)) { - dbg("%s:%s OSHP fails=0x%x\n", __FUNCTION__, path_name, - status); - } else { - dbg("%s:%s OSHP passes\n", __FUNCTION__, path_name); + if (ACPI_FAILURE(status)) + printk(KERN_ERR "%s:%s OSHP fails=0x%x\n", __FUNCTION__, + path_name, status); + else + pr_debug("%s:%s OSHP passes\n", __FUNCTION__, path_name); + acpi_os_free(path_name); + return status; +} +EXPORT_SYMBOL_GPL(acpi_run_oshp); + + + +/* acpi_get_hp_params_from_firmware + * + * @dev - the pci_dev of the newly added device + * @hpp - allocated by the caller + */ +acpi_status acpi_get_hp_params_from_firmware(struct pci_dev *dev, + struct hotplug_params *hpp) +{ + acpi_status status = AE_NOT_FOUND; + struct pci_dev *pdev = dev; + + /* + * _HPP settings apply to all child buses, until another _HPP is + * encountered. If we don't find an _HPP for the input pci dev, + * look for it in the parent device scope since that would apply to + * this pci dev. If we don't find any _HPP, use hardcoded defaults + */ + while (pdev && (ACPI_FAILURE(status))) { + acpi_handle handle = DEVICE_ACPI_HANDLE(&(pdev->dev)); + if (!handle) + break; + status = acpi_run_hpp(handle, hpp); + if (!(pdev->bus->parent)) + break; + /* Check if a parent object supports _HPP */ + pdev = pdev->bus->parent->self; } return status; } +EXPORT_SYMBOL_GPL(acpi_get_hp_params_from_firmware); -static int is_root_bridge(acpi_handle handle) + +/* acpi_root_bridge - check to see if this acpi object is a root bridge + * + * @handle - the acpi object in question. + */ +int acpi_root_bridge(acpi_handle handle) { acpi_status status; struct acpi_device_info *info; @@ -165,93 +220,8 @@ static int is_root_bridge(acpi_handle handle) } } } + acpi_os_free(buffer.pointer); } return 0; } - -int pciehp_get_hp_hw_control_from_firmware(struct pci_dev *dev) -{ - acpi_status status; - acpi_handle chandle, handle = DEVICE_ACPI_HANDLE(&(dev->dev)); - struct pci_dev *pdev = dev; - struct pci_bus *parent; - u8 *path_name; - - /* - * Per PCI firmware specification, we should run the ACPI _OSC - * method to get control of hotplug hardware before using it. - * If an _OSC is missing, we look for an OSHP to do the same thing. - * To handle different BIOS behavior, we look for _OSC and OSHP - * within the scope of the hotplug controller and its parents, upto - * the host bridge under which this controller exists. - */ - while (!handle) { - /* - * This hotplug controller was not listed in the ACPI name - * space at all. Try to get acpi handle of parent pci bus. - */ - if (!pdev || !pdev->bus->parent) - break; - parent = pdev->bus->parent; - dbg("Could not find %s in acpi namespace, trying parent\n", - pci_name(pdev)); - if (!parent->self) - /* Parent must be a host bridge */ - handle = acpi_get_pci_rootbridge_handle( - pci_domain_nr(parent), - parent->number); - else - handle = DEVICE_ACPI_HANDLE( - &(parent->self->dev)); - pdev = parent->self; - } - - while (handle) { - path_name = acpi_path_name(handle); - dbg("Trying to get hotplug control for %s \n", path_name); - status = pci_osc_control_set(handle, - OSC_PCI_EXPRESS_NATIVE_HP_CONTROL); - if (status == AE_NOT_FOUND) - status = acpi_run_oshp(handle); - if (ACPI_SUCCESS(status)) { - dbg("Gained control for hotplug HW for pci %s (%s)\n", - pci_name(dev), path_name); - return 0; - } - if (is_root_bridge(handle)) - break; - chandle = handle; - status = acpi_get_parent(chandle, &handle); - if (ACPI_FAILURE(status)) - break; - } - - err("Cannot get control of hotplug hardware for pci %s\n", - pci_name(dev)); - return -1; -} - -void pciehp_get_hp_params_from_firmware(struct pci_dev *dev, - struct hotplug_params *hpp) -{ - acpi_status status = AE_NOT_FOUND; - struct pci_dev *pdev = dev; - - /* - * _HPP settings apply to all child buses, until another _HPP is - * encountered. If we don't find an _HPP for the input pci dev, - * look for it in the parent device scope since that would apply to - * this pci dev. If we don't find any _HPP, use hardcoded defaults - */ - while (pdev && (ACPI_FAILURE(status))) { - acpi_handle handle = DEVICE_ACPI_HANDLE(&(pdev->dev)); - if (!handle) - break; - status = acpi_run_hpp(handle, hpp); - if (!(pdev->bus->parent)) - break; - /* Check if a parent object supports _HPP */ - pdev = pdev->bus->parent->self; - } -} - +EXPORT_SYMBOL_GPL(acpi_root_bridge); diff --git a/drivers/pci/hotplug/acpiphp.h b/drivers/pci/hotplug/acpiphp.h index de9df80ffb50..467ac70a46ff 100644 --- a/drivers/pci/hotplug/acpiphp.h +++ b/drivers/pci/hotplug/acpiphp.h @@ -64,19 +64,6 @@ struct slot { struct acpiphp_slot *acpi_slot; }; -/** - * struct hpp_param - ACPI 2.0 _HPP Hot Plug Parameters - * @cache_line_size in DWORD - * @latency_timer in PCI clock - * @enable_SERR 0 or 1 - * @enable_PERR 0 or 1 - */ -struct hpp_param { - u8 cache_line_size; - u8 latency_timer; - u8 enable_SERR; - u8 enable_PERR; -}; /** @@ -100,7 +87,7 @@ struct acpiphp_bridge { struct pci_dev *pci_dev; /* ACPI 2.0 _HPP parameters */ - struct hpp_param hpp; + struct hotplug_params hpp; spinlock_t res_lock; }; diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index c7e6387983df..053ee843863c 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c @@ -285,57 +285,19 @@ static int detect_ejectable_slots(acpi_handle *bridge_handle) static void decode_hpp(struct acpiphp_bridge *bridge) { acpi_status status; - struct acpi_buffer buffer = { .length = ACPI_ALLOCATE_BUFFER, - .pointer = NULL}; - union acpi_object *package; - int i; - - /* default numbers */ - bridge->hpp.cache_line_size = 0x10; - bridge->hpp.latency_timer = 0x40; - bridge->hpp.enable_SERR = 0; - bridge->hpp.enable_PERR = 0; - - status = acpi_evaluate_object(bridge->handle, "_HPP", NULL, &buffer); + status = acpi_get_hp_params_from_firmware(bridge->pci_dev, &bridge->hpp); if (ACPI_FAILURE(status)) { - dbg("_HPP evaluation failed\n"); - return; + /* use default numbers */ + bridge->hpp.cache_line_size = 0x10; + bridge->hpp.latency_timer = 0x40; + bridge->hpp.enable_serr = 0; + bridge->hpp.enable_perr = 0; } - - package = (union acpi_object *) buffer.pointer; - - if (!package || package->type != ACPI_TYPE_PACKAGE || - package->package.count != 4 || !package->package.elements) { - err("invalid _HPP object; ignoring\n"); - goto err_exit; - } - - for (i = 0; i < 4; i++) { - if (package->package.elements[i].type != ACPI_TYPE_INTEGER) { - err("invalid _HPP parameter type; ignoring\n"); - goto err_exit; - } - } - - bridge->hpp.cache_line_size = package->package.elements[0].integer.value; - bridge->hpp.latency_timer = package->package.elements[1].integer.value; - bridge->hpp.enable_SERR = package->package.elements[2].integer.value; - bridge->hpp.enable_PERR = package->package.elements[3].integer.value; - - dbg("_HPP parameter = (%02x, %02x, %02x, %02x)\n", - bridge->hpp.cache_line_size, - bridge->hpp.latency_timer, - bridge->hpp.enable_SERR, - bridge->hpp.enable_PERR); - - bridge->flags |= BRIDGE_HAS_HPP; - - err_exit: - kfree(buffer.pointer); } + /* initialize miscellaneous stuff for both root and PCI-to-PCI bridge */ static void init_bridge_misc(struct acpiphp_bridge *bridge) { @@ -1154,11 +1116,11 @@ static void program_hpp(struct pci_dev *dev, struct acpiphp_bridge *bridge) pci_write_config_byte(dev, PCI_LATENCY_TIMER, bridge->hpp.latency_timer); pci_read_config_word(dev, PCI_COMMAND, &pci_cmd); - if (bridge->hpp.enable_SERR) + if (bridge->hpp.enable_serr) pci_cmd |= PCI_COMMAND_SERR; else pci_cmd &= ~PCI_COMMAND_SERR; - if (bridge->hpp.enable_PERR) + if (bridge->hpp.enable_perr) pci_cmd |= PCI_COMMAND_PARITY; else pci_cmd &= ~PCI_COMMAND_PARITY; @@ -1169,11 +1131,11 @@ static void program_hpp(struct pci_dev *dev, struct acpiphp_bridge *bridge) pci_write_config_byte(dev, PCI_SEC_LATENCY_TIMER, bridge->hpp.latency_timer); pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &pci_bctl); - if (bridge->hpp.enable_SERR) + if (bridge->hpp.enable_serr) pci_bctl |= PCI_BRIDGE_CTL_SERR; else pci_bctl &= ~PCI_BRIDGE_CTL_SERR; - if (bridge->hpp.enable_PERR) + if (bridge->hpp.enable_perr) pci_bctl |= PCI_BRIDGE_CTL_PARITY; else pci_bctl &= ~PCI_BRIDGE_CTL_PARITY; @@ -1193,6 +1155,7 @@ static void acpiphp_set_hpp_values(acpi_handle handle, struct pci_bus *bus) memset(&bridge, 0, sizeof(bridge)); bridge.handle = handle; + bridge.pci_dev = bus->self; decode_hpp(&bridge); list_for_each_entry(dev, &bus->devices, bus_list) program_hpp(dev, &bridge); @@ -1409,41 +1372,13 @@ void handle_hotplug_event_func(acpi_handle handle, u32 type, void *context) } } -static int is_root_bridge(acpi_handle handle) -{ - acpi_status status; - struct acpi_device_info *info; - struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; - int i; - - status = acpi_get_object_info(handle, &buffer); - if (ACPI_SUCCESS(status)) { - info = buffer.pointer; - if ((info->valid & ACPI_VALID_HID) && - !strcmp(PCI_ROOT_HID_STRING, - info->hardware_id.value)) { - acpi_os_free(buffer.pointer); - return 1; - } - if (info->valid & ACPI_VALID_CID) { - for (i=0; i < info->compatibility_id.count; i++) { - if (!strcmp(PCI_ROOT_HID_STRING, - info->compatibility_id.id[i].value)) { - acpi_os_free(buffer.pointer); - return 1; - } - } - } - } - return 0; -} static acpi_status find_root_bridges(acpi_handle handle, u32 lvl, void *context, void **rv) { int *count = (int *)context; - if (is_root_bridge(handle)) { + if (acpi_root_bridge(handle)) { acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY, handle_hotplug_event_bridge, NULL); (*count)++; diff --git a/drivers/pci/hotplug/pci_hotplug.h b/drivers/pci/hotplug/pci_hotplug.h index 88d44f7fef29..e476ed033384 100644 --- a/drivers/pci/hotplug/pci_hotplug.h +++ b/drivers/pci/hotplug/pci_hotplug.h @@ -176,5 +176,22 @@ extern int pci_hp_change_slot_info (struct hotplug_slot *slot, struct hotplug_slot_info *info); extern struct subsystem pci_hotplug_slots_subsys; +struct hotplug_params { + u8 cache_line_size; + u8 latency_timer; + u8 enable_serr; + u8 enable_perr; +}; + +#ifdef CONFIG_ACPI +#include +#include +#include +extern acpi_status acpi_run_oshp(acpi_handle handle); +extern acpi_status acpi_get_hp_params_from_firmware(struct pci_dev *dev, + struct hotplug_params *hpp); +extern u8 * acpi_path_name(acpi_handle handle); +int acpi_root_bridge(acpi_handle handle); +#endif #endif diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h index e0adf4bc89e8..92c1f0f1e1ad 100644 --- a/drivers/pci/hotplug/pciehp.h +++ b/drivers/pci/hotplug/pciehp.h @@ -50,12 +50,6 @@ extern int pciehp_force; #define info(format, arg...) printk(KERN_INFO "%s: " format, MY_NAME , ## arg) #define warn(format, arg...) printk(KERN_WARNING "%s: " format, MY_NAME , ## arg) -struct hotplug_params { - u8 cache_line_size; - u8 latency_timer; - u8 enable_serr; - u8 enable_perr; -}; struct slot { struct slot *next; @@ -192,9 +186,6 @@ extern u8 pciehp_handle_power_fault (u8 hp_slot, void *inst_id); /* pci functions */ extern int pciehp_configure_device (struct slot *p_slot); extern int pciehp_unconfigure_device (struct slot *p_slot); -extern int pciehp_get_hp_hw_control_from_firmware(struct pci_dev *dev); -extern void pciehp_get_hp_params_from_firmware(struct pci_dev *dev, - struct hotplug_params *hpp); @@ -286,4 +277,19 @@ struct hpc_ops { int (*check_lnk_status) (struct controller *ctrl); }; + +#ifdef CONFIG_ACPI +#define pciehp_get_hp_hw_control_from_firmware(dev) \ + pciehp_acpi_get_hp_hw_control_from_firmware(dev) +static inline int pciehp_get_hp_params_from_firmware(struct pci_dev *dev, + struct hotplug_params *hpp) +{ + if (ACPI_FAILURE(acpi_get_hp_params_from_firmware(dev, hpp))) + return -ENODEV; + return 0; +} +#else +#define pciehp_get_hp_hw_control_from_firmware(dev) 0 +#define pciehp_get_hp_params_from_firmware(dev, hpp) (-ENODEV) +#endif /* CONFIG_ACPI */ #endif /* _PCIEHP_H */ diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index 2427b0862cbf..22dcd12e4c1c 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c @@ -38,7 +38,10 @@ #include "../pci.h" #include "pciehp.h" - +#include +#include +#include +#include #ifdef DEBUG #define DBG_K_TRACE_ENTRY ((unsigned int)0x00000001) /* On function entry */ #define DBG_K_TRACE_EXIT ((unsigned int)0x00000002) /* On function exit */ @@ -1236,6 +1239,75 @@ static struct hpc_ops pciehp_hpc_ops = { .check_lnk_status = hpc_check_lnk_status, }; +#ifdef CONFIG_ACPI +int pciehp_acpi_get_hp_hw_control_from_firmware(struct pci_dev *dev) +{ + acpi_status status; + acpi_handle chandle, handle = DEVICE_ACPI_HANDLE(&(dev->dev)); + struct pci_dev *pdev = dev; + struct pci_bus *parent; + u8 *path_name = NULL; + + /* + * Per PCI firmware specification, we should run the ACPI _OSC + * method to get control of hotplug hardware before using it. + * If an _OSC is missing, we look for an OSHP to do the same thing. + * To handle different BIOS behavior, we look for _OSC and OSHP + * within the scope of the hotplug controller and its parents, upto + * the host bridge under which this controller exists. + */ + while (!handle) { + /* + * This hotplug controller was not listed in the ACPI name + * space at all. Try to get acpi handle of parent pci bus. + */ + if (!pdev || !pdev->bus->parent) + break; + parent = pdev->bus->parent; + dbg("Could not find %s in acpi namespace, trying parent\n", + pci_name(pdev)); + if (!parent->self) + /* Parent must be a host bridge */ + handle = acpi_get_pci_rootbridge_handle( + pci_domain_nr(parent), + parent->number); + else + handle = DEVICE_ACPI_HANDLE( + &(parent->self->dev)); + pdev = parent->self; + } + + while (handle) { + path_name = acpi_path_name(handle); + dbg("Trying to get hotplug control for %s \n", path_name); + status = pci_osc_control_set(handle, + OSC_PCI_EXPRESS_NATIVE_HP_CONTROL); + if (status == AE_NOT_FOUND) + status = acpi_run_oshp(handle); + if (ACPI_SUCCESS(status)) { + dbg("Gained control for hotplug HW for pci %s (%s)\n", + pci_name(dev), path_name); + acpi_os_free(path_name); + return 0; + } + if (acpi_root_bridge(handle)) + break; + chandle = handle; + status = acpi_get_parent(chandle, &handle); + if (ACPI_FAILURE(status)) + break; + } + + err("Cannot get control of hotplug hardware for pci %s\n", + pci_name(dev)); + if (path_name) + acpi_os_free(path_name); + return -1; +} +#endif + + + int pcie_init(struct controller * ctrl, struct pcie_device *dev) { struct php_ctlr_state_s *php_ctlr, *p; diff --git a/drivers/pci/hotplug/pciehprm_nonacpi.c b/drivers/pci/hotplug/pciehprm_nonacpi.c deleted file mode 100644 index 29180dfe8493..000000000000 --- a/drivers/pci/hotplug/pciehprm_nonacpi.c +++ /dev/null @@ -1,47 +0,0 @@ -/* - * PCIEHPRM NONACPI: PHP Resource Manager for Non-ACPI/Legacy platform - * - * Copyright (C) 1995,2001 Compaq Computer Corporation - * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com) - * Copyright (C) 2001 IBM Corp. - * Copyright (C) 2003-2004 Intel Corporation - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or - * NON INFRINGEMENT. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * Send feedback to , - * - */ - -#include -#include -#include -#include -#include -#include -#include "pciehp.h" - -void pciehp_get_hp_params_from_firmware(struct pci_dev *dev, - struct hotplug_params *hpp) -{ - return; -} - -int pciehp_get_hp_hw_control_from_firmware(struct pci_dev *dev) -{ - return 0; -} diff --git a/drivers/pci/hotplug/shpchp.h b/drivers/pci/hotplug/shpchp.h index f10f1ba877af..5c70f43908c4 100644 --- a/drivers/pci/hotplug/shpchp.h +++ b/drivers/pci/hotplug/shpchp.h @@ -106,12 +106,6 @@ struct controller { volatile int cmd_busy; }; -struct hotplug_params { - u8 cache_line_size; - u8 latency_timer; - u8 enable_serr; - u8 enable_perr; -}; /* Define AMD SHPC ID */ #define PCI_DEVICE_ID_AMD_GOLAM_7450 0x7450 @@ -193,15 +187,29 @@ extern u8 shpchp_handle_power_fault(u8 hp_slot, void *inst_id); extern int shpchp_save_config(struct controller *ctrl, int busnumber, int num_ctlr_slots, int first_device_num); extern int shpchp_configure_device(struct slot *p_slot); extern int shpchp_unconfigure_device(struct slot *p_slot); -extern void get_hp_hw_control_from_firmware(struct pci_dev *dev); -extern void get_hp_params_from_firmware(struct pci_dev *dev, - struct hotplug_params *hpp); -extern int shpchprm_get_physical_slot_number(struct controller *ctrl, - u32 *sun, u8 busnum, u8 devnum); extern void shpchp_remove_ctrl_files(struct controller *ctrl); extern void cleanup_slots(struct controller *ctrl); extern void queue_pushbutton_work(void *data); + +#ifdef CONFIG_ACPI +static inline int get_hp_params_from_firmware(struct pci_dev *dev, + struct hotplug_params *hpp) +{ + if (ACPI_FAILURE(acpi_get_hp_params_from_firmware(dev, hpp))) + return -ENODEV; + return 0; +} +#define get_hp_hw_control_from_firmware(pdev) \ + do { \ + if (DEVICE_ACPI_HANDLE(&(pdev->dev))) \ + acpi_run_oshp(DEVICE_ACPI_HANDLE(&(pdev->dev))); \ + } while (0) +#else +#define get_hp_params_from_firmware(dev, hpp) (-ENODEV) +#define get_hp_hw_control_from_firmware(dev) do { } while (0) +#endif + struct ctrl_reg { volatile u32 base_offset; volatile u32 slot_avail1; diff --git a/drivers/pci/hotplug/shpchp_core.c b/drivers/pci/hotplug/shpchp_core.c index 0e83c5fbc9df..3be4d492ccc2 100644 --- a/drivers/pci/hotplug/shpchp_core.c +++ b/drivers/pci/hotplug/shpchp_core.c @@ -104,6 +104,23 @@ static void make_slot_name(struct slot *slot) slot->bus, slot->number); } + + + +static int +shpchprm_get_physical_slot_number(struct controller *ctrl, u32 *sun, + u8 busnum, u8 devnum) +{ + int offset = devnum - ctrl->slot_device_offset; + + dbg("%s: ctrl->slot_num_inc %d, offset %d\n", __FUNCTION__, + ctrl->slot_num_inc, offset); + *sun = (u8) (ctrl->first_slot + ctrl->slot_num_inc *offset); + return 0; +} + + + static int init_slots(struct controller *ctrl) { struct slot *slot; diff --git a/drivers/pci/hotplug/shpchp_pci.c b/drivers/pci/hotplug/shpchp_pci.c index 19e1a5e1e30b..257adc233996 100644 --- a/drivers/pci/hotplug/shpchp_pci.c +++ b/drivers/pci/hotplug/shpchp_pci.c @@ -38,7 +38,7 @@ static void program_fw_provided_values(struct pci_dev *dev) { u16 pci_cmd, pci_bctl; struct pci_dev *cdev; - struct hotplug_params hpp = {0x8, 0x40, 0, 0}; /* defaults */ + struct hotplug_params hpp; /* Program hpp values for this device */ if (!(dev->hdr_type == PCI_HEADER_TYPE_NORMAL || @@ -46,7 +46,13 @@ static void program_fw_provided_values(struct pci_dev *dev) (dev->class >> 8) == PCI_CLASS_BRIDGE_PCI))) return; - get_hp_params_from_firmware(dev, &hpp); + /* use default values if we can't get them from firmware */ + if (get_hp_params_from_firmware(dev, &hpp)) { + hpp.cache_line_size = 8; + hpp.latency_timer = 0x40; + hpp.enable_serr = 0; + hpp.enable_perr = 0; + } pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, hpp.cache_line_size); pci_write_config_byte(dev, PCI_LATENCY_TIMER, hpp.latency_timer); diff --git a/drivers/pci/hotplug/shpchprm_acpi.c b/drivers/pci/hotplug/shpchprm_acpi.c deleted file mode 100644 index 17145e52223a..000000000000 --- a/drivers/pci/hotplug/shpchprm_acpi.c +++ /dev/null @@ -1,186 +0,0 @@ -/* - * SHPCHPRM ACPI: PHP Resource Manager for ACPI platform - * - * Copyright (C) 2003-2004 Intel Corporation - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or - * NON INFRINGEMENT. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * Send feedback to - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include "shpchp.h" - -#define METHOD_NAME__SUN "_SUN" -#define METHOD_NAME__HPP "_HPP" -#define METHOD_NAME_OSHP "OSHP" - -static u8 * acpi_path_name( acpi_handle handle) -{ - acpi_status status; - static u8 path_name[ACPI_PATHNAME_MAX]; - struct acpi_buffer ret_buf = { ACPI_PATHNAME_MAX, path_name }; - - memset(path_name, 0, sizeof (path_name)); - status = acpi_get_name(handle, ACPI_FULL_PATHNAME, &ret_buf); - - if (ACPI_FAILURE(status)) - return NULL; - else - return path_name; -} - -static acpi_status -acpi_run_hpp(acpi_handle handle, struct hotplug_params *hpp) -{ - acpi_status status; - u8 nui[4]; - struct acpi_buffer ret_buf = { 0, NULL}; - union acpi_object *ext_obj, *package; - u8 *path_name = acpi_path_name(handle); - int i, len = 0; - - /* get _hpp */ - status = acpi_evaluate_object(handle, METHOD_NAME__HPP, NULL, &ret_buf); - switch (status) { - case AE_BUFFER_OVERFLOW: - ret_buf.pointer = kmalloc (ret_buf.length, GFP_KERNEL); - if (!ret_buf.pointer) { - err ("%s:%s alloc for _HPP fail\n", __FUNCTION__, - path_name); - return AE_NO_MEMORY; - } - status = acpi_evaluate_object(handle, METHOD_NAME__HPP, - NULL, &ret_buf); - if (ACPI_SUCCESS(status)) - break; - default: - if (ACPI_FAILURE(status)) { - dbg("%s:%s _HPP fail=0x%x\n", __FUNCTION__, - path_name, status); - return status; - } - } - - ext_obj = (union acpi_object *) ret_buf.pointer; - if (ext_obj->type != ACPI_TYPE_PACKAGE) { - err ("%s:%s _HPP obj not a package\n", __FUNCTION__, - path_name); - status = AE_ERROR; - goto free_and_return; - } - - len = ext_obj->package.count; - package = (union acpi_object *) ret_buf.pointer; - for ( i = 0; (i < len) || (i < 4); i++) { - ext_obj = (union acpi_object *) &package->package.elements[i]; - switch (ext_obj->type) { - case ACPI_TYPE_INTEGER: - nui[i] = (u8)ext_obj->integer.value; - break; - default: - err ("%s:%s _HPP obj type incorrect\n", __FUNCTION__, - path_name); - status = AE_ERROR; - goto free_and_return; - } - } - - hpp->cache_line_size = nui[0]; - hpp->latency_timer = nui[1]; - hpp->enable_serr = nui[2]; - hpp->enable_perr = nui[3]; - - dbg(" _HPP: cache_line_size=0x%x\n", hpp->cache_line_size); - dbg(" _HPP: latency timer =0x%x\n", hpp->latency_timer); - dbg(" _HPP: enable SERR =0x%x\n", hpp->enable_serr); - dbg(" _HPP: enable PERR =0x%x\n", hpp->enable_perr); - -free_and_return: - kfree(ret_buf.pointer); - return status; -} - -static void acpi_run_oshp(acpi_handle handle) -{ - acpi_status status; - u8 *path_name = acpi_path_name(handle); - - /* run OSHP */ - status = acpi_evaluate_object(handle, METHOD_NAME_OSHP, NULL, NULL); - if (ACPI_FAILURE(status)) { - err("%s:%s OSHP fails=0x%x\n", __FUNCTION__, path_name, - status); - } else { - dbg("%s:%s OSHP passes\n", __FUNCTION__, path_name); - } -} - -int shpchprm_get_physical_slot_number(struct controller *ctrl, u32 *sun, u8 busnum, u8 devnum) -{ - int offset = devnum - ctrl->slot_device_offset; - - dbg("%s: ctrl->slot_num_inc %d, offset %d\n", __FUNCTION__, ctrl->slot_num_inc, offset); - *sun = (u8) (ctrl->first_slot + ctrl->slot_num_inc *offset); - return 0; -} - -void get_hp_hw_control_from_firmware(struct pci_dev *dev) -{ - /* - * OSHP is an optional ACPI firmware control method. If present, - * we need to run it to inform BIOS that we will control SHPC - * hardware from now on. - */ - acpi_handle handle = DEVICE_ACPI_HANDLE(&(dev->dev)); - if (!handle) - return; - acpi_run_oshp(handle); -} - -void get_hp_params_from_firmware(struct pci_dev *dev, - struct hotplug_params *hpp) -{ - acpi_status status = AE_NOT_FOUND; - struct pci_dev *pdev = dev; - - /* - * _HPP settings apply to all child buses, until another _HPP is - * encountered. If we don't find an _HPP for the input pci dev, - * look for it in the parent device scope since that would apply to - * this pci dev. If we don't find any _HPP, use hardcoded defaults - */ - while (pdev && (ACPI_FAILURE(status))) { - acpi_handle handle = DEVICE_ACPI_HANDLE(&(pdev->dev)); - if (!handle) - break; - status = acpi_run_hpp(handle, hpp); - if (!(pdev->bus->parent)) - break; - /* Check if a parent object supports _HPP */ - pdev = pdev->bus->parent->self; - } -} - diff --git a/drivers/pci/hotplug/shpchprm_legacy.c b/drivers/pci/hotplug/shpchprm_legacy.c deleted file mode 100644 index ed6c1254bf6f..000000000000 --- a/drivers/pci/hotplug/shpchprm_legacy.c +++ /dev/null @@ -1,54 +0,0 @@ -/* - * SHPCHPRM Legacy: PHP Resource Manager for Non-ACPI/Legacy platform - * - * Copyright (C) 1995,2001 Compaq Computer Corporation - * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com) - * Copyright (C) 2001 IBM Corp. - * Copyright (C) 2003-2004 Intel Corporation - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or - * NON INFRINGEMENT. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * Send feedback to , - * - */ - -#include -#include -#include -#include -#include "shpchp.h" - -int shpchprm_get_physical_slot_number(struct controller *ctrl, u32 *sun, u8 busnum, u8 devnum) -{ - int offset = devnum - ctrl->slot_device_offset; - - *sun = (u8) (ctrl->first_slot + ctrl->slot_num_inc * offset); - return 0; -} - -void get_hp_params_from_firmware(struct pci_dev *dev, - struct hotplug_params *hpp) -{ - return; -} - -void get_hp_hw_control_from_firmware(struct pci_dev *dev) -{ - return; -} - diff --git a/drivers/pci/hotplug/shpchprm_nonacpi.c b/drivers/pci/hotplug/shpchprm_nonacpi.c deleted file mode 100644 index c6b40998eeb3..000000000000 --- a/drivers/pci/hotplug/shpchprm_nonacpi.c +++ /dev/null @@ -1,57 +0,0 @@ -/* - * SHPCHPRM NONACPI: PHP Resource Manager for Non-ACPI/Legacy platform - * - * Copyright (C) 1995,2001 Compaq Computer Corporation - * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com) - * Copyright (C) 2001 IBM Corp. - * Copyright (C) 2003-2004 Intel Corporation - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or - * NON INFRINGEMENT. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * Send feedback to , - * - */ - -#include -#include -#include -#include -#include -#include - -#include "shpchp.h" - -int shpchprm_get_physical_slot_number(struct controller *ctrl, u32 *sun, u8 busnum, u8 devnum) -{ - int offset = devnum - ctrl->slot_device_offset; - - dbg("%s: ctrl->slot_num_inc %d, offset %d\n", __FUNCTION__, ctrl->slot_num_inc, offset); - *sun = (u8) (ctrl->first_slot + ctrl->slot_num_inc * offset); - return 0; -} - -void get_hp_params_from_firmware(struct pci_dev *dev, - struct hotplug_params *hpp) -{ - return; -} - -void get_hp_hw_control_from_firmware(struct pci_dev *dev) -{ - return; -} From dc6712d1261ee4585771724320d28580888818eb Mon Sep 17 00:00:00 2001 From: Kristen Accardi Date: Tue, 14 Mar 2006 16:24:47 -0800 Subject: [PATCH 48/49] [PATCH] ibmphp: remove TRUE and FALSE This patch removes the defines TRUE and FALSE and just uses 0 or 1. Signed-off-by: Kristen Carlson Accardi Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/ibmphp.h | 2 -- drivers/pci/hotplug/ibmphp_core.c | 4 +-- drivers/pci/hotplug/ibmphp_ebda.c | 2 +- drivers/pci/hotplug/ibmphp_hpc.c | 54 ++++++++++++++-------------- drivers/pci/hotplug/ibmphp_pci.c | 58 +++++++++++++++---------------- drivers/pci/hotplug/ibmphp_res.c | 48 ++++++++++++------------- 6 files changed, 83 insertions(+), 85 deletions(-) diff --git a/drivers/pci/hotplug/ibmphp.h b/drivers/pci/hotplug/ibmphp.h index c22e0284d7b1..dba6d8ca9bda 100644 --- a/drivers/pci/hotplug/ibmphp.h +++ b/drivers/pci/hotplug/ibmphp.h @@ -406,8 +406,6 @@ extern void ibmphp_hpc_stop_poll_thread (void); //---------------------------------------------------------------------------- // HPC return codes //---------------------------------------------------------------------------- -#define FALSE 0x00 -#define TRUE 0x01 #define HPC_ERROR 0xFF //----------------------------------------------------------------------------- diff --git a/drivers/pci/hotplug/ibmphp_core.c b/drivers/pci/hotplug/ibmphp_core.c index 45e2a0d9b596..e13d5b87241a 100644 --- a/drivers/pci/hotplug/ibmphp_core.c +++ b/drivers/pci/hotplug/ibmphp_core.c @@ -1239,9 +1239,9 @@ int ibmphp_do_disable_slot(struct slot *slot_cur) } flag = slot_cur->flag; - slot_cur->flag = TRUE; + slot_cur->flag = 1; - if (flag == TRUE) { + if (flag == 1) { rc = validate(slot_cur, DISABLE); /* checking if powered off already & valid slot # */ if (rc) diff --git a/drivers/pci/hotplug/ibmphp_ebda.c b/drivers/pci/hotplug/ibmphp_ebda.c index ba12034c5d3a..05e4f5a1927a 100644 --- a/drivers/pci/hotplug/ibmphp_ebda.c +++ b/drivers/pci/hotplug/ibmphp_ebda.c @@ -944,7 +944,7 @@ static int __init ebda_rsrc_controller (void) goto error_no_slot; } - tmp_slot->flag = TRUE; + tmp_slot->flag = 1; tmp_slot->capabilities = hpc_ptr->slots[index].slot_cap; if ((hpc_ptr->slots[index].slot_cap & EBDA_SLOT_133_MAX) == EBDA_SLOT_133_MAX) diff --git a/drivers/pci/hotplug/ibmphp_hpc.c b/drivers/pci/hotplug/ibmphp_hpc.c index d680bb472c7b..c3ac98a0a6a6 100644 --- a/drivers/pci/hotplug/ibmphp_hpc.c +++ b/drivers/pci/hotplug/ibmphp_hpc.c @@ -38,7 +38,7 @@ #include "ibmphp.h" -static int to_debug = FALSE; +static int to_debug = 0; #define debug_polling(fmt, arg...) do { if (to_debug) debug (fmt, arg); } while (0) //---------------------------------------------------------------------------- @@ -95,8 +95,8 @@ static int to_debug = FALSE; //---------------------------------------------------------------------------- // macro utilities //---------------------------------------------------------------------------- -// if bits 20,22,25,26,27,29,30 are OFF return TRUE -#define HPC_I2CSTATUS_CHECK(s) ((u8)((s & 0x00000A76) ? FALSE : TRUE)) +// if bits 20,22,25,26,27,29,30 are OFF return 1 +#define HPC_I2CSTATUS_CHECK(s) ((u8)((s & 0x00000A76) ? 0 : 1)) //---------------------------------------------------------------------------- // global variables @@ -136,8 +136,8 @@ void __init ibmphp_hpc_initvars (void) mutex_init(&sem_hpcaccess); init_MUTEX (&semOperations); init_MUTEX_LOCKED (&sem_exit); - to_debug = FALSE; - ibmphp_shutdown = FALSE; + to_debug = 0; + ibmphp_shutdown = 0; tid_poll = 0; debug ("%s - Exit\n", __FUNCTION__); @@ -739,21 +739,21 @@ int ibmphp_hpc_writeslot (struct slot * pslot, u8 cmd) // check controller is still not working on the command //-------------------------------------------------------------------- timeout = CMD_COMPLETE_TOUT_SEC; - done = FALSE; + done = 0; while (!done) { rc = hpc_wait_ctlr_notworking (HPC_CTLR_WORKING_TOUT, ctlr_ptr, wpg_bbar, &status); if (!rc) { if (NEEDTOCHECK_CMDSTATUS (cmd)) { if (CTLR_FINISHED (status) == HPC_CTLR_FINISHED_YES) - done = TRUE; + done = 1; } else - done = TRUE; + done = 1; } if (!done) { msleep(1000); if (timeout < 1) { - done = TRUE; + done = 1; err ("%s - Error command complete timeout\n", __FUNCTION__); rc = -EFAULT; } else @@ -799,7 +799,7 @@ void free_hpc_access (void) void ibmphp_lock_operations (void) { down (&semOperations); - to_debug = TRUE; + to_debug = 1; } /*---------------------------------------------------------------------- @@ -809,7 +809,7 @@ void ibmphp_unlock_operations (void) { debug ("%s - Entry\n", __FUNCTION__); up (&semOperations); - to_debug = FALSE; + to_debug = 0; debug ("%s - Exit\n", __FUNCTION__); } @@ -937,40 +937,40 @@ static int process_changeinstatus (struct slot *pslot, struct slot *poldslot) { u8 status; int rc = 0; - u8 disable = FALSE; - u8 update = FALSE; + u8 disable = 0; + u8 update = 0; debug ("process_changeinstatus - Entry pslot[%p], poldslot[%p]\n", pslot, poldslot); // bit 0 - HPC_SLOT_POWER if ((pslot->status & 0x01) != (poldslot->status & 0x01)) - update = TRUE; + update = 1; // bit 1 - HPC_SLOT_CONNECT // ignore // bit 2 - HPC_SLOT_ATTN if ((pslot->status & 0x04) != (poldslot->status & 0x04)) - update = TRUE; + update = 1; // bit 3 - HPC_SLOT_PRSNT2 // bit 4 - HPC_SLOT_PRSNT1 if (((pslot->status & 0x08) != (poldslot->status & 0x08)) || ((pslot->status & 0x10) != (poldslot->status & 0x10))) - update = TRUE; + update = 1; // bit 5 - HPC_SLOT_PWRGD if ((pslot->status & 0x20) != (poldslot->status & 0x20)) // OFF -> ON: ignore, ON -> OFF: disable slot if ((poldslot->status & 0x20) && (SLOT_CONNECT (poldslot->status) == HPC_SLOT_CONNECTED) && (SLOT_PRESENT (poldslot->status))) - disable = TRUE; + disable = 1; // bit 6 - HPC_SLOT_BUS_SPEED // ignore // bit 7 - HPC_SLOT_LATCH if ((pslot->status & 0x80) != (poldslot->status & 0x80)) { - update = TRUE; + update = 1; // OPEN -> CLOSE if (pslot->status & 0x80) { if (SLOT_PWRGD (pslot->status)) { @@ -979,7 +979,7 @@ static int process_changeinstatus (struct slot *pslot, struct slot *poldslot) msleep(1000); rc = ibmphp_hpc_readslot (pslot, READ_SLOTSTATUS, &status); if (SLOT_PWRGD (status)) - update = TRUE; + update = 1; else // overwrite power in pslot to OFF pslot->status &= ~HPC_SLOT_POWER; } @@ -987,17 +987,17 @@ static int process_changeinstatus (struct slot *pslot, struct slot *poldslot) // CLOSE -> OPEN else if ((SLOT_PWRGD (poldslot->status) == HPC_SLOT_PWRGD_GOOD) && (SLOT_CONNECT (poldslot->status) == HPC_SLOT_CONNECTED) && (SLOT_PRESENT (poldslot->status))) { - disable = TRUE; + disable = 1; } // else - ignore } // bit 4 - HPC_SLOT_BLINK_ATTN if ((pslot->ext_status & 0x08) != (poldslot->ext_status & 0x08)) - update = TRUE; + update = 1; if (disable) { debug ("process_changeinstatus - disable slot\n"); - pslot->flag = FALSE; + pslot->flag = 0; rc = ibmphp_do_disable_slot (pslot); } @@ -1102,7 +1102,7 @@ void __exit ibmphp_hpc_stop_poll_thread (void) { debug ("%s - Entry\n", __FUNCTION__); - ibmphp_shutdown = TRUE; + ibmphp_shutdown = 1; debug ("before locking operations \n"); ibmphp_lock_operations (); debug ("after locking operations \n"); @@ -1136,7 +1136,7 @@ static int hpc_wait_ctlr_notworking (int timeout, struct controller *ctlr_ptr, v u8 * pstatus) { int rc = 0; - u8 done = FALSE; + u8 done = 0; debug_polling ("hpc_wait_ctlr_notworking - Entry timeout[%d]\n", timeout); @@ -1144,14 +1144,14 @@ static int hpc_wait_ctlr_notworking (int timeout, struct controller *ctlr_ptr, v *pstatus = ctrl_read (ctlr_ptr, wpg_bbar, WPG_CTLR_INDEX); if (*pstatus == HPC_ERROR) { rc = HPC_ERROR; - done = TRUE; + done = 1; } if (CTLR_WORKING (*pstatus) == HPC_CTLR_WORKING_NO) - done = TRUE; + done = 1; if (!done) { msleep(1000); if (timeout < 1) { - done = TRUE; + done = 1; err ("HPCreadslot - Error ctlr timeout\n"); rc = HPC_ERROR; } else diff --git a/drivers/pci/hotplug/ibmphp_pci.c b/drivers/pci/hotplug/ibmphp_pci.c index 97753ddcd856..d87a9e3eaeeb 100644 --- a/drivers/pci/hotplug/ibmphp_pci.c +++ b/drivers/pci/hotplug/ibmphp_pci.c @@ -199,7 +199,7 @@ int ibmphp_configure_card (struct pci_func *func, u8 slotno) } pci_bus_read_config_byte (ibmphp_pci_bus, devfn, PCI_SECONDARY_BUS, &sec_number); - flag = FALSE; + flag = 0; for (i = 0; i < 32; i++) { if (func->devices[i]) { newfunc = kzalloc(sizeof(*newfunc), GFP_KERNEL); @@ -226,7 +226,7 @@ int ibmphp_configure_card (struct pci_func *func, u8 slotno) cleanup_count = 2; goto error; } - flag = TRUE; + flag = 1; } } @@ -272,7 +272,7 @@ int ibmphp_configure_card (struct pci_func *func, u8 slotno) cur_func->busno, device, function); pci_bus_read_config_byte (ibmphp_pci_bus, devfn, PCI_SECONDARY_BUS, &sec_number); debug ("after configuring bridge..., sec_number = %x\n", sec_number); - flag = FALSE; + flag = 0; for (i = 0; i < 32; i++) { if (func->devices[i]) { debug ("inside for loop, device is %x\n", i); @@ -301,7 +301,7 @@ int ibmphp_configure_card (struct pci_func *func, u8 slotno) cleanup_count = 2; goto error; } - flag = TRUE; + flag = 1; } } @@ -449,7 +449,7 @@ static int configure_device (struct pci_func *func) pfmem[count]->devfunc = PCI_DEVFN(func->device, func->function); pfmem[count]->len = len[count]; - pfmem[count]->fromMem = FALSE; + pfmem[count]->fromMem = 0; if (ibmphp_check_resource (pfmem[count], 0) == 0) { ibmphp_add_resource (pfmem[count]); func->pfmem[count] = pfmem[count]; @@ -467,7 +467,7 @@ static int configure_device (struct pci_func *func) debug ("there's no pfmem... going into mem.\n"); if (ibmphp_check_resource (mem_tmp, 0) == 0) { ibmphp_add_resource (mem_tmp); - pfmem[count]->fromMem = TRUE; + pfmem[count]->fromMem = 1; pfmem[count]->rangeno = mem_tmp->rangeno; pfmem[count]->start = mem_tmp->start; pfmem[count]->end = mem_tmp->end; @@ -571,11 +571,11 @@ static int configure_bridge (struct pci_func **func_passed, u8 slotno) u16 pfmem_base; u32 bar[2]; u32 len[2]; - u8 flag_io = FALSE; - u8 flag_mem = FALSE; - u8 flag_pfmem = FALSE; - u8 need_io_upper = FALSE; - u8 need_pfmem_upper = FALSE; + u8 flag_io = 0; + u8 flag_mem = 0; + u8 flag_pfmem = 0; + u8 need_io_upper = 0; + u8 need_pfmem_upper = 0; struct res_needed *amount_needed = NULL; struct resource_node *io = NULL; struct resource_node *bus_io[2] = {NULL, NULL}; @@ -713,7 +713,7 @@ static int configure_bridge (struct pci_func **func_passed, u8 slotno) bus_pfmem[count]->devfunc = PCI_DEVFN(func->device, func->function); bus_pfmem[count]->len = len[count]; - bus_pfmem[count]->fromMem = FALSE; + bus_pfmem[count]->fromMem = 0; if (ibmphp_check_resource (bus_pfmem[count], 0) == 0) { ibmphp_add_resource (bus_pfmem[count]); func->pfmem[count] = bus_pfmem[count]; @@ -730,7 +730,7 @@ static int configure_bridge (struct pci_func **func_passed, u8 slotno) mem_tmp->len = bus_pfmem[count]->len; if (ibmphp_check_resource (mem_tmp, 0) == 0) { ibmphp_add_resource (mem_tmp); - bus_pfmem[count]->fromMem = TRUE; + bus_pfmem[count]->fromMem = 1; bus_pfmem[count]->rangeno = mem_tmp->rangeno; ibmphp_add_pfmem_from_mem (bus_pfmem[count]); func->pfmem[count] = bus_pfmem[count]; @@ -826,7 +826,7 @@ static int configure_bridge (struct pci_func **func_passed, u8 slotno) if (!amount_needed->io) { debug ("it doesn't want IO?\n"); - flag_io = TRUE; + flag_io = 1; } else { debug ("it wants %x IO behind the bridge\n", amount_needed->io); io = kzalloc(sizeof(*io), GFP_KERNEL); @@ -843,13 +843,13 @@ static int configure_bridge (struct pci_func **func_passed, u8 slotno) if (ibmphp_check_resource (io, 1) == 0) { debug ("were we able to add io\n"); ibmphp_add_resource (io); - flag_io = TRUE; + flag_io = 1; } } if (!amount_needed->mem) { debug ("it doesn't want n.e.memory?\n"); - flag_mem = TRUE; + flag_mem = 1; } else { debug ("it wants %x memory behind the bridge\n", amount_needed->mem); mem = kzalloc(sizeof(*mem), GFP_KERNEL); @@ -864,14 +864,14 @@ static int configure_bridge (struct pci_func **func_passed, u8 slotno) mem->len = amount_needed->mem; if (ibmphp_check_resource (mem, 1) == 0) { ibmphp_add_resource (mem); - flag_mem = TRUE; + flag_mem = 1; debug ("were we able to add mem\n"); } } if (!amount_needed->pfmem) { debug ("it doesn't want n.e.pfmem mem?\n"); - flag_pfmem = TRUE; + flag_pfmem = 1; } else { debug ("it wants %x pfmemory behind the bridge\n", amount_needed->pfmem); pfmem = kzalloc(sizeof(*pfmem), GFP_KERNEL); @@ -884,10 +884,10 @@ static int configure_bridge (struct pci_func **func_passed, u8 slotno) pfmem->busno = func->busno; pfmem->devfunc = PCI_DEVFN(func->device, func->function); pfmem->len = amount_needed->pfmem; - pfmem->fromMem = FALSE; + pfmem->fromMem = 0; if (ibmphp_check_resource (pfmem, 1) == 0) { ibmphp_add_resource (pfmem); - flag_pfmem = TRUE; + flag_pfmem = 1; } else { mem_tmp = kzalloc(sizeof(*mem_tmp), GFP_KERNEL); if (!mem_tmp) { @@ -901,10 +901,10 @@ static int configure_bridge (struct pci_func **func_passed, u8 slotno) mem_tmp->len = pfmem->len; if (ibmphp_check_resource (mem_tmp, 1) == 0) { ibmphp_add_resource (mem_tmp); - pfmem->fromMem = TRUE; + pfmem->fromMem = 1; pfmem->rangeno = mem_tmp->rangeno; ibmphp_add_pfmem_from_mem (pfmem); - flag_pfmem = TRUE; + flag_pfmem = 1; } } } @@ -950,11 +950,11 @@ static int configure_bridge (struct pci_func **func_passed, u8 slotno) if ((io_base & PCI_IO_RANGE_TYPE_MASK) == PCI_IO_RANGE_TYPE_32) { debug ("io 32\n"); - need_io_upper = TRUE; + need_io_upper = 1; } if ((pfmem_base & PCI_PREF_RANGE_TYPE_MASK) == PCI_PREF_RANGE_TYPE_64) { debug ("pfmem 64\n"); - need_pfmem_upper = TRUE; + need_pfmem_upper = 1; } if (bus->noIORanges) { @@ -1119,7 +1119,7 @@ static struct res_needed *scan_behind_bridge (struct pci_func * func, u8 busno) debug ("hdr_type behind the bridge is %x\n", hdr_type); if (hdr_type & PCI_HEADER_TYPE_BRIDGE) { err ("embedded bridges not supported for hot-plugging.\n"); - amount->not_correct = TRUE; + amount->not_correct = 1; return amount; } @@ -1127,12 +1127,12 @@ static struct res_needed *scan_behind_bridge (struct pci_func * func, u8 busno) if (class == PCI_CLASS_NOT_DEFINED_VGA) { err ("The device %x is VGA compatible and as is not supported for hot plugging. " "Please choose another device.\n", device); - amount->not_correct = TRUE; + amount->not_correct = 1; return amount; } else if (class == PCI_CLASS_DISPLAY_VGA) { err ("The device %x is not supported for hot plugging. " "Please choose another device.\n", device); - amount->not_correct = TRUE; + amount->not_correct = 1; return amount; } @@ -1192,9 +1192,9 @@ static struct res_needed *scan_behind_bridge (struct pci_func * func, u8 busno) } /* end for */ if (!howmany) - amount->not_correct = TRUE; + amount->not_correct = 1; else - amount->not_correct = FALSE; + amount->not_correct = 0; if ((amount->io) && (amount->io < IOBRIDGE)) amount->io = IOBRIDGE; if ((amount->mem) && (amount->mem < MEMBRIDGE)) diff --git a/drivers/pci/hotplug/ibmphp_res.c b/drivers/pci/hotplug/ibmphp_res.c index 852a98bf07d3..5636b1ac2a2e 100644 --- a/drivers/pci/hotplug/ibmphp_res.c +++ b/drivers/pci/hotplug/ibmphp_res.c @@ -325,7 +325,7 @@ int __init ibmphp_rsrc_init (void) if (!new_pfmem) return -ENOMEM; new_pfmem->type = PFMEM; - new_pfmem->fromMem = FALSE; + new_pfmem->fromMem = 0; if (ibmphp_add_resource (new_pfmem) < 0) { newbus = alloc_error_bus (curr, 0, 0); if (!newbus) @@ -462,7 +462,7 @@ static int add_range (int type, struct range_node *range, struct bus_node *bus_c static void update_resources (struct bus_node *bus_cur, int type, int rangeno) { struct resource_node *res = NULL; - u8 eol = FALSE; /* end of list indicator */ + u8 eol = 0; /* end of list indicator */ switch (type) { case MEM: @@ -488,7 +488,7 @@ static void update_resources (struct bus_node *bus_cur, int type, int rangeno) else if (res->nextRange) res = res->nextRange; else { - eol = TRUE; + eol = 1; break; } } @@ -979,7 +979,7 @@ int ibmphp_check_resource (struct resource_node *res, u8 bridge) int noranges = 0; u32 tmp_start; /* this is to make sure start address is divisible by the length needed */ u32 tmp_divide; - u8 flag = FALSE; + u8 flag = 0; if (!res) return -EINVAL; @@ -1046,17 +1046,17 @@ int ibmphp_check_resource (struct resource_node *res, u8 bridge) if ((range->start % tmp_divide) == 0) { /* just perfect, starting address is divisible by length */ - flag = TRUE; + flag = 1; len_cur = len_tmp; start_cur = range->start; } else { /* Needs adjusting */ tmp_start = range->start; - flag = FALSE; + flag = 0; while ((len_tmp = res_cur->start - 1 - tmp_start) >= res->len) { if ((tmp_start % tmp_divide) == 0) { - flag = TRUE; + flag = 1; len_cur = len_tmp; start_cur = tmp_start; break; @@ -1085,17 +1085,17 @@ int ibmphp_check_resource (struct resource_node *res, u8 bridge) if (((res_cur->end + 1) % tmp_divide) == 0) { /* just perfect, starting address is divisible by length */ - flag = TRUE; + flag = 1; len_cur = len_tmp; start_cur = res_cur->end + 1; } else { /* Needs adjusting */ tmp_start = res_cur->end + 1; - flag = FALSE; + flag = 0; while ((len_tmp = range->end - tmp_start) >= res->len) { if ((tmp_start % tmp_divide) == 0) { - flag = TRUE; + flag = 1; len_cur = len_tmp; start_cur = tmp_start; break; @@ -1123,17 +1123,17 @@ int ibmphp_check_resource (struct resource_node *res, u8 bridge) if ((len_tmp < len_cur) || (len_cur == 0)) { if ((range->start % tmp_divide) == 0) { /* just perfect, starting address is divisible by length */ - flag = TRUE; + flag = 1; len_cur = len_tmp; start_cur = range->start; } else { /* Needs adjusting */ tmp_start = range->start; - flag = FALSE; + flag = 0; while ((len_tmp = res_cur->start - 1 - tmp_start) >= res->len) { if ((tmp_start % tmp_divide) == 0) { - flag = TRUE; + flag = 1; len_cur = len_tmp; start_cur = tmp_start; break; @@ -1158,17 +1158,17 @@ int ibmphp_check_resource (struct resource_node *res, u8 bridge) if ((len_tmp < len_cur) || (len_cur == 0)) { if (((res_prev->end + 1) % tmp_divide) == 0) { /* just perfect, starting address's divisible by length */ - flag = TRUE; + flag = 1; len_cur = len_tmp; start_cur = res_prev->end + 1; } else { /* Needs adjusting */ tmp_start = res_prev->end + 1; - flag = FALSE; + flag = 0; while ((len_tmp = res_cur->start - 1 - tmp_start) >= res->len) { if ((tmp_start % tmp_divide) == 0) { - flag = TRUE; + flag = 1; len_cur = len_tmp; start_cur = tmp_start; break; @@ -1217,17 +1217,17 @@ int ibmphp_check_resource (struct resource_node *res, u8 bridge) if ((len_tmp < len_cur) || (len_cur == 0)) { if ((range->start % tmp_divide) == 0) { /* just perfect, starting address's divisible by length */ - flag = TRUE; + flag = 1; len_cur = len_tmp; start_cur = range->start; } else { /* Needs adjusting */ tmp_start = range->start; - flag = FALSE; + flag = 0; while ((len_tmp = range->end - tmp_start) >= res->len) { if ((tmp_start % tmp_divide) == 0) { - flag = TRUE; + flag = 1; len_cur = len_tmp; start_cur = tmp_start; break; @@ -1281,17 +1281,17 @@ int ibmphp_check_resource (struct resource_node *res, u8 bridge) if ((len_tmp < len_cur) || (len_cur == 0)) { if ((range->start % tmp_divide) == 0) { /* just perfect, starting address's divisible by length */ - flag = TRUE; + flag = 1; len_cur = len_tmp; start_cur = range->start; } else { /* Needs adjusting */ tmp_start = range->start; - flag = FALSE; + flag = 0; while ((len_tmp = range->end - tmp_start) >= res->len) { if ((tmp_start % tmp_divide) == 0) { - flag = TRUE; + flag = 1; len_cur = len_tmp; start_cur = tmp_start; break; @@ -1684,7 +1684,7 @@ static int __init once_over (void) bus_cur = list_entry (tmp, struct bus_node, bus_list); if ((!bus_cur->rangePFMem) && (bus_cur->firstPFMem)) { for (pfmem_cur = bus_cur->firstPFMem, pfmem_prev = NULL; pfmem_cur; pfmem_prev = pfmem_cur, pfmem_cur = pfmem_cur->next) { - pfmem_cur->fromMem = TRUE; + pfmem_cur->fromMem = 1; if (pfmem_prev) pfmem_prev->next = pfmem_cur->next; else @@ -2129,7 +2129,7 @@ static int __init update_bridge_ranges (struct bus_node **bus) pfmem->start = start_address; pfmem->end = end_address + 0xfffff; pfmem->len = pfmem->end - pfmem->start + 1; - pfmem->fromMem = FALSE; + pfmem->fromMem = 0; ibmphp_add_resource (pfmem); } From b2e6e3ba7deb525f180df64f32f3fcb214538bea Mon Sep 17 00:00:00 2001 From: MUNEDA Takahiro Date: Fri, 17 Mar 2006 09:18:39 +0900 Subject: [PATCH 49/49] [PATCH] acpiphp: fix acpi_path_name I encountered the problem that the insmod of the acpiphp fails because of the mis-freeing of the memory. I tested this patch on my tiger4 box. Signed-off-by: MUNEDA Takahiro Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/acpi_pcihp.c | 54 +++++++++++-------------------- drivers/pci/hotplug/pci_hotplug.h | 1 - drivers/pci/hotplug/pciehp_hpc.c | 15 +++++---- 3 files changed, 27 insertions(+), 43 deletions(-) diff --git a/drivers/pci/hotplug/acpi_pcihp.c b/drivers/pci/hotplug/acpi_pcihp.c index 0f7135317542..39af9c325f35 100644 --- a/drivers/pci/hotplug/acpi_pcihp.c +++ b/drivers/pci/hotplug/acpi_pcihp.c @@ -37,28 +37,6 @@ #define METHOD_NAME__HPP "_HPP" #define METHOD_NAME_OSHP "OSHP" -/* acpi_path_name - * - * @handle - the acpi_handle of the object who's name you want. - * - * Caller must free buffer. - */ -u8 * acpi_path_name(acpi_handle handle) -{ - acpi_status status; - struct acpi_buffer ret_buf = {ACPI_ALLOCATE_BUFFER, NULL}; - union acpi_object *obj; - - status = acpi_get_name(handle, ACPI_FULL_PATHNAME, &ret_buf); - if (ACPI_FAILURE(status)) { - return NULL; - } - obj = ret_buf.pointer; - return obj->string.pointer; -} -EXPORT_SYMBOL_GPL(acpi_path_name); - - static acpi_status acpi_run_hpp(acpi_handle handle, struct hotplug_params *hpp) @@ -66,10 +44,12 @@ acpi_run_hpp(acpi_handle handle, struct hotplug_params *hpp) acpi_status status; u8 nui[4]; struct acpi_buffer ret_buf = { 0, NULL}; + struct acpi_buffer string = { ACPI_ALLOCATE_BUFFER, NULL }; union acpi_object *ext_obj, *package; - u8 *path_name = acpi_path_name(handle); int i, len = 0; + acpi_get_name(handle, ACPI_FULL_PATHNAME, &string); + /* get _hpp */ status = acpi_evaluate_object(handle, METHOD_NAME__HPP, NULL, &ret_buf); switch (status) { @@ -77,8 +57,8 @@ acpi_run_hpp(acpi_handle handle, struct hotplug_params *hpp) ret_buf.pointer = kmalloc (ret_buf.length, GFP_KERNEL); if (!ret_buf.pointer) { printk(KERN_ERR "%s:%s alloc for _HPP fail\n", - __FUNCTION__, path_name); - acpi_os_free(path_name); + __FUNCTION__, (char *)string.pointer); + acpi_os_free(string.pointer); return AE_NO_MEMORY; } status = acpi_evaluate_object(handle, METHOD_NAME__HPP, @@ -88,8 +68,8 @@ acpi_run_hpp(acpi_handle handle, struct hotplug_params *hpp) default: if (ACPI_FAILURE(status)) { pr_debug("%s:%s _HPP fail=0x%x\n", __FUNCTION__, - path_name, status); - acpi_os_free(path_name); + (char *)string.pointer, status); + acpi_os_free(string.pointer); return status; } } @@ -97,7 +77,7 @@ acpi_run_hpp(acpi_handle handle, struct hotplug_params *hpp) ext_obj = (union acpi_object *) ret_buf.pointer; if (ext_obj->type != ACPI_TYPE_PACKAGE) { printk(KERN_ERR "%s:%s _HPP obj not a package\n", __FUNCTION__, - path_name); + (char *)string.pointer); status = AE_ERROR; goto free_and_return; } @@ -112,7 +92,7 @@ acpi_run_hpp(acpi_handle handle, struct hotplug_params *hpp) break; default: printk(KERN_ERR "%s:%s _HPP obj type incorrect\n", - __FUNCTION__, path_name); + __FUNCTION__, (char *)string.pointer); status = AE_ERROR; goto free_and_return; } @@ -129,8 +109,8 @@ acpi_run_hpp(acpi_handle handle, struct hotplug_params *hpp) pr_debug(" _HPP: enable PERR =0x%x\n", hpp->enable_perr); free_and_return: - acpi_os_free(path_name); - kfree(ret_buf.pointer); + acpi_os_free(string.pointer); + acpi_os_free(ret_buf.pointer); return status; } @@ -143,16 +123,20 @@ free_and_return: acpi_status acpi_run_oshp(acpi_handle handle) { acpi_status status; - u8 *path_name = acpi_path_name(handle); + struct acpi_buffer string = { ACPI_ALLOCATE_BUFFER, NULL }; + + acpi_get_name(handle, ACPI_FULL_PATHNAME, &string); /* run OSHP */ status = acpi_evaluate_object(handle, METHOD_NAME_OSHP, NULL, NULL); if (ACPI_FAILURE(status)) printk(KERN_ERR "%s:%s OSHP fails=0x%x\n", __FUNCTION__, - path_name, status); + (char *)string.pointer, status); else - pr_debug("%s:%s OSHP passes\n", __FUNCTION__, path_name); - acpi_os_free(path_name); + pr_debug("%s:%s OSHP passes\n", __FUNCTION__, + (char *)string.pointer); + + acpi_os_free(string.pointer); return status; } EXPORT_SYMBOL_GPL(acpi_run_oshp); diff --git a/drivers/pci/hotplug/pci_hotplug.h b/drivers/pci/hotplug/pci_hotplug.h index e476ed033384..eb0d01d47236 100644 --- a/drivers/pci/hotplug/pci_hotplug.h +++ b/drivers/pci/hotplug/pci_hotplug.h @@ -190,7 +190,6 @@ struct hotplug_params { extern acpi_status acpi_run_oshp(acpi_handle handle); extern acpi_status acpi_get_hp_params_from_firmware(struct pci_dev *dev, struct hotplug_params *hpp); -extern u8 * acpi_path_name(acpi_handle handle); int acpi_root_bridge(acpi_handle handle); #endif #endif diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index 22dcd12e4c1c..6c14d9e46b2e 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c @@ -1246,7 +1246,7 @@ int pciehp_acpi_get_hp_hw_control_from_firmware(struct pci_dev *dev) acpi_handle chandle, handle = DEVICE_ACPI_HANDLE(&(dev->dev)); struct pci_dev *pdev = dev; struct pci_bus *parent; - u8 *path_name = NULL; + struct acpi_buffer string = { ACPI_ALLOCATE_BUFFER, NULL }; /* * Per PCI firmware specification, we should run the ACPI _OSC @@ -1278,16 +1278,17 @@ int pciehp_acpi_get_hp_hw_control_from_firmware(struct pci_dev *dev) } while (handle) { - path_name = acpi_path_name(handle); - dbg("Trying to get hotplug control for %s \n", path_name); + acpi_get_name(handle, ACPI_FULL_PATHNAME, &string); + dbg("Trying to get hotplug control for %s \n", + (char *)string.pointer); status = pci_osc_control_set(handle, OSC_PCI_EXPRESS_NATIVE_HP_CONTROL); if (status == AE_NOT_FOUND) status = acpi_run_oshp(handle); if (ACPI_SUCCESS(status)) { dbg("Gained control for hotplug HW for pci %s (%s)\n", - pci_name(dev), path_name); - acpi_os_free(path_name); + pci_name(dev), (char *)string.pointer); + acpi_os_free(string.pointer); return 0; } if (acpi_root_bridge(handle)) @@ -1300,8 +1301,8 @@ int pciehp_acpi_get_hp_hw_control_from_firmware(struct pci_dev *dev) err("Cannot get control of hotplug hardware for pci %s\n", pci_name(dev)); - if (path_name) - acpi_os_free(path_name); + + acpi_os_free(string.pointer); return -1; } #endif