From 988cbb15e00e6f924d052874b40c6a5447f9fdd7 Mon Sep 17 00:00:00 2001 From: Mitch Williams Date: Fri, 30 Mar 2007 11:54:08 -0700 Subject: [PATCH 01/59] PCI: Flush MSI-X table writes This patch fixes a kernel bug which is triggered when using the irqbalance daemon with MSI-X hardware. Because both MSI-X interrupt messages and MSI-X table writes are posted, it's possible for them to cross while in-flight. This results in interrupts being received long after the kernel thinks they're disabled, and in interrupts being sent to stale vectors after rebalancing. This patch performs a read flush after writes to the MSI-X table for mask and unmask operations. Since the SMP affinity is set while the interrupt is masked, and since it's unmasked immediately after, no additional flushes are required in the various affinity setting routines. This patch has been validated with (unreleased) network hardware which uses MSI-X. Revised with input from Eric Biederman. Signed-off-by: Mitch Williams Acked-by: "Eric W. Biederman" Signed-off-by: Greg Kroah-Hartman --- drivers/pci/msi.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index 435c1958a7b7..a4ef93ea4c54 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c @@ -68,6 +68,29 @@ static void msix_set_enable(struct pci_dev *dev, int enable) } } +static void msix_flush_writes(unsigned int irq) +{ + struct msi_desc *entry; + + entry = get_irq_msi(irq); + BUG_ON(!entry || !entry->dev); + switch (entry->msi_attrib.type) { + case PCI_CAP_ID_MSI: + /* nothing to do */ + break; + case PCI_CAP_ID_MSIX: + { + int offset = entry->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE + + PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET; + readl(entry->mask_base + offset); + break; + } + default: + BUG(); + break; + } +} + static void msi_set_mask_bit(unsigned int irq, int flag) { struct msi_desc *entry; @@ -187,11 +210,13 @@ void write_msi_msg(unsigned int irq, struct msi_msg *msg) void mask_msi_irq(unsigned int irq) { msi_set_mask_bit(irq, 1); + msix_flush_writes(irq); } void unmask_msi_irq(unsigned int irq) { msi_set_mask_bit(irq, 0); + msix_flush_writes(irq); } static int msi_free_irq(struct pci_dev* dev, int irq); From f7bdd12d234d9064bd0aa1b5610508959120a9b4 Mon Sep 17 00:00:00 2001 From: Brian King Date: Fri, 6 Apr 2007 16:39:36 -0500 Subject: [PATCH 02/59] pci: New PCI-E reset API Adds a new API which can be used to issue various types of PCI-E reset, including PCI-E warm reset and PCI-E hot reset. This is needed for an ipr PCI-E adapter which does not properly implement BIST. Running BIST on this adapter results in PCI-E errors. The only reliable reset mechanism that exists on this hardware is PCI Fundamental reset (warm reset). Since driving this type of reset is architecture unique, this provides the necessary hooks for architectures to add this support. Signed-off-by: Brian King Acked-by: Linas Vepstas Signed-off-by: Greg Kroah-Hartman --- drivers/pci/pci.c | 29 +++++++++++++++++++++++++++++ include/linux/pci.h | 14 ++++++++++++++ 2 files changed, 43 insertions(+) diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 2a458279327a..2086cd1b5e0e 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -891,6 +891,34 @@ pci_disable_device(struct pci_dev *dev) pcibios_disable_device(dev); } +/** + * pcibios_set_pcie_reset_state - set reset state for device dev + * @dev: the PCI-E device reset + * @state: Reset state to enter into + * + * + * Sets the PCI-E reset state for the device. This is the default + * implementation. Architecture implementations can override this. + */ +int __attribute__ ((weak)) pcibios_set_pcie_reset_state(struct pci_dev *dev, + enum pcie_reset_state state) +{ + return -EINVAL; +} + +/** + * pci_set_pcie_reset_state - set reset state for device dev + * @dev: the PCI-E device reset + * @state: Reset state to enter into + * + * + * Sets the PCI reset state for the device. + */ +int pci_set_pcie_reset_state(struct pci_dev *dev, enum pcie_reset_state state) +{ + return pcibios_set_pcie_reset_state(dev, state); +} + /** * pci_enable_wake - enable PCI device as wakeup event source * @dev: PCI device affected @@ -1427,4 +1455,5 @@ EXPORT_SYMBOL(pci_set_power_state); EXPORT_SYMBOL(pci_save_state); EXPORT_SYMBOL(pci_restore_state); EXPORT_SYMBOL(pci_enable_wake); +EXPORT_SYMBOL_GPL(pci_set_pcie_reset_state); diff --git a/include/linux/pci.h b/include/linux/pci.h index 972491089ac9..3aba02a04792 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -96,6 +96,19 @@ enum pci_channel_state { pci_channel_io_perm_failure = (__force pci_channel_state_t) 3, }; +typedef unsigned int __bitwise pcie_reset_state_t; + +enum pcie_reset_state { + /* Reset is NOT asserted (Use to deassert reset) */ + pcie_deassert_reset = (__force pcie_reset_state_t) 1, + + /* Use #PERST to reset PCI-E device */ + pcie_warm_reset = (__force pcie_reset_state_t) 2, + + /* Use PCI-E Hot Reset to reset device */ + pcie_hot_reset = (__force pcie_reset_state_t) 3 +}; + typedef unsigned short __bitwise pci_bus_flags_t; enum pci_bus_flags { PCI_BUS_FLAGS_NO_MSI = (__force pci_bus_flags_t) 1, @@ -532,6 +545,7 @@ static inline int pci_is_managed(struct pci_dev *pdev) void pci_disable_device(struct pci_dev *dev); void pci_set_master(struct pci_dev *dev); +int pci_set_pcie_reset_state(struct pci_dev *dev, enum pcie_reset_state state); #define HAVE_PCI_SET_MWI int __must_check pci_set_mwi(struct pci_dev *dev); void pci_clear_mwi(struct pci_dev *dev); From 5d386e1ac4025b4bcc6bad6811e771cb76064dfe Mon Sep 17 00:00:00 2001 From: Kenji Kaneshige Date: Tue, 6 Mar 2007 15:02:26 -0800 Subject: [PATCH 03/59] pciehp: Event handling rework The event handler of PCIEHP 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 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/pciehp.h | 16 +- drivers/pci/hotplug/pciehp_core.c | 44 +-- drivers/pci/hotplug/pciehp_ctrl.c | 612 ++++++++++++++---------------- drivers/pci/hotplug/pciehp_hpc.c | 34 +- 4 files changed, 319 insertions(+), 387 deletions(-) diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h index d19fcae8a7c0..c98e27128cc4 100644 --- a/drivers/pci/hotplug/pciehp.h +++ b/drivers/pci/hotplug/pciehp.h @@ -43,6 +43,7 @@ extern int pciehp_poll_mode; extern int pciehp_poll_time; extern int pciehp_debug; extern int pciehp_force; +extern struct workqueue_struct *pciehp_wq; #define dbg(format, arg...) \ do { \ @@ -70,14 +71,16 @@ struct slot { struct list_head slot_list; char name[SLOT_NAME_SIZE]; unsigned long last_emi_toggle; + struct delayed_work work; /* work for button event */ + struct mutex lock; }; struct event_info { u32 event_type; - u8 hp_slot; + struct slot *p_slot; + struct work_struct work; }; -#define MAX_EVENTS 10 struct controller { struct controller *next; struct mutex crit_sect; /* critical section mutex */ @@ -86,11 +89,9 @@ struct controller { int slot_num_inc; /* 1 or -1 */ struct pci_dev *pci_dev; struct list_head slot_list; - struct event_info event_queue[MAX_EVENTS]; struct slot *slot; struct hpc_ops *hpc_ops; wait_queue_head_t queue; /* sleep & wake process */ - u8 next_event; u8 bus; u8 device; u8 function; @@ -149,16 +150,15 @@ struct controller { #define HP_SUPR_RM(cap) (cap & HP_SUPR_RM_SUP) #define EMI(cap) (cap & EMI_PRSN) -extern int pciehp_event_start_thread(void); -extern void pciehp_event_stop_thread(void); -extern int pciehp_enable_slot(struct slot *slot); -extern int pciehp_disable_slot(struct slot *slot); +extern int pciehp_sysfs_enable_slot(struct slot *slot); +extern int pciehp_sysfs_disable_slot(struct slot *slot); extern u8 pciehp_handle_attention_button(u8 hp_slot, struct controller *ctrl); extern u8 pciehp_handle_switch_change(u8 hp_slot, struct controller *ctrl); extern u8 pciehp_handle_presence_change(u8 hp_slot, struct controller *ctrl); extern u8 pciehp_handle_power_fault(u8 hp_slot, struct controller *ctrl); extern int pciehp_configure_device(struct slot *p_slot); extern int pciehp_unconfigure_device(struct slot *p_slot); +extern void queue_pushbutton_work(struct work_struct *work); int pcie_init(struct controller *ctrl, struct pcie_device *dev); /* Global variables */ diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c index a92eda6e02f6..749227ecdb04 100644 --- a/drivers/pci/hotplug/pciehp_core.c +++ b/drivers/pci/hotplug/pciehp_core.c @@ -41,6 +41,7 @@ int pciehp_debug; int pciehp_poll_mode; int pciehp_poll_time; int pciehp_force; +struct workqueue_struct *pciehp_wq; struct controller *pciehp_ctrl_list; #define DRIVER_VERSION "0.4" @@ -62,7 +63,6 @@ MODULE_PARM_DESC(pciehp_force, "Force pciehp, even if _OSC and OSHP are missing" #define PCIE_MODULE_NAME "pciehp" -static int pcie_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); @@ -229,6 +229,8 @@ static int init_slots(struct controller *ctrl) slot->device = ctrl->slot_device_offset + i; slot->hpc_ops = ctrl->hpc_ops; slot->number = ctrl->first_slot; + mutex_init(&slot->lock); + INIT_DELAYED_WORK(&slot->work, queue_pushbutton_work); /* register this slot with the hotplug pci core */ hotplug_slot->private = slot; @@ -286,6 +288,9 @@ static void cleanup_slots(struct controller *ctrl) if (EMI(ctrl->ctrlcap)) sysfs_remove_file(&slot->hotplug_slot->kobj, &hotplug_slot_attr_lock.attr); + cancel_delayed_work(&slot->work); + flush_scheduled_work(); + flush_workqueue(pciehp_wq); pci_hp_deregister(slot->hotplug_slot); } } @@ -314,7 +319,7 @@ static int enable_slot(struct hotplug_slot *hotplug_slot) dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); - return pciehp_enable_slot(slot); + return pciehp_sysfs_enable_slot(slot); } @@ -324,7 +329,7 @@ static int disable_slot(struct hotplug_slot *hotplug_slot) dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); - return pciehp_disable_slot(slot); + return pciehp_sysfs_disable_slot(slot); } static int get_power_status(struct hotplug_slot *hotplug_slot, u8 *value) @@ -466,9 +471,6 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_ t_slot = pciehp_find_slot(ctrl, ctrl->slot_device_offset); - /* Finish setting up the hot plug ctrl device */ - ctrl->next_event = 0; - if (!pciehp_ctrl_list) { pciehp_ctrl_list = ctrl; ctrl->next = NULL; @@ -496,22 +498,6 @@ err_out_none: return -ENODEV; } - -static int pcie_start_thread(void) -{ - int retval = 0; - - dbg("Initialize + Start the notification/polling mechanism \n"); - - retval = pciehp_event_start_thread(); - if (retval) { - dbg("pciehp_event_start_thread() failed\n"); - return retval; - } - - return retval; -} - static void __exit unload_pciehpd(void) { struct controller *ctrl; @@ -529,10 +515,6 @@ static void __exit unload_pciehpd(void) kfree(tctrl); } - - /* Stop the notification mechanism */ - pciehp_event_stop_thread(); - } static void pciehp_remove (struct pcie_device *device) @@ -585,21 +567,11 @@ static int __init pcied_init(void) pciehp_poll_mode = 1; #endif - retval = pcie_start_thread(); - if (retval) - goto error_hpc_init; - retval = pcie_port_service_register(&hpdriver_portdrv); dbg("pcie_port_service_register = %d\n", retval); info(DRIVER_DESC " version: " DRIVER_VERSION "\n"); if (retval) dbg("%s: Failure to register service\n", __FUNCTION__); - -error_hpc_init: - if (retval) { - pciehp_event_stop_thread(); - }; - return retval; } diff --git a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c index 4283ef56dbd9..91441e5ae631 100644 --- a/drivers/pci/hotplug/pciehp_ctrl.c +++ b/drivers/pci/hotplug/pciehp_ctrl.c @@ -32,92 +32,61 @@ #include #include #include +#include #include "../pci.h" #include "pciehp.h" -static void interrupt_event_handler(struct controller *ctrl); +static void interrupt_event_handler(struct work_struct *work); +static int pciehp_enable_slot(struct slot *p_slot); +static int pciehp_disable_slot(struct slot *p_slot); -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 unsigned long surprise_rm_pending; /* = 0 */ - -static inline char *slot_name(struct slot *p_slot) +static int queue_interrupt_event(struct slot *p_slot, u32 event_type) { - return p_slot->hotplug_slot->name; + 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); + + schedule_work(&info->work); + + return 0; } u8 pciehp_handle_attention_button(u8 hp_slot, struct controller *ctrl) { struct slot *p_slot; - u8 rc = 0; - u8 getstatus; - struct event_info *taskInfo; + u32 event_type; /* Attention Button Change */ dbg("pciehp: 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 = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); - p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); - - ctrl->next_event = (ctrl->next_event + 1) % MAX_EVENTS; - taskInfo->hp_slot = hp_slot; - - rc++; - /* * Button pressed - See if need to TAKE ACTION!!! */ - info("Button pressed on Slot(%s)\n", slot_name(p_slot)); - taskInfo->event_type = INT_BUTTON_PRESS; + info("Button pressed on Slot(%s)\n", p_slot->name); + 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 - */ - taskInfo->event_type = INT_BUTTON_CANCEL; - info("Button cancel on Slot(%s)\n", slot_name(p_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 - */ - taskInfo->event_type = INT_BUTTON_IGNORE; - info("Button ignore on Slot(%s)\n", slot_name(p_slot)); - } - - if (rc) - up(&event_semaphore); /* signal event thread that new event is posted */ + queue_interrupt_event(p_slot, event_type); return 0; - } u8 pciehp_handle_switch_change(u8 hp_slot, struct controller *ctrl) { struct slot *p_slot; - u8 rc = 0; u8 getstatus; - struct event_info *taskInfo; + u32 event_type; /* Switch Change */ dbg("pciehp: 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) % MAX_EVENTS; - taskInfo->hp_slot = hp_slot; - - rc++; p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); @@ -125,39 +94,30 @@ u8 pciehp_handle_switch_change(u8 hp_slot, struct controller *ctrl) /* * Switch opened */ - info("Latch open on Slot(%s)\n", slot_name(p_slot)); - taskInfo->event_type = INT_SWITCH_OPEN; + info("Latch open on Slot(%s)\n", p_slot->name); + event_type = INT_SWITCH_OPEN; } else { /* * Switch closed */ - info("Latch close on Slot(%s)\n", slot_name(p_slot)); - taskInfo->event_type = INT_SWITCH_CLOSE; + info("Latch close on Slot(%s)\n", p_slot->name); + 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 pciehp_handle_presence_change(u8 hp_slot, struct controller *ctrl) { struct slot *p_slot; - u8 presence_save, rc = 0; - struct event_info *taskInfo; + u32 event_type; + u8 presence_save; /* Presence Change */ dbg("pciehp: 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) % MAX_EVENTS; - taskInfo->hp_slot = hp_slot; - - rc++; p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); /* Switch is open, assume a presence change @@ -168,59 +128,49 @@ u8 pciehp_handle_presence_change(u8 hp_slot, struct controller *ctrl) /* * Card Present */ - info("Card present on Slot(%s)\n", slot_name(p_slot)); - taskInfo->event_type = INT_PRESENCE_ON; + info("Card present on Slot(%s)\n", p_slot->name); + event_type = INT_PRESENCE_ON; } else { /* * Not Present */ - info("Card not present on Slot(%s)\n", slot_name(p_slot)); - taskInfo->event_type = INT_PRESENCE_OFF; + info("Card not present on Slot(%s)\n", p_slot->name); + 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 pciehp_handle_power_fault(u8 hp_slot, struct controller *ctrl) { struct slot *p_slot; - u8 rc = 0; - struct event_info *taskInfo; + u32 event_type; /* power fault */ dbg("pciehp: 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) % MAX_EVENTS; - taskInfo->hp_slot = hp_slot; - - rc++; p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); if ( !(p_slot->hpc_ops->query_power_fault(p_slot))) { /* * power fault Cleared */ - info("Power fault cleared on Slot(%s)\n", slot_name(p_slot)); - taskInfo->event_type = INT_POWER_FAULT_CLEAR; + info("Power fault cleared on Slot(%s)\n", p_slot->name); + event_type = INT_POWER_FAULT_CLEAR; } else { /* * power fault */ - info("Power fault on Slot(%s)\n", slot_name(p_slot)); - taskInfo->event_type = INT_POWER_FAULT; + info("Power fault on Slot(%s)\n", p_slot->name); + event_type = INT_POWER_FAULT; 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 @@ -357,13 +307,10 @@ static int remove_board(struct slot *p_slot) return 0; } - -static void pushbutton_helper_thread(unsigned long data) -{ - pushbutton_pending = data; - - up(&event_semaphore); -} +struct power_work_info { + struct slot *p_slot; + struct work_struct work; +}; /** * pciehp_pushbutton_thread @@ -372,276 +319,214 @@ static void pushbutton_helper_thread(unsigned long data) * Handles all pending events and exits. * */ -static void pciehp_pushbutton_thread(unsigned long slot) +static void pciehp_power_thread(struct work_struct *work) { - struct slot *p_slot = (struct slot *) slot; - 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; - dbg("%s: disabling bus:device(%x:%x)\n", __FUNCTION__, - p_slot->bus, p_slot->device); + struct power_work_info *info = + container_of(work, struct power_work_info, work); + struct slot *p_slot = info->p_slot; + mutex_lock(&p_slot->lock); + switch (p_slot->state) { + case POWEROFF_STATE: + mutex_unlock(&p_slot->lock); + dbg("%s: disabling bus:device(%x:%x)\n", + __FUNCTION__, p_slot->bus, p_slot->device); pciehp_disable_slot(p_slot); + mutex_lock(&p_slot->lock); p_slot->state = STATIC_STATE; - } else { - p_slot->state = POWERON_STATE; - dbg("%s: adding bus:device(%x:%x)\n", __FUNCTION__, - p_slot->bus, p_slot->device); - + break; + case POWERON_STATE: + mutex_unlock(&p_slot->lock); if (pciehp_enable_slot(p_slot) && PWR_LED(p_slot->ctrl->ctrlcap)) 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); - return; + kfree(info); } -/** - * pciehp_surprise_rm_thread - * - * Scheduled procedure to handle blocking stuff for the surprise removal - * Handles all pending events and exits. - * - */ -static void pciehp_surprise_rm_thread(unsigned long slot) +void queue_pushbutton_work(struct work_struct *work) { - struct slot *p_slot = (struct slot *) slot; - u8 getstatus; - - surprise_rm_pending = 0; + struct slot *p_slot = container_of(work, struct slot, work.work); + struct power_work_info *info; - if (!p_slot) { - dbg("%s: Error! slot NULL\n", __FUNCTION__); + 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, pciehp_power_thread); - p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus); - if (!getstatus) { + mutex_lock(&p_slot->lock); + switch (p_slot->state) { + case BLINKINGOFF_STATE: p_slot->state = POWEROFF_STATE; - dbg("%s: removing bus:device(%x:%x)\n", - __FUNCTION__, p_slot->bus, p_slot->device); - - pciehp_disable_slot(p_slot); - p_slot->state = STATIC_STATE; - } else { + break; + case BLINKINGON_STATE: p_slot->state = POWERON_STATE; - dbg("%s: adding bus:device(%x:%x)\n", - __FUNCTION__, p_slot->bus, p_slot->device); - - if (pciehp_enable_slot(p_slot) && - PWR_LED(p_slot->ctrl->ctrlcap)) - p_slot->hpc_ops->green_led_off(p_slot); - - p_slot->state = STATIC_STATE; + break; + default: + goto out; } - - return; + queue_work(pciehp_wq, &info->work); + out: + mutex_unlock(&p_slot->lock); } - - -/* this is the main worker thread */ -static int event_thread(void* data) -{ - struct controller *ctrl; - lock_kernel(); - daemonize("pciehpd_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) - pciehp_pushbutton_thread(pushbutton_pending); - else if (surprise_rm_pending) - pciehp_surprise_rm_thread(surprise_rm_pending); - else - for (ctrl = pciehp_ctrl_list; ctrl; ctrl=ctrl->next) - interrupt_event_handler(ctrl); - } - dbg("event_thread signals exit\n"); - up(&event_exit); - return 0; -} - -int pciehp_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 pciehp_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; - /* char buffer[SLOT_NAME_SIZE]; */ int result; - info = kmalloc(sizeof(struct hotplug_slot_info), GFP_KERNEL); + info = kmalloc(sizeof(*info), GFP_KERNEL); if (!info) return -ENOMEM; - /* make_slot_name (&buffer[0], SLOT_NAME_SIZE, slot); */ - slot->hpc_ops->get_power_status(slot, &(info->power_status)); slot->hpc_ops->get_attention_status(slot, &(info->attention_status)); slot->hpc_ops->get_latch_status(slot, &(info->latch_status)); slot->hpc_ops->get_adapter_status(slot, &(info->adapter_status)); - /* result = pci_hp_change_slot_info(buffer, info); */ result = pci_hp_change_slot_info(slot->hotplug_slot, info); kfree (info); return result; } -static void interrupt_event_handler(struct controller *ctrl) +/* + * Note: This function must be called with slot->lock held + */ +static void handle_button_press_event(struct slot *p_slot) { - int loop = 0; - int change = 1; - u8 hp_slot; + struct controller *ctrl = p_slot->ctrl; u8 getstatus; - struct slot *p_slot; - while (change) { - change = 0; + switch (p_slot->state) { + case STATIC_STATE: + p_slot->hpc_ops->get_power_status(p_slot, &getstatus); + if (getstatus) { + p_slot->state = BLINKINGOFF_STATE; + info("PCI slot #%s - powering off due to button " + "press.\n", p_slot->name); + } else { + p_slot->state = BLINKINGON_STATE; + info("PCI slot #%s - powering on due to button " + "press.\n", p_slot->name); + } + /* blink green LED and turn off amber */ + if (PWR_LED(ctrl->ctrlcap)) + p_slot->hpc_ops->green_led_blink(p_slot); + if (ATTN_LED(ctrl->ctrlcap)) + p_slot->hpc_ops->set_attention_status(p_slot, 0); - for (loop = 0; loop < MAX_EVENTS; loop++) { - if (ctrl->event_queue[loop].event_type != 0) { - hp_slot = ctrl->event_queue[loop].hp_slot; - - p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); - - if (ctrl->event_queue[loop].event_type == INT_BUTTON_CANCEL) { - dbg("button cancel\n"); - del_timer(&p_slot->task_event); - - switch (p_slot->state) { - case BLINKINGOFF_STATE: - if (PWR_LED(ctrl->ctrlcap)) - p_slot->hpc_ops->green_led_on(p_slot); - - if (ATTN_LED(ctrl->ctrlcap)) - p_slot->hpc_ops->set_attention_status(p_slot, 0); - break; - case BLINKINGON_STATE: - if (PWR_LED(ctrl->ctrlcap)) - p_slot->hpc_ops->green_led_off(p_slot); - - if (ATTN_LED(ctrl->ctrlcap)) - p_slot->hpc_ops->set_attention_status(p_slot, 0); - break; - default: - warn("Not a valid state\n"); - return; - } - info("PCI slot #%s - action canceled due to button press.\n", slot_name(p_slot)); - p_slot->state = STATIC_STATE; - } - /* ***********Button Pressed (No action on 1st press...) */ - else if (ctrl->event_queue[loop].event_type == INT_BUTTON_PRESS) { - - if (ATTN_BUTTN(ctrl->ctrlcap)) { - dbg("Button pressed\n"); - p_slot->hpc_ops->get_power_status(p_slot, &getstatus); - if (getstatus) { - /* slot is on */ - dbg("slot is on\n"); - p_slot->state = BLINKINGOFF_STATE; - info("PCI slot #%s - powering off due to button press.\n", slot_name(p_slot)); - } else { - /* slot is off */ - dbg("slot is off\n"); - p_slot->state = BLINKINGON_STATE; - info("PCI slot #%s - powering on due to button press.\n", slot_name(p_slot)); - } - - /* blink green LED and turn off amber */ - if (PWR_LED(ctrl->ctrlcap)) - p_slot->hpc_ops->green_led_blink(p_slot); - - if (ATTN_LED(ctrl->ctrlcap)) - 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; - - add_timer(&p_slot->task_event); - } - } - /***********POWER FAULT********************/ - else if (ctrl->event_queue[loop].event_type == INT_POWER_FAULT) { - if (POWER_CTRL(ctrl->ctrlcap)) { - dbg("power fault\n"); - if (ATTN_LED(ctrl->ctrlcap)) - p_slot->hpc_ops->set_attention_status(p_slot, 1); - - if (PWR_LED(ctrl->ctrlcap)) - p_slot->hpc_ops->green_led_off(p_slot); - } - } - /***********SURPRISE REMOVAL********************/ - else if ((ctrl->event_queue[loop].event_type == INT_PRESENCE_ON) || - (ctrl->event_queue[loop].event_type == INT_PRESENCE_OFF)) { - if (HP_SUPR_RM(ctrl->ctrlcap)) { - dbg("Surprise Removal\n"); - if (p_slot) { - surprise_rm_pending = (unsigned long) p_slot; - up(&event_semaphore); - update_slot_info(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 */ + 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) { + if (PWR_LED(ctrl->ctrlcap)) + p_slot->hpc_ops->green_led_on(p_slot); + } else { + if (PWR_LED(ctrl->ctrlcap)) + p_slot->hpc_ops->green_led_off(p_slot); + } + if (ATTN_LED(ctrl->ctrlcap)) + p_slot->hpc_ops->set_attention_status(p_slot, 0); + info("PCI slot #%s - action canceled due to button press\n", + p_slot->name); + 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; } } +/* + * Note: This function must be called with slot->lock held + */ +static void handle_surprise_event(struct slot *p_slot) +{ + u8 getstatus; + struct power_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, pciehp_power_thread); + + p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus); + if (!getstatus) + p_slot->state = POWEROFF_STATE; + else + p_slot->state = POWERON_STATE; + + queue_work(pciehp_wq, &info->work); +} + +static void interrupt_event_handler(struct work_struct *work) +{ + struct event_info *info = container_of(work, struct event_info, work); + struct slot *p_slot = info->p_slot; + struct controller *ctrl = p_slot->ctrl; + + mutex_lock(&p_slot->lock); + switch (info->event_type) { + case INT_BUTTON_PRESS: + handle_button_press_event(p_slot); + break; + case INT_POWER_FAULT: + if (!POWER_CTRL(ctrl->ctrlcap)) + break; + if (ATTN_LED(ctrl->ctrlcap)) + p_slot->hpc_ops->set_attention_status(p_slot, 1); + if (PWR_LED(ctrl->ctrlcap)) + p_slot->hpc_ops->green_led_off(p_slot); + break; + case INT_PRESENCE_ON: + case INT_PRESENCE_OFF: + if (!HP_SUPR_RM(ctrl->ctrlcap)) + break; + dbg("Surprise Removal\n"); + update_slot_info(p_slot); + handle_surprise_event(p_slot); + break; + default: + update_slot_info(p_slot); + break; + } + mutex_unlock(&p_slot->lock); + + kfree(info); +} + int pciehp_enable_slot(struct slot *p_slot) { u8 getstatus = 0; @@ -653,7 +538,7 @@ int pciehp_enable_slot(struct slot *p_slot) rc = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus); if (rc || !getstatus) { info("%s: no adapter on slot(%s)\n", __FUNCTION__, - slot_name(p_slot)); + p_slot->name); mutex_unlock(&p_slot->ctrl->crit_sect); return -ENODEV; } @@ -661,7 +546,7 @@ int pciehp_enable_slot(struct slot *p_slot) rc = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); if (rc || getstatus) { info("%s: latch open on slot(%s)\n", __FUNCTION__, - slot_name(p_slot)); + p_slot->name); mutex_unlock(&p_slot->ctrl->crit_sect); return -ENODEV; } @@ -671,7 +556,7 @@ int pciehp_enable_slot(struct slot *p_slot) rc = p_slot->hpc_ops->get_power_status(p_slot, &getstatus); if (rc || getstatus) { info("%s: already enabled on slot(%s)\n", __FUNCTION__, - slot_name(p_slot)); + p_slot->name); mutex_unlock(&p_slot->ctrl->crit_sect); return -EINVAL; } @@ -706,7 +591,7 @@ int pciehp_disable_slot(struct slot *p_slot) ret = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus); if (ret || !getstatus) { info("%s: no adapter on slot(%s)\n", __FUNCTION__, - slot_name(p_slot)); + p_slot->name); mutex_unlock(&p_slot->ctrl->crit_sect); return -ENODEV; } @@ -716,7 +601,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(%s)\n", __FUNCTION__, - slot_name(p_slot)); + p_slot->name); mutex_unlock(&p_slot->ctrl->crit_sect); return -ENODEV; } @@ -726,7 +611,7 @@ 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(%s)\n", __FUNCTION__, - slot_name(p_slot)); + p_slot->name); mutex_unlock(&p_slot->ctrl->crit_sect); return -EINVAL; } @@ -739,3 +624,66 @@ int pciehp_disable_slot(struct slot *p_slot) return ret; } +int pciehp_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 = pciehp_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 pciehp_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 = pciehp_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; +} diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index fbc64aa2dd68..9aac6a87eb53 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c @@ -71,6 +71,8 @@ #define DBG_LEAVE_ROUTINE #endif /* DEBUG */ +static atomic_t pciehp_num_controllers = ATOMIC_INIT(0); + struct ctrl_reg { u8 cap_id; u8 nxt_ptr; @@ -219,10 +221,7 @@ static inline int pciehp_writel(struct controller *ctrl, int reg, u32 value) #define EMI_STATE 0x0080 #define EMI_STATUS_BIT 7 -static spinlock_t hpc_event_lock; - DEFINE_DBG_BUFFER /* Debug string buffer for entire HPC defined here */ -static int ctlr_seq_num = 0; /* Controller sequence # */ static irqreturn_t pcie_isr(int irq, void *dev_id); static void start_int_poll_timer(struct controller *ctrl, int sec); @@ -656,6 +655,13 @@ static void hpc_release_ctlr(struct controller *ctrl) else free_irq(ctrl->pci_dev->irq, ctrl); + /* + * If this is the last controller to be released, destroy the + * pciehp work queue + */ + if (atomic_dec_and_test(&pciehp_num_controllers)) + destroy_workqueue(pciehp_wq); + DBG_LEAVE_ROUTINE } @@ -1152,7 +1158,6 @@ int pciehp_acpi_get_hp_hw_control_from_firmware(struct pci_dev *dev) int pcie_init(struct controller * ctrl, struct pcie_device *dev) { int rc; - static int first = 1; u16 temp_word; u16 cap_reg; u16 intr_enable = 0; @@ -1221,11 +1226,6 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev) dbg("%s: SLOTCTRL offset %x slot_ctrl %x\n", __FUNCTION__, ctrl->cap_base + SLOTCTRL, slot_ctrl); - if (first) { - spin_lock_init(&hpc_event_lock); - first = 0; - } - for ( rc = 0; rc < DEVICE_COUNT_RESOURCE; rc++) if (pci_resource_len(pdev, rc) > 0) dbg("pci resource[%d] start=0x%llx(len=0x%llx)\n", rc, @@ -1286,7 +1286,8 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev) rc = request_irq(ctrl->pci_dev->irq, pcie_isr, IRQF_SHARED, MY_NAME, (void *)ctrl); dbg("%s: request_irq %d for hpc%d (returns %d)\n", - __FUNCTION__, ctrl->pci_dev->irq, ctlr_seq_num, rc); + __FUNCTION__, ctrl->pci_dev->irq, + atomic_read(&pciehp_num_controllers), rc); if (rc) { err("Can't get irq %d for the hotplug controller\n", ctrl->pci_dev->irq); @@ -1296,6 +1297,18 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev) dbg("pciehp ctrl b:d:f:irq=0x%x:%x:%x:%x\n", pdev->bus->number, PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn), dev->irq); + /* + * If this is the first controller to be initialized, + * initialize the pciehp work queue + */ + if (atomic_add_return(1, &pciehp_num_controllers) == 1) { + pciehp_wq = create_singlethread_workqueue("pciehpd"); + if (!pciehp_wq) { + rc = -ENOMEM; + goto abort_free_irq; + } + } + rc = pciehp_readw(ctrl, SLOTCTRL, &temp_word); if (rc) { err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__); @@ -1349,7 +1362,6 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev) goto abort_disable_intr; } - ctlr_seq_num++; ctrl->hpc_ops = &pciehp_hpc_ops; DBG_LEAVE_ROUTINE From 9233352628bc8e284f66fc90c4dc74473db1fbc1 Mon Sep 17 00:00:00 2001 From: Kenji Kaneshige Date: Tue, 6 Mar 2007 15:02:32 -0800 Subject: [PATCH 04/59] pciehp: Adapt to device driver model This patch adapts PCIEHP driver to PCI device driver model. Signed-off-by: Kenji Kaneshige Signed-off-by: Kristen Carlson Accardi Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/pciehp.h | 3 --- drivers/pci/hotplug/pciehp_core.c | 38 +++++-------------------------- 2 files changed, 6 insertions(+), 35 deletions(-) diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h index c98e27128cc4..74d0bf62e649 100644 --- a/drivers/pci/hotplug/pciehp.h +++ b/drivers/pci/hotplug/pciehp.h @@ -161,9 +161,6 @@ extern int pciehp_unconfigure_device(struct slot *p_slot); extern void queue_pushbutton_work(struct work_struct *work); int pcie_init(struct controller *ctrl, struct pcie_device *dev); -/* Global variables */ -extern struct controller *pciehp_ctrl_list; - static inline struct slot *pciehp_find_slot(struct controller *ctrl, u8 device) { struct slot *slot; diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c index 749227ecdb04..0550edf0ce25 100644 --- a/drivers/pci/hotplug/pciehp_core.c +++ b/drivers/pci/hotplug/pciehp_core.c @@ -42,7 +42,6 @@ int pciehp_poll_mode; int pciehp_poll_time; int pciehp_force; struct workqueue_struct *pciehp_wq; -struct controller *pciehp_ctrl_list; #define DRIVER_VERSION "0.4" #define DRIVER_AUTHOR "Dan Zink , Greg Kroah-Hartman , Dely Sy " @@ -471,14 +470,6 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_ t_slot = pciehp_find_slot(ctrl, ctrl->slot_device_offset); - if (!pciehp_ctrl_list) { - pciehp_ctrl_list = ctrl; - ctrl->next = NULL; - } else { - ctrl->next = pciehp_ctrl_list; - pciehp_ctrl_list = ctrl; - } - t_slot->hpc_ops->get_adapter_status(t_slot, &value); /* Check if slot is occupied */ if ((POWER_CTRL(ctrl->ctrlcap)) && !value) { rc = t_slot->hpc_ops->power_off_slot(t_slot); /* Power off slot if not occupied*/ @@ -498,28 +489,14 @@ err_out_none: return -ENODEV; } -static void __exit unload_pciehpd(void) +static void pciehp_remove (struct pcie_device *dev) { - struct controller *ctrl; - struct controller *tctrl; + struct pci_dev *pdev = dev->port; + struct controller *ctrl = pci_get_drvdata(pdev); - ctrl = pciehp_ctrl_list; - - while (ctrl) { - cleanup_slots(ctrl); - - ctrl->hpc_ops->release_ctlr(ctrl); - - tctrl = ctrl; - ctrl = ctrl->next; - - kfree(tctrl); - } -} - -static void pciehp_remove (struct pcie_device *device) -{ - /* XXX - Needs to be adapted to device driver model */ + cleanup_slots(ctrl); + ctrl->hpc_ops->release_ctlr(ctrl); + kfree(ctrl); } #ifdef CONFIG_PM @@ -578,10 +555,7 @@ static int __init pcied_init(void) static void __exit pcied_cleanup(void) { dbg("unload_pciehpd()\n"); - unload_pciehpd(); - pcie_port_service_unregister(&hpdriver_portdrv); - info(DRIVER_DESC " version: " DRIVER_VERSION " unloaded\n"); } From e325e1f0783382298141c74737712637943c6063 Mon Sep 17 00:00:00 2001 From: Kristen Carlson Accardi Date: Wed, 21 Mar 2007 11:45:31 -0700 Subject: [PATCH 05/59] PCI: fix multiple definition of `queue_pushbutton_work' Fix duplicate names in shpchp and pciehp. Signed-off-by: Kristen Carlson Accardi Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/pciehp.h | 2 +- drivers/pci/hotplug/pciehp_core.c | 2 +- drivers/pci/hotplug/pciehp_ctrl.c | 2 +- drivers/pci/hotplug/shpchp.h | 2 +- drivers/pci/hotplug/shpchp_core.c | 2 +- drivers/pci/hotplug/shpchp_ctrl.c | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h index 74d0bf62e649..ccc57627201e 100644 --- a/drivers/pci/hotplug/pciehp.h +++ b/drivers/pci/hotplug/pciehp.h @@ -158,7 +158,7 @@ extern u8 pciehp_handle_presence_change(u8 hp_slot, struct controller *ctrl); extern u8 pciehp_handle_power_fault(u8 hp_slot, struct controller *ctrl); extern int pciehp_configure_device(struct slot *p_slot); extern int pciehp_unconfigure_device(struct slot *p_slot); -extern void queue_pushbutton_work(struct work_struct *work); +extern void pciehp_queue_pushbutton_work(struct work_struct *work); int pcie_init(struct controller *ctrl, struct pcie_device *dev); static inline struct slot *pciehp_find_slot(struct controller *ctrl, u8 device) diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c index 0550edf0ce25..e5d3f0b4f45a 100644 --- a/drivers/pci/hotplug/pciehp_core.c +++ b/drivers/pci/hotplug/pciehp_core.c @@ -229,7 +229,7 @@ static int init_slots(struct controller *ctrl) slot->hpc_ops = ctrl->hpc_ops; slot->number = ctrl->first_slot; mutex_init(&slot->lock); - INIT_DELAYED_WORK(&slot->work, queue_pushbutton_work); + INIT_DELAYED_WORK(&slot->work, pciehp_queue_pushbutton_work); /* register this slot with the hotplug pci core */ hotplug_slot->private = slot; diff --git a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c index 91441e5ae631..7f22caa70178 100644 --- a/drivers/pci/hotplug/pciehp_ctrl.c +++ b/drivers/pci/hotplug/pciehp_ctrl.c @@ -351,7 +351,7 @@ static void pciehp_power_thread(struct work_struct *work) kfree(info); } -void queue_pushbutton_work(struct work_struct *work) +void pciehp_queue_pushbutton_work(struct work_struct *work) { struct slot *p_slot = container_of(work, struct slot, work.work); struct power_work_info *info; diff --git a/drivers/pci/hotplug/shpchp.h b/drivers/pci/hotplug/shpchp.h index 01d31a1f697c..37ed0884b972 100644 --- a/drivers/pci/hotplug/shpchp.h +++ b/drivers/pci/hotplug/shpchp.h @@ -166,7 +166,7 @@ extern u8 shpchp_handle_power_fault(u8 hp_slot, struct controller *ctrl); extern int shpchp_configure_device(struct slot *p_slot); extern int shpchp_unconfigure_device(struct slot *p_slot); extern void cleanup_slots(struct controller *ctrl); -extern void queue_pushbutton_work(struct work_struct *work); +extern void shpchp_queue_pushbutton_work(struct work_struct *work); extern int shpc_init( struct controller *ctrl, struct pci_dev *pdev); #ifdef CONFIG_ACPI diff --git a/drivers/pci/hotplug/shpchp_core.c b/drivers/pci/hotplug/shpchp_core.c index 5f4bc08a633a..80dec9796b31 100644 --- a/drivers/pci/hotplug/shpchp_core.c +++ b/drivers/pci/hotplug/shpchp_core.c @@ -136,7 +136,7 @@ static int init_slots(struct controller *ctrl) slot->hpc_ops = ctrl->hpc_ops; slot->number = ctrl->first_slot + (ctrl->slot_num_inc * i); mutex_init(&slot->lock); - INIT_DELAYED_WORK(&slot->work, queue_pushbutton_work); + INIT_DELAYED_WORK(&slot->work, shpchp_queue_pushbutton_work); /* register this slot with the hotplug pci core */ hotplug_slot->private = slot; diff --git a/drivers/pci/hotplug/shpchp_ctrl.c b/drivers/pci/hotplug/shpchp_ctrl.c index b746bd265bc6..2c94d44279a3 100644 --- a/drivers/pci/hotplug/shpchp_ctrl.c +++ b/drivers/pci/hotplug/shpchp_ctrl.c @@ -433,7 +433,7 @@ static void shpchp_pushbutton_thread(struct work_struct *work) kfree(info); } -void queue_pushbutton_work(struct work_struct *work) +void shpchp_queue_pushbutton_work(struct work_struct *work) { struct slot *p_slot = container_of(work, struct slot, work.work); struct pushbutton_work_info *info; From a9dfd281a7e12f6d9b53b5a28649b3a3c76a70e6 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Tue, 6 Mar 2007 02:45:12 -0800 Subject: [PATCH 06/59] PCI: scatterlist.h needs types.h Most architectures' scatterlist.h use the type dma_addr_t, but omit to include which defines it. This could lead to build failures, so let's add the missing includes. Signed-off-by: Jean Delvare Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- include/asm-alpha/scatterlist.h | 1 + include/asm-avr32/scatterlist.h | 2 ++ include/asm-frv/scatterlist.h | 2 ++ include/asm-h8300/scatterlist.h | 2 ++ include/asm-i386/scatterlist.h | 2 ++ include/asm-ia64/scatterlist.h | 2 ++ include/asm-m32r/scatterlist.h | 2 ++ include/asm-m68knommu/scatterlist.h | 1 + include/asm-mips/scatterlist.h | 2 ++ include/asm-parisc/scatterlist.h | 1 + include/asm-sh/scatterlist.h | 2 ++ include/asm-sh64/scatterlist.h | 2 ++ include/asm-sparc64/scatterlist.h | 1 + include/asm-v850/scatterlist.h | 2 ++ include/asm-x86_64/scatterlist.h | 2 ++ include/asm-xtensa/scatterlist.h | 2 ++ 16 files changed, 28 insertions(+) diff --git a/include/asm-alpha/scatterlist.h b/include/asm-alpha/scatterlist.h index 6afb8bd3aaf9..917365405e83 100644 --- a/include/asm-alpha/scatterlist.h +++ b/include/asm-alpha/scatterlist.h @@ -2,6 +2,7 @@ #define _ALPHA_SCATTERLIST_H #include +#include struct scatterlist { struct page *page; diff --git a/include/asm-avr32/scatterlist.h b/include/asm-avr32/scatterlist.h index bfe7d753423c..c6d5ce3b3a25 100644 --- a/include/asm-avr32/scatterlist.h +++ b/include/asm-avr32/scatterlist.h @@ -1,6 +1,8 @@ #ifndef __ASM_AVR32_SCATTERLIST_H #define __ASM_AVR32_SCATTERLIST_H +#include + struct scatterlist { struct page *page; unsigned int offset; diff --git a/include/asm-frv/scatterlist.h b/include/asm-frv/scatterlist.h index fb38fd329a5f..8e827fa853f1 100644 --- a/include/asm-frv/scatterlist.h +++ b/include/asm-frv/scatterlist.h @@ -1,6 +1,8 @@ #ifndef _ASM_SCATTERLIST_H #define _ASM_SCATTERLIST_H +#include + /* * Drivers must set either ->address or (preferred) ->page and ->offset * to indicate where data must be transferred to/from. diff --git a/include/asm-h8300/scatterlist.h b/include/asm-h8300/scatterlist.h index 7627f0cd1a2f..985fdf54eaca 100644 --- a/include/asm-h8300/scatterlist.h +++ b/include/asm-h8300/scatterlist.h @@ -1,6 +1,8 @@ #ifndef _H8300_SCATTERLIST_H #define _H8300_SCATTERLIST_H +#include + struct scatterlist { struct page *page; unsigned int offset; diff --git a/include/asm-i386/scatterlist.h b/include/asm-i386/scatterlist.h index 55d6c953a76e..d7e45a8f1aae 100644 --- a/include/asm-i386/scatterlist.h +++ b/include/asm-i386/scatterlist.h @@ -1,6 +1,8 @@ #ifndef _I386_SCATTERLIST_H #define _I386_SCATTERLIST_H +#include + struct scatterlist { struct page *page; unsigned int offset; diff --git a/include/asm-ia64/scatterlist.h b/include/asm-ia64/scatterlist.h index 9dbea8844d5e..a452ea24205a 100644 --- a/include/asm-ia64/scatterlist.h +++ b/include/asm-ia64/scatterlist.h @@ -6,6 +6,8 @@ * David Mosberger-Tang , Hewlett-Packard Co */ +#include + struct scatterlist { struct page *page; unsigned int offset; diff --git a/include/asm-m32r/scatterlist.h b/include/asm-m32r/scatterlist.h index c2de96cb69ed..352415ff5eb9 100644 --- a/include/asm-m32r/scatterlist.h +++ b/include/asm-m32r/scatterlist.h @@ -1,6 +1,8 @@ #ifndef _ASM_M32R_SCATTERLIST_H #define _ASM_M32R_SCATTERLIST_H +#include + struct scatterlist { char * address; /* Location data is to be transferred to, NULL for * highmem page */ diff --git a/include/asm-m68knommu/scatterlist.h b/include/asm-m68knommu/scatterlist.h index 2085d6ff8782..4da79d3d3f34 100644 --- a/include/asm-m68knommu/scatterlist.h +++ b/include/asm-m68knommu/scatterlist.h @@ -2,6 +2,7 @@ #define _M68KNOMMU_SCATTERLIST_H #include +#include struct scatterlist { struct page *page; diff --git a/include/asm-mips/scatterlist.h b/include/asm-mips/scatterlist.h index 22634706e9d5..7af104c95b20 100644 --- a/include/asm-mips/scatterlist.h +++ b/include/asm-mips/scatterlist.h @@ -1,6 +1,8 @@ #ifndef __ASM_SCATTERLIST_H #define __ASM_SCATTERLIST_H +#include + struct scatterlist { struct page * page; unsigned int offset; diff --git a/include/asm-parisc/scatterlist.h b/include/asm-parisc/scatterlist.h index 236c1d0fba33..e7211c748446 100644 --- a/include/asm-parisc/scatterlist.h +++ b/include/asm-parisc/scatterlist.h @@ -2,6 +2,7 @@ #define _ASM_PARISC_SCATTERLIST_H #include +#include struct scatterlist { struct page *page; diff --git a/include/asm-sh/scatterlist.h b/include/asm-sh/scatterlist.h index d19e7cd3b023..b9ae53c38365 100644 --- a/include/asm-sh/scatterlist.h +++ b/include/asm-sh/scatterlist.h @@ -1,6 +1,8 @@ #ifndef __ASM_SH_SCATTERLIST_H #define __ASM_SH_SCATTERLIST_H +#include + struct scatterlist { struct page * page; /* Location for highmem page, if any */ unsigned int offset;/* for highmem, page offset */ diff --git a/include/asm-sh64/scatterlist.h b/include/asm-sh64/scatterlist.h index 5d8fa32d2e9d..1c723f2d7a95 100644 --- a/include/asm-sh64/scatterlist.h +++ b/include/asm-sh64/scatterlist.h @@ -11,6 +11,8 @@ #ifndef __ASM_SH64_SCATTERLIST_H #define __ASM_SH64_SCATTERLIST_H +#include + struct scatterlist { struct page * page; /* Location for highmem page, if any */ unsigned int offset;/* for highmem, page offset */ diff --git a/include/asm-sparc64/scatterlist.h b/include/asm-sparc64/scatterlist.h index ec4f3c63fe98..048fdb40e81d 100644 --- a/include/asm-sparc64/scatterlist.h +++ b/include/asm-sparc64/scatterlist.h @@ -3,6 +3,7 @@ #define _SPARC64_SCATTERLIST_H #include +#include struct scatterlist { struct page *page; diff --git a/include/asm-v850/scatterlist.h b/include/asm-v850/scatterlist.h index af1cba69a526..56f402920db9 100644 --- a/include/asm-v850/scatterlist.h +++ b/include/asm-v850/scatterlist.h @@ -14,6 +14,8 @@ #ifndef __V850_SCATTERLIST_H__ #define __V850_SCATTERLIST_H__ +#include + struct scatterlist { struct page *page; unsigned offset; diff --git a/include/asm-x86_64/scatterlist.h b/include/asm-x86_64/scatterlist.h index 49d89f8129cd..eaf7ada27e14 100644 --- a/include/asm-x86_64/scatterlist.h +++ b/include/asm-x86_64/scatterlist.h @@ -1,6 +1,8 @@ #ifndef _X8664_SCATTERLIST_H #define _X8664_SCATTERLIST_H +#include + struct scatterlist { struct page *page; unsigned int offset; diff --git a/include/asm-xtensa/scatterlist.h b/include/asm-xtensa/scatterlist.h index 38a2b9acd658..ca337a294290 100644 --- a/include/asm-xtensa/scatterlist.h +++ b/include/asm-xtensa/scatterlist.h @@ -11,6 +11,8 @@ #ifndef _XTENSA_SCATTERLIST_H #define _XTENSA_SCATTERLIST_H +#include + struct scatterlist { struct page *page; unsigned int offset; From 6473d160b4aba8023bcf38519a5989694dfd51a7 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Tue, 6 Mar 2007 02:45:12 -0800 Subject: [PATCH 07/59] PCI: Cleanup the includes of I noticed that many source files include while they do not appear to need it. Here is an attempt to clean it all up. In order to find all possibly affected files, I searched for all files including but without any other occurence of "pci" or "PCI". I removed the include statement from all of these, then I compiled an allmodconfig kernel on both i386 and x86_64 and fixed the false positives manually. My tests covered 66% of the affected files, so there could be false positives remaining. Untested files are: arch/alpha/kernel/err_common.c arch/alpha/kernel/err_ev6.c arch/alpha/kernel/err_ev7.c arch/ia64/sn/kernel/huberror.c arch/ia64/sn/kernel/xpnet.c arch/m68knommu/kernel/dma.c arch/mips/lib/iomap.c arch/powerpc/platforms/pseries/ras.c arch/ppc/8260_io/enet.c arch/ppc/8260_io/fcc_enet.c arch/ppc/8xx_io/enet.c arch/ppc/syslib/ppc4xx_sgdma.c arch/sh64/mach-cayman/iomap.c arch/xtensa/kernel/xtensa_ksyms.c arch/xtensa/platform-iss/setup.c drivers/i2c/busses/i2c-at91.c drivers/i2c/busses/i2c-mpc.c drivers/media/video/saa711x.c drivers/misc/hdpuftrs/hdpu_cpustate.c drivers/misc/hdpuftrs/hdpu_nexus.c drivers/net/au1000_eth.c drivers/net/fec_8xx/fec_main.c drivers/net/fec_8xx/fec_mii.c drivers/net/fs_enet/fs_enet-main.c drivers/net/fs_enet/mac-fcc.c drivers/net/fs_enet/mac-fec.c drivers/net/fs_enet/mac-scc.c drivers/net/fs_enet/mii-bitbang.c drivers/net/fs_enet/mii-fec.c drivers/net/ibm_emac/ibm_emac_core.c drivers/net/lasi_82596.c drivers/parisc/hppb.c drivers/sbus/sbus.c drivers/video/g364fb.c drivers/video/platinumfb.c drivers/video/stifb.c drivers/video/valkyriefb.c include/asm-arm/arch-ixp4xx/dma.h sound/oss/au1550_ac97.c I would welcome test reports for these files. I am fine with removing the untested files from the patch if the general opinion is that these changes aren't safe. The tested part would still be nice to have. Note that this patch depends on another header fixup patch I submitted to LKML yesterday: [PATCH] scatterlist.h needs types.h http://lkml.org/lkml/2007/3/01/141 Signed-off-by: Jean Delvare Cc: Badari Pulavarty Signed-off-by: Greg Kroah-Hartman --- arch/alpha/kernel/err_common.c | 1 - arch/alpha/kernel/err_ev6.c | 1 - arch/alpha/kernel/err_ev7.c | 1 - arch/i386/kernel/cpu/cpufreq/speedstep-lib.c | 1 - arch/i386/kernel/cpu/cpufreq/speedstep-smi.c | 2 +- arch/ia64/sn/kernel/huberror.c | 1 - arch/ia64/sn/kernel/xpnet.c | 1 - arch/m68knommu/kernel/dma.c | 1 - arch/mips/lib/iomap.c | 1 - arch/powerpc/platforms/pseries/ras.c | 1 - arch/ppc/8260_io/enet.c | 1 - arch/ppc/8260_io/fcc_enet.c | 1 - arch/ppc/8xx_io/enet.c | 1 - arch/ppc/syslib/ppc4xx_sgdma.c | 1 - arch/sh64/mach-cayman/iomap.c | 1 - arch/xtensa/kernel/xtensa_ksyms.c | 1 - arch/xtensa/platform-iss/setup.c | 1 - drivers/atm/adummy.c | 1 - drivers/char/hw_random/via-rng.c | 1 - drivers/char/pcmcia/synclink_cs.c | 1 - drivers/char/tpm/tpm.h | 1 - drivers/char/watchdog/sc1200wdt.c | 1 - drivers/char/watchdog/scx200_wdt.c | 2 +- drivers/i2c/busses/i2c-at91.c | 1 - drivers/i2c/busses/i2c-mpc.c | 1 - drivers/i2c/busses/i2c-pca-isa.c | 1 - drivers/ieee1394/hosts.c | 1 - drivers/infiniband/core/cm.c | 1 - drivers/infiniband/core/iwcm.c | 1 - drivers/infiniband/core/mad_priv.h | 1 - drivers/infiniband/core/multicast.c | 1 - drivers/infiniband/core/sa_query.c | 1 - drivers/infiniband/core/user_mad.c | 1 - drivers/infiniband/hw/ipath/ipath_fs.c | 1 - drivers/infiniband/hw/ipath/ipath_layer.c | 1 - drivers/infiniband/hw/ipath/ipath_stats.c | 2 -- drivers/infiniband/hw/ipath/ipath_sysfs.c | 1 - drivers/infiniband/hw/mthca/mthca_memfree.h | 1 - drivers/infiniband/ulp/ipoib/ipoib.h | 1 - drivers/isdn/hisax/netjet.c | 1 - drivers/isdn/hysdn/hysdn_proclog.c | 1 - drivers/media/dvb/cinergyT2/cinergyT2.c | 2 +- drivers/media/video/adv7170.c | 1 - drivers/media/video/adv7175.c | 1 - drivers/media/video/bt819.c | 1 - drivers/media/video/bt856.c | 1 - drivers/media/video/bt866.c | 1 - drivers/media/video/cx88/cx88-tvaudio.c | 1 - drivers/media/video/em28xx/em28xx-cards.c | 1 - drivers/media/video/saa7111.c | 1 - drivers/media/video/saa7114.c | 1 - drivers/media/video/saa711x.c | 1 - drivers/media/video/saa7185.c | 1 - drivers/misc/hdpuftrs/hdpu_cpustate.c | 1 - drivers/misc/hdpuftrs/hdpu_nexus.c | 1 - drivers/mtd/devices/doc2000.c | 1 - drivers/mtd/devices/doc2001.c | 1 - drivers/mtd/devices/doc2001plus.c | 1 - drivers/mtd/devices/docecc.c | 1 - drivers/mtd/inftlmount.c | 1 - drivers/mtd/nand/cs553x_nand.c | 1 - drivers/mtd/nftlcore.c | 1 - drivers/net/atl1/atl1_param.c | 1 - drivers/net/au1000_eth.c | 1 - drivers/net/fec_8xx/fec_main.c | 1 - drivers/net/fec_8xx/fec_mii.c | 1 - drivers/net/fs_enet/fs_enet-main.c | 1 - drivers/net/fs_enet/mac-fcc.c | 1 - drivers/net/fs_enet/mac-fec.c | 1 - drivers/net/fs_enet/mac-scc.c | 1 - drivers/net/fs_enet/mii-bitbang.c | 1 - drivers/net/fs_enet/mii-fec.c | 1 - drivers/net/ibm_emac/ibm_emac_core.c | 1 - drivers/net/ixgb/ixgb_osdep.h | 1 - drivers/net/lasi_82596.c | 1 - drivers/net/tokenring/madgemc.c | 1 - drivers/net/tokenring/smctr.c | 1 - drivers/net/tulip/21142.c | 1 - drivers/net/tulip/pnic.c | 1 - drivers/net/tulip/pnic2.c | 1 - drivers/net/tulip/timer.c | 1 - drivers/net/tulip/tulip.h | 1 + drivers/net/wan/lmc/lmc_media.c | 1 - drivers/net/wan/lmc/lmc_proto.c | 1 - drivers/net/wan/pc300_tty.c | 1 - drivers/parisc/hppb.c | 2 -- drivers/pcmcia/cs.c | 1 - drivers/pcmcia/socket_sysfs.c | 1 - drivers/sbus/sbus.c | 1 - drivers/scsi/aacraid/dpcsup.c | 1 - drivers/scsi/aacraid/sa.c | 1 - drivers/scsi/aha1542.c | 1 - drivers/scsi/aic94xx/aic94xx_scb.c | 1 - drivers/scsi/arcmsr/arcmsr_attr.c | 1 - drivers/scsi/libsas/sas_expander.c | 1 - drivers/scsi/libsrp.c | 1 - drivers/usb/net/kaweth.c | 1 - drivers/video/aty/radeon_i2c.c | 1 - drivers/video/g364fb.c | 1 - drivers/video/platinumfb.c | 1 - drivers/video/stifb.c | 1 - drivers/video/valkyriefb.c | 1 - include/asm-arm/arch-ixp4xx/dma.h | 1 - include/rdma/ib_mad.h | 2 -- sound/core/init.c | 1 - sound/oss/au1550_ac97.c | 1 - sound/oss/soundcard.c | 1 + sound/pci/ca0106/ca0106_mixer.c | 2 +- sound/pci/ca0106/ca0106_proc.c | 2 +- sound/pci/cs46xx/dsp_spos.c | 1 - sound/pci/cs46xx/dsp_spos_scb_lib.c | 1 - sound/pci/hda/hda_generic.c | 1 - sound/pci/hda/hda_proc.c | 1 - sound/pci/hda/patch_atihdmi.c | 1 - sound/pci/hda/patch_si3054.c | 1 - sound/pci/hda/patch_via.c | 1 - 116 files changed, 7 insertions(+), 117 deletions(-) diff --git a/arch/alpha/kernel/err_common.c b/arch/alpha/kernel/err_common.c index 687580b16b41..13d53b1c9657 100644 --- a/arch/alpha/kernel/err_common.c +++ b/arch/alpha/kernel/err_common.c @@ -7,7 +7,6 @@ */ #include -#include #include #include diff --git a/arch/alpha/kernel/err_ev6.c b/arch/alpha/kernel/err_ev6.c index 69b5f4ea7355..11aee012a8ae 100644 --- a/arch/alpha/kernel/err_ev6.c +++ b/arch/alpha/kernel/err_ev6.c @@ -7,7 +7,6 @@ */ #include -#include #include #include diff --git a/arch/alpha/kernel/err_ev7.c b/arch/alpha/kernel/err_ev7.c index 95463ab1cf35..bc799f72d8c1 100644 --- a/arch/alpha/kernel/err_ev7.c +++ b/arch/alpha/kernel/err_ev7.c @@ -7,7 +7,6 @@ */ #include -#include #include #include diff --git a/arch/i386/kernel/cpu/cpufreq/speedstep-lib.c b/arch/i386/kernel/cpu/cpufreq/speedstep-lib.c index d59277c00911..b1acc8ce3167 100644 --- a/arch/i386/kernel/cpu/cpufreq/speedstep-lib.c +++ b/arch/i386/kernel/cpu/cpufreq/speedstep-lib.c @@ -13,7 +13,6 @@ #include #include #include -#include #include #include diff --git a/arch/i386/kernel/cpu/cpufreq/speedstep-smi.c b/arch/i386/kernel/cpu/cpufreq/speedstep-smi.c index ff0d89806114..e1c509aa3054 100644 --- a/arch/i386/kernel/cpu/cpufreq/speedstep-smi.c +++ b/arch/i386/kernel/cpu/cpufreq/speedstep-smi.c @@ -17,10 +17,10 @@ #include #include #include -#include #include #include #include +#include #include "speedstep-lib.h" diff --git a/arch/ia64/sn/kernel/huberror.c b/arch/ia64/sn/kernel/huberror.c index fcf7f93c4b61..2c3f9dfca78b 100644 --- a/arch/ia64/sn/kernel/huberror.c +++ b/arch/ia64/sn/kernel/huberror.c @@ -8,7 +8,6 @@ #include #include -#include #include #include #include "ioerror.h" diff --git a/arch/ia64/sn/kernel/xpnet.c b/arch/ia64/sn/kernel/xpnet.c index 5419acb89a8c..88fad85ceeff 100644 --- a/arch/ia64/sn/kernel/xpnet.c +++ b/arch/ia64/sn/kernel/xpnet.c @@ -24,7 +24,6 @@ #include #include -#include #include #include #include diff --git a/arch/m68knommu/kernel/dma.c b/arch/m68knommu/kernel/dma.c index 14b19c4161f4..0a25874a2aae 100644 --- a/arch/m68knommu/kernel/dma.c +++ b/arch/m68knommu/kernel/dma.c @@ -8,7 +8,6 @@ #include #include #include -#include #include void *dma_alloc_coherent(struct device *dev, size_t size, diff --git a/arch/mips/lib/iomap.c b/arch/mips/lib/iomap.c index d51d5cb0a4a9..e3acb2dad33a 100644 --- a/arch/mips/lib/iomap.c +++ b/arch/mips/lib/iomap.c @@ -6,7 +6,6 @@ * (C) Copyright 2007 MIPS Technologies, Inc. * written by Ralf Baechle */ -#include #include #include diff --git a/arch/powerpc/platforms/pseries/ras.c b/arch/powerpc/platforms/pseries/ras.c index 53aa04101ced..3a393c7f390e 100644 --- a/arch/powerpc/platforms/pseries/ras.c +++ b/arch/powerpc/platforms/pseries/ras.c @@ -31,7 +31,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/ppc/8260_io/enet.c b/arch/ppc/8260_io/enet.c index 48ce84f5be93..4c0a7d732f69 100644 --- a/arch/ppc/8260_io/enet.c +++ b/arch/ppc/8260_io/enet.c @@ -32,7 +32,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/ppc/8260_io/fcc_enet.c b/arch/ppc/8260_io/fcc_enet.c index 9db825fe37f0..cab395da25da 100644 --- a/arch/ppc/8260_io/fcc_enet.c +++ b/arch/ppc/8260_io/fcc_enet.c @@ -29,7 +29,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/ppc/8xx_io/enet.c b/arch/ppc/8xx_io/enet.c index bfa3f52996d1..e58288e14369 100644 --- a/arch/ppc/8xx_io/enet.c +++ b/arch/ppc/8xx_io/enet.c @@ -30,7 +30,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/ppc/syslib/ppc4xx_sgdma.c b/arch/ppc/syslib/ppc4xx_sgdma.c index 939abe3c1f45..5dadca3e0d61 100644 --- a/arch/ppc/syslib/ppc4xx_sgdma.c +++ b/arch/ppc/syslib/ppc4xx_sgdma.c @@ -23,7 +23,6 @@ #include #include #include -#include #include #include diff --git a/arch/sh64/mach-cayman/iomap.c b/arch/sh64/mach-cayman/iomap.c index 2d06e9a55137..a5c645f02d57 100644 --- a/arch/sh64/mach-cayman/iomap.c +++ b/arch/sh64/mach-cayman/iomap.c @@ -9,7 +9,6 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. */ -#include #include #include diff --git a/arch/xtensa/kernel/xtensa_ksyms.c b/arch/xtensa/kernel/xtensa_ksyms.c index 0b4cb93db5a3..cd7e6a020602 100644 --- a/arch/xtensa/kernel/xtensa_ksyms.c +++ b/arch/xtensa/kernel/xtensa_ksyms.c @@ -18,7 +18,6 @@ #include #include #include -#include #include #include diff --git a/arch/xtensa/platform-iss/setup.c b/arch/xtensa/platform-iss/setup.c index c8a42b60c57a..f60c8cf6dfbe 100644 --- a/arch/xtensa/platform-iss/setup.c +++ b/arch/xtensa/platform-iss/setup.c @@ -20,7 +20,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/atm/adummy.c b/drivers/atm/adummy.c index 8d60c4eb54fe..2ebd07f2ef81 100644 --- a/drivers/atm/adummy.c +++ b/drivers/atm/adummy.c @@ -6,7 +6,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/char/hw_random/via-rng.c b/drivers/char/hw_random/via-rng.c index 9ebf84d18655..ec435cb25c4f 100644 --- a/drivers/char/hw_random/via-rng.c +++ b/drivers/char/hw_random/via-rng.c @@ -26,7 +26,6 @@ #include #include -#include #include #include #include diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c index 157b1d09ab55..13808f6083a0 100644 --- a/drivers/char/pcmcia/synclink_cs.c +++ b/drivers/char/pcmcia/synclink_cs.c @@ -42,7 +42,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h index bb9a43c6cf3d..9f273f032b0f 100644 --- a/drivers/char/tpm/tpm.h +++ b/drivers/char/tpm/tpm.h @@ -19,7 +19,6 @@ * */ #include -#include #include #include #include diff --git a/drivers/char/watchdog/sc1200wdt.c b/drivers/char/watchdog/sc1200wdt.c index 1e4a8d751a71..2f7ba7a514fe 100644 --- a/drivers/char/watchdog/sc1200wdt.c +++ b/drivers/char/watchdog/sc1200wdt.c @@ -38,7 +38,6 @@ #include #include #include -#include #include #include diff --git a/drivers/char/watchdog/scx200_wdt.c b/drivers/char/watchdog/scx200_wdt.c index fc0e0347f9d2..d4fd0fa2f176 100644 --- a/drivers/char/watchdog/scx200_wdt.c +++ b/drivers/char/watchdog/scx200_wdt.c @@ -25,7 +25,7 @@ #include #include #include -#include +#include #include #include diff --git a/drivers/i2c/busses/i2c-at91.c b/drivers/i2c/busses/i2c-at91.c index 67f91bdda089..f35156c58922 100644 --- a/drivers/i2c/busses/i2c-at91.c +++ b/drivers/i2c/busses/i2c-at91.c @@ -17,7 +17,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c index ee65aa1be13a..c6b6898592b1 100644 --- a/drivers/i2c/busses/i2c-mpc.c +++ b/drivers/i2c/busses/i2c-mpc.c @@ -17,7 +17,6 @@ #include #include #include -#include #include #include diff --git a/drivers/i2c/busses/i2c-pca-isa.c b/drivers/i2c/busses/i2c-pca-isa.c index cc6536a19eca..6b03e0d0a8e3 100644 --- a/drivers/i2c/busses/i2c-pca-isa.c +++ b/drivers/i2c/busses/i2c-pca-isa.c @@ -25,7 +25,6 @@ #include #include #include -#include #include #include diff --git a/drivers/ieee1394/hosts.c b/drivers/ieee1394/hosts.c index 6164a9a83396..bd0755c789c5 100644 --- a/drivers/ieee1394/hosts.c +++ b/drivers/ieee1394/hosts.c @@ -15,7 +15,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/infiniband/core/cm.c b/drivers/infiniband/core/cm.c index 842cd0b53e91..eff591deeb46 100644 --- a/drivers/infiniband/core/cm.c +++ b/drivers/infiniband/core/cm.c @@ -40,7 +40,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/infiniband/core/iwcm.c b/drivers/infiniband/core/iwcm.c index 891d1fa7b2eb..223b1aa7d92b 100644 --- a/drivers/infiniband/core/iwcm.c +++ b/drivers/infiniband/core/iwcm.c @@ -39,7 +39,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/infiniband/core/mad_priv.h b/drivers/infiniband/core/mad_priv.h index de89717f49fe..9be5cc00a3a9 100644 --- a/drivers/infiniband/core/mad_priv.h +++ b/drivers/infiniband/core/mad_priv.h @@ -39,7 +39,6 @@ #include #include -#include #include #include #include diff --git a/drivers/infiniband/core/multicast.c b/drivers/infiniband/core/multicast.c index 4a579b3a1c90..1e13ab42b70b 100644 --- a/drivers/infiniband/core/multicast.c +++ b/drivers/infiniband/core/multicast.c @@ -34,7 +34,6 @@ #include #include #include -#include #include #include diff --git a/drivers/infiniband/core/sa_query.c b/drivers/infiniband/core/sa_query.c index 9a7eaadb1688..6469406ea9d8 100644 --- a/drivers/infiniband/core/sa_query.c +++ b/drivers/infiniband/core/sa_query.c @@ -40,7 +40,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/infiniband/core/user_mad.c b/drivers/infiniband/core/user_mad.c index 8199b83052a9..d97ded25c4ff 100644 --- a/drivers/infiniband/core/user_mad.c +++ b/drivers/infiniband/core/user_mad.c @@ -40,7 +40,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/infiniband/hw/ipath/ipath_fs.c b/drivers/infiniband/hw/ipath/ipath_fs.c index ed55979bfd34..036ed1ef1796 100644 --- a/drivers/infiniband/hw/ipath/ipath_fs.c +++ b/drivers/infiniband/hw/ipath/ipath_fs.c @@ -38,7 +38,6 @@ #include #include #include -#include #include "ipath_kernel.h" diff --git a/drivers/infiniband/hw/ipath/ipath_layer.c b/drivers/infiniband/hw/ipath/ipath_layer.c index e46aa4ed2a7e..05a1d2b01d9d 100644 --- a/drivers/infiniband/hw/ipath/ipath_layer.c +++ b/drivers/infiniband/hw/ipath/ipath_layer.c @@ -37,7 +37,6 @@ */ #include -#include #include #include "ipath_kernel.h" diff --git a/drivers/infiniband/hw/ipath/ipath_stats.c b/drivers/infiniband/hw/ipath/ipath_stats.c index 9307f7187ca5..d8b5e4cefe25 100644 --- a/drivers/infiniband/hw/ipath/ipath_stats.c +++ b/drivers/infiniband/hw/ipath/ipath_stats.c @@ -31,8 +31,6 @@ * SOFTWARE. */ -#include - #include "ipath_kernel.h" struct infinipath_stats ipath_stats; diff --git a/drivers/infiniband/hw/ipath/ipath_sysfs.c b/drivers/infiniband/hw/ipath/ipath_sysfs.c index ffa6318ad0cc..4dc398d5e011 100644 --- a/drivers/infiniband/hw/ipath/ipath_sysfs.c +++ b/drivers/infiniband/hw/ipath/ipath_sysfs.c @@ -32,7 +32,6 @@ */ #include -#include #include "ipath_kernel.h" #include "ipath_common.h" diff --git a/drivers/infiniband/hw/mthca/mthca_memfree.h b/drivers/infiniband/hw/mthca/mthca_memfree.h index 594144145f45..a1ab06847b75 100644 --- a/drivers/infiniband/hw/mthca/mthca_memfree.h +++ b/drivers/infiniband/hw/mthca/mthca_memfree.h @@ -38,7 +38,6 @@ #define MTHCA_MEMFREE_H #include -#include #include #define MTHCA_ICM_CHUNK_LEN \ diff --git a/drivers/infiniband/ulp/ipoib/ipoib.h b/drivers/infiniband/ulp/ipoib/ipoib.h index fd558267d1cb..d8f6bb4f53fc 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib.h +++ b/drivers/infiniband/ulp/ipoib/ipoib.h @@ -41,7 +41,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/isdn/hisax/netjet.c b/drivers/isdn/hisax/netjet.c index 38f648f9b0ed..02c6fbaeccf8 100644 --- a/drivers/isdn/hisax/netjet.c +++ b/drivers/isdn/hisax/netjet.c @@ -19,7 +19,6 @@ #include "isac.h" #include "hscx.h" #include "isdnl1.h" -#include #include #include #include diff --git a/drivers/isdn/hysdn/hysdn_proclog.c b/drivers/isdn/hysdn/hysdn_proclog.c index f7e83a86f444..4c7dedac0e51 100644 --- a/drivers/isdn/hysdn/hysdn_proclog.c +++ b/drivers/isdn/hysdn/hysdn_proclog.c @@ -13,7 +13,6 @@ #include #include #include -#include #include #include "hysdn_defs.h" diff --git a/drivers/media/dvb/cinergyT2/cinergyT2.c b/drivers/media/dvb/cinergyT2/cinergyT2.c index a6cbbdd262d6..34d7abc900d7 100644 --- a/drivers/media/dvb/cinergyT2/cinergyT2.c +++ b/drivers/media/dvb/cinergyT2/cinergyT2.c @@ -26,11 +26,11 @@ #include #include #include -#include #include #include #include #include +#include #include "dmxdev.h" #include "dvb_demux.h" diff --git a/drivers/media/video/adv7170.c b/drivers/media/video/adv7170.c index 2aa9ce920607..823cd6cc471e 100644 --- a/drivers/media/video/adv7170.c +++ b/drivers/media/video/adv7170.c @@ -37,7 +37,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/media/video/adv7175.c b/drivers/media/video/adv7175.c index a3246a283aa4..05c7820fe53e 100644 --- a/drivers/media/video/adv7175.c +++ b/drivers/media/video/adv7175.c @@ -33,7 +33,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/media/video/bt819.c b/drivers/media/video/bt819.c index 68673863d5c9..59a43603b5cb 100644 --- a/drivers/media/video/bt819.c +++ b/drivers/media/video/bt819.c @@ -37,7 +37,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/media/video/bt856.c b/drivers/media/video/bt856.c index 42e2299dcb22..853b1a3d6a1d 100644 --- a/drivers/media/video/bt856.c +++ b/drivers/media/video/bt856.c @@ -37,7 +37,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/media/video/bt866.c b/drivers/media/video/bt866.c index 772fd52d551a..2e4cf1efdd21 100644 --- a/drivers/media/video/bt866.c +++ b/drivers/media/video/bt866.c @@ -37,7 +37,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/media/video/cx88/cx88-tvaudio.c b/drivers/media/video/cx88/cx88-tvaudio.c index 97ef421dd093..e627062fde3a 100644 --- a/drivers/media/video/cx88/cx88-tvaudio.c +++ b/drivers/media/video/cx88/cx88-tvaudio.c @@ -43,7 +43,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index ed882ebc7b95..418ea8b7f85a 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c @@ -23,7 +23,6 @@ #include #include -#include #include #include #include diff --git a/drivers/media/video/saa7111.c b/drivers/media/video/saa7111.c index 44dc7479119c..74839f98b7c4 100644 --- a/drivers/media/video/saa7111.c +++ b/drivers/media/video/saa7111.c @@ -36,7 +36,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/media/video/saa7114.c b/drivers/media/video/saa7114.c index 2ce3321ab995..87c3144ec7fc 100644 --- a/drivers/media/video/saa7114.c +++ b/drivers/media/video/saa7114.c @@ -39,7 +39,6 @@ #include #include -#include #include #include #include diff --git a/drivers/media/video/saa711x.c b/drivers/media/video/saa711x.c index 269d7114a93a..80bf91187856 100644 --- a/drivers/media/video/saa711x.c +++ b/drivers/media/video/saa711x.c @@ -30,7 +30,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/media/video/saa7185.c b/drivers/media/video/saa7185.c index e0fdb1ab7580..339592e7722d 100644 --- a/drivers/media/video/saa7185.c +++ b/drivers/media/video/saa7185.c @@ -33,7 +33,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/misc/hdpuftrs/hdpu_cpustate.c b/drivers/misc/hdpuftrs/hdpu_cpustate.c index ca86f113f36a..276ba3c5143f 100644 --- a/drivers/misc/hdpuftrs/hdpu_cpustate.c +++ b/drivers/misc/hdpuftrs/hdpu_cpustate.c @@ -18,7 +18,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/misc/hdpuftrs/hdpu_nexus.c b/drivers/misc/hdpuftrs/hdpu_nexus.c index 6a51e99a8079..60c8b26f0678 100644 --- a/drivers/misc/hdpuftrs/hdpu_nexus.c +++ b/drivers/misc/hdpuftrs/hdpu_nexus.c @@ -18,7 +18,6 @@ #include #include #include -#include #include diff --git a/drivers/mtd/devices/doc2000.c b/drivers/mtd/devices/doc2000.c index 8a0c4dec6351..c73e96bfafc6 100644 --- a/drivers/mtd/devices/doc2000.c +++ b/drivers/mtd/devices/doc2000.c @@ -13,7 +13,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/mtd/devices/doc2001.c b/drivers/mtd/devices/doc2001.c index 6f368aec5d5d..6413efc045e0 100644 --- a/drivers/mtd/devices/doc2001.c +++ b/drivers/mtd/devices/doc2001.c @@ -13,7 +13,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/mtd/devices/doc2001plus.c b/drivers/mtd/devices/doc2001plus.c index 88ba82df0fbb..2b30b587c6e8 100644 --- a/drivers/mtd/devices/doc2001plus.c +++ b/drivers/mtd/devices/doc2001plus.c @@ -17,7 +17,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/mtd/devices/docecc.c b/drivers/mtd/devices/docecc.c index 52b5d638077f..fd8a8daba3a8 100644 --- a/drivers/mtd/devices/docecc.c +++ b/drivers/mtd/devices/docecc.c @@ -29,7 +29,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/mtd/inftlmount.c b/drivers/mtd/inftlmount.c index acf3ba223298..ecac0e438f49 100644 --- a/drivers/mtd/inftlmount.c +++ b/drivers/mtd/inftlmount.c @@ -31,7 +31,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/mtd/nand/cs553x_nand.c b/drivers/mtd/nand/cs553x_nand.c index 8296305c8297..89deff007116 100644 --- a/drivers/mtd/nand/cs553x_nand.c +++ b/drivers/mtd/nand/cs553x_nand.c @@ -20,7 +20,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/mtd/nftlcore.c b/drivers/mtd/nftlcore.c index e6ef7d7f9f14..0c9ce19ea27a 100644 --- a/drivers/mtd/nftlcore.c +++ b/drivers/mtd/nftlcore.c @@ -17,7 +17,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/net/atl1/atl1_param.c b/drivers/net/atl1/atl1_param.c index c407214339f6..bcd0bd891722 100644 --- a/drivers/net/atl1/atl1_param.c +++ b/drivers/net/atl1/atl1_param.c @@ -22,7 +22,6 @@ */ #include -#include #include #include "atl1.h" diff --git a/drivers/net/au1000_eth.c b/drivers/net/au1000_eth.c index d10fb80e9a63..c39ab803c5d8 100644 --- a/drivers/net/au1000_eth.c +++ b/drivers/net/au1000_eth.c @@ -45,7 +45,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/net/fec_8xx/fec_main.c b/drivers/net/fec_8xx/fec_main.c index e824d5d231af..88efe9731bab 100644 --- a/drivers/net/fec_8xx/fec_main.c +++ b/drivers/net/fec_8xx/fec_main.c @@ -19,7 +19,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/net/fec_8xx/fec_mii.c b/drivers/net/fec_8xx/fec_mii.c index e79700abf7b6..b3fa0d6a159c 100644 --- a/drivers/net/fec_8xx/fec_mii.c +++ b/drivers/net/fec_8xx/fec_mii.c @@ -19,7 +19,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/net/fs_enet/fs_enet-main.c b/drivers/net/fs_enet/fs_enet-main.c index e2ddd617493a..a4a2a0ea43d3 100644 --- a/drivers/net/fs_enet/fs_enet-main.c +++ b/drivers/net/fs_enet/fs_enet-main.c @@ -24,7 +24,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/net/fs_enet/mac-fcc.c b/drivers/net/fs_enet/mac-fcc.c index 8545e84fc9a0..5603121132cd 100644 --- a/drivers/net/fs_enet/mac-fcc.c +++ b/drivers/net/fs_enet/mac-fcc.c @@ -21,7 +21,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/net/fs_enet/mac-fec.c b/drivers/net/fs_enet/mac-fec.c index cdcfb96f360f..04b4f80a1cde 100644 --- a/drivers/net/fs_enet/mac-fec.c +++ b/drivers/net/fs_enet/mac-fec.c @@ -21,7 +21,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/net/fs_enet/mac-scc.c b/drivers/net/fs_enet/mac-scc.c index 65925b5a224f..d0f28981b55a 100644 --- a/drivers/net/fs_enet/mac-scc.c +++ b/drivers/net/fs_enet/mac-scc.c @@ -21,7 +21,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/net/fs_enet/mii-bitbang.c b/drivers/net/fs_enet/mii-bitbang.c index f91447837fd4..d3840108ffbd 100644 --- a/drivers/net/fs_enet/mii-bitbang.c +++ b/drivers/net/fs_enet/mii-bitbang.c @@ -22,7 +22,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/net/fs_enet/mii-fec.c b/drivers/net/fs_enet/mii-fec.c index 235b177fb9ac..0a563a83016f 100644 --- a/drivers/net/fs_enet/mii-fec.c +++ b/drivers/net/fs_enet/mii-fec.c @@ -21,7 +21,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/net/ibm_emac/ibm_emac_core.c b/drivers/net/ibm_emac/ibm_emac_core.c index 3d82d46f4998..50035ebd4f52 100644 --- a/drivers/net/ibm_emac/ibm_emac_core.c +++ b/drivers/net/ibm_emac/ibm_emac_core.c @@ -27,7 +27,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/net/ixgb/ixgb_osdep.h b/drivers/net/ixgb/ixgb_osdep.h index 8434d752fd81..9e04a6b3ae0d 100644 --- a/drivers/net/ixgb/ixgb_osdep.h +++ b/drivers/net/ixgb/ixgb_osdep.h @@ -34,7 +34,6 @@ #define _IXGB_OSDEP_H_ #include -#include #include #include #include diff --git a/drivers/net/lasi_82596.c b/drivers/net/lasi_82596.c index 0edcd125fd61..6b49fc4bd1a1 100644 --- a/drivers/net/lasi_82596.c +++ b/drivers/net/lasi_82596.c @@ -81,7 +81,6 @@ #include #include #include -#include #include #include diff --git a/drivers/net/tokenring/madgemc.c b/drivers/net/tokenring/madgemc.c index ed274d6909d0..f8f4d74f01f1 100644 --- a/drivers/net/tokenring/madgemc.c +++ b/drivers/net/tokenring/madgemc.c @@ -23,7 +23,6 @@ static const char version[] = "madgemc.c: v0.91 23/01/2000 by Adam Fritzler\n"; #include #include #include -#include #include #include #include diff --git a/drivers/net/tokenring/smctr.c b/drivers/net/tokenring/smctr.c index 9bbea5c8acf4..58d7e5d452fa 100644 --- a/drivers/net/tokenring/smctr.c +++ b/drivers/net/tokenring/smctr.c @@ -41,7 +41,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/net/tulip/21142.c b/drivers/net/tulip/21142.c index 942b839ccc5b..6c400ccd38b4 100644 --- a/drivers/net/tulip/21142.c +++ b/drivers/net/tulip/21142.c @@ -14,7 +14,6 @@ */ -#include #include #include "tulip.h" diff --git a/drivers/net/tulip/pnic.c b/drivers/net/tulip/pnic.c index 85a521e0d052..be82a2effee3 100644 --- a/drivers/net/tulip/pnic.c +++ b/drivers/net/tulip/pnic.c @@ -15,7 +15,6 @@ */ #include -#include #include #include "tulip.h" diff --git a/drivers/net/tulip/pnic2.c b/drivers/net/tulip/pnic2.c index c31be0e377a8..4e4a879c3fa5 100644 --- a/drivers/net/tulip/pnic2.c +++ b/drivers/net/tulip/pnic2.c @@ -76,7 +76,6 @@ -#include #include "tulip.h" #include diff --git a/drivers/net/tulip/timer.c b/drivers/net/tulip/timer.c index df326fe1cc8f..d2c1f42109b0 100644 --- a/drivers/net/tulip/timer.c +++ b/drivers/net/tulip/timer.c @@ -14,7 +14,6 @@ */ -#include #include "tulip.h" diff --git a/drivers/net/tulip/tulip.h b/drivers/net/tulip/tulip.h index c840d2e67b23..16f26a8364f0 100644 --- a/drivers/net/tulip/tulip.h +++ b/drivers/net/tulip/tulip.h @@ -22,6 +22,7 @@ #include #include #include +#include #include #include diff --git a/drivers/net/wan/lmc/lmc_media.c b/drivers/net/wan/lmc/lmc_media.c index ae01555d24cf..574737b55f39 100644 --- a/drivers/net/wan/lmc/lmc_media.c +++ b/drivers/net/wan/lmc/lmc_media.c @@ -8,7 +8,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/net/wan/lmc/lmc_proto.c b/drivers/net/wan/lmc/lmc_proto.c index 74876c0073e8..31e1799571ad 100644 --- a/drivers/net/wan/lmc/lmc_proto.c +++ b/drivers/net/wan/lmc/lmc_proto.c @@ -27,7 +27,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/net/wan/pc300_tty.c b/drivers/net/wan/pc300_tty.c index 07dbdfbfc15d..e24a7b095dd6 100644 --- a/drivers/net/wan/pc300_tty.c +++ b/drivers/net/wan/pc300_tty.c @@ -38,7 +38,6 @@ #include #include -#include #include #include #include diff --git a/drivers/parisc/hppb.c b/drivers/parisc/hppb.c index 9bb4db552f3c..a68b3b3761a2 100644 --- a/drivers/parisc/hppb.c +++ b/drivers/parisc/hppb.c @@ -22,8 +22,6 @@ #include #include -#include - struct hppb_card { unsigned long hpa; struct resource mmio_region; diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c index ac004248324a..50cad3a59a6c 100644 --- a/drivers/pcmcia/cs.c +++ b/drivers/pcmcia/cs.c @@ -26,7 +26,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/pcmcia/socket_sysfs.c b/drivers/pcmcia/socket_sysfs.c index ea5765c3bdc0..a2bb46526b56 100644 --- a/drivers/pcmcia/socket_sysfs.c +++ b/drivers/pcmcia/socket_sysfs.c @@ -22,7 +22,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/sbus/sbus.c b/drivers/sbus/sbus.c index eee590a51d8a..002643392d42 100644 --- a/drivers/sbus/sbus.c +++ b/drivers/sbus/sbus.c @@ -6,7 +6,6 @@ #include #include #include -#include #include #include diff --git a/drivers/scsi/aacraid/dpcsup.c b/drivers/scsi/aacraid/dpcsup.c index d38b628be1ad..66aeb57dcc2d 100644 --- a/drivers/scsi/aacraid/dpcsup.c +++ b/drivers/scsi/aacraid/dpcsup.c @@ -32,7 +32,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/scsi/aacraid/sa.c b/drivers/scsi/aacraid/sa.c index 6f1a1780efce..f4b5e9742ab0 100644 --- a/drivers/scsi/aacraid/sa.c +++ b/drivers/scsi/aacraid/sa.c @@ -31,7 +31,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/scsi/aha1542.c b/drivers/scsi/aha1542.c index 1d239f6c0103..cbbfbc9f3e0f 100644 --- a/drivers/scsi/aha1542.c +++ b/drivers/scsi/aha1542.c @@ -35,7 +35,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/scsi/aic94xx/aic94xx_scb.c b/drivers/scsi/aic94xx/aic94xx_scb.c index 8f43ff772f23..db6ab1a3b81e 100644 --- a/drivers/scsi/aic94xx/aic94xx_scb.c +++ b/drivers/scsi/aic94xx/aic94xx_scb.c @@ -24,7 +24,6 @@ * */ -#include #include #include "aic94xx.h" diff --git a/drivers/scsi/arcmsr/arcmsr_attr.c b/drivers/scsi/arcmsr/arcmsr_attr.c index 12497da5529d..03bfed61bffc 100644 --- a/drivers/scsi/arcmsr/arcmsr_attr.c +++ b/drivers/scsi/arcmsr/arcmsr_attr.c @@ -49,7 +49,6 @@ #include #include #include -#include #include #include diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c index dc70c180e115..e34442e405e8 100644 --- a/drivers/scsi/libsas/sas_expander.c +++ b/drivers/scsi/libsas/sas_expander.c @@ -22,7 +22,6 @@ * */ -#include #include #include "sas_internal.h" diff --git a/drivers/scsi/libsrp.c b/drivers/scsi/libsrp.c index 89403b00e042..6335830df810 100644 --- a/drivers/scsi/libsrp.c +++ b/drivers/scsi/libsrp.c @@ -22,7 +22,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/usb/net/kaweth.c b/drivers/usb/net/kaweth.c index a0cc05d21a6a..60d29440f316 100644 --- a/drivers/usb/net/kaweth.c +++ b/drivers/usb/net/kaweth.c @@ -55,7 +55,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/video/aty/radeon_i2c.c b/drivers/video/aty/radeon_i2c.c index 508479920705..7db9de681716 100644 --- a/drivers/video/aty/radeon_i2c.c +++ b/drivers/video/aty/radeon_i2c.c @@ -1,7 +1,6 @@ #include #include #include -#include #include diff --git a/drivers/video/g364fb.c b/drivers/video/g364fb.c index ca93a75f2997..b7655c05da53 100644 --- a/drivers/video/g364fb.c +++ b/drivers/video/g364fb.c @@ -26,7 +26,6 @@ #include #include #include -#include #include #include diff --git a/drivers/video/platinumfb.c b/drivers/video/platinumfb.c index 233871655824..e64f8b5d0056 100644 --- a/drivers/video/platinumfb.c +++ b/drivers/video/platinumfb.c @@ -28,7 +28,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/video/stifb.c b/drivers/video/stifb.c index 69f3b264a22e..c97709ecbad0 100644 --- a/drivers/video/stifb.c +++ b/drivers/video/stifb.c @@ -64,7 +64,6 @@ #include #include #include -#include #include /* for HP-UX compatibility */ #include diff --git a/drivers/video/valkyriefb.c b/drivers/video/valkyriefb.c index 06fc19a61192..ad66f070acb8 100644 --- a/drivers/video/valkyriefb.c +++ b/drivers/video/valkyriefb.c @@ -51,7 +51,6 @@ #include #include #include -#include #include #include #include diff --git a/include/asm-arm/arch-ixp4xx/dma.h b/include/asm-arm/arch-ixp4xx/dma.h index 789f7f53c357..2c7f5327d80f 100644 --- a/include/asm-arm/arch-ixp4xx/dma.h +++ b/include/asm-arm/arch-ixp4xx/dma.h @@ -12,7 +12,6 @@ #define __ASM_ARCH_DMA_H #include -#include #include #include #include diff --git a/include/rdma/ib_mad.h b/include/rdma/ib_mad.h index 585d28e960dd..739fa4d0e539 100644 --- a/include/rdma/ib_mad.h +++ b/include/rdma/ib_mad.h @@ -39,8 +39,6 @@ #if !defined( IB_MAD_H ) #define IB_MAD_H -#include - #include /* Management base version */ diff --git a/sound/core/init.c b/sound/core/init.c index 4a431e3ea3a2..f2fe35737186 100644 --- a/sound/core/init.c +++ b/sound/core/init.c @@ -26,7 +26,6 @@ #include #include #include -#include #include #include diff --git a/sound/oss/au1550_ac97.c b/sound/oss/au1550_ac97.c index a339f0c0d512..23018a7c063a 100644 --- a/sound/oss/au1550_ac97.c +++ b/sound/oss/au1550_ac97.c @@ -47,7 +47,6 @@ #include #include #include -#include #include #include #include diff --git a/sound/oss/soundcard.c b/sound/oss/soundcard.c index dcd8d6d2f56f..a9c23b2502ad 100644 --- a/sound/oss/soundcard.c +++ b/sound/oss/soundcard.c @@ -44,6 +44,7 @@ #include #include #include +#include /* * This ought to be moved into include/asm/dma.h diff --git a/sound/pci/ca0106/ca0106_mixer.c b/sound/pci/ca0106/ca0106_mixer.c index b913a1fb8c21..9c3a9c8d1dc2 100644 --- a/sound/pci/ca0106/ca0106_mixer.c +++ b/sound/pci/ca0106/ca0106_mixer.c @@ -62,7 +62,6 @@ #include #include #include -#include #include #include #include @@ -71,6 +70,7 @@ #include #include #include +#include #include "ca0106.h" diff --git a/sound/pci/ca0106/ca0106_proc.c b/sound/pci/ca0106/ca0106_proc.c index 75ca421eb3a1..ae80f51d8c4f 100644 --- a/sound/pci/ca0106/ca0106_proc.c +++ b/sound/pci/ca0106/ca0106_proc.c @@ -64,7 +64,6 @@ #include #include #include -#include #include #include #include @@ -73,6 +72,7 @@ #include #include #include +#include #include "ca0106.h" diff --git a/sound/pci/cs46xx/dsp_spos.c b/sound/pci/cs46xx/dsp_spos.c index 89c402770a1d..336e77e2600c 100644 --- a/sound/pci/cs46xx/dsp_spos.c +++ b/sound/pci/cs46xx/dsp_spos.c @@ -23,7 +23,6 @@ #include #include #include -#include #include #include #include diff --git a/sound/pci/cs46xx/dsp_spos_scb_lib.c b/sound/pci/cs46xx/dsp_spos_scb_lib.c index 343f51d5311b..57e357de1500 100644 --- a/sound/pci/cs46xx/dsp_spos_scb_lib.c +++ b/sound/pci/cs46xx/dsp_spos_scb_lib.c @@ -24,7 +24,6 @@ #include #include #include -#include #include #include #include diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c index 1589d2f2917f..1e5ff0cd3709 100644 --- a/sound/pci/hda/hda_generic.c +++ b/sound/pci/hda/hda_generic.c @@ -23,7 +23,6 @@ #include #include #include -#include #include #include "hda_codec.h" #include "hda_local.h" diff --git a/sound/pci/hda/hda_proc.c b/sound/pci/hda/hda_proc.c index 17df4d0fe135..e313e685f161 100644 --- a/sound/pci/hda/hda_proc.c +++ b/sound/pci/hda/hda_proc.c @@ -23,7 +23,6 @@ #include #include -#include #include #include "hda_codec.h" #include "hda_local.h" diff --git a/sound/pci/hda/patch_atihdmi.c b/sound/pci/hda/patch_atihdmi.c index 7333f275decd..831469d3a923 100644 --- a/sound/pci/hda/patch_atihdmi.c +++ b/sound/pci/hda/patch_atihdmi.c @@ -25,7 +25,6 @@ #include #include #include -#include #include #include "hda_codec.h" #include "hda_local.h" diff --git a/sound/pci/hda/patch_si3054.c b/sound/pci/hda/patch_si3054.c index ed5e45e35963..6fcda9bcf0cf 100644 --- a/sound/pci/hda/patch_si3054.c +++ b/sound/pci/hda/patch_si3054.c @@ -26,7 +26,6 @@ #include #include #include -#include #include #include "hda_codec.h" #include "hda_local.h" diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c index 4c839b031729..2b11ac8689b9 100644 --- a/sound/pci/hda/patch_via.c +++ b/sound/pci/hda/patch_via.c @@ -35,7 +35,6 @@ #include #include #include -#include #include #include "hda_codec.h" #include "hda_local.h" From 8d7d86e9bd377e5779bf3c8da03b27d823c039b4 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Fri, 16 Mar 2007 19:55:52 -0700 Subject: [PATCH 08/59] PCI: kernel-doc fix Warning(linux-2621-rc3g7/drivers/pci/pci.c:1283): No description found for parameter 'dev' Signed-off-by: Randy Dunlap Signed-off-by: Greg Kroah-Hartman --- drivers/pci/pci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 2086cd1b5e0e..7bd8a725bea2 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -1323,7 +1323,7 @@ pci_intx(struct pci_dev *pdev, int enable) /** * pci_msi_off - disables any msi or msix capabilities - * @pdev: the PCI device to operate on + * @dev: the PCI device to operate on * * If you want to use msi see pci_enable_msi and friends. * This is a lower level primitive that allows us to disable From 40ee9e9f8d52d85f2446bbdda7823a3f1de62f3f Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Sat, 24 Mar 2007 11:03:32 -0700 Subject: [PATCH 09/59] PCI: fix sysfs rom file creation for BIOS ROM shadows At one time, if a BIOS ROM shadow was detected for the boot video device (stored at offset 0xc0000), we'd set a special resource flag, IORESOURCE_ROM_SHADOW, so that the sysfs ROM file code could handle it properly. That broke along the way somewhere though, so current kernels will be missing 'rom' files in sysfs if the video device doesn't have an explicit ROM BAR. This patch fixes the regression by moving the video fixup quirk to a little later in the boot cycle (to avoid having its work undone by PCI resource allocation) and checking in the PCI sysfs code whether a rom file should be created due to a shadow resource, which is also moved to a little later in the boot cycle so it will occur after the video fixup. Tested and works on my i386 test box. Signed-off-by: Jesse Barnes Signed-off-by: Greg Kroah-Hartman --- arch/i386/pci/fixup.c | 2 +- drivers/pci/pci-sysfs.c | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/arch/i386/pci/fixup.c b/arch/i386/pci/fixup.c index 8053b17ab647..b62eafb997bc 100644 --- a/arch/i386/pci/fixup.c +++ b/arch/i386/pci/fixup.c @@ -354,7 +354,7 @@ static void __devinit pci_fixup_video(struct pci_dev *pdev) printk(KERN_DEBUG "Boot video device is %s\n", pci_name(pdev)); } } -DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pci_fixup_video); +DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, pci_fixup_video); /* * Some Toshiba laptops need extra code to enable their TI TSB43AB22/A. diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c index cd913a2a416f..29676fe4f23e 100644 --- a/drivers/pci/pci-sysfs.c +++ b/drivers/pci/pci-sysfs.c @@ -620,7 +620,8 @@ int __must_check pci_create_sysfs_dev_files (struct pci_dev *pdev) goto err_bin_file; /* If the device has a ROM, try to expose it in sysfs. */ - if (pci_resource_len(pdev, PCI_ROM_RESOURCE)) { + if (pci_resource_len(pdev, PCI_ROM_RESOURCE) || + (pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW)) { rom_attr = kzalloc(sizeof(*rom_attr), GFP_ATOMIC); if (rom_attr) { pdev->rom_attr = rom_attr; @@ -695,4 +696,4 @@ static int __init pci_sysfs_init(void) return 0; } -__initcall(pci_sysfs_init); +late_initcall(pci_sysfs_init); From 6ba186361ed2cda7e174856a3ab8a8e3237b3c3d Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Sat, 7 Apr 2007 17:21:28 +0200 Subject: [PATCH 10/59] PCI: Require vendor and device for new_id Currently, there is no minimum number of fields required when adding a new device ID to a PCI driver through the new_id sysfs file. It is possible to add a new ID with only the vendor ID set, causing the driver to attempt to attach to all PCI devices from that vendor. This has been reported to happen accidentally: http://lists.lm-sensors.org/pipermail/lm-sensors/2007-March/019366.html It is even possible to not even set the vendor ID field, causing the driver to attempt to attach to _all_ the PCI devices. This sounds dangerous and I fail to see any valid use of this "feature". Thus I suggest that we now require at least the first two fields (vendor ID and device ID) to be set. For what it's worth, this is what the USB subsystem does. Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- Documentation/pci.txt | 6 +++--- drivers/pci/pci-driver.c | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Documentation/pci.txt b/Documentation/pci.txt index cdf2f3c0ab14..a8ded1a8bd62 100644 --- a/Documentation/pci.txt +++ b/Documentation/pci.txt @@ -163,9 +163,9 @@ echo "vendor device subvendor subdevice class class_mask driver_data" > \ /sys/bus/pci/drivers/{driver}/new_id All fields are passed in as hexadecimal values (no leading 0x). -Users need pass only as many fields as necessary: - o vendor, device, subvendor, and subdevice fields default - to PCI_ANY_ID (FFFFFFFF), +The vendor and device fields are mandatory, the others are optional. Users +need pass only as many optional fields as necessary: + o subvendor and subdevice fields default to PCI_ANY_ID (FFFFFFFF) o class and classmask fields default to 0 o driver_data defaults to 0UL. diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c index 39e80fcef4b3..07fdb3cd6172 100644 --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c @@ -52,7 +52,7 @@ store_new_id(struct device_driver *driver, const char *buf, size_t count) { struct pci_dynid *dynid; struct pci_driver *pdrv = to_pci_driver(driver); - __u32 vendor=PCI_ANY_ID, device=PCI_ANY_ID, subvendor=PCI_ANY_ID, + __u32 vendor, device, subvendor=PCI_ANY_ID, subdevice=PCI_ANY_ID, class=0, class_mask=0; unsigned long driver_data=0; int fields=0; @@ -61,7 +61,7 @@ store_new_id(struct device_driver *driver, const char *buf, size_t count) fields = sscanf(buf, "%x %x %x %x %x %x %lux", &vendor, &device, &subvendor, &subdevice, &class, &class_mask, &driver_data); - if (fields < 0) + if (fields < 2) return -EINVAL; dynid = kzalloc(sizeof(*dynid), GFP_KERNEL); From 96bde06a2df1b363206d3cdef53134b84ff37813 Mon Sep 17 00:00:00 2001 From: Sam Ravnborg Date: Mon, 26 Mar 2007 21:53:30 -0800 Subject: [PATCH 11/59] pci: do not mark exported functions as __devinit Functions marked __devinit will be removed after kernel init. But being exported they are potentially called by a module much later. So the safer choice seems to be to keep the function even in the non CONFIG_HOTPLUG case. This silence the follwoing section mismatch warnings: WARNING: drivers/built-in.o - Section mismatch: reference to .init.text:pci_bus_add_device from __ksymtab_gpl between '__ksymtab_pci_bus_add_device' (at offset 0x20) and '__ksymtab_pci_walk_bus' WARNING: drivers/built-in.o - Section mismatch: reference to .init.text:pci_create_bus from __ksymtab_gpl between '__ksymtab_pci_create_bus' (at offset 0x40) and '__ksymtab_pci_stop_bus_device' WARNING: drivers/built-in.o - Section mismatch: reference to .init.text:pci_bus_max_busnr from __ksymtab_gpl between '__ksymtab_pci_bus_max_busnr' (at offset 0xc0) and '__ksymtab_pci_assign_resource_fixed' WARNING: drivers/built-in.o - Section mismatch: reference to .init.text:pci_claim_resource from __ksymtab_gpl between '__ksymtab_pci_claim_resource' (at offset 0xe0) and '__ksymtab_pcie_port_bus_type' WARNING: drivers/built-in.o - Section mismatch: reference to .init.text:pci_bus_add_devices from __ksymtab between '__ksymtab_pci_bus_add_devices' (at offset 0x70) and '__ksymtab_pci_bus_alloc_resource' WARNING: drivers/built-in.o - Section mismatch: reference to .init.text:pci_scan_bus_parented from __ksymtab between '__ksymtab_pci_scan_bus_parented' (at offset 0x90) and '__ksymtab_pci_root_buses' WARNING: drivers/built-in.o - Section mismatch: reference to .init.text:pci_bus_assign_resources from __ksymtab between '__ksymtab_pci_bus_assign_resources' (at offset 0x4d0) and '__ksymtab_pci_bus_size_bridges' WARNING: drivers/built-in.o - Section mismatch: reference to .init.text:pci_bus_size_bridges from __ksymtab between '__ksymtab_pci_bus_size_bridges' (at offset 0x4e0) and '__ksymtab_pci_setup_cardbus' Signed-off-by: Sam Ravnborg Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- drivers/pci/bus.c | 4 ++-- drivers/pci/pci.c | 3 +-- drivers/pci/probe.c | 23 +++++++++++------------ drivers/pci/search.c | 3 +-- drivers/pci/setup-bus.c | 21 +++++++-------------- drivers/pci/setup-res.c | 6 ++---- 6 files changed, 24 insertions(+), 36 deletions(-) diff --git a/drivers/pci/bus.c b/drivers/pci/bus.c index aadaa3c8096b..9e5ea074ad20 100644 --- a/drivers/pci/bus.c +++ b/drivers/pci/bus.c @@ -77,7 +77,7 @@ pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res, * This adds a single pci device to the global * device list and adds sysfs and procfs entries */ -int __devinit pci_bus_add_device(struct pci_dev *dev) +int pci_bus_add_device(struct pci_dev *dev) { int retval; retval = device_add(&dev->dev); @@ -105,7 +105,7 @@ int __devinit pci_bus_add_device(struct pci_dev *dev) * * Call hotplug for each new devices. */ -void __devinit pci_bus_add_devices(struct pci_bus *bus) +void pci_bus_add_devices(struct pci_bus *bus) { struct pci_dev *dev; int retval; diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 7bd8a725bea2..fd47ac0c4730 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -35,8 +35,7 @@ unsigned long pci_cardbus_mem_size = DEFAULT_CARDBUS_MEM_SIZE; * Given a PCI bus, returns the highest PCI bus number present in the set * including the given PCI bus and its list of child PCI buses. */ -unsigned char __devinit -pci_bus_max_busnr(struct pci_bus* bus) +unsigned char pci_bus_max_busnr(struct pci_bus* bus) { struct list_head *tmp; unsigned char max, n; diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 2fe1d690eb13..629edf39a07d 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -364,7 +364,7 @@ void __devinit pci_read_bridge_bases(struct pci_bus *child) } } -static struct pci_bus * __devinit pci_alloc_bus(void) +static struct pci_bus * pci_alloc_bus(void) { struct pci_bus *b; @@ -432,7 +432,7 @@ error_register: return NULL; } -struct pci_bus * __devinit pci_add_new_bus(struct pci_bus *parent, struct pci_dev *dev, int busnr) +struct pci_bus *pci_add_new_bus(struct pci_bus *parent, struct pci_dev *dev, int busnr) { struct pci_bus *child; @@ -461,7 +461,7 @@ static void pci_enable_crs(struct pci_dev *dev) pci_write_config_word(dev, rpcap + PCI_EXP_RTCTL, rpctl); } -static void __devinit pci_fixup_parent_subordinate_busnr(struct pci_bus *child, int max) +static void pci_fixup_parent_subordinate_busnr(struct pci_bus *child, int max) { struct pci_bus *parent = child->parent; @@ -477,7 +477,7 @@ static void __devinit pci_fixup_parent_subordinate_busnr(struct pci_bus *child, } } -unsigned int __devinit pci_scan_child_bus(struct pci_bus *bus); +unsigned int pci_scan_child_bus(struct pci_bus *bus); /* * If it's a bridge, configure it and scan the bus behind it. @@ -489,7 +489,7 @@ unsigned int __devinit pci_scan_child_bus(struct pci_bus *bus); * them, we proceed to assigning numbers to the remaining buses in * order to avoid overlaps between old and new bus numbers. */ -int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max, int pass) +int pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max, int pass) { struct pci_bus *child; int is_cardbus = (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS); @@ -912,7 +912,7 @@ pci_scan_device(struct pci_bus *bus, int devfn) return dev; } -void __devinit pci_device_add(struct pci_dev *dev, struct pci_bus *bus) +void pci_device_add(struct pci_dev *dev, struct pci_bus *bus) { device_initialize(&dev->dev); dev->dev.release = pci_release_dev; @@ -935,8 +935,7 @@ void __devinit pci_device_add(struct pci_dev *dev, struct pci_bus *bus) up_write(&pci_bus_sem); } -struct pci_dev * __devinit -pci_scan_single_device(struct pci_bus *bus, int devfn) +struct pci_dev *pci_scan_single_device(struct pci_bus *bus, int devfn) { struct pci_dev *dev; @@ -958,7 +957,7 @@ pci_scan_single_device(struct pci_bus *bus, int devfn) * discovered devices to the @bus->devices list. New devices * will have an empty dev->global_list head. */ -int __devinit pci_scan_slot(struct pci_bus *bus, int devfn) +int pci_scan_slot(struct pci_bus *bus, int devfn) { int func, nr = 0; int scan_all_fns; @@ -991,7 +990,7 @@ int __devinit pci_scan_slot(struct pci_bus *bus, int devfn) return nr; } -unsigned int __devinit pci_scan_child_bus(struct pci_bus *bus) +unsigned int pci_scan_child_bus(struct pci_bus *bus) { unsigned int devfn, pass, max = bus->secondary; struct pci_dev *dev; @@ -1041,7 +1040,7 @@ unsigned int __devinit pci_do_scan_bus(struct pci_bus *bus) return max; } -struct pci_bus * __devinit pci_create_bus(struct device *parent, +struct pci_bus * pci_create_bus(struct device *parent, int bus, struct pci_ops *ops, void *sysdata) { int error; @@ -1119,7 +1118,7 @@ err_out: } EXPORT_SYMBOL_GPL(pci_create_bus); -struct pci_bus * __devinit pci_scan_bus_parented(struct device *parent, +struct pci_bus *pci_scan_bus_parented(struct device *parent, int bus, struct pci_ops *ops, void *sysdata) { struct pci_bus *b; diff --git a/drivers/pci/search.c b/drivers/pci/search.c index 2dd8681d6b31..b137a27472c7 100644 --- a/drivers/pci/search.c +++ b/drivers/pci/search.c @@ -15,8 +15,7 @@ DECLARE_RWSEM(pci_bus_sem); -static struct pci_bus * -pci_do_find_bus(struct pci_bus* bus, unsigned char busnr) +static struct pci_bus *pci_do_find_bus(struct pci_bus *bus, unsigned char busnr) { struct pci_bus* child; struct list_head *tmp; diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c index 3554f3948814..5ec297d7a5b4 100644 --- a/drivers/pci/setup-bus.c +++ b/drivers/pci/setup-bus.c @@ -36,8 +36,7 @@ #define ROUND_UP(x, a) (((x) + (a) - 1) & ~((a) - 1)) -static void __devinit -pbus_assign_resources_sorted(struct pci_bus *bus) +static void pbus_assign_resources_sorted(struct pci_bus *bus) { struct pci_dev *dev; struct resource *res; @@ -220,8 +219,7 @@ pci_setup_bridge(struct pci_bus *bus) /* Check whether the bridge supports optional I/O and prefetchable memory ranges. If not, the respective base/limit registers must be read-only and read as 0. */ -static void __devinit -pci_bridge_check_ranges(struct pci_bus *bus) +static void pci_bridge_check_ranges(struct pci_bus *bus) { u16 io; u32 pmem; @@ -259,8 +257,7 @@ pci_bridge_check_ranges(struct pci_bus *bus) bus resource of a given type. Note: we intentionally skip the bus resources which have already been assigned (that is, have non-NULL parent resource). */ -static struct resource * __devinit -find_free_bus_resource(struct pci_bus *bus, unsigned long type) +static struct resource *find_free_bus_resource(struct pci_bus *bus, unsigned long type) { int i; struct resource *r; @@ -281,8 +278,7 @@ find_free_bus_resource(struct pci_bus *bus, unsigned long type) since these windows have 4K granularity and the IO ranges of non-bridge PCI devices are limited to 256 bytes. We must be careful with the ISA aliasing though. */ -static void __devinit -pbus_size_io(struct pci_bus *bus) +static void pbus_size_io(struct pci_bus *bus) { struct pci_dev *dev; struct resource *b_res = find_free_bus_resource(bus, IORESOURCE_IO); @@ -326,8 +322,7 @@ pbus_size_io(struct pci_bus *bus) /* Calculate the size of the bus and minimal alignment which guarantees that all child resources fit in this size. */ -static int __devinit -pbus_size_mem(struct pci_bus *bus, unsigned long mask, unsigned long type) +static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, unsigned long type) { struct pci_dev *dev; unsigned long min_align, align, size; @@ -447,8 +442,7 @@ pci_bus_size_cardbus(struct pci_bus *bus) } } -void __devinit -pci_bus_size_bridges(struct pci_bus *bus) +void pci_bus_size_bridges(struct pci_bus *bus) { struct pci_dev *dev; unsigned long mask, prefmask; @@ -498,8 +492,7 @@ pci_bus_size_bridges(struct pci_bus *bus) } EXPORT_SYMBOL(pci_bus_size_bridges); -void __devinit -pci_bus_assign_resources(struct pci_bus *bus) +void pci_bus_assign_resources(struct pci_bus *bus) { struct pci_bus *b; struct pci_dev *dev; diff --git a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c index cb4ced3560e9..6dfd86167e39 100644 --- a/drivers/pci/setup-res.c +++ b/drivers/pci/setup-res.c @@ -101,8 +101,7 @@ pci_update_resource(struct pci_dev *dev, struct resource *res, int resno) new & ~PCI_REGION_FLAG_MASK); } -int __devinit -pci_claim_resource(struct pci_dev *dev, int resource) +int pci_claim_resource(struct pci_dev *dev, int resource) { struct resource *res = &dev->resource[resource]; struct resource *root = NULL; @@ -212,8 +211,7 @@ EXPORT_SYMBOL_GPL(pci_assign_resource_fixed); #endif /* Sort resources by alignment */ -void __devinit -pdev_sort_resources(struct pci_dev *dev, struct resource_list *head) +void pdev_sort_resources(struct pci_dev *dev, struct resource_list *head) { int i; From 0da0ead90122578ef6e4afba9ba4bcd3455fd8e8 Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Sun, 1 Apr 2007 21:13:58 +0400 Subject: [PATCH 12/59] PCI: define pci_request/release_regions() for CONFIG_PCI=n Balance declarations of pci_request_regions() and pci_release_regions() with empty inline definitions for the CONFIG_PCI=n case -- otherwise my patch to drivers/net/3c59x.c in the -mm tree doesn't compile. :-) Signed-off-by: Sergei Shtylyov Signed-off-by: Greg Kroah-Hartman --- include/linux/pci.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/include/linux/pci.h b/include/linux/pci.h index 3aba02a04792..99d45751830c 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -744,6 +744,9 @@ static inline int pci_set_power_state(struct pci_dev *dev, pci_power_t state) { static inline pci_power_t pci_choose_state(struct pci_dev *dev, pm_message_t state) { return PCI_D0; } static inline int pci_enable_wake(struct pci_dev *dev, pci_power_t state, int enable) { return 0; } +static inline int pci_request_regions(struct pci_dev *dev, const char *res_name) { return -EIO; } +static inline void pci_release_regions(struct pci_dev *dev) { } + #define pci_dma_burst_advice(pdev, strat, strategy_parameter) do { } while (0) static inline void pci_block_user_cfg_access(struct pci_dev *dev) { } From 54eee4c5bf553ad54ba200d00487b61eb6b155f6 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Wed, 4 Apr 2007 21:35:39 -0700 Subject: [PATCH 13/59] PCI Documentation: power/pci.txt fix copy/paste error Correct function name copy-paste error. Signed-off-by: Randy Dunlap Signed-off-by: Greg Kroah-Hartman --- Documentation/power/pci.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/power/pci.txt b/Documentation/power/pci.txt index b6a3cbf7e846..e00b099a4b86 100644 --- a/Documentation/power/pci.txt +++ b/Documentation/power/pci.txt @@ -203,7 +203,7 @@ resume Usage: -if (dev->driver && dev->driver->suspend) +if (dev->driver && dev->driver->resume) dev->driver->resume(dev) The resume callback may be called from any power state, and is always meant to From e387b9eefe89a23245f2446f947529cce5d6db35 Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Thu, 22 Mar 2007 21:51:27 +1100 Subject: [PATCH 14/59] MSI: Simplify BUG() handling in pci_disable_msi() Although it might be nice to do a printk before BUG'ing, it's really not necessary, and it complicates the code. Signed-off-by: Michael Ellerman Acked-by: Eric W. Biederman Signed-off-by: Greg Kroah-Hartman --- drivers/pci/msi.c | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index a4ef93ea4c54..9213c57cd968 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c @@ -572,18 +572,15 @@ void pci_disable_msi(struct pci_dev* dev) if (!entry || !entry->dev || entry->msi_attrib.type != PCI_CAP_ID_MSI) { return; } - if (irq_has_action(dev->first_msi_irq)) { - printk(KERN_WARNING "PCI: %s: pci_disable_msi() called without " - "free_irq() on MSI irq %d\n", - pci_name(dev), dev->first_msi_irq); - BUG_ON(irq_has_action(dev->first_msi_irq)); - } else { - default_irq = entry->msi_attrib.default_irq; - msi_free_irq(dev, dev->first_msi_irq); - /* Restore dev->irq to its default pin-assertion irq */ - dev->irq = default_irq; - } + BUG_ON(irq_has_action(dev->first_msi_irq)); + + default_irq = entry->msi_attrib.default_irq; + msi_free_irq(dev, dev->first_msi_irq); + + /* Restore dev->irq to its default pin-assertion irq */ + dev->irq = default_irq; + dev->first_msi_irq = 0; } From 54bc6c0b0edd164fc2ea85b3964736c182f6bd5d Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Thu, 22 Mar 2007 21:51:27 +1100 Subject: [PATCH 15/59] MSI: Simplify BUG() handling in pci_disable_msix() Although it might be nice to do a printk before BUG'ing, it's really not necessary, and it complicates the code. The behaviour has changed slightly, in that before we set a flag if the irq had an action, and continued freeing the other irqs. But as I see it that's all irrelevant because we end up BUG'ing anyway. Signed-off-by: Michael Ellerman Acked-by: Eric W. Biederman Signed-off-by: Greg Kroah-Hartman --- drivers/pci/msi.c | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index 9213c57cd968..db452319be90 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c @@ -676,7 +676,7 @@ int pci_enable_msix(struct pci_dev* dev, struct msix_entry *entries, int nvec) void pci_disable_msix(struct pci_dev* dev) { - int irq, head, tail = 0, warning = 0; + int irq, head, tail = 0; if (!pci_msi_enable) return; @@ -693,19 +693,14 @@ void pci_disable_msix(struct pci_dev* dev) irq = head = dev->first_msi_irq; while (head != tail) { tail = get_irq_msi(irq)->link.tail; - if (irq_has_action(irq)) - warning = 1; - else if (irq != head) /* Release MSI-X irq */ + + BUG_ON(irq_has_action(irq)); + + if (irq != head) /* Release MSI-X irq */ msi_free_irq(dev, irq); irq = tail; } msi_free_irq(dev, irq); - if (warning) { - printk(KERN_WARNING "PCI: %s: pci_disable_msix() called without " - "free_irq() on all MSI-X irqs\n", - pci_name(dev)); - BUG_ON(warning > 0); - } dev->first_msi_irq = 0; } From c31af3987020eeb1facf64d702dcf39e6c7382e6 Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Thu, 22 Mar 2007 21:51:31 +1100 Subject: [PATCH 16/59] MSI: Simplify BUG() handling in msi_remove_pci_irq_vectors() part 1 Although it might be nice to do a printk before BUG'ing, it's really not necessary, and it complicates the code. Signed-off-by: Michael Ellerman Acked-by: Eric W. Biederman Signed-off-by: Greg Kroah-Hartman --- drivers/pci/msi.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index db452319be90..2a119f8d0dc6 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c @@ -719,13 +719,8 @@ void msi_remove_pci_irq_vectors(struct pci_dev* dev) return; if (dev->msi_enabled) { - if (irq_has_action(dev->first_msi_irq)) { - printk(KERN_WARNING "PCI: %s: msi_remove_pci_irq_vectors() " - "called without free_irq() on MSI irq %d\n", - pci_name(dev), dev->first_msi_irq); - BUG_ON(irq_has_action(dev->first_msi_irq)); - } else /* Release MSI irq assigned to this device */ - msi_free_irq(dev, dev->first_msi_irq); + BUG_ON(irq_has_action(dev->first_msi_irq)); + msi_free_irq(dev, dev->first_msi_irq); } if (dev->msix_enabled) { int irq, head, tail = 0, warning = 0; From 00ba16ab2658afe11d4fdcaf16a331292c44bee6 Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Thu, 22 Mar 2007 21:51:31 +1100 Subject: [PATCH 17/59] MSI: Simplify BUG() handling in msi_remove_pci_irq_vectors() part 2 Although it might be nice to do a printk before BUG'ing, it's really not necessary, and it complicates the code. The behaviour has changed slightly, in that before we set a flag if the irq had an action, and continued freeing the other irqs. But as I see it that's all irrelevant because we end up BUG'ing anyway. Signed-off-by: Michael Ellerman Acked-by: Eric W. Biederman Signed-off-by: Greg Kroah-Hartman --- drivers/pci/msi.c | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index 2a119f8d0dc6..91fed543fc84 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c @@ -723,27 +723,21 @@ void msi_remove_pci_irq_vectors(struct pci_dev* dev) msi_free_irq(dev, dev->first_msi_irq); } if (dev->msix_enabled) { - int irq, head, tail = 0, warning = 0; + int irq, head, tail = 0; void __iomem *base = NULL; irq = head = dev->first_msi_irq; while (head != tail) { tail = get_irq_msi(irq)->link.tail; base = get_irq_msi(irq)->mask_base; - if (irq_has_action(irq)) - warning = 1; - else if (irq != head) /* Release MSI-X irq */ + + BUG_ON(irq_has_action(irq)); + + if (irq != head) /* Release MSI-X irq */ msi_free_irq(dev, irq); irq = tail; } msi_free_irq(dev, irq); - if (warning) { - iounmap(base); - printk(KERN_WARNING "PCI: %s: msi_remove_pci_irq_vectors() " - "called without free_irq() on all MSI-X irqs\n", - pci_name(dev)); - BUG_ON(warning > 0); - } } } From fc4afc7b2bdd81e2dbded5a8222676d3161758d3 Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Thu, 22 Mar 2007 21:51:33 +1100 Subject: [PATCH 18/59] MSI: Consolidate MSI-X irq freeing code For the MSI-X case we do exactly the same logic in pci_disable_msix() and msi_remove_pci_irq_vectors(), so consolidate them. msi_remove_pci_irq_vectors() wasn't setting dev->first_msi_irq to 0, but I think it should have been, so the consolidated version does. Signed-off-by: Michael Ellerman Acked-by: Eric W. Biederman Signed-off-by: Greg Kroah-Hartman --- drivers/pci/msi.c | 49 +++++++++++++++++++---------------------------- 1 file changed, 20 insertions(+), 29 deletions(-) diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index 91fed543fc84..4f326f38f9bf 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c @@ -674,10 +674,26 @@ int pci_enable_msix(struct pci_dev* dev, struct msix_entry *entries, int nvec) return status; } -void pci_disable_msix(struct pci_dev* dev) +static void msix_free_all_irqs(struct pci_dev *dev) { int irq, head, tail = 0; + irq = head = dev->first_msi_irq; + while (head != tail) { + tail = get_irq_msi(irq)->link.tail; + + BUG_ON(irq_has_action(irq)); + + if (irq != head) + msi_free_irq(dev, irq); + irq = tail; + } + msi_free_irq(dev, irq); + dev->first_msi_irq = 0; +} + +void pci_disable_msix(struct pci_dev* dev) +{ if (!pci_msi_enable) return; if (!dev) @@ -690,18 +706,7 @@ void pci_disable_msix(struct pci_dev* dev) pci_intx(dev, 1); /* enable intx */ dev->msix_enabled = 0; - irq = head = dev->first_msi_irq; - while (head != tail) { - tail = get_irq_msi(irq)->link.tail; - - BUG_ON(irq_has_action(irq)); - - if (irq != head) /* Release MSI-X irq */ - msi_free_irq(dev, irq); - irq = tail; - } - msi_free_irq(dev, irq); - dev->first_msi_irq = 0; + msix_free_all_irqs(dev); } /** @@ -722,23 +727,9 @@ void msi_remove_pci_irq_vectors(struct pci_dev* dev) BUG_ON(irq_has_action(dev->first_msi_irq)); msi_free_irq(dev, dev->first_msi_irq); } - if (dev->msix_enabled) { - int irq, head, tail = 0; - void __iomem *base = NULL; - irq = head = dev->first_msi_irq; - while (head != tail) { - tail = get_irq_msi(irq)->link.tail; - base = get_irq_msi(irq)->mask_base; - - BUG_ON(irq_has_action(irq)); - - if (irq != head) /* Release MSI-X irq */ - msi_free_irq(dev, irq); - irq = tail; - } - msi_free_irq(dev, irq); - } + if (dev->msix_enabled) + msix_free_all_irqs(dev); } void pci_no_msi(void) From 7ede9c1fa50e01a8222217d4606bcbc44cd68f1a Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Thu, 22 Mar 2007 21:51:34 +1100 Subject: [PATCH 19/59] MSI: Consolidate BUG_ON()s. When freeing MSIs and MSI-Xs, we BUG_ON() if the irq has not been freed, ie. if it still has an action. We can consolidate all of these BUG_ON()s into msi_free_irqs() as all the code paths lead there almost immediately anyway. Signed-off-by: Michael Ellerman Acked-by: Eric W. Biederman Signed-off-by: Greg Kroah-Hartman --- drivers/pci/msi.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index 4f326f38f9bf..38e4c807f80f 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c @@ -573,8 +573,6 @@ void pci_disable_msi(struct pci_dev* dev) return; } - BUG_ON(irq_has_action(dev->first_msi_irq)); - default_irq = entry->msi_attrib.default_irq; msi_free_irq(dev, dev->first_msi_irq); @@ -590,6 +588,8 @@ static int msi_free_irq(struct pci_dev* dev, int irq) int head, entry_nr, type; void __iomem *base; + BUG_ON(irq_has_action(irq)); + entry = get_irq_msi(irq); if (!entry || entry->dev != dev) { return -EINVAL; @@ -682,8 +682,6 @@ static void msix_free_all_irqs(struct pci_dev *dev) while (head != tail) { tail = get_irq_msi(irq)->link.tail; - BUG_ON(irq_has_action(irq)); - if (irq != head) msi_free_irq(dev, irq); irq = tail; @@ -723,10 +721,8 @@ void msi_remove_pci_irq_vectors(struct pci_dev* dev) if (!pci_msi_enable || !dev) return; - if (dev->msi_enabled) { - BUG_ON(irq_has_action(dev->first_msi_irq)); + if (dev->msi_enabled) msi_free_irq(dev, dev->first_msi_irq); - } if (dev->msix_enabled) msix_free_all_irqs(dev); From 4cc086fa5b648dc3dcd56c963e42a212f2d9df29 Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Thu, 22 Mar 2007 21:51:34 +1100 Subject: [PATCH 20/59] MSI: Move EXPORT_SYMBOL()s near their definition Move EXPORT_SYMBOL()s near their definition. Signed-off-by: Michael Ellerman Acked-by: Eric W. Biederman Signed-off-by: Greg Kroah-Hartman --- drivers/pci/msi.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index 38e4c807f80f..a2002e7dc188 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c @@ -550,6 +550,7 @@ int pci_enable_msi(struct pci_dev* dev) status = msi_capability_init(dev); return status; } +EXPORT_SYMBOL(pci_enable_msi); void pci_disable_msi(struct pci_dev* dev) { @@ -581,6 +582,7 @@ void pci_disable_msi(struct pci_dev* dev) dev->first_msi_irq = 0; } +EXPORT_SYMBOL(pci_disable_msi); static int msi_free_irq(struct pci_dev* dev, int irq) { @@ -673,6 +675,7 @@ int pci_enable_msix(struct pci_dev* dev, struct msix_entry *entries, int nvec) status = msix_capability_init(dev, entries, nvec); return status; } +EXPORT_SYMBOL(pci_enable_msix); static void msix_free_all_irqs(struct pci_dev *dev) { @@ -706,6 +709,7 @@ void pci_disable_msix(struct pci_dev* dev) msix_free_all_irqs(dev); } +EXPORT_SYMBOL(pci_disable_msix); /** * msi_remove_pci_irq_vectors - reclaim MSI(X) irqs to unused state @@ -732,8 +736,3 @@ void pci_no_msi(void) { pci_msi_enable = 0; } - -EXPORT_SYMBOL(pci_enable_msi); -EXPORT_SYMBOL(pci_disable_msi); -EXPORT_SYMBOL(pci_enable_msix); -EXPORT_SYMBOL(pci_disable_msix); From 3e916c0503a34ba32202a69df1cfeb82f2c5749d Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Thu, 22 Mar 2007 21:51:36 +1100 Subject: [PATCH 21/59] MSI: Remove msi_cache We don't need a special cache just for msi descriptors. They're not particularly large, under 100 bytes for sure, and don't seem to require any special alignment etc. On most systems there will be relatively few MSIs, and hence we waste most of a page on the cache. Better to just kzalloc the space for the few we do need. Signed-off-by: Michael Ellerman Acked-by: Eric W. Biederman Signed-off-by: Greg Kroah-Hartman --- drivers/pci/msi.c | 44 ++++---------------------------------------- 1 file changed, 4 insertions(+), 40 deletions(-) diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index a2002e7dc188..762bff18187d 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c @@ -24,20 +24,8 @@ #include "pci.h" #include "msi.h" -static struct kmem_cache* msi_cachep; - static int pci_msi_enable = 1; -static int msi_cache_init(void) -{ - msi_cachep = kmem_cache_create("msi_cache", sizeof(struct msi_desc), - 0, SLAB_HWCACHE_ALIGN, NULL, NULL); - if (!msi_cachep) - return -ENOMEM; - - return 0; -} - static void msi_set_enable(struct pci_dev *dev, int enable) { int pos; @@ -221,28 +209,12 @@ void unmask_msi_irq(unsigned int irq) static int msi_free_irq(struct pci_dev* dev, int irq); -static int msi_init(void) -{ - static int status = -ENOMEM; - - if (!status) - return status; - - status = msi_cache_init(); - if (status < 0) { - pci_msi_enable = 0; - printk(KERN_WARNING "PCI: MSI cache init failed\n"); - return status; - } - - return status; -} static struct msi_desc* alloc_msi_entry(void) { struct msi_desc *entry; - entry = kmem_cache_zalloc(msi_cachep, GFP_KERNEL); + entry = kzalloc(sizeof(struct msi_desc), GFP_KERNEL); if (!entry) return NULL; @@ -368,7 +340,7 @@ static int msi_capability_init(struct pci_dev *dev) /* Configure MSI capability structure */ irq = arch_setup_msi_irq(dev, entry); if (irq < 0) { - kmem_cache_free(msi_cachep, entry); + kfree(entry); return irq; } entry->link.head = irq; @@ -441,7 +413,7 @@ static int msix_capability_init(struct pci_dev *dev, /* Configure MSI-X capability structure */ irq = arch_setup_msi_irq(dev, entry); if (irq < 0) { - kmem_cache_free(msi_cachep, entry); + kfree(entry); break; } entries[i].vector = irq; @@ -530,10 +502,6 @@ int pci_enable_msi(struct pci_dev* dev) if (pci_msi_supported(dev) < 0) return -EINVAL; - status = msi_init(); - if (status < 0) - return status; - pos = pci_find_capability(dev, PCI_CAP_ID_MSI); if (!pos) return -EINVAL; @@ -604,7 +572,7 @@ static int msi_free_irq(struct pci_dev* dev, int irq) get_irq_msi(entry->link.tail)->link.head = entry->link.head; arch_teardown_msi_irq(irq); - kmem_cache_free(msi_cachep, entry); + kfree(entry); if (type == PCI_CAP_ID_MSIX) { writel(1, base + entry_nr * PCI_MSIX_ENTRY_SIZE + @@ -641,10 +609,6 @@ int pci_enable_msix(struct pci_dev* dev, struct msix_entry *entries, int nvec) if (!entries || pci_msi_supported(dev) < 0) return -EINVAL; - status = msi_init(); - if (status < 0) - return status; - pos = pci_find_capability(dev, PCI_CAP_ID_MSIX); if (!pos) return -EINVAL; From b1e2303dba021ee417c65a89e467a2b145ff9217 Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Thu, 22 Mar 2007 21:51:39 +1100 Subject: [PATCH 22/59] MSI: Expand pci_msi_supported() pci_enable_msi() and pci_enable_msix() both search for the MSI/MSI-X capability, we can fold this into pci_msi_supported() by passing the type in. Update the code to match the comment for pci_msi_supported(). That is it returns 0 on success, and anything else indicates an error. Signed-off-by: Michael Ellerman Signed-off-by: Greg Kroah-Hartman --- drivers/pci/msi.c | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index 762bff18187d..d5b9b94a2ac5 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c @@ -459,12 +459,13 @@ static int msix_capability_init(struct pci_dev *dev, /** * pci_msi_supported - check whether MSI may be enabled on device * @dev: pointer to the pci_dev data structure of MSI device function + * @type: are we checking for MSI or MSI-X ? * * Look at global flags, the device itself, and its parent busses * to return 0 if MSI are supported for the device. **/ static -int pci_msi_supported(struct pci_dev * dev) +int pci_msi_supported(struct pci_dev * dev, int type) { struct pci_bus *bus; @@ -482,6 +483,9 @@ int pci_msi_supported(struct pci_dev * dev) if (bus->bus_flags & PCI_BUS_FLAGS_NO_MSI) return -EINVAL; + if (!pci_find_capability(dev, type)) + return -EINVAL; + return 0; } @@ -497,13 +501,9 @@ int pci_msi_supported(struct pci_dev * dev) **/ int pci_enable_msi(struct pci_dev* dev) { - int pos, status; + int status; - if (pci_msi_supported(dev) < 0) - return -EINVAL; - - pos = pci_find_capability(dev, PCI_CAP_ID_MSI); - if (!pos) + if (pci_msi_supported(dev, PCI_CAP_ID_MSI)) return -EINVAL; WARN_ON(!!dev->msi_enabled); @@ -606,13 +606,10 @@ int pci_enable_msix(struct pci_dev* dev, struct msix_entry *entries, int nvec) int i, j; u16 control; - if (!entries || pci_msi_supported(dev) < 0) + if (!entries || pci_msi_supported(dev, PCI_CAP_ID_MSIX)) return -EINVAL; pos = pci_find_capability(dev, PCI_CAP_ID_MSIX); - if (!pos) - return -EINVAL; - pci_read_config_word(dev, msi_control_reg(pos), &control); nr_entries = multi_msix_capable(control); if (nvec > nr_entries) From 128bc5fced238752d01b5169077f2ec624b3d59b Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Thu, 22 Mar 2007 21:51:39 +1100 Subject: [PATCH 23/59] MSI: Consolidate precondition checks Consolidate precondition checks into a single if statement. Signed-off-by: Michael Ellerman Acked-by: Eric W. Biederman Signed-off-by: Greg Kroah-Hartman --- drivers/pci/msi.c | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index d5b9b94a2ac5..b6dc69ef80a7 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c @@ -525,12 +525,7 @@ void pci_disable_msi(struct pci_dev* dev) struct msi_desc *entry; int default_irq; - if (!pci_msi_enable) - return; - if (!dev) - return; - - if (!dev->msi_enabled) + if (!pci_msi_enable || !dev || !dev->msi_enabled) return; msi_set_enable(dev, 0); @@ -656,12 +651,7 @@ static void msix_free_all_irqs(struct pci_dev *dev) void pci_disable_msix(struct pci_dev* dev) { - if (!pci_msi_enable) - return; - if (!dev) - return; - - if (!dev->msix_enabled) + if (!pci_msi_enable || !dev || !dev->msix_enabled) return; msix_set_enable(dev, 0); From 17bbc12acdb23ffb9613e12ca974fafd31bfcb56 Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Thu, 5 Apr 2007 17:19:07 +1000 Subject: [PATCH 24/59] MSI: Rename pci_msi_supported() to pci_msi_check_device() As pointed out by Eric, the name pci_msi_supported() suggests it should return a boolean value, however it doesn't. So update the name to be a bit less confusing and update the doco too. Signed-off-by: Michael Ellerman Signed-off-by: Greg Kroah-Hartman --- drivers/pci/msi.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index b6dc69ef80a7..34087af68833 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c @@ -457,15 +457,15 @@ static int msix_capability_init(struct pci_dev *dev, } /** - * pci_msi_supported - check whether MSI may be enabled on device + * pci_msi_check_device - check whether MSI may be enabled on a device * @dev: pointer to the pci_dev data structure of MSI device function * @type: are we checking for MSI or MSI-X ? * * Look at global flags, the device itself, and its parent busses - * to return 0 if MSI are supported for the device. + * to determine if MSI/-X are supported for the device. If MSI/-X is + * supported return 0, else return an error code. **/ -static -int pci_msi_supported(struct pci_dev * dev, int type) +static int pci_msi_check_device(struct pci_dev * dev, int type) { struct pci_bus *bus; @@ -503,7 +503,7 @@ int pci_enable_msi(struct pci_dev* dev) { int status; - if (pci_msi_supported(dev, PCI_CAP_ID_MSI)) + if (pci_msi_check_device(dev, PCI_CAP_ID_MSI)) return -EINVAL; WARN_ON(!!dev->msi_enabled); @@ -601,7 +601,7 @@ int pci_enable_msix(struct pci_dev* dev, struct msix_entry *entries, int nvec) int i, j; u16 control; - if (!entries || pci_msi_supported(dev, PCI_CAP_ID_MSIX)) + if (!entries || pci_msi_check_device(dev, PCI_CAP_ID_MSIX)) return -EINVAL; pos = pci_find_capability(dev, PCI_CAP_ID_MSIX); From c9953a73e92df11edd812d863ff741877ea9e58c Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Thu, 5 Apr 2007 17:19:08 +1000 Subject: [PATCH 25/59] MSI: Add an arch_msi_check_device() Add an arch_check_device(), which gives archs a chance to check the input to pci_enable_msi/x. The arch might be interested in the value of nvec so pass it in. Propagate the error value returned from the arch routine out to the caller. Signed-off-by: Michael Ellerman Signed-off-by: Greg Kroah-Hartman --- drivers/pci/msi.c | 29 +++++++++++++++++++++++++---- include/linux/msi.h | 1 + 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index 34087af68833..5902c00f4fce 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c @@ -459,15 +459,17 @@ static int msix_capability_init(struct pci_dev *dev, /** * pci_msi_check_device - check whether MSI may be enabled on a device * @dev: pointer to the pci_dev data structure of MSI device function + * @nvec: how many MSIs have been requested ? * @type: are we checking for MSI or MSI-X ? * * Look at global flags, the device itself, and its parent busses * to determine if MSI/-X are supported for the device. If MSI/-X is * supported return 0, else return an error code. **/ -static int pci_msi_check_device(struct pci_dev * dev, int type) +static int pci_msi_check_device(struct pci_dev* dev, int nvec, int type) { struct pci_bus *bus; + int ret; /* MSI must be globally enabled and supported by the device */ if (!pci_msi_enable || !dev || dev->no_msi) @@ -483,6 +485,10 @@ static int pci_msi_check_device(struct pci_dev * dev, int type) if (bus->bus_flags & PCI_BUS_FLAGS_NO_MSI) return -EINVAL; + ret = arch_msi_check_device(dev, nvec, type); + if (ret) + return ret; + if (!pci_find_capability(dev, type)) return -EINVAL; @@ -503,8 +509,9 @@ int pci_enable_msi(struct pci_dev* dev) { int status; - if (pci_msi_check_device(dev, PCI_CAP_ID_MSI)) - return -EINVAL; + status = pci_msi_check_device(dev, 1, PCI_CAP_ID_MSI); + if (status) + return status; WARN_ON(!!dev->msi_enabled); @@ -601,9 +608,13 @@ int pci_enable_msix(struct pci_dev* dev, struct msix_entry *entries, int nvec) int i, j; u16 control; - if (!entries || pci_msi_check_device(dev, PCI_CAP_ID_MSIX)) + if (!entries) return -EINVAL; + status = pci_msi_check_device(dev, nvec, PCI_CAP_ID_MSIX); + if (status) + return status; + pos = pci_find_capability(dev, PCI_CAP_ID_MSIX); pci_read_config_word(dev, msi_control_reg(pos), &control); nr_entries = multi_msix_capable(control); @@ -687,3 +698,13 @@ void pci_no_msi(void) { pci_msi_enable = 0; } + + +/* Arch hooks */ + +int __attribute__ ((weak)) +arch_msi_check_device(struct pci_dev* dev, int nvec, int type) +{ + return 0; +} + diff --git a/include/linux/msi.h b/include/linux/msi.h index e38fe6822cb4..d2a200048b22 100644 --- a/include/linux/msi.h +++ b/include/linux/msi.h @@ -41,6 +41,7 @@ struct msi_desc { */ int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc); void arch_teardown_msi_irq(unsigned int irq); +extern int arch_msi_check_device(struct pci_dev* dev, int nvec, int type); #endif /* LINUX_MSI_H */ From 65891215e6b822c368fb3f36abf129ed48af8be0 Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Thu, 5 Apr 2007 17:19:08 +1000 Subject: [PATCH 26/59] PCI: Create alloc_pci_dev(), the one true way to create a struct pci_dev There are currently several places in the kernel where we kmalloc() a struct pci_dev and start initialising it. It'd be preferable to have an allocator so we can ensure the pci_dev is correctly initialised in one place. Signed-off-by: Michael Ellerman Signed-off-by: Greg Kroah-Hartman --- drivers/pci/probe.c | 15 +++++++++++++++ include/linux/pci.h | 2 ++ 2 files changed, 17 insertions(+) diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 629edf39a07d..70d37bbf09bb 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -846,6 +846,21 @@ static void pci_release_bus_bridge_dev(struct device *dev) kfree(dev); } +struct pci_dev *alloc_pci_dev(void) +{ + struct pci_dev *dev; + + dev = kzalloc(sizeof(struct pci_dev), GFP_KERNEL); + if (!dev) + return NULL; + + INIT_LIST_HEAD(&dev->global_list); + INIT_LIST_HEAD(&dev->bus_list); + + return dev; +} +EXPORT_SYMBOL(alloc_pci_dev); + /* * Read the config data for a PCI device, sanity-check it * and fill in the dev structure... diff --git a/include/linux/pci.h b/include/linux/pci.h index 99d45751830c..c02074785d40 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -193,6 +193,8 @@ struct pci_dev { #endif }; +extern struct pci_dev *alloc_pci_dev(void); + #define pci_dev_g(n) list_entry(n, struct pci_dev, global_list) #define pci_dev_b(n) list_entry(n, struct pci_dev, bus_list) #define to_pci_dev(n) container_of(n, struct pci_dev, dev) From bab41e9be75121c473b00df2ffa33af3c44066a7 Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Thu, 5 Apr 2007 17:19:09 +1000 Subject: [PATCH 27/59] PCI: Convert to alloc_pci_dev() Convert code that allocs a struct pci_dev to use alloc_pci_dev(). Signed-off-by: Michael Ellerman Signed-off-by: Greg Kroah-Hartman --- arch/powerpc/kernel/pci_64.c | 2 +- drivers/char/agp/alpha-agp.c | 2 +- drivers/char/agp/parisc-agp.c | 2 +- drivers/pci/hotplug/fakephp.c | 2 +- drivers/pci/probe.c | 2 +- drivers/scsi/megaraid.c | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c index 60d7d4baa227..7138092826aa 100644 --- a/arch/powerpc/kernel/pci_64.c +++ b/arch/powerpc/kernel/pci_64.c @@ -340,7 +340,7 @@ struct pci_dev *of_create_pci_dev(struct device_node *node, struct pci_dev *dev; const char *type; - dev = kzalloc(sizeof(struct pci_dev), GFP_KERNEL); + dev = alloc_pci_dev(); if (!dev) return NULL; type = of_get_property(node, "device_type", NULL); diff --git a/drivers/char/agp/alpha-agp.c b/drivers/char/agp/alpha-agp.c index b0acf41c0db9..aa8f3a39a704 100644 --- a/drivers/char/agp/alpha-agp.c +++ b/drivers/char/agp/alpha-agp.c @@ -173,7 +173,7 @@ alpha_core_agp_setup(void) /* * Build a fake pci_dev struct */ - pdev = kmalloc(sizeof(struct pci_dev), GFP_KERNEL); + pdev = alloc_pci_dev(); if (!pdev) return -ENOMEM; pdev->vendor = 0xffff; diff --git a/drivers/char/agp/parisc-agp.c b/drivers/char/agp/parisc-agp.c index 3d83b461ccad..f4562cc22343 100644 --- a/drivers/char/agp/parisc-agp.c +++ b/drivers/char/agp/parisc-agp.c @@ -329,7 +329,7 @@ parisc_agp_setup(void __iomem *ioc_hpa, void __iomem *lba_hpa) struct agp_bridge_data *bridge; int error = 0; - fake_bridge_dev = kmalloc(sizeof (struct pci_dev), GFP_KERNEL); + fake_bridge_dev = alloc_pci_dev(); if (!fake_bridge_dev) { error = -ENOMEM; goto fail; diff --git a/drivers/pci/hotplug/fakephp.c b/drivers/pci/hotplug/fakephp.c index e27907c91d92..027f6865d7e3 100644 --- a/drivers/pci/hotplug/fakephp.c +++ b/drivers/pci/hotplug/fakephp.c @@ -238,7 +238,7 @@ static void pci_rescan_bus(const struct pci_bus *bus) { unsigned int devfn; struct pci_dev *dev; - dev = kzalloc(sizeof(struct pci_dev), GFP_KERNEL); + dev = alloc_pci_dev(); if (!dev) return; diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 70d37bbf09bb..c659f8ae441a 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -900,7 +900,7 @@ 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 = kzalloc(sizeof(struct pci_dev), GFP_KERNEL); + dev = alloc_pci_dev(); if (!dev) return NULL; diff --git a/drivers/scsi/megaraid.c b/drivers/scsi/megaraid.c index 0aa3304f6b9b..7fc6e06ea7e1 100644 --- a/drivers/scsi/megaraid.c +++ b/drivers/scsi/megaraid.c @@ -2088,7 +2088,7 @@ megaraid_abort_and_reset(adapter_t *adapter, Scsi_Cmnd *cmd, int aor) static inline int make_local_pdev(adapter_t *adapter, struct pci_dev **pdev) { - *pdev = kmalloc(sizeof(struct pci_dev), GFP_KERNEL); + *pdev = alloc_pci_dev(); if( *pdev == NULL ) return -1; From 4aa9bc955d61fdf03b5f9cee67db188fe1ffa8b7 Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Thu, 5 Apr 2007 17:19:10 +1000 Subject: [PATCH 28/59] MSI: Use a list instead of the custom link structure The msi descriptors are linked together with what looks a lot like a linked list, but isn't a struct list_head list. Make it one. The only complication is that previously we walked a list of irqs, and got the descriptor for each with get_irq_msi(). Now we have a list of descriptors and need to get the irq out of it, so it needs to be in the actual struct msi_desc. We use 0 to indicate no irq is setup. Signed-off-by: Michael Ellerman Signed-off-by: Greg Kroah-Hartman --- drivers/pci/msi.c | 66 +++++++++++++++++---------------------------- drivers/pci/pci.h | 2 ++ drivers/pci/probe.c | 2 ++ include/linux/msi.h | 8 +++--- include/linux/pci.h | 1 + 5 files changed, 33 insertions(+), 46 deletions(-) diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index 5902c00f4fce..434c7182d926 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c @@ -218,7 +218,8 @@ static struct msi_desc* alloc_msi_entry(void) if (!entry) return NULL; - entry->link.tail = entry->link.head = 0; /* single message */ + INIT_LIST_HEAD(&entry->list); + entry->irq = 0; entry->dev = NULL; return entry; @@ -253,7 +254,6 @@ static void __pci_restore_msi_state(struct pci_dev *dev) static void __pci_restore_msix_state(struct pci_dev *dev) { int pos; - int irq, head, tail = 0; struct msi_desc *entry; u16 control; @@ -263,18 +263,14 @@ static void __pci_restore_msix_state(struct pci_dev *dev) /* route the table */ pci_intx(dev, 0); /* disable intx */ msix_set_enable(dev, 0); - irq = head = dev->first_msi_irq; - entry = get_irq_msi(irq); - pos = entry->msi_attrib.pos; - while (head != tail) { - entry = get_irq_msi(irq); - write_msi_msg(irq, &entry->msg); - msi_set_mask_bit(irq, entry->msi_attrib.masked); - tail = entry->link.tail; - irq = tail; + list_for_each_entry(entry, &dev->msi_list, list) { + write_msi_msg(entry->irq, &entry->msg); + msi_set_mask_bit(entry->irq, entry->msi_attrib.masked); } + entry = get_irq_msi(dev->first_msi_irq); + pos = entry->msi_attrib.pos; pci_read_config_word(dev, pos + PCI_MSIX_FLAGS, &control); control &= ~PCI_MSIX_FLAGS_MASKALL; control |= PCI_MSIX_FLAGS_ENABLE; @@ -343,8 +339,8 @@ static int msi_capability_init(struct pci_dev *dev) kfree(entry); return irq; } - entry->link.head = irq; - entry->link.tail = irq; + entry->irq = irq; + list_add(&entry->list, &dev->msi_list); dev->first_msi_irq = irq; set_irq_msi(irq, entry); @@ -370,8 +366,8 @@ static int msi_capability_init(struct pci_dev *dev) static int msix_capability_init(struct pci_dev *dev, struct msix_entry *entries, int nvec) { - struct msi_desc *head = NULL, *tail = NULL, *entry = NULL; - int irq, pos, i, j, nr_entries, temp = 0; + struct msi_desc *entry; + int irq, pos, i, j, nr_entries; unsigned long phys_addr; u32 table_offset; u16 control; @@ -416,19 +412,9 @@ static int msix_capability_init(struct pci_dev *dev, kfree(entry); break; } + entry->irq = irq; entries[i].vector = irq; - if (!head) { - entry->link.head = irq; - entry->link.tail = irq; - head = entry; - } else { - entry->link.head = temp; - entry->link.tail = tail->link.tail; - tail->link.tail = irq; - head->link.head = irq; - } - temp = irq; - tail = entry; + list_add(&entry->list, &dev->msi_list); set_irq_msi(irq, entry); } @@ -557,7 +543,7 @@ EXPORT_SYMBOL(pci_disable_msi); static int msi_free_irq(struct pci_dev* dev, int irq) { struct msi_desc *entry; - int head, entry_nr, type; + int entry_nr, type; void __iomem *base; BUG_ON(irq_has_action(irq)); @@ -568,10 +554,8 @@ static int msi_free_irq(struct pci_dev* dev, int irq) } type = entry->msi_attrib.type; entry_nr = entry->msi_attrib.entry_nr; - head = entry->link.head; base = entry->mask_base; - get_irq_msi(entry->link.head)->link.tail = entry->link.tail; - get_irq_msi(entry->link.tail)->link.head = entry->link.head; + list_del(&entry->list); arch_teardown_msi_irq(irq); kfree(entry); @@ -580,7 +564,7 @@ static int msi_free_irq(struct pci_dev* dev, int irq) writel(1, base + entry_nr * PCI_MSIX_ENTRY_SIZE + PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET); - if (head == irq) + if (list_empty(&dev->msi_list)) iounmap(base); } @@ -646,17 +630,10 @@ EXPORT_SYMBOL(pci_enable_msix); static void msix_free_all_irqs(struct pci_dev *dev) { - int irq, head, tail = 0; + struct msi_desc *entry; - irq = head = dev->first_msi_irq; - while (head != tail) { - tail = get_irq_msi(irq)->link.tail; - - if (irq != head) - msi_free_irq(dev, irq); - irq = tail; - } - msi_free_irq(dev, irq); + list_for_each_entry(entry, &dev->msi_list, list) + msi_free_irq(dev, entry->irq); dev->first_msi_irq = 0; } @@ -699,6 +676,11 @@ void pci_no_msi(void) pci_msi_enable = 0; } +void pci_msi_init_pci_dev(struct pci_dev *dev) +{ + INIT_LIST_HEAD(&dev->msi_list); +} + /* Arch hooks */ diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index 62ea04c8af64..3fec13d3add7 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h @@ -47,8 +47,10 @@ extern unsigned int pci_pm_d3_delay; #ifdef CONFIG_PCI_MSI void pci_no_msi(void); +extern void pci_msi_init_pci_dev(struct pci_dev *dev); #else static inline void pci_no_msi(void) { } +static inline void pci_msi_init_pci_dev(struct pci_dev *dev) { } #endif #if defined(CONFIG_PCI_MSI) && defined(CONFIG_PM) diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index c659f8ae441a..e48fcf089621 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -857,6 +857,8 @@ struct pci_dev *alloc_pci_dev(void) INIT_LIST_HEAD(&dev->global_list); INIT_LIST_HEAD(&dev->bus_list); + pci_msi_init_pci_dev(dev); + return dev; } EXPORT_SYMBOL(alloc_pci_dev); diff --git a/include/linux/msi.h b/include/linux/msi.h index d2a200048b22..931e013f1db5 100644 --- a/include/linux/msi.h +++ b/include/linux/msi.h @@ -1,6 +1,8 @@ #ifndef LINUX_MSI_H #define LINUX_MSI_H +#include + struct msi_msg { u32 address_lo; /* low 32 bits of msi message address */ u32 address_hi; /* high 32 bits of msi message address */ @@ -24,10 +26,8 @@ struct msi_desc { unsigned default_irq; /* default pre-assigned irq */ }msi_attrib; - struct { - __u16 head; - __u16 tail; - }link; + unsigned int irq; + struct list_head list; void __iomem *mask_base; struct pci_dev *dev; diff --git a/include/linux/pci.h b/include/linux/pci.h index c02074785d40..d43097dc8672 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -190,6 +190,7 @@ struct pci_dev { struct bin_attribute *res_attr[DEVICE_COUNT_RESOURCE]; /* sysfs file for resources */ #ifdef CONFIG_PCI_MSI unsigned int first_msi_irq; + struct list_head msi_list; #endif }; From 314e77b3eec57001eaff82b82920150175b74e09 Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Thu, 5 Apr 2007 17:19:12 +1000 Subject: [PATCH 29/59] MSI: Remove dev->first_msi_irq Now that we keep a list of msi descriptors, we don't need first_msi_irq in the pci dev. If we somehow have zero MSIs configured list_entry() will give us weird oopes or nice memory corruption bugs. So be paranoid. Add BUG_ONs and also a check in pci_msi_check_device() to make sure nvec > 0. Signed-off-by: Michael Ellerman Signed-off-by: Greg Kroah-Hartman --- drivers/pci/msi.c | 31 ++++++++++++++++++++----------- include/linux/pci.h | 1 - 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index 434c7182d926..7a44ba467481 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c @@ -269,7 +269,8 @@ static void __pci_restore_msix_state(struct pci_dev *dev) msi_set_mask_bit(entry->irq, entry->msi_attrib.masked); } - entry = get_irq_msi(dev->first_msi_irq); + BUG_ON(list_empty(&dev->msi_list)); + entry = list_entry(dev->msi_list.next, struct msi_desc, list); pos = entry->msi_attrib.pos; pci_read_config_word(dev, pos + PCI_MSIX_FLAGS, &control); control &= ~PCI_MSIX_FLAGS_MASKALL; @@ -341,7 +342,6 @@ static int msi_capability_init(struct pci_dev *dev) } entry->irq = irq; list_add(&entry->list, &dev->msi_list); - dev->first_msi_irq = irq; set_irq_msi(irq, entry); /* Set MSI enabled bits */ @@ -433,7 +433,6 @@ static int msix_capability_init(struct pci_dev *dev, avail = -EBUSY; return avail; } - dev->first_msi_irq = entries[0].vector; /* Set MSI-X enabled bits */ pci_intx(dev, 0); /* disable intx */ msix_set_enable(dev, 1); @@ -461,6 +460,14 @@ static int pci_msi_check_device(struct pci_dev* dev, int nvec, int type) if (!pci_msi_enable || !dev || dev->no_msi) return -EINVAL; + /* + * You can't ask to have 0 or less MSIs configured. + * a) it's stupid .. + * b) the list manipulation code assumes nvec >= 1. + */ + if (nvec < 1) + return -ERANGE; + /* Any bridge which does NOT route MSI transactions from it's * secondary bus to it's primary bus must set NO_MSI flag on * the secondary pci_bus. @@ -525,18 +532,17 @@ void pci_disable_msi(struct pci_dev* dev) pci_intx(dev, 1); /* enable intx */ dev->msi_enabled = 0; - entry = get_irq_msi(dev->first_msi_irq); - if (!entry || !entry->dev || entry->msi_attrib.type != PCI_CAP_ID_MSI) { + BUG_ON(list_empty(&dev->msi_list)); + entry = list_entry(dev->msi_list.next, struct msi_desc, list); + if (!entry->dev || entry->msi_attrib.type != PCI_CAP_ID_MSI) { return; } default_irq = entry->msi_attrib.default_irq; - msi_free_irq(dev, dev->first_msi_irq); + msi_free_irq(dev, entry->irq); /* Restore dev->irq to its default pin-assertion irq */ dev->irq = default_irq; - - dev->first_msi_irq = 0; } EXPORT_SYMBOL(pci_disable_msi); @@ -634,7 +640,6 @@ static void msix_free_all_irqs(struct pci_dev *dev) list_for_each_entry(entry, &dev->msi_list, list) msi_free_irq(dev, entry->irq); - dev->first_msi_irq = 0; } void pci_disable_msix(struct pci_dev* dev) @@ -664,8 +669,12 @@ void msi_remove_pci_irq_vectors(struct pci_dev* dev) if (!pci_msi_enable || !dev) return; - if (dev->msi_enabled) - msi_free_irq(dev, dev->first_msi_irq); + if (dev->msi_enabled) { + struct msi_desc *entry; + BUG_ON(list_empty(&dev->msi_list)); + entry = list_entry(dev->msi_list.next, struct msi_desc, list); + msi_free_irq(dev, entry->irq); + } if (dev->msix_enabled) msix_free_all_irqs(dev); diff --git a/include/linux/pci.h b/include/linux/pci.h index d43097dc8672..a15569bf78b5 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -189,7 +189,6 @@ struct pci_dev { int rom_attr_enabled; /* has display of the rom attribute been enabled? */ struct bin_attribute *res_attr[DEVICE_COUNT_RESOURCE]; /* sysfs file for resources */ #ifdef CONFIG_PCI_MSI - unsigned int first_msi_irq; struct list_head msi_list; #endif }; From f282b97021ddc95c6092b9016f667c0963858fb1 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Wed, 18 Apr 2007 18:46:20 +1000 Subject: [PATCH 30/59] msi: introduce ARCH_SUPPORTS_MSI Kconfig option (rev2) Allows architectures to advertise that they support MSI rather than listing each architecture as a PCI_MSI dependency. Signed-off-by: Dan Williams Acked-by: "Eric W. Biederman" Signed-off-by: Greg Kroah-Hartman --- arch/arm/Kconfig | 1 + arch/i386/Kconfig | 1 + arch/ia64/Kconfig | 1 + arch/sparc64/Kconfig | 1 + arch/x86_64/Kconfig | 1 + drivers/pci/Kconfig | 6 +++++- 6 files changed, 10 insertions(+), 1 deletion(-) diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index e7baca29f3fb..db00376aca15 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -255,6 +255,7 @@ config ARCH_IOP13XX depends on MMU select PLAT_IOP select PCI + select ARCH_SUPPORTS_MSI help Support for Intel's IOP13XX (XScale) family of processors. diff --git a/arch/i386/Kconfig b/arch/i386/Kconfig index 53d62373a524..bcf2fc408a1a 100644 --- a/arch/i386/Kconfig +++ b/arch/i386/Kconfig @@ -1073,6 +1073,7 @@ config PCI bool "PCI support" if !X86_VISWS depends on !X86_VOYAGER default y if X86_VISWS + select ARCH_SUPPORTS_MSI if (X86_LOCAL_APIC && X86_IO_APIC) help Find out whether you have a PCI motherboard. PCI is the name of a bus system, i.e. the way the CPU talks to the other stuff inside diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig index e19185d26554..3b71f97d0b60 100644 --- a/arch/ia64/Kconfig +++ b/arch/ia64/Kconfig @@ -14,6 +14,7 @@ config IA64 select PCI if (!IA64_HP_SIM) select ACPI if (!IA64_HP_SIM) select PM if (!IA64_HP_SIM) + select ARCH_SUPPORTS_MSI default y help The Itanium Processor Family is Intel's 64-bit successor to diff --git a/arch/sparc64/Kconfig b/arch/sparc64/Kconfig index 590a41b864b9..be9e10b94ef8 100644 --- a/arch/sparc64/Kconfig +++ b/arch/sparc64/Kconfig @@ -306,6 +306,7 @@ config SUN_IO config PCI bool "PCI support" + select ARCH_SUPPORTS_MSI help Find out whether you have a PCI motherboard. PCI is the name of a bus system, i.e. the way the CPU talks to the other stuff inside diff --git a/arch/x86_64/Kconfig b/arch/x86_64/Kconfig index 56eb14c98475..e9b4f058a49a 100644 --- a/arch/x86_64/Kconfig +++ b/arch/x86_64/Kconfig @@ -676,6 +676,7 @@ menu "Bus options (PCI etc.)" config PCI bool "PCI support" + select ARCH_SUPPORTS_MSI if (X86_LOCAL_APIC && X86_IO_APIC) # x86-64 doesn't support PCI BIOS access from long mode so always go direct. config PCI_DIRECT diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig index 5ea5bc70cb82..70efe8f285a6 100644 --- a/drivers/pci/Kconfig +++ b/drivers/pci/Kconfig @@ -1,10 +1,14 @@ # # PCI configuration # +config ARCH_SUPPORTS_MSI + bool + default n + config PCI_MSI bool "Message Signaled Interrupts (MSI and MSI-X)" depends on PCI - depends on (X86_LOCAL_APIC && X86_IO_APIC) || IA64 || SPARC64 + depends on ARCH_SUPPORTS_MSI help This allows device drivers to enable MSI (Message Signaled Interrupts). Message Signaled Interrupts enable a device to From 7fe3730de729b758e9f69b862b9255d998671b5f Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Wed, 18 Apr 2007 19:39:21 +1000 Subject: [PATCH 31/59] MSI: arch must connect the irq and the msi_desc set_irq_msi() currently connects an irq_desc to an msi_desc. The archs call it at some point in their setup routine, and then the generic code sets up the reverse mapping from the msi_desc back to the irq. set_irq_msi() should do both connections, making it the one and only call required to connect an irq with it's MSI desc and vice versa. The arch code MUST call set_irq_msi(), and it must do so only once it's sure it's not going to fail the irq allocation. Given that there's no need for the arch to return the irq anymore, the return value from the arch setup routine just becomes 0 for success and anything else for failure. Signed-off-by: Michael Ellerman Signed-off-by: Greg Kroah-Hartman --- arch/i386/kernel/io_apic.c | 4 ++-- arch/ia64/sn/kernel/msi_sn.c | 4 ++-- arch/sparc64/kernel/pci.c | 4 ++-- arch/sparc64/kernel/pci_sun4v.c | 4 ++-- arch/x86_64/kernel/io_apic.c | 4 ++-- drivers/pci/msi.c | 23 +++++++++-------------- kernel/irq/chip.c | 3 +++ 7 files changed, 22 insertions(+), 24 deletions(-) diff --git a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c index b3ab8ffebd27..89d85d244926 100644 --- a/arch/i386/kernel/io_apic.c +++ b/arch/i386/kernel/io_apic.c @@ -2611,19 +2611,19 @@ int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc) if (irq < 0) return irq; - set_irq_msi(irq, desc); ret = msi_compose_msg(dev, irq, &msg); if (ret < 0) { destroy_irq(irq); return ret; } + set_irq_msi(irq, desc); write_msi_msg(irq, &msg); set_irq_chip_and_handler_name(irq, &msi_chip, handle_edge_irq, "edge"); - return irq; + return 0; } void arch_teardown_msi_irq(unsigned int irq) diff --git a/arch/ia64/sn/kernel/msi_sn.c b/arch/ia64/sn/kernel/msi_sn.c index 49873aa4a37d..83f190ffe350 100644 --- a/arch/ia64/sn/kernel/msi_sn.c +++ b/arch/ia64/sn/kernel/msi_sn.c @@ -87,7 +87,6 @@ int sn_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *entry) if (irq < 0) return irq; - set_irq_msi(irq, entry); /* * Set up the vector plumbing. Let the prom (via sn_intr_alloc) * decide which cpu to direct this msi at by default. @@ -144,10 +143,11 @@ int sn_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *entry) */ msg.data = 0x100 + irq; + set_irq_msi(irq, entry); write_msi_msg(irq, &msg); set_irq_chip_and_handler(irq, &sn_msi_chip, handle_edge_irq); - return irq; + return 0; } #ifdef CONFIG_SMP diff --git a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c index 023af41ad68d..9a549547cb2b 100644 --- a/arch/sparc64/kernel/pci.c +++ b/arch/sparc64/kernel/pci.c @@ -1092,10 +1092,10 @@ int arch_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc) return -EINVAL; err = p->setup_msi_irq(&virt_irq, pdev, desc); - if (err < 0) + if (err) return err; - return virt_irq; + return 0; } void arch_teardown_msi_irq(unsigned int virt_irq) diff --git a/arch/sparc64/kernel/pci_sun4v.c b/arch/sparc64/kernel/pci_sun4v.c index 94295c219329..1ccf4c9a9a43 100644 --- a/arch/sparc64/kernel/pci_sun4v.c +++ b/arch/sparc64/kernel/pci_sun4v.c @@ -1169,8 +1169,6 @@ static int pci_sun4v_setup_msi_irq(unsigned int *virt_irq_p, if (!devino) goto out_err; - set_irq_msi(*virt_irq_p, entry); - msiqid = ((devino - pbm->msiq_first_devino) + pbm->msiq_first); @@ -1204,6 +1202,8 @@ static int pci_sun4v_setup_msi_irq(unsigned int *virt_irq_p, msg.address_lo = pbm->msi32_start; } msg.data = msi_num; + + set_irq_msi(*virt_irq_p, entry); write_msi_msg(*virt_irq_p, &msg); irq_install_pre_handler(*virt_irq_p, diff --git a/arch/x86_64/kernel/io_apic.c b/arch/x86_64/kernel/io_apic.c index c6a5bc7e8118..b7d2b76b92d4 100644 --- a/arch/x86_64/kernel/io_apic.c +++ b/arch/x86_64/kernel/io_apic.c @@ -1983,18 +1983,18 @@ int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc) if (irq < 0) return irq; - set_irq_msi(irq, desc); ret = msi_compose_msg(dev, irq, &msg); if (ret < 0) { destroy_irq(irq); return ret; } + set_irq_msi(irq, desc); write_msi_msg(irq, &msg); set_irq_chip_and_handler_name(irq, &msi_chip, handle_edge_irq, "edge"); - return irq; + return 0; } void arch_teardown_msi_irq(unsigned int irq) diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index 7a44ba467481..88362f1bd9cf 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c @@ -297,7 +297,7 @@ void pci_restore_msi_state(struct pci_dev *dev) static int msi_capability_init(struct pci_dev *dev) { struct msi_desc *entry; - int pos, irq; + int pos, ret; u16 control; msi_set_enable(dev, 0); /* Ensure msi is disabled as I set it up */ @@ -335,21 +335,19 @@ static int msi_capability_init(struct pci_dev *dev) maskbits); } /* Configure MSI capability structure */ - irq = arch_setup_msi_irq(dev, entry); - if (irq < 0) { + ret = arch_setup_msi_irq(dev, entry); + if (ret) { kfree(entry); - return irq; + return ret; } - entry->irq = irq; list_add(&entry->list, &dev->msi_list); - set_irq_msi(irq, entry); /* Set MSI enabled bits */ pci_intx(dev, 0); /* disable intx */ msi_set_enable(dev, 1); dev->msi_enabled = 1; - dev->irq = irq; + dev->irq = entry->irq; return 0; } @@ -367,7 +365,7 @@ static int msix_capability_init(struct pci_dev *dev, struct msix_entry *entries, int nvec) { struct msi_desc *entry; - int irq, pos, i, j, nr_entries; + int irq, pos, i, j, nr_entries, ret; unsigned long phys_addr; u32 table_offset; u16 control; @@ -407,16 +405,13 @@ static int msix_capability_init(struct pci_dev *dev, entry->mask_base = base; /* Configure MSI-X capability structure */ - irq = arch_setup_msi_irq(dev, entry); - if (irq < 0) { + ret = arch_setup_msi_irq(dev, entry); + if (ret) { kfree(entry); break; } - entry->irq = irq; - entries[i].vector = irq; + entries[i].vector = entry->irq; list_add(&entry->list, &dev->msi_list); - - set_irq_msi(irq, entry); } if (i != nvec) { int avail = i - 1; diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c index 0133f4f9e9f0..615ce97c6cfd 100644 --- a/kernel/irq/chip.c +++ b/kernel/irq/chip.c @@ -11,6 +11,7 @@ */ #include +#include #include #include #include @@ -185,6 +186,8 @@ int set_irq_msi(unsigned int irq, struct msi_desc *entry) desc = irq_desc + irq; spin_lock_irqsave(&desc->lock, flags); desc->msi_desc = entry; + if (entry) + entry->irq = irq; spin_unlock_irqrestore(&desc->lock, flags); return 0; } From 9c8313343c83c0ca731ceb8d2a4ab1e022ed9c94 Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Wed, 18 Apr 2007 19:39:21 +1000 Subject: [PATCH 32/59] MSI: Give archs the option to allocate all MSI/Xs at once. This patch introduces an optional function, arch_setup_msi_irqs(), (note the plural) which gives an arch the opportunity to do per-device setup for MSI/X and then allocate all the requested MSI/Xs at once. If that's not required by the arch, the default version simply calls arch_setup_msi_irq() for each MSI irq required. arch_setup_msi_irqs() is passed a pdev, attached to the pdev is a list of msi_descs with irq == 0, it is up to the arch to connect these up to an irq (via set_irq_msi()) or return an error. For convenience the number of vectors and the type are passed also. All msi_descs with irq != 0 are considered allocated, and the arch teardown routine will be called on them when necessary. The existing semantics of pci_enable_msix() are that if the requested number of irqs can not be allocated, the maximum number that _could_ be allocated is returned. To support that, we define that in case of an error from arch_setup_msi_irqs(), the number of msi_descs with irq != 0 are considered allocated, and are counted toward the "max that could be allocated". Signed-off-by: Michael Ellerman Signed-off-by: Greg Kroah-Hartman --- drivers/pci/msi.c | 63 +++++++++++++++++++++++++++++++-------------- include/linux/msi.h | 1 + 2 files changed, 45 insertions(+), 19 deletions(-) diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index 88362f1bd9cf..c71e8e4c7168 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c @@ -334,13 +334,15 @@ static int msi_capability_init(struct pci_dev *dev) msi_mask_bits_reg(pos, is_64bit_address(control)), maskbits); } + list_add(&entry->list, &dev->msi_list); + /* Configure MSI capability structure */ - ret = arch_setup_msi_irq(dev, entry); + ret = arch_setup_msi_irqs(dev, 1, PCI_CAP_ID_MSI); if (ret) { + list_del(&entry->list); kfree(entry); return ret; } - list_add(&entry->list, &dev->msi_list); /* Set MSI enabled bits */ pci_intx(dev, 0); /* disable intx */ @@ -365,7 +367,7 @@ static int msix_capability_init(struct pci_dev *dev, struct msix_entry *entries, int nvec) { struct msi_desc *entry; - int irq, pos, i, j, nr_entries, ret; + int pos, i, j, nr_entries, ret; unsigned long phys_addr; u32 table_offset; u16 control; @@ -404,30 +406,33 @@ static int msix_capability_init(struct pci_dev *dev, entry->dev = dev; entry->mask_base = base; - /* Configure MSI-X capability structure */ - ret = arch_setup_msi_irq(dev, entry); - if (ret) { - kfree(entry); - break; - } - entries[i].vector = entry->irq; list_add(&entry->list, &dev->msi_list); } - if (i != nvec) { - int avail = i - 1; - i--; - for (; i >= 0; i--) { - irq = (entries + i)->vector; - msi_free_irq(dev, irq); - (entries + i)->vector = 0; + + ret = arch_setup_msi_irqs(dev, nvec, PCI_CAP_ID_MSIX); + if (ret) { + int avail = 0; + list_for_each_entry(entry, &dev->msi_list, list) { + if (entry->irq != 0) { + avail++; + msi_free_irq(dev, entry->irq); + } } + /* If we had some success report the number of irqs * we succeeded in setting up. */ - if (avail <= 0) - avail = -EBUSY; + if (avail == 0) + avail = ret; return avail; } + + i = 0; + list_for_each_entry(entry, &dev->msi_list, list) { + entries[i].vector = entry->irq; + set_irq_msi(entry->irq, entry); + i++; + } /* Set MSI-X enabled bits */ pci_intx(dev, 0); /* disable intx */ msix_set_enable(dev, 1); @@ -694,3 +699,23 @@ arch_msi_check_device(struct pci_dev* dev, int nvec, int type) return 0; } +int __attribute__ ((weak)) +arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *entry) +{ + return 0; +} + +int __attribute__ ((weak)) +arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) +{ + struct msi_desc *entry; + int ret; + + list_for_each_entry(entry, &dev->msi_list, list) { + ret = arch_setup_msi_irq(dev, entry); + if (ret) + return ret; + } + + return 0; +} diff --git a/include/linux/msi.h b/include/linux/msi.h index 931e013f1db5..494627ae021f 100644 --- a/include/linux/msi.h +++ b/include/linux/msi.h @@ -41,6 +41,7 @@ struct msi_desc { */ int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc); void arch_teardown_msi_irq(unsigned int irq); +extern int arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type); extern int arch_msi_check_device(struct pci_dev* dev, int nvec, int type); From 032de8e2fe3c0eec5fb0ffe4d38aa602dad397dc Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Wed, 18 Apr 2007 19:39:22 +1000 Subject: [PATCH 33/59] MSI: Give archs the option to free all MSI/Xs at once. This patch introduces an optional function, arch_teardown_msi_irqs(), which gives an arch the opportunity to do per-device teardown for MSI/X. If that's not required, the default version simply calls arch_teardown_msi_irq() for each msi irq required. arch_teardown_msi_irqs() is simply passed a pdev, attached to the pdev is a list of msi_descs, it is up to the arch to free the irq associated with each of these as appropriate. For archs that _don't_ implement arch_teardown_msi_irqs(), all msi_descs with irq == 0 are considered unallocated, and the arch teardown routine is not called on them. Signed-off-by: Michael Ellerman Signed-off-by: Greg Kroah-Hartman --- drivers/pci/msi.c | 75 +++++++++++++++++++++++---------------------- include/linux/msi.h | 1 + 2 files changed, 40 insertions(+), 36 deletions(-) diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index c71e8e4c7168..9e1321d0d5e6 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c @@ -207,7 +207,7 @@ void unmask_msi_irq(unsigned int irq) msix_flush_writes(irq); } -static int msi_free_irq(struct pci_dev* dev, int irq); +static int msi_free_irqs(struct pci_dev* dev); static struct msi_desc* alloc_msi_entry(void) @@ -339,8 +339,7 @@ static int msi_capability_init(struct pci_dev *dev) /* Configure MSI capability structure */ ret = arch_setup_msi_irqs(dev, 1, PCI_CAP_ID_MSI); if (ret) { - list_del(&entry->list); - kfree(entry); + msi_free_irqs(dev); return ret; } @@ -415,10 +414,11 @@ static int msix_capability_init(struct pci_dev *dev, list_for_each_entry(entry, &dev->msi_list, list) { if (entry->irq != 0) { avail++; - msi_free_irq(dev, entry->irq); } } + msi_free_irqs(dev); + /* If we had some success report the number of irqs * we succeeded in setting up. */ @@ -539,39 +539,33 @@ void pci_disable_msi(struct pci_dev* dev) } default_irq = entry->msi_attrib.default_irq; - msi_free_irq(dev, entry->irq); + msi_free_irqs(dev); /* Restore dev->irq to its default pin-assertion irq */ dev->irq = default_irq; } EXPORT_SYMBOL(pci_disable_msi); -static int msi_free_irq(struct pci_dev* dev, int irq) +static int msi_free_irqs(struct pci_dev* dev) { - struct msi_desc *entry; - int entry_nr, type; - void __iomem *base; + struct msi_desc *entry, *tmp; - BUG_ON(irq_has_action(irq)); + list_for_each_entry(entry, &dev->msi_list, list) + BUG_ON(irq_has_action(entry->irq)); - entry = get_irq_msi(irq); - if (!entry || entry->dev != dev) { - return -EINVAL; - } - type = entry->msi_attrib.type; - entry_nr = entry->msi_attrib.entry_nr; - base = entry->mask_base; - list_del(&entry->list); + arch_teardown_msi_irqs(dev); - arch_teardown_msi_irq(irq); - kfree(entry); + list_for_each_entry_safe(entry, tmp, &dev->msi_list, list) { + if (entry->msi_attrib.type == PCI_CAP_ID_MSIX) { + if (list_is_last(&entry->list, &dev->msi_list)) + iounmap(entry->mask_base); - if (type == PCI_CAP_ID_MSIX) { - writel(1, base + entry_nr * PCI_MSIX_ENTRY_SIZE + - PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET); - - if (list_empty(&dev->msi_list)) - iounmap(base); + writel(1, entry->mask_base + entry->msi_attrib.entry_nr + * PCI_MSIX_ENTRY_SIZE + + PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET); + } + list_del(&entry->list); + kfree(entry); } return 0; @@ -636,10 +630,7 @@ EXPORT_SYMBOL(pci_enable_msix); static void msix_free_all_irqs(struct pci_dev *dev) { - struct msi_desc *entry; - - list_for_each_entry(entry, &dev->msi_list, list) - msi_free_irq(dev, entry->irq); + msi_free_irqs(dev); } void pci_disable_msix(struct pci_dev* dev) @@ -669,12 +660,8 @@ void msi_remove_pci_irq_vectors(struct pci_dev* dev) if (!pci_msi_enable || !dev) return; - if (dev->msi_enabled) { - struct msi_desc *entry; - BUG_ON(list_empty(&dev->msi_list)); - entry = list_entry(dev->msi_list.next, struct msi_desc, list); - msi_free_irq(dev, entry->irq); - } + if (dev->msi_enabled) + msi_free_irqs(dev); if (dev->msix_enabled) msix_free_all_irqs(dev); @@ -719,3 +706,19 @@ arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) return 0; } + +void __attribute__ ((weak)) arch_teardown_msi_irq(unsigned int irq) +{ + return; +} + +void __attribute__ ((weak)) +arch_teardown_msi_irqs(struct pci_dev *dev) +{ + struct msi_desc *entry; + + list_for_each_entry(entry, &dev->msi_list, list) { + if (entry->irq != 0) + arch_teardown_msi_irq(entry->irq); + } +} diff --git a/include/linux/msi.h b/include/linux/msi.h index 494627ae021f..94bb46d82efd 100644 --- a/include/linux/msi.h +++ b/include/linux/msi.h @@ -42,6 +42,7 @@ struct msi_desc { int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc); void arch_teardown_msi_irq(unsigned int irq); extern int arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type); +extern void arch_teardown_msi_irqs(struct pci_dev *dev); extern int arch_msi_check_device(struct pci_dev* dev, int nvec, int type); From 5adc55da4a7758021bcc374904b0f8b076508a11 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Tue, 27 Mar 2007 03:02:51 +0200 Subject: [PATCH 34/59] PCI: remove the broken PCI_MULTITHREAD_PROBE option This patch removes the PCI_MULTITHREAD_PROBE option that had already been marked as broken. Signed-off-by: Adrian Bunk Signed-off-by: Greg Kroah-Hartman --- Documentation/pci.txt | 4 ---- drivers/base/dd.c | 41 +++------------------------------------- drivers/pci/Kconfig | 25 ------------------------ drivers/pci/pci-driver.c | 15 --------------- include/linux/device.h | 1 - 5 files changed, 3 insertions(+), 83 deletions(-) diff --git a/Documentation/pci.txt b/Documentation/pci.txt index a8ded1a8bd62..40c4717d236b 100644 --- a/Documentation/pci.txt +++ b/Documentation/pci.txt @@ -124,10 +124,6 @@ initialization with a pointer to a structure describing the driver err_handler See Documentation/pci-error-recovery.txt - multithread_probe Enable multi-threaded probe/scan. Driver must - provide its own locking/syncronization for init - operations if this is enabled. - The ID table is an array of struct pci_device_id entries ending with an all-zero entry. Each entry consists of: diff --git a/drivers/base/dd.c b/drivers/base/dd.c index 18dba8e78da7..92428e55b0c2 100644 --- a/drivers/base/dd.c +++ b/drivers/base/dd.c @@ -226,12 +226,10 @@ static int device_probe_drivers(void *data) * * Walk the list of drivers that the bus has and call * driver_probe_device() for each pair. If a compatible - * pair is found, break out and return. If the bus specifies - * multithreaded probing, walking the list of drivers is done - * on a probing thread. + * pair is found, break out and return. * * Returns 1 if the device was bound to a driver; - * 0 if no matching device was found or multithreaded probing is done; + * 0 if no matching device was found; * -ENODEV if the device is not registered. * * When called for a USB interface, @dev->parent->sem must be held. @@ -239,7 +237,6 @@ static int device_probe_drivers(void *data) int device_attach(struct device * dev) { int ret = 0; - struct task_struct *probe_task = ERR_PTR(-ENOMEM); down(&dev->sem); if (dev->driver) { @@ -251,12 +248,7 @@ int device_attach(struct device * dev) ret = 0; } } else { - if (dev->bus->multithread_probe) - probe_task = kthread_run(device_probe_drivers, dev, - "probe-%s", dev->bus_id); - if(IS_ERR(probe_task)) - ret = bus_for_each_drv(dev->bus, NULL, dev, - __device_attach); + ret = bus_for_each_drv(dev->bus, NULL, dev, __device_attach); } up(&dev->sem); return ret; @@ -383,33 +375,6 @@ void driver_detach(struct device_driver * drv) } } -#ifdef CONFIG_PCI_MULTITHREAD_PROBE -static int __init wait_for_probes(void) -{ - DEFINE_WAIT(wait); - - printk(KERN_INFO "%s: waiting for %d threads\n", __FUNCTION__, - atomic_read(&probe_count)); - if (!atomic_read(&probe_count)) - return 0; - while (atomic_read(&probe_count)) { - prepare_to_wait(&probe_waitqueue, &wait, TASK_UNINTERRUPTIBLE); - if (atomic_read(&probe_count)) - schedule(); - } - finish_wait(&probe_waitqueue, &wait); - return 0; -} - -core_initcall_sync(wait_for_probes); -postcore_initcall_sync(wait_for_probes); -arch_initcall_sync(wait_for_probes); -subsys_initcall_sync(wait_for_probes); -fs_initcall_sync(wait_for_probes); -device_initcall_sync(wait_for_probes); -late_initcall_sync(wait_for_probes); -#endif - EXPORT_SYMBOL_GPL(device_bind_driver); EXPORT_SYMBOL_GPL(device_release_driver); EXPORT_SYMBOL_GPL(device_attach); diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig index 70efe8f285a6..7a1d6d512837 100644 --- a/drivers/pci/Kconfig +++ b/drivers/pci/Kconfig @@ -21,31 +21,6 @@ config PCI_MSI If you don't know what to do here, say N. -config PCI_MULTITHREAD_PROBE - bool "PCI Multi-threaded probe (EXPERIMENTAL)" - depends on PCI && EXPERIMENTAL && BROKEN - help - Say Y here if you want the PCI core to spawn a new thread for - every PCI device that is probed. This can cause a huge - speedup in boot times on multiprocessor machines, and even a - smaller speedup on single processor machines. - - But it can also cause lots of bad things to happen. A number - of PCI drivers cannot properly handle running in this way, - some will just not work properly at all, while others might - decide to blow up power supplies with a huge load all at once, - so use this option at your own risk. - - It is very unwise to use this option if you are not using a - boot process that can handle devices being created in any - order. A program that can create persistent block and network - device names (like udev) is a good idea if you wish to use - this option. - - Again, use this option at your own risk, you have been warned! - - When in doubt, say N. - config PCI_DEBUG bool "PCI Debugging" depends on PCI && DEBUG_KERNEL diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c index 07fdb3cd6172..3bb7739d26a5 100644 --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c @@ -13,20 +13,6 @@ #include #include "pci.h" -/* - * Registration of PCI drivers and handling of hot-pluggable devices. - */ - -/* multithreaded probe logic */ -static int pci_multithread_probe = -#ifdef CONFIG_PCI_MULTITHREAD_PROBE - 1; -#else - 0; -#endif -__module_param_call("", pci_multithread_probe, param_set_bool, param_get_bool, &pci_multithread_probe, 0644); - - /* * Dynamic device IDs are disabled for !CONFIG_HOTPLUG */ @@ -569,7 +555,6 @@ struct bus_type pci_bus_type = { static int __init pci_driver_init(void) { - pci_bus_type.multithread_probe = pci_multithread_probe; return bus_register(&pci_bus_type); } diff --git a/include/linux/device.h b/include/linux/device.h index a0cd2ced31a9..ff83b61d283d 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -80,7 +80,6 @@ struct bus_type { int (*resume)(struct device * dev); unsigned int drivers_autoprobe:1; - unsigned int multithread_probe:1; }; extern int __must_check bus_register(struct bus_type * bus); From ecf36501bc4ad399e6df2e0bdaa513a2d510b7ec Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Fri, 6 Apr 2007 12:19:48 +0200 Subject: [PATCH 35/59] PCI: the overdue removal of pci_module_init() Unless we finally completely remove it, people will always add new users. Signed-off-by: Adrian Bunk Signed-off-by: Greg Kroah-Hartman --- Documentation/feature-removal-schedule.txt | 7 ------- Documentation/pci.txt | 2 -- include/linux/pci.h | 6 ------ 3 files changed, 15 deletions(-) diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt index 5c88ba1ea262..144058cf849a 100644 --- a/Documentation/feature-removal-schedule.txt +++ b/Documentation/feature-removal-schedule.txt @@ -117,13 +117,6 @@ Who: Adrian Bunk --------------------------- -What: pci_module_init(driver) -When: January 2007 -Why: Is replaced by pci_register_driver(pci_driver). -Who: Richard Knutsson and Greg Kroah-Hartman - ---------------------------- - What: Usage of invalid timevals in setitimer When: March 2007 Why: POSIX requires to validate timevals in the setitimer call. This diff --git a/Documentation/pci.txt b/Documentation/pci.txt index 40c4717d236b..e2c9d0a0c43d 100644 --- a/Documentation/pci.txt +++ b/Documentation/pci.txt @@ -545,8 +545,6 @@ pci_find_slot() Find pci_dev corresponding to given bus and pci_set_power_state() Set PCI Power Management state (0=D0 ... 3=D3) pci_find_capability() Find specified capability in device's capability list. -pci_module_init() Inline helper function for ensuring correct - pci_driver initialization and error handling. pci_resource_start() Returns bus start address for a given PCI region pci_resource_end() Returns bus end address for a given PCI region pci_resource_len() Returns the byte length of a PCI region diff --git a/include/linux/pci.h b/include/linux/pci.h index a15569bf78b5..fbf3766dac1e 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -407,12 +407,6 @@ struct pci_driver { .vendor = PCI_ANY_ID, .device = PCI_ANY_ID, \ .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID -/* - * pci_module_init is obsolete, this stays here till we fix up all usages of it - * in the tree. - */ -#define pci_module_init pci_register_driver - /** * PCI_VDEVICE - macro used to describe a specific pci device in short form * @vend: the vendor name From f14e3136509e3825a83f6689cb709f41dfacea47 Mon Sep 17 00:00:00 2001 From: Chuck Ebbert Date: Tue, 10 Apr 2007 10:25:44 -0400 Subject: [PATCH 36/59] PCI: add debug information to resource collision message Add more information to PCI resource collision message to help with debugging. Signed-off-by: Chuck Ebbert Signed-off-by: Greg Kroah-Hartman --- arch/i386/pci/i386.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/i386/pci/i386.c b/arch/i386/pci/i386.c index 43005f044424..bcd2f94b732c 100644 --- a/arch/i386/pci/i386.c +++ b/arch/i386/pci/i386.c @@ -246,8 +246,8 @@ int pcibios_enable_resources(struct pci_dev *dev, int mask) continue; if (!r->start && r->end) { printk(KERN_ERR "PCI: Device %s not available " - "because of resource collisions\n", - pci_name(dev)); + "because of resource %d collisions\n", + pci_name(dev), idx); return -EINVAL; } if (r->flags & IORESOURCE_IO) From bf8cbae47559170d2f2947dd547492714f195dd3 Mon Sep 17 00:00:00 2001 From: Linas Vepstas Date: Fri, 13 Apr 2007 15:34:07 -0700 Subject: [PATCH 37/59] PCI: rpaphp: Cleanup flow of control for rpaphp_add_slot Cleanup the flow of control for rpaphp_add_slot(), so as to make it easier to read. The ext patch will fix a bug in this same code. Signed-off-by: Linas Vepstas Cc: John Rose Signed-off-by: Kristen Carlson Accardi Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/rpaphp_core.c | 36 +++++++++++++++---------------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/drivers/pci/hotplug/rpaphp_core.c b/drivers/pci/hotplug/rpaphp_core.c index 71a2cb8baa4a..f6c05f3621ca 100644 --- a/drivers/pci/hotplug/rpaphp_core.c +++ b/drivers/pci/hotplug/rpaphp_core.c @@ -299,32 +299,32 @@ int rpaphp_add_slot(struct device_node *dn) const int *indexes, *names, *types, *power_domains; char *name, *type; + if (!dn->name || strcmp(dn->name, "pci")) + return 0; + + if (!is_php_dn(dn, &indexes, &names, &types, &power_domains)) + return 0; + dbg("Entry %s: dn->full_name=%s\n", __FUNCTION__, dn->full_name); /* register PCI devices */ - if (dn->name != 0 && strcmp(dn->name, "pci") == 0) { - if (!is_php_dn(dn, &indexes, &names, &types, &power_domains)) - goto exit; + name = (char *) &names[1]; + type = (char *) &types[1]; + for (i = 0; i < indexes[0]; i++) { - name = (char *) &names[1]; - type = (char *) &types[1]; - for (i = 0; i < indexes[0]; i++, - name += (strlen(name) + 1), type += (strlen(type) + 1)) { + slot = alloc_slot_struct(dn, indexes[i + 1], name, power_domains[i + 1]); + if (!slot) + return -ENOMEM; - if (!(slot = alloc_slot_struct(dn, indexes[i + 1], name, - power_domains[i + 1]))) { - retval = -ENOMEM; - goto exit; - } - slot->type = simple_strtoul(type, NULL, 10); + slot->type = simple_strtoul(type, NULL, 10); - dbg("Found drc-index:0x%x drc-name:%s drc-type:%s\n", - indexes[i + 1], name, type); + dbg("Found drc-index:0x%x drc-name:%s drc-type:%s\n", + indexes[i + 1], name, type); - retval = rpaphp_register_pci_slot(slot); - } + retval = rpaphp_register_pci_slot(slot); + name += strlen(name) + 1; + type += strlen(type) + 1; } -exit: dbg("%s - Exit: num_slots=%d rc[%d]\n", __FUNCTION__, num_slots, retval); return retval; From fa1891596ca252e48e8803738fd8ead5b3082217 Mon Sep 17 00:00:00 2001 From: Linas Vepstas Date: Fri, 13 Apr 2007 15:34:08 -0700 Subject: [PATCH 38/59] PCI: rpaphp: Remove global num_slots variable Cleanup cruft: remove the global "num_slots" variable; although scattered across multiple files, it is used only once, in a debug statement. Signed-off-by: Linas Vepstas Cc: John Rose Signed-off-by: Kristen Carlson Accardi Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/rpaphp.h | 1 - drivers/pci/hotplug/rpaphp_core.c | 4 +--- drivers/pci/hotplug/rpaphp_slot.c | 3 --- 3 files changed, 1 insertion(+), 7 deletions(-) diff --git a/drivers/pci/hotplug/rpaphp.h b/drivers/pci/hotplug/rpaphp.h index 2e7accf0f734..2ccbe8d4229d 100644 --- a/drivers/pci/hotplug/rpaphp.h +++ b/drivers/pci/hotplug/rpaphp.h @@ -83,7 +83,6 @@ struct slot { extern struct hotplug_slot_ops rpaphp_hotplug_slot_ops; extern struct list_head rpaphp_slot_head; -extern int num_slots; /* function prototypes */ diff --git a/drivers/pci/hotplug/rpaphp_core.c b/drivers/pci/hotplug/rpaphp_core.c index f6c05f3621ca..3afd154bf543 100644 --- a/drivers/pci/hotplug/rpaphp_core.c +++ b/drivers/pci/hotplug/rpaphp_core.c @@ -41,7 +41,6 @@ int debug; static struct semaphore rpaphp_sem; LIST_HEAD(rpaphp_slot_head); -int num_slots; #define DRIVER_VERSION "0.1" #define DRIVER_AUTHOR "Linda Xie " @@ -325,8 +324,7 @@ int rpaphp_add_slot(struct device_node *dn) name += strlen(name) + 1; type += strlen(type) + 1; } - dbg("%s - Exit: num_slots=%d rc[%d]\n", - __FUNCTION__, num_slots, retval); + dbg("%s - Exit: rc[%d]\n", __FUNCTION__, retval); return retval; } diff --git a/drivers/pci/hotplug/rpaphp_slot.c b/drivers/pci/hotplug/rpaphp_slot.c index 3009193f0058..907f1301f84a 100644 --- a/drivers/pci/hotplug/rpaphp_slot.c +++ b/drivers/pci/hotplug/rpaphp_slot.c @@ -140,8 +140,6 @@ int rpaphp_deregister_slot(struct slot *slot) retval = pci_hp_deregister(php_slot); if (retval) err("Problem unregistering a slot %s\n", slot->name); - else - num_slots--; dbg("%s - Exit: rc[%d]\n", __FUNCTION__, retval); return retval; @@ -181,7 +179,6 @@ int rpaphp_register_slot(struct slot *slot) list_add(&slot->rpaphp_slot_list, &rpaphp_slot_head); info("Slot [%s](PCI location=%s) registered\n", slot->name, slot->location); - num_slots++; return 0; sysfs_fail: From 31be7586d1122538747519d786408f142f59dd46 Mon Sep 17 00:00:00 2001 From: Linas Vepstas Date: Fri, 13 Apr 2007 15:34:09 -0700 Subject: [PATCH 39/59] PCI: rpaphp: match up alloc and free in same routine The routine that called an alloc should be the same routine that calles the mathcing free, if anything in the middle failed. Signed-off-by: Linas Vepstas Cc: John Rose Signed-off-by: Kristen Carlson Accardi Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/rpaphp_core.c | 5 +++++ drivers/pci/hotplug/rpaphp_pci.c | 1 - drivers/pci/hotplug/rpaphp_slot.c | 1 - 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/pci/hotplug/rpaphp_core.c b/drivers/pci/hotplug/rpaphp_core.c index 3afd154bf543..ca95e1515d6f 100644 --- a/drivers/pci/hotplug/rpaphp_core.c +++ b/drivers/pci/hotplug/rpaphp_core.c @@ -321,10 +321,15 @@ int rpaphp_add_slot(struct device_node *dn) indexes[i + 1], name, type); retval = rpaphp_register_pci_slot(slot); + if (retval) + dealloc_slot_struct(slot); + name += strlen(name) + 1; type += strlen(type) + 1; } dbg("%s - Exit: rc[%d]\n", __FUNCTION__, retval); + + /* XXX FIXME: reports a failure only if last entry in loop failed */ return retval; } diff --git a/drivers/pci/hotplug/rpaphp_pci.c b/drivers/pci/hotplug/rpaphp_pci.c index 6f6cbede5135..a669ba3f29c9 100644 --- a/drivers/pci/hotplug/rpaphp_pci.c +++ b/drivers/pci/hotplug/rpaphp_pci.c @@ -195,7 +195,6 @@ static int setup_pci_slot(struct slot *slot) } return 0; exit_rc: - dealloc_slot_struct(slot); return -EINVAL; } diff --git a/drivers/pci/hotplug/rpaphp_slot.c b/drivers/pci/hotplug/rpaphp_slot.c index 907f1301f84a..dd1e275a82ce 100644 --- a/drivers/pci/hotplug/rpaphp_slot.c +++ b/drivers/pci/hotplug/rpaphp_slot.c @@ -184,7 +184,6 @@ int rpaphp_register_slot(struct slot *slot) sysfs_fail: pci_hp_deregister(php_slot); register_fail: - rpaphp_release_slot(php_slot); return retval; } From 5fd39c35a016150e93b68c472a04b2d4b5574a2b Mon Sep 17 00:00:00 2001 From: Linas Vepstas Date: Fri, 13 Apr 2007 15:34:10 -0700 Subject: [PATCH 40/59] PCI: rpaphp: Fix a memleak; slot->location string was never freed Fix a memleak; the slot->location string was never freed. Fix some whitespace and overlong-line probelms while we're here. Signed-off-by: Linas Vepstas Cc: John Rose Signed-off-by: Kristen Carlson Accardi Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/rpaphp_slot.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/drivers/pci/hotplug/rpaphp_slot.c b/drivers/pci/hotplug/rpaphp_slot.c index dd1e275a82ce..865b0b7ef20c 100644 --- a/drivers/pci/hotplug/rpaphp_slot.c +++ b/drivers/pci/hotplug/rpaphp_slot.c @@ -56,7 +56,6 @@ static struct hotplug_slot_attribute php_attr_location = { static void rpaphp_release_slot(struct hotplug_slot *hotplug_slot) { struct slot *slot = (struct slot *) hotplug_slot->private; - dealloc_slot_struct(slot); } @@ -65,12 +64,12 @@ void dealloc_slot_struct(struct slot *slot) kfree(slot->hotplug_slot->info); kfree(slot->hotplug_slot->name); kfree(slot->hotplug_slot); + kfree(slot->location); kfree(slot); - return; } -struct slot *alloc_slot_struct(struct device_node *dn, int drc_index, char *drc_name, - int power_domain) +struct slot *alloc_slot_struct(struct device_node *dn, + int drc_index, char *drc_name, int power_domain) { struct slot *slot; @@ -115,7 +114,7 @@ error_nomem: static int is_registered(struct slot *slot) { - struct slot *tmp_slot; + struct slot *tmp_slot; list_for_each_entry(tmp_slot, &rpaphp_slot_head, rpaphp_slot_list) { if (!strcmp(tmp_slot->name, slot->name)) From 3499f0726ec179afd19669070681ac457d27033f Mon Sep 17 00:00:00 2001 From: Linas Vepstas Date: Fri, 13 Apr 2007 15:34:11 -0700 Subject: [PATCH 41/59] PCI: rpaphp: Remove un-needed goto Remove un-needed goto. Signed-off-by: Linas Vepstas Cc: John Rose Signed-off-by: Kristen Carlson Accardi Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/rpaphp_slot.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/pci/hotplug/rpaphp_slot.c b/drivers/pci/hotplug/rpaphp_slot.c index 865b0b7ef20c..9b9400727985 100644 --- a/drivers/pci/hotplug/rpaphp_slot.c +++ b/drivers/pci/hotplug/rpaphp_slot.c @@ -157,14 +157,13 @@ int rpaphp_register_slot(struct slot *slot) /* should not try to register the same slot twice */ if (is_registered(slot)) { err("rpaphp_register_slot: slot[%s] is already registered\n", slot->name); - retval = -EAGAIN; - goto register_fail; + return -EAGAIN; } retval = pci_hp_register(php_slot); if (retval) { err("pci_hp_register failed with error %d\n", retval); - goto register_fail; + return retval; } /* create "phy_location" file */ @@ -182,7 +181,6 @@ int rpaphp_register_slot(struct slot *slot) sysfs_fail: pci_hp_deregister(php_slot); -register_fail: return retval; } From 517d5a0417e19101eaa769039d1921d626ee546c Mon Sep 17 00:00:00 2001 From: Linas Vepstas Date: Fri, 13 Apr 2007 15:34:12 -0700 Subject: [PATCH 42/59] PCI: rpaphp: remove a function that does nothing but wrap debug printks Remove a stove-pipe-- a function that is called from only one place, does nothing but wraps another function with debug printk's. Signed-off-by: Linas Vepstas Cc: John Rose Signed-off-by: Kristen Carlson Accardi Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/rpaphp_pci.c | 37 +++++++++++--------------------- 1 file changed, 13 insertions(+), 24 deletions(-) diff --git a/drivers/pci/hotplug/rpaphp_pci.c b/drivers/pci/hotplug/rpaphp_pci.c index a669ba3f29c9..881e8073c807 100644 --- a/drivers/pci/hotplug/rpaphp_pci.c +++ b/drivers/pci/hotplug/rpaphp_pci.c @@ -116,23 +116,6 @@ static void print_slot_pci_funcs(struct pci_bus *bus) return; } -static int setup_pci_hotplug_slot_info(struct slot *slot) -{ - struct hotplug_slot_info *hotplug_slot_info = slot->hotplug_slot->info; - - dbg("%s Initilize the PCI slot's hotplug->info structure ...\n", - __FUNCTION__); - rpaphp_get_power_status(slot, &hotplug_slot_info->power_status); - rpaphp_get_pci_adapter_status(slot, 1, - &hotplug_slot_info->adapter_status); - if (hotplug_slot_info->adapter_status == NOT_VALID) { - err("%s: NOT_VALID: skip dn->full_name=%s\n", - __FUNCTION__, slot->dn->full_name); - return -EINVAL; - } - return 0; -} - static void set_slot_name(struct slot *slot) { struct pci_bus *bus = slot->bus; @@ -200,14 +183,20 @@ exit_rc: int rpaphp_register_pci_slot(struct slot *slot) { - int rc = -EINVAL; + struct hotplug_slot_info *info = slot->hotplug_slot->info; + + rpaphp_get_power_status(slot, &info->power_status); + rpaphp_get_pci_adapter_status(slot, 1, &info->adapter_status); + + if (info->adapter_status == NOT_VALID) { + err("%s: NOT_VALID: skip dn->full_name=%s\n", + __FUNCTION__, slot->dn->full_name); + return -EINVAL; + } - if (setup_pci_hotplug_slot_info(slot)) - goto exit_rc; if (setup_pci_slot(slot)) - goto exit_rc; - rc = rpaphp_register_slot(slot); -exit_rc: - return rc; + return -EINVAL; + + return rpaphp_register_slot(slot); } From 427310ff02e80cc80826407c0121cec3694c9e7d Mon Sep 17 00:00:00 2001 From: Linas Vepstas Date: Fri, 13 Apr 2007 15:34:13 -0700 Subject: [PATCH 43/59] PCI: rpaphp: Remve another call that is a wrapper Remove another stovepipe: a call which wraps another call, and just adds printks. Signed-off-by: Linas Vepstas Cc: John Rose Signed-off-by: Kristen Carlson Accardi Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/rpaphp.h | 1 - drivers/pci/hotplug/rpaphp_core.c | 6 ++++-- drivers/pci/hotplug/rpaphp_pci.c | 7 ++++++- drivers/pci/hotplug/rpaphp_slot.c | 18 ------------------ 4 files changed, 10 insertions(+), 22 deletions(-) diff --git a/drivers/pci/hotplug/rpaphp.h b/drivers/pci/hotplug/rpaphp.h index 2ccbe8d4229d..fdd99b2ebe5f 100644 --- a/drivers/pci/hotplug/rpaphp.h +++ b/drivers/pci/hotplug/rpaphp.h @@ -103,7 +103,6 @@ extern void dealloc_slot_struct(struct slot *slot); extern struct slot *alloc_slot_struct(struct device_node *dn, int drc_index, char *drc_name, int power_domain); extern int rpaphp_register_slot(struct slot *slot); extern int rpaphp_deregister_slot(struct slot *slot); -extern int rpaphp_get_power_status(struct slot *slot, u8 * value); extern int rpaphp_set_attention_status(struct slot *slot, u8 status); #endif /* _PPC64PHP_H */ diff --git a/drivers/pci/hotplug/rpaphp_core.c b/drivers/pci/hotplug/rpaphp_core.c index ca95e1515d6f..2d919fb1931c 100644 --- a/drivers/pci/hotplug/rpaphp_core.c +++ b/drivers/pci/hotplug/rpaphp_core.c @@ -100,11 +100,13 @@ static int set_attention_status(struct hotplug_slot *hotplug_slot, u8 value) */ static int get_power_status(struct hotplug_slot *hotplug_slot, u8 * value) { - int retval; + int retval, level; struct slot *slot = (struct slot *)hotplug_slot->private; down(&rpaphp_sem); - retval = rpaphp_get_power_status(slot, value); + retval = rtas_get_power_level (slot->power_domain, &level); + if (!retval) + *value = level; up(&rpaphp_sem); return retval; } diff --git a/drivers/pci/hotplug/rpaphp_pci.c b/drivers/pci/hotplug/rpaphp_pci.c index 881e8073c807..ba8c83770abe 100644 --- a/drivers/pci/hotplug/rpaphp_pci.c +++ b/drivers/pci/hotplug/rpaphp_pci.c @@ -183,9 +183,14 @@ exit_rc: int rpaphp_register_pci_slot(struct slot *slot) { + int rc, level; struct hotplug_slot_info *info = slot->hotplug_slot->info; - rpaphp_get_power_status(slot, &info->power_status); + rc = rtas_get_power_level(slot->power_domain, &level); + if (rc) + return rc; + info->power_status = level; + rpaphp_get_pci_adapter_status(slot, 1, &info->adapter_status); if (info->adapter_status == NOT_VALID) { diff --git a/drivers/pci/hotplug/rpaphp_slot.c b/drivers/pci/hotplug/rpaphp_slot.c index 9b9400727985..30c9dc98e4ec 100644 --- a/drivers/pci/hotplug/rpaphp_slot.c +++ b/drivers/pci/hotplug/rpaphp_slot.c @@ -184,24 +184,6 @@ sysfs_fail: return retval; } -int rpaphp_get_power_status(struct slot *slot, u8 * value) -{ - int rc = 0, level; - - rc = rtas_get_power_level(slot->power_domain, &level); - if (rc < 0) { - err("failed to get power-level for slot(%s), rc=0x%x\n", - slot->location, rc); - return rc; - } - - dbg("%s the power level of slot %s(pwd-domain:0x%x) is %d\n", - __FUNCTION__, slot->name, slot->power_domain, level); - *value = level; - - return rc; -} - int rpaphp_set_attention_status(struct slot *slot, u8 status) { int rc; From bf0af511fcc856649a2a39c627828695b580d124 Mon Sep 17 00:00:00 2001 From: Linas Vepstas Date: Fri, 13 Apr 2007 15:34:14 -0700 Subject: [PATCH 44/59] PCI: rpaphp: Remove another wrappered function Remove another stove-pipe; this funcion was called from two different places, with a compile-time const that is then run-time checked to perform two different things. Signed-off-by: Linas Vepstas Cc: John Rose Signed-off-by: Kristen Carlson Accardi Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/rpaphp.h | 1 - drivers/pci/hotplug/rpaphp_core.c | 16 +++++++-- drivers/pci/hotplug/rpaphp_pci.c | 59 +++++++++---------------------- 3 files changed, 29 insertions(+), 47 deletions(-) diff --git a/drivers/pci/hotplug/rpaphp.h b/drivers/pci/hotplug/rpaphp.h index fdd99b2ebe5f..a2b22575cf77 100644 --- a/drivers/pci/hotplug/rpaphp.h +++ b/drivers/pci/hotplug/rpaphp.h @@ -89,7 +89,6 @@ extern struct list_head rpaphp_slot_head; /* rpaphp_pci.c */ extern int rpaphp_enable_pci_slot(struct slot *slot); extern int rpaphp_register_pci_slot(struct slot *slot); -extern int rpaphp_get_pci_adapter_status(struct slot *slot, int is_init, u8 * value); extern int rpaphp_get_sensor_state(struct slot *slot, int *state); /* rpaphp_core.c */ diff --git a/drivers/pci/hotplug/rpaphp_core.c b/drivers/pci/hotplug/rpaphp_core.c index 2d919fb1931c..cab7cee65741 100644 --- a/drivers/pci/hotplug/rpaphp_core.c +++ b/drivers/pci/hotplug/rpaphp_core.c @@ -130,12 +130,22 @@ static int get_attention_status(struct hotplug_slot *hotplug_slot, u8 * value) static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 * value) { struct slot *slot = (struct slot *)hotplug_slot->private; - int retval = 0; + int rc, state; down(&rpaphp_sem); - retval = rpaphp_get_pci_adapter_status(slot, 0, value); + rc = rpaphp_get_sensor_state(slot, &state); up(&rpaphp_sem); - return retval; + + *value = NOT_VALID; + if (rc) + return rc; + + if (state == EMPTY) + *value = EMPTY; + else if (state == PRESENT) + *value = slot->state; + + return 0; } static int get_max_bus_speed(struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value) diff --git a/drivers/pci/hotplug/rpaphp_pci.c b/drivers/pci/hotplug/rpaphp_pci.c index ba8c83770abe..b6a991ab9b7e 100644 --- a/drivers/pci/hotplug/rpaphp_pci.c +++ b/drivers/pci/hotplug/rpaphp_pci.c @@ -64,43 +64,6 @@ int rpaphp_get_sensor_state(struct slot *slot, int *state) return rc; } -/** - * get_pci_adapter_status - get the status of a slot - * - * 0-- slot is empty - * 1-- adapter is configured - * 2-- adapter is not configured - * 3-- not valid - */ -int rpaphp_get_pci_adapter_status(struct slot *slot, int is_init, u8 * value) -{ - struct pci_bus *bus; - int state, rc; - - *value = NOT_VALID; - rc = rpaphp_get_sensor_state(slot, &state); - if (rc) - goto exit; - - if (state == EMPTY) - *value = EMPTY; - else if (state == PRESENT) { - if (!is_init) { - /* at run-time slot->state can be changed by */ - /* config/unconfig adapter */ - *value = slot->state; - } else { - bus = pcibios_find_pci_bus(slot->dn); - if (bus && !list_empty(&bus->devices)) - *value = CONFIGURED; - else - *value = NOT_CONFIGURED; - } - } -exit: - return rc; -} - static void print_slot_pci_funcs(struct pci_bus *bus) { struct device_node *dn; @@ -183,20 +146,30 @@ exit_rc: int rpaphp_register_pci_slot(struct slot *slot) { - int rc, level; + int rc, level, state; + struct pci_bus *bus; struct hotplug_slot_info *info = slot->hotplug_slot->info; + /* Find out if the power is turned on for the slot */ rc = rtas_get_power_level(slot->power_domain, &level); if (rc) return rc; info->power_status = level; - rpaphp_get_pci_adapter_status(slot, 1, &info->adapter_status); + /* Figure out if there is an adapter in the slot */ + info->adapter_status = NOT_VALID; + rc = rpaphp_get_sensor_state(slot, &state); + if (rc) + return rc; - if (info->adapter_status == NOT_VALID) { - err("%s: NOT_VALID: skip dn->full_name=%s\n", - __FUNCTION__, slot->dn->full_name); - return -EINVAL; + if (state == EMPTY) + info->adapter_status = EMPTY; + else if (state == PRESENT) { + bus = pcibios_find_pci_bus(slot->dn); + if (bus && !list_empty(&bus->devices)) + info->adapter_status = CONFIGURED; + else + info->adapter_status = NOT_CONFIGURED; } if (setup_pci_slot(slot)) From ebf42c0edd5ee325043d4ae8fbb8caebd707e791 Mon Sep 17 00:00:00 2001 From: Linas Vepstas Date: Fri, 13 Apr 2007 15:34:15 -0700 Subject: [PATCH 45/59] PCI: rpaphp: remove a call that does nothing but a pointer lookup Delete another stovepipe: a call to a routine which does nothing. Remove un-needed semaphore as well. Signed-off-by: Linas Vepstas Cc: John Rose Signed-off-by: Kristen Carlson Accardi Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/rpaphp_core.c | 17 ++--------------- 1 file changed, 2 insertions(+), 15 deletions(-) diff --git a/drivers/pci/hotplug/rpaphp_core.c b/drivers/pci/hotplug/rpaphp_core.c index cab7cee65741..3970cacc0b86 100644 --- a/drivers/pci/hotplug/rpaphp_core.c +++ b/drivers/pci/hotplug/rpaphp_core.c @@ -54,11 +54,6 @@ MODULE_LICENSE("GPL"); module_param(debug, bool, 0644); -static int rpaphp_get_attention_status(struct slot *slot) -{ - return slot->hotplug_slot->info->attention_status; -} - /** * set_attention_status - set attention LED * echo 0 > attention -- set LED OFF @@ -95,8 +90,6 @@ static int set_attention_status(struct hotplug_slot *hotplug_slot, u8 value) * get_power_status - get power status of a slot * @hotplug_slot: slot to get status * @value: pointer to store status - * - * */ static int get_power_status(struct hotplug_slot *hotplug_slot, u8 * value) { @@ -113,18 +106,12 @@ static int get_power_status(struct hotplug_slot *hotplug_slot, u8 * value) /** * get_attention_status - get attention LED status - * - * */ static int get_attention_status(struct hotplug_slot *hotplug_slot, u8 * value) { - int retval = 0; struct slot *slot = (struct slot *)hotplug_slot->private; - - down(&rpaphp_sem); - *value = rpaphp_get_attention_status(slot); - up(&rpaphp_sem); - return retval; + *value = slot->hotplug_slot->info->attention_status; + return 0; } static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 * value) From 03a667559138d47cea487823332c4712fc6fbec7 Mon Sep 17 00:00:00 2001 From: Linas Vepstas Date: Fri, 13 Apr 2007 15:34:16 -0700 Subject: [PATCH 46/59] PCI: rpaphp: Remove setup_pci_slot() The setup_pci_slot() routine appears to be nothing else than a big, complicated wrapper around pcibios_add_pci_devices(). Remove the wrapping, and call pcibios_add_pci_devices() directly. Signed-off-by: Linas Vepstas Cc: John Rose Signed-off-by: Kristen Carlson Accardi Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/rpaphp_pci.c | 96 +++++++++++--------------------- 1 file changed, 33 insertions(+), 63 deletions(-) diff --git a/drivers/pci/hotplug/rpaphp_pci.c b/drivers/pci/hotplug/rpaphp_pci.c index b6a991ab9b7e..6417b7074ed4 100644 --- a/drivers/pci/hotplug/rpaphp_pci.c +++ b/drivers/pci/hotplug/rpaphp_pci.c @@ -92,64 +92,15 @@ static void set_slot_name(struct slot *slot) bus->number); } -static int setup_pci_slot(struct slot *slot) -{ - struct device_node *dn = slot->dn; - struct pci_bus *bus; - - BUG_ON(!dn); - bus = pcibios_find_pci_bus(dn); - if (!bus) { - err("%s: no pci_bus for dn %s\n", __FUNCTION__, dn->full_name); - goto exit_rc; - } - - slot->bus = bus; - slot->pci_devs = &bus->devices; - set_slot_name(slot); - - /* find slot's pci_dev if it's not empty */ - if (slot->hotplug_slot->info->adapter_status == EMPTY) { - slot->state = EMPTY; /* slot is empty */ - } else { - /* slot is occupied */ - if (!dn->child) { - /* non-empty slot has to have child */ - err("%s: slot[%s]'s device_node doesn't have child for adapter\n", - __FUNCTION__, slot->name); - goto exit_rc; - } - - if (slot->hotplug_slot->info->adapter_status == NOT_CONFIGURED) { - dbg("%s CONFIGURING pci adapter in slot[%s]\n", - __FUNCTION__, slot->name); - pcibios_add_pci_devices(slot->bus); - - } else if (slot->hotplug_slot->info->adapter_status != CONFIGURED) { - err("%s: slot[%s]'s adapter_status is NOT_VALID.\n", - __FUNCTION__, slot->name); - goto exit_rc; - } - print_slot_pci_funcs(slot->bus); - if (!list_empty(slot->pci_devs)) { - slot->state = CONFIGURED; - } else { - /* DLPAR add as opposed to - * boot time */ - slot->state = NOT_CONFIGURED; - } - } - return 0; -exit_rc: - return -EINVAL; -} - int rpaphp_register_pci_slot(struct slot *slot) { int rc, level, state; struct pci_bus *bus; struct hotplug_slot_info *info = slot->hotplug_slot->info; + info->adapter_status = NOT_VALID; + slot->state = EMPTY; + /* Find out if the power is turned on for the slot */ rc = rtas_get_power_level(slot->power_domain, &level); if (rc) @@ -157,23 +108,42 @@ int rpaphp_register_pci_slot(struct slot *slot) info->power_status = level; /* Figure out if there is an adapter in the slot */ - info->adapter_status = NOT_VALID; rc = rpaphp_get_sensor_state(slot, &state); if (rc) return rc; - if (state == EMPTY) - info->adapter_status = EMPTY; - else if (state == PRESENT) { - bus = pcibios_find_pci_bus(slot->dn); - if (bus && !list_empty(&bus->devices)) - info->adapter_status = CONFIGURED; - else - info->adapter_status = NOT_CONFIGURED; + bus = pcibios_find_pci_bus(slot->dn); + if (!bus) { + err("%s: no pci_bus for dn %s\n", __FUNCTION__, slot->dn->full_name); + return -EINVAL; } - if (setup_pci_slot(slot)) - return -EINVAL; + info->adapter_status = EMPTY; + slot->bus = bus; + slot->pci_devs = &bus->devices; + set_slot_name(slot); + + /* if there's an adapter in the slot, go add the pci devices */ + if (state == PRESENT) { + info->adapter_status = NOT_CONFIGURED; + slot->state = NOT_CONFIGURED; + + /* non-empty slot has to have child */ + if (!slot->dn->child) { + err("%s: slot[%s]'s device_node doesn't have child for adapter\n", + __FUNCTION__, slot->name); + return -EINVAL; + } + + if (list_empty(&bus->devices)) + pcibios_add_pci_devices(bus); + + print_slot_pci_funcs(bus); + if (!list_empty(&bus->devices)) { + info->adapter_status = CONFIGURED; + slot->state = CONFIGURED; + } + } return rpaphp_register_slot(slot); } From 307ff12e35526cfab9f09cafcb17239286e6eb85 Mon Sep 17 00:00:00 2001 From: Linas Vepstas Date: Fri, 13 Apr 2007 15:34:17 -0700 Subject: [PATCH 47/59] PCI: rpaphp: remove print_slot_pci_funcs() The debug function print_slot_pci_funcs() is a large wrapper around two debug print statements. Just invoke these directly. Signed-off-by: Linas Vepstas Cc: John Rose Signed-off-by: Kristen Carlson Accardi Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/rpaphp_pci.c | 23 +++++++---------------- 1 file changed, 7 insertions(+), 16 deletions(-) diff --git a/drivers/pci/hotplug/rpaphp_pci.c b/drivers/pci/hotplug/rpaphp_pci.c index 6417b7074ed4..6271be8b155e 100644 --- a/drivers/pci/hotplug/rpaphp_pci.c +++ b/drivers/pci/hotplug/rpaphp_pci.c @@ -64,21 +64,6 @@ int rpaphp_get_sensor_state(struct slot *slot, int *state) return rc; } -static void print_slot_pci_funcs(struct pci_bus *bus) -{ - struct device_node *dn; - struct pci_dev *dev; - - dn = pci_bus_to_OF_node(bus); - if (!dn) - return; - - dbg("%s: pci_devs of slot[%s]\n", __FUNCTION__, dn->full_name); - list_for_each_entry (dev, &bus->devices, bus_list) - dbg("\t%s\n", pci_name(dev)); - return; -} - static void set_slot_name(struct slot *slot) { struct pci_bus *bus = slot->bus; @@ -138,11 +123,17 @@ int rpaphp_register_pci_slot(struct slot *slot) if (list_empty(&bus->devices)) pcibios_add_pci_devices(bus); - print_slot_pci_funcs(bus); if (!list_empty(&bus->devices)) { info->adapter_status = CONFIGURED; slot->state = CONFIGURED; } + + if (debug) { + struct pci_dev *dev; + dbg("%s: pci_devs of slot[%s]\n", __FUNCTION__, slot->dn->full_name); + list_for_each_entry (dev, &bus->devices, bus_list) + dbg("\t%s\n", pci_name(dev)); + } } return rpaphp_register_slot(slot); From c02929c278f2bca68635e4c2daa00b7825d71061 Mon Sep 17 00:00:00 2001 From: Linas Vepstas Date: Fri, 13 Apr 2007 15:34:18 -0700 Subject: [PATCH 48/59] PCI: rpaphp: remove rpaphp_set_attention_status() The rpaphp_set_attention_status() routine seems to be a wrapper around a single rtas call. Abolish it. Signed-off-by: Linas Vepstas Cc: John Rose Signed-off-by: Kristen Carlson Accardi Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/rpaphp.h | 1 - drivers/pci/hotplug/rpaphp_core.c | 21 ++++++++++----------- drivers/pci/hotplug/rpaphp_slot.c | 12 ------------ 3 files changed, 10 insertions(+), 24 deletions(-) diff --git a/drivers/pci/hotplug/rpaphp.h b/drivers/pci/hotplug/rpaphp.h index a2b22575cf77..e28e93cd00fd 100644 --- a/drivers/pci/hotplug/rpaphp.h +++ b/drivers/pci/hotplug/rpaphp.h @@ -102,6 +102,5 @@ extern void dealloc_slot_struct(struct slot *slot); extern struct slot *alloc_slot_struct(struct device_node *dn, int drc_index, char *drc_name, int power_domain); extern int rpaphp_register_slot(struct slot *slot); extern int rpaphp_deregister_slot(struct slot *slot); -extern int rpaphp_set_attention_status(struct slot *slot, u8 status); #endif /* _PPC64PHP_H */ diff --git a/drivers/pci/hotplug/rpaphp_core.c b/drivers/pci/hotplug/rpaphp_core.c index 3970cacc0b86..e9c157d30e82 100644 --- a/drivers/pci/hotplug/rpaphp_core.c +++ b/drivers/pci/hotplug/rpaphp_core.c @@ -63,27 +63,26 @@ module_param(debug, bool, 0644); */ static int set_attention_status(struct hotplug_slot *hotplug_slot, u8 value) { - int retval = 0; + int rc; struct slot *slot = (struct slot *)hotplug_slot->private; down(&rpaphp_sem); switch (value) { case 0: - retval = rpaphp_set_attention_status(slot, LED_OFF); - hotplug_slot->info->attention_status = 0; - break; case 1: - default: - retval = rpaphp_set_attention_status(slot, LED_ON); - hotplug_slot->info->attention_status = 1; - break; case 2: - retval = rpaphp_set_attention_status(slot, LED_ID); - hotplug_slot->info->attention_status = 2; + break; + default: + value = 1; break; } up(&rpaphp_sem); - return retval; + + rc = rtas_set_indicator(DR_INDICATOR, slot->index, value); + if (!rc) + hotplug_slot->info->attention_status = value; + + return rc; } /** diff --git a/drivers/pci/hotplug/rpaphp_slot.c b/drivers/pci/hotplug/rpaphp_slot.c index 30c9dc98e4ec..d4ee8723fcb3 100644 --- a/drivers/pci/hotplug/rpaphp_slot.c +++ b/drivers/pci/hotplug/rpaphp_slot.c @@ -184,15 +184,3 @@ sysfs_fail: return retval; } -int rpaphp_set_attention_status(struct slot *slot, u8 status) -{ - int rc; - - /* status: LED_OFF or LED_ON */ - rc = rtas_set_indicator(DR_INDICATOR, slot->index, status); - if (rc < 0) - err("slot(name=%s location=%s index=0x%x) set attention-status(%d) failed! rc=0x%x\n", - slot->name, slot->location, slot->index, status, rc); - - return rc; -} From 6f79eb749df7f1eea76c947f31603ade7d2b5f6d Mon Sep 17 00:00:00 2001 From: Linas Vepstas Date: Fri, 13 Apr 2007 15:34:19 -0700 Subject: [PATCH 49/59] PCI: rpaphp: refactor tail call to rpaphp_register_slot() Eliminate the tail call to rpaphp_register_slot() by placing it in the caller. This will help later dis-entanglement. Signed-off-by: Linas Vepstas Cc: John Rose Signed-off-by: Kristen Carlson Accardi Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/rpaphp_core.c | 3 +++ drivers/pci/hotplug/rpaphp_pci.c | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/pci/hotplug/rpaphp_core.c b/drivers/pci/hotplug/rpaphp_core.c index e9c157d30e82..d8e5f9fd357d 100644 --- a/drivers/pci/hotplug/rpaphp_core.c +++ b/drivers/pci/hotplug/rpaphp_core.c @@ -319,6 +319,9 @@ int rpaphp_add_slot(struct device_node *dn) indexes[i + 1], name, type); retval = rpaphp_register_pci_slot(slot); + if (!retval) + retval = rpaphp_register_slot(slot); + if (retval) dealloc_slot_struct(slot); diff --git a/drivers/pci/hotplug/rpaphp_pci.c b/drivers/pci/hotplug/rpaphp_pci.c index 6271be8b155e..2e297b9ffa75 100644 --- a/drivers/pci/hotplug/rpaphp_pci.c +++ b/drivers/pci/hotplug/rpaphp_pci.c @@ -136,6 +136,6 @@ int rpaphp_register_pci_slot(struct slot *slot) } } - return rpaphp_register_slot(slot); + return 0; } From fea54b8cc9c8290b4c99d481c3e600c46eb18fd5 Mon Sep 17 00:00:00 2001 From: Linas Vepstas Date: Fri, 13 Apr 2007 15:34:20 -0700 Subject: [PATCH 50/59] PCI: rpaphp: Rename rpaphp_register_pci_slot() to rpaphp_enable_slot() Rename rpaphp_register_pci_slot() because its easy to confuse with rpaphp_register_slot() even though it does something completely different. Rename it to rpaphp_enable_slot() because its almost identical to enbale_slot(). Signed-off-by: Linas Vepstas Cc: John Rose Signed-off-by: Kristen Carlson Accardi Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/rpaphp.h | 4 +--- drivers/pci/hotplug/rpaphp_core.c | 2 +- drivers/pci/hotplug/rpaphp_pci.c | 10 +++++++++- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/drivers/pci/hotplug/rpaphp.h b/drivers/pci/hotplug/rpaphp.h index e28e93cd00fd..c822a779653f 100644 --- a/drivers/pci/hotplug/rpaphp.h +++ b/drivers/pci/hotplug/rpaphp.h @@ -87,13 +87,11 @@ extern struct list_head rpaphp_slot_head; /* function prototypes */ /* rpaphp_pci.c */ -extern int rpaphp_enable_pci_slot(struct slot *slot); -extern int rpaphp_register_pci_slot(struct slot *slot); +extern int rpaphp_enable_slot(struct slot *slot); extern int rpaphp_get_sensor_state(struct slot *slot, int *state); /* rpaphp_core.c */ extern int rpaphp_add_slot(struct device_node *dn); -extern int rpaphp_remove_slot(struct slot *slot); extern int rpaphp_get_drc_props(struct device_node *dn, int *drc_index, char **drc_name, char **drc_type, int *drc_power_domain); diff --git a/drivers/pci/hotplug/rpaphp_core.c b/drivers/pci/hotplug/rpaphp_core.c index d8e5f9fd357d..75113d9e84ee 100644 --- a/drivers/pci/hotplug/rpaphp_core.c +++ b/drivers/pci/hotplug/rpaphp_core.c @@ -318,7 +318,7 @@ int rpaphp_add_slot(struct device_node *dn) dbg("Found drc-index:0x%x drc-name:%s drc-type:%s\n", indexes[i + 1], name, type); - retval = rpaphp_register_pci_slot(slot); + retval = rpaphp_enable_slot(slot); if (!retval) retval = rpaphp_register_slot(slot); diff --git a/drivers/pci/hotplug/rpaphp_pci.c b/drivers/pci/hotplug/rpaphp_pci.c index 2e297b9ffa75..54ca8650d511 100644 --- a/drivers/pci/hotplug/rpaphp_pci.c +++ b/drivers/pci/hotplug/rpaphp_pci.c @@ -77,7 +77,15 @@ static void set_slot_name(struct slot *slot) bus->number); } -int rpaphp_register_pci_slot(struct slot *slot) +/** + * rpaphp_enable_slot - record slot state, config pci device + * + * Initialize values in the slot, and the hotplug_slot info + * structures to indicate if there is a pci card plugged into + * the slot. If the slot is not empty, run the pcibios routine + * to get pcibios stuff correctly set up. + */ +int rpaphp_enable_slot(struct slot *slot) { int rc, level, state; struct pci_bus *bus; From 8485d1a123e0d367bbcbfec36acf134e6895f39a Mon Sep 17 00:00:00 2001 From: Linas Vepstas Date: Fri, 13 Apr 2007 15:34:21 -0700 Subject: [PATCH 51/59] PCI: rpaphp: Document find_php_slot() Document some of the interaction between dlpar and hotplug. viz, the a dlpar remove of a htoplug slot uses hotplug to remove it. Signed-off-by: Linas Vepstas Cc: John Rose Signed-off-by: Kristen Carlson Accardi Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/rpadlpar_core.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/drivers/pci/hotplug/rpadlpar_core.c b/drivers/pci/hotplug/rpadlpar_core.c index 72383467a0d5..4d74f0b6079f 100644 --- a/drivers/pci/hotplug/rpadlpar_core.c +++ b/drivers/pci/hotplug/rpadlpar_core.c @@ -98,7 +98,15 @@ static struct device_node *find_dlpar_node(char *drc_name, int *node_type) return NULL; } -static struct slot *find_slot(struct device_node *dn) +/** + * find_php_slot - return hotplug slot structure for device node + * + * This routine will return the hotplug slot structure + * for a given device node. Note that built-in PCI slots + * may be dlpar-able, but not hot-pluggable, so this routine + * will return NULL for built-in PCI slots. + */ +static struct slot *find_php_slot(struct device_node *dn) { struct list_head *tmp, *n; struct slot *slot; @@ -224,9 +232,9 @@ static int dlpar_remove_phb(char *drc_name, struct device_node *dn) if (!pcibios_find_pci_bus(dn)) return -EINVAL; - slot = find_slot(dn); + /* If pci slot is hotplugable, use hotplug to remove it */ + slot = find_php_slot(dn); if (slot) { - /* Remove hotplug slot */ if (rpaphp_deregister_slot(slot)) { printk(KERN_ERR "%s: unable to remove hotplug slot %s\n", @@ -370,9 +378,9 @@ int dlpar_remove_pci_slot(char *drc_name, struct device_node *dn) if (!bus) return -EINVAL; - slot = find_slot(dn); + /* If pci slot is hotplugable, use hotplug to remove it */ + slot = find_php_slot(dn); if (slot) { - /* Remove hotplug slot */ if (rpaphp_deregister_slot(slot)) { printk(KERN_ERR "%s: unable to remove hotplug slot %s\n", From da65944be2441191539f50ce71cd1f8030699be1 Mon Sep 17 00:00:00 2001 From: Linas Vepstas Date: Fri, 13 Apr 2007 15:34:22 -0700 Subject: [PATCH 52/59] PCI: rpaphp: Document is_php_dn() Fix up the documentation: the rpaphp_add_slot() does not actually handle embedded slots: in fact, it ignores them. Fix the flow of control in the routine that checks for embedded slots. Signed-off-by: Linas Vepstas Cc: John Rose Signed-off-by: Kristen Carlson Accardi Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/rpaphp_core.c | 42 +++++++++++++++++++++---------- 1 file changed, 29 insertions(+), 13 deletions(-) diff --git a/drivers/pci/hotplug/rpaphp_core.c b/drivers/pci/hotplug/rpaphp_core.c index 75113d9e84ee..aa8d9a60d0a6 100644 --- a/drivers/pci/hotplug/rpaphp_core.c +++ b/drivers/pci/hotplug/rpaphp_core.c @@ -262,6 +262,14 @@ static int is_php_type(char *drc_type) return 1; } +/** + * is_php_dn() - return 1 if this is a hotpluggable pci slot, else 0 + * + * This routine will return true only if the device node is + * a hotpluggable slot. This routine will return false + * for built-in pci slots (even when the built-in slots are + * dlparable.) + */ static int is_php_dn(struct device_node *dn, const int **indexes, const int **names, const int **types, const int **power_domains) { @@ -269,24 +277,31 @@ static int is_php_dn(struct device_node *dn, const int **indexes, int rc; rc = get_children_props(dn, indexes, names, &drc_types, power_domains); - if (rc >= 0) { - if (is_php_type((char *) &drc_types[1])) { - *types = drc_types; - return 1; - } - } + if (rc < 0) + return 0; - return 0; + if (!is_php_type((char *) &drc_types[1])) + return 0; + + *types = drc_types; + return 1; } /** - * rpaphp_add_slot -- add hotplug or dlpar slot + * rpaphp_add_slot -- declare a hotplug slot to the hotplug subsystem. + * @dn device node of slot * - * rpaphp not only registers PCI hotplug slots(HOTPLUG), - * but also logical DR slots(EMBEDDED). - * HOTPLUG slot: An adapter can be physically added/removed. - * EMBEDDED slot: An adapter can be logically removed/added - * from/to a partition with the slot. + * This subroutine will register a hotplugable slot with the + * PCI hotplug infrastructure. This routine is typicaly called + * during boot time, if the hotplug slots are present at boot time, + * or is called later, by the dlpar add code, if the slot is + * being dynamically added during runtime. + * + * If the device node points at an embedded (built-in) slot, this + * routine will just return without doing anything, since embedded + * slots cannot be hotplugged. + * + * To remove a slot, it suffices to call rpaphp_deregister_slot() */ int rpaphp_add_slot(struct device_node *dn) { @@ -299,6 +314,7 @@ int rpaphp_add_slot(struct device_node *dn) if (!dn->name || strcmp(dn->name, "pci")) return 0; + /* If this is not a hotplug slot, return without doing anything. */ if (!is_php_dn(dn, &indexes, &names, &types, &power_domains)) return 0; From e70ea2634afe7d04ffaf7417df7bfdbfdc460e10 Mon Sep 17 00:00:00 2001 From: Linas Vepstas Date: Fri, 13 Apr 2007 15:34:23 -0700 Subject: [PATCH 53/59] PCI: rpaphp: Use pcibios_remove_pci_devices() symmetrically At first blush, the disable_slot() routine does not look at all like its symmetric with the enable_slot() routine; as it seems to call a very different set of routines. However, this is easily fixed: pcibios_remove_pci_devices() does the right thing. Signed-off-by: Linas Vepstas Cc: John Rose Signed-off-by: Kristen Carlson Accardi Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/rpaphp_core.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/drivers/pci/hotplug/rpaphp_core.c b/drivers/pci/hotplug/rpaphp_core.c index aa8d9a60d0a6..4efdaa19e8f9 100644 --- a/drivers/pci/hotplug/rpaphp_core.c +++ b/drivers/pci/hotplug/rpaphp_core.c @@ -424,18 +424,12 @@ static int enable_slot(struct hotplug_slot *hotplug_slot) return retval; } -static int __disable_slot(struct slot *slot) +static inline int __disable_slot(struct slot *slot) { - struct pci_dev *dev, *tmp; - if (slot->state == NOT_CONFIGURED) return -EINVAL; - list_for_each_entry_safe(dev, tmp, &slot->bus->devices, bus_list) { - eeh_remove_bus_device(dev); - pci_remove_bus_device(dev); - } - + pcibios_remove_pci_devices(slot->bus); slot->state = NOT_CONFIGURED; return 0; } From b5661479eeb863749ae28b9ee0dd288464311854 Mon Sep 17 00:00:00 2001 From: Linas Vepstas Date: Fri, 13 Apr 2007 15:34:24 -0700 Subject: [PATCH 54/59] PCI: rpaphp: Ensure more pcibios_add/pcibios_remove symmetry Calls to pcibios_add should be symmetric with calls to pcibios_remove. Signed-off-by: Linas Vepstas Cc: John Rose Signed-off-by: Kristen Carlson Accardi Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/rpadlpar_core.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/drivers/pci/hotplug/rpadlpar_core.c b/drivers/pci/hotplug/rpadlpar_core.c index 4d74f0b6079f..bb3c101c2c5a 100644 --- a/drivers/pci/hotplug/rpadlpar_core.c +++ b/drivers/pci/hotplug/rpadlpar_core.c @@ -387,13 +387,8 @@ int dlpar_remove_pci_slot(char *drc_name, struct device_node *dn) __FUNCTION__, drc_name); return -EIO; } - } else { - struct pci_dev *dev, *tmp; - list_for_each_entry_safe(dev, tmp, &bus->devices, bus_list) { - eeh_remove_bus_device(dev); - pci_remove_bus_device(dev); - } - } + } else + pcibios_remove_pci_devices(bus); if (unmap_bus_range(bus)) { printk(KERN_ERR "%s: failed to unmap bus range\n", From ac1f0e9923356652f21756526e194a4a1a37dd38 Mon Sep 17 00:00:00 2001 From: Linas Vepstas Date: Fri, 13 Apr 2007 15:34:25 -0700 Subject: [PATCH 55/59] PCI: rpaphp: Remove semaphores Remove the semaphores from the get routine. These do not appear to be protecting anything that I can make out, and they also do not seem to be required by the hotplug driver. Signed-off-by: Linas Vepstas Cc: John Rose Signed-off-by: Kristen Carlson Accardi Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/rpaphp_core.c | 38 +++---------------------------- 1 file changed, 3 insertions(+), 35 deletions(-) diff --git a/drivers/pci/hotplug/rpaphp_core.c b/drivers/pci/hotplug/rpaphp_core.c index 4efdaa19e8f9..847936fe327e 100644 --- a/drivers/pci/hotplug/rpaphp_core.c +++ b/drivers/pci/hotplug/rpaphp_core.c @@ -39,7 +39,6 @@ #include "rpaphp.h" int debug; -static struct semaphore rpaphp_sem; LIST_HEAD(rpaphp_slot_head); #define DRIVER_VERSION "0.1" @@ -66,7 +65,6 @@ static int set_attention_status(struct hotplug_slot *hotplug_slot, u8 value) int rc; struct slot *slot = (struct slot *)hotplug_slot->private; - down(&rpaphp_sem); switch (value) { case 0: case 1: @@ -76,7 +74,6 @@ static int set_attention_status(struct hotplug_slot *hotplug_slot, u8 value) value = 1; break; } - up(&rpaphp_sem); rc = rtas_set_indicator(DR_INDICATOR, slot->index, value); if (!rc) @@ -95,11 +92,9 @@ static int get_power_status(struct hotplug_slot *hotplug_slot, u8 * value) int retval, level; struct slot *slot = (struct slot *)hotplug_slot->private; - down(&rpaphp_sem); retval = rtas_get_power_level (slot->power_domain, &level); if (!retval) *value = level; - up(&rpaphp_sem); return retval; } @@ -118,9 +113,7 @@ static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 * value) struct slot *slot = (struct slot *)hotplug_slot->private; int rc, state; - down(&rpaphp_sem); rc = rpaphp_get_sensor_state(slot, &state); - up(&rpaphp_sem); *value = NOT_VALID; if (rc) @@ -138,7 +131,6 @@ static int get_max_bus_speed(struct hotplug_slot *hotplug_slot, enum pci_bus_spe { struct slot *slot = (struct slot *)hotplug_slot->private; - down(&rpaphp_sem); switch (slot->type) { case 1: case 2: @@ -169,7 +161,6 @@ static int get_max_bus_speed(struct hotplug_slot *hotplug_slot, enum pci_bus_spe break; } - up(&rpaphp_sem); return 0; } @@ -374,7 +365,6 @@ static int __init rpaphp_init(void) struct device_node *dn = NULL; info(DRIVER_DESC " version: " DRIVER_VERSION "\n"); - init_MUTEX(&rpaphp_sem); while ((dn = of_find_node_by_name(dn, "pci"))) rpaphp_add_slot(dn); @@ -387,8 +377,9 @@ static void __exit rpaphp_exit(void) cleanup_slots(); } -static int __enable_slot(struct slot *slot) +static int enable_slot(struct hotplug_slot *hotplug_slot) { + struct slot *slot = (struct slot *)hotplug_slot->private; int state; int retval; @@ -412,20 +403,9 @@ static int __enable_slot(struct slot *slot) return 0; } -static int enable_slot(struct hotplug_slot *hotplug_slot) +static int disable_slot(struct hotplug_slot *hotplug_slot) { - int retval; struct slot *slot = (struct slot *)hotplug_slot->private; - - down(&rpaphp_sem); - retval = __enable_slot(slot); - up(&rpaphp_sem); - - return retval; -} - -static inline int __disable_slot(struct slot *slot) -{ if (slot->state == NOT_CONFIGURED) return -EINVAL; @@ -434,18 +414,6 @@ static inline int __disable_slot(struct slot *slot) return 0; } -static int disable_slot(struct hotplug_slot *hotplug_slot) -{ - struct slot *slot = (struct slot *)hotplug_slot->private; - int retval; - - down(&rpaphp_sem); - retval = __disable_slot (slot); - up(&rpaphp_sem); - - return retval; -} - struct hotplug_slot_ops rpaphp_hotplug_slot_ops = { .owner = THIS_MODULE, .enable_slot = enable_slot, From 03555d591d2c8ee9291db171c0d21d3c9cab04d9 Mon Sep 17 00:00:00 2001 From: Scott Murray Date: Fri, 13 Apr 2007 15:34:26 -0700 Subject: [PATCH 56/59] PCI: ZT5550 CPCI Hotplug driver fix cc: Philip Guo Here's a small patch against the current git tree for the ZT5550 CPCI hotplug driver to fix an issue with port freeing that Philip Guo found. Signed-off-by: Scott Murray Signed-off-by: Kristen Carlson Accardi Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/cpcihp_zt5550.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/pci/hotplug/cpcihp_zt5550.c b/drivers/pci/hotplug/cpcihp_zt5550.c index 1c12e9171097..41f6a8d79c81 100644 --- a/drivers/pci/hotplug/cpcihp_zt5550.c +++ b/drivers/pci/hotplug/cpcihp_zt5550.c @@ -296,13 +296,17 @@ static struct pci_driver zt5550_hc_driver = { static int __init zt5550_init(void) { struct resource* r; + int rc; info(DRIVER_DESC " version: " DRIVER_VERSION); r = request_region(ENUM_PORT, 1, "#ENUM hotswap signal register"); if(!r) return -EBUSY; - return pci_register_driver(&zt5550_hc_driver); + rc = pci_register_driver(&zt5550_hc_driver); + if(rc < 0) + release_region(ENUM_PORT, 1); + return rc; } static void __exit From d4770143fe72979d463a911d7a1f75f27ce6437b Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Fri, 13 Apr 2007 15:34:27 -0700 Subject: [PATCH 57/59] PCI hotplug: Use menuconfig objects Use menuconfigs instead of menus, so the whole menu can be disabled at once instead of going through all options. Signed-off-by: Jan Engelhardt Cc: Scott Murray Signed-off-by: Kristen Carlson Accardi Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/Kconfig | 25 ++++++++++--------------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/drivers/pci/hotplug/Kconfig b/drivers/pci/hotplug/Kconfig index be92695a7833..63d62752fb91 100644 --- a/drivers/pci/hotplug/Kconfig +++ b/drivers/pci/hotplug/Kconfig @@ -2,9 +2,7 @@ # PCI Hotplug support # -menu "PCI Hotplug Support" - -config HOTPLUG_PCI +menuconfig HOTPLUG_PCI tristate "Support for PCI Hotplug (EXPERIMENTAL)" depends on PCI && EXPERIMENTAL && HOTPLUG ---help--- @@ -17,9 +15,10 @@ config HOTPLUG_PCI When in doubt, say N. +if HOTPLUG_PCI + config HOTPLUG_PCI_FAKE tristate "Fake PCI Hotplug driver" - depends on HOTPLUG_PCI help Say Y here if you want to use the fake PCI hotplug driver. It can be used to simulate PCI hotplug events if even if your system is @@ -42,7 +41,7 @@ config HOTPLUG_PCI_FAKE config HOTPLUG_PCI_COMPAQ tristate "Compaq PCI Hotplug driver" - depends on HOTPLUG_PCI && X86 && PCI_BIOS + depends on X86 && PCI_BIOS help Say Y here if you have a motherboard with a Compaq PCI Hotplug controller. @@ -64,7 +63,7 @@ config HOTPLUG_PCI_COMPAQ_NVRAM config HOTPLUG_PCI_IBM tristate "IBM PCI Hotplug driver" - depends on HOTPLUG_PCI && X86_IO_APIC && X86 && PCI_BIOS + depends on X86_IO_APIC && X86 && PCI_BIOS help Say Y here if you have a motherboard with a IBM PCI Hotplug controller. @@ -76,7 +75,6 @@ config HOTPLUG_PCI_IBM config HOTPLUG_PCI_ACPI tristate "ACPI PCI Hotplug driver" - depends on HOTPLUG_PCI depends on (!ACPI_DOCK && ACPI) || (ACPI_DOCK) help Say Y here if you have a system that supports PCI Hotplug using @@ -101,7 +99,6 @@ config HOTPLUG_PCI_ACPI_IBM config HOTPLUG_PCI_CPCI bool "CompactPCI Hotplug driver" - depends on HOTPLUG_PCI help Say Y here if you have a CompactPCI system card with CompactPCI hotswap support per the PICMG 2.1 specification. @@ -110,7 +107,7 @@ config HOTPLUG_PCI_CPCI config HOTPLUG_PCI_CPCI_ZT5550 tristate "Ziatech ZT5550 CompactPCI Hotplug driver" - depends on HOTPLUG_PCI && HOTPLUG_PCI_CPCI && X86 + depends on HOTPLUG_PCI_CPCI && X86 help Say Y here if you have an Performance Technologies (formerly Intel, formerly just Ziatech) Ziatech ZT5550 CompactPCI system card. @@ -122,7 +119,7 @@ config HOTPLUG_PCI_CPCI_ZT5550 config HOTPLUG_PCI_CPCI_GENERIC tristate "Generic port I/O CompactPCI Hotplug driver" - depends on HOTPLUG_PCI && HOTPLUG_PCI_CPCI && X86 + depends on HOTPLUG_PCI_CPCI && X86 help Say Y here if you have a CompactPCI system card that exposes the #ENUM hotswap signal as a bit in a system register that can be read through @@ -135,7 +132,6 @@ config HOTPLUG_PCI_CPCI_GENERIC config HOTPLUG_PCI_SHPC tristate "SHPC PCI Hotplug driver" - depends on HOTPLUG_PCI help Say Y here if you have a motherboard with a SHPC PCI Hotplug controller. @@ -147,7 +143,7 @@ config HOTPLUG_PCI_SHPC config HOTPLUG_PCI_RPA tristate "RPA PCI Hotplug driver" - depends on HOTPLUG_PCI && PPC_PSERIES && PPC64 && !HOTPLUG_PCI_FAKE + depends on PPC_PSERIES && PPC64 && !HOTPLUG_PCI_FAKE help Say Y here if you have a RPA system that supports PCI Hotplug. @@ -170,12 +166,11 @@ config HOTPLUG_PCI_RPA_DLPAR config HOTPLUG_PCI_SGI tristate "SGI PCI Hotplug Support" - depends on HOTPLUG_PCI && (IA64_SGI_SN2 || IA64_GENERIC) + depends on IA64_SGI_SN2 || IA64_GENERIC help Say Y here if you want to use the SGI Altix Hotplug Driver for PCI devices. When in doubt, say N. -endmenu - +endif # HOTPLUG_PCI From c0affe9db42bf85f4a606b3262c35ec59a5d3788 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 16 Apr 2007 13:59:18 +0900 Subject: [PATCH 58/59] pci-quirks: disable MSI on RS400-200 and RS480 MSI doesn't work on RS400-200 and RS480 requiring pci=nomsi kernel boot parameter for ahci to work. This patch disables MSI on those chips. http://thread.gmane.org/gmane.linux.ide/17820 http://thread.gmane.org/gmane.linux.ide/17516 https://bugzilla.novell.com/show_bug.cgi?id=263893 Signed-off-by: Tejun Heo Signed-off-by: Greg Kroah-Hartman --- drivers/pci/quirks.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 3411483240cd..147d86f8edbf 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -1648,6 +1648,8 @@ static void __devinit quirk_disable_msi(struct pci_dev *dev) } } DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8131_BRIDGE, quirk_disable_msi); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RS400_200, quirk_disable_msi); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RS480, quirk_disable_msi); /* Go through the list of Hypertransport capabilities and * return 1 if a HT MSI capability is found and enabled */ From 9890b12a4a65a7b3181dd963421740edf0e14d69 Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Wed, 18 Apr 2007 13:34:12 +1000 Subject: [PATCH 59/59] PCI: Free resource files in error path of pci_create_sysfs_dev_files() pci_create_sysfs_dev_files() should call pci_remove_resource_files() in its error path, to match the call it makes to pci_create_resource_files(). Signed-off-by: Michael Ellerman Signed-off-by: Greg Kroah-Hartman --- drivers/pci/pci-sysfs.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c index 29676fe4f23e..284e83a527f9 100644 --- a/drivers/pci/pci-sysfs.c +++ b/drivers/pci/pci-sysfs.c @@ -636,7 +636,7 @@ int __must_check pci_create_sysfs_dev_files (struct pci_dev *pdev) goto err_rom; } else { retval = -ENOMEM; - goto err_bin_file; + goto err_resource_files; } } /* add platform-specific attributes */ @@ -646,6 +646,8 @@ int __must_check pci_create_sysfs_dev_files (struct pci_dev *pdev) err_rom: kfree(rom_attr); +err_resource_files: + pci_remove_resource_files(pdev); err_bin_file: if (pdev->cfg_size < 4096) sysfs_remove_bin_file(&pdev->dev.kobj, &pci_config_attr);