From 823bccfc4002296ba88c3ad0f049e1abd8108d30 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 13 Apr 2007 13:15:19 -0700 Subject: remove "struct subsystem" as it is no longer needed We need to work on cleaning up the relationship between kobjects, ksets and ktypes. The removal of 'struct subsystem' is the first step of this, especially as it is not really needed at all. Thanks to Kay for fixing the bugs in this patch. Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/acpiphp_ibm.c | 4 ++-- drivers/pci/hotplug/pci_hotplug_core.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/pci/hotplug') diff --git a/drivers/pci/hotplug/acpiphp_ibm.c b/drivers/pci/hotplug/acpiphp_ibm.c index 7f03881a8b68..e7322c25d377 100644 --- a/drivers/pci/hotplug/acpiphp_ibm.c +++ b/drivers/pci/hotplug/acpiphp_ibm.c @@ -424,7 +424,7 @@ static int __init ibm_acpiphp_init(void) int retval = 0; acpi_status status; struct acpi_device *device; - struct kobject *sysdir = &pci_hotplug_slots_subsys.kset.kobj; + struct kobject *sysdir = &pci_hotplug_slots_subsys.kobj; dbg("%s\n", __FUNCTION__); @@ -471,7 +471,7 @@ init_return: static void __exit ibm_acpiphp_exit(void) { acpi_status status; - struct kobject *sysdir = &pci_hotplug_slots_subsys.kset.kobj; + struct kobject *sysdir = &pci_hotplug_slots_subsys.kobj; dbg("%s\n", __FUNCTION__); diff --git a/drivers/pci/hotplug/pci_hotplug_core.c b/drivers/pci/hotplug/pci_hotplug_core.c index f5d632e72323..63f3bd1eecc4 100644 --- a/drivers/pci/hotplug/pci_hotplug_core.c +++ b/drivers/pci/hotplug/pci_hotplug_core.c @@ -62,7 +62,7 @@ static int debug; static LIST_HEAD(pci_hotplug_slot_list); -struct subsystem pci_hotplug_slots_subsys; +struct kset pci_hotplug_slots_subsys; static ssize_t hotplug_slot_attr_show(struct kobject *kobj, struct attribute *attr, char *buf) @@ -764,7 +764,7 @@ static int __init pci_hotplug_init (void) { int result; - kset_set_kset_s(&pci_hotplug_slots_subsys, pci_bus_type.subsys); + kobj_set_kset_s(&pci_hotplug_slots_subsys, pci_bus_type.subsys); result = subsystem_register(&pci_hotplug_slots_subsys); if (result) { err("Register subsys with error %d\n", result); -- cgit v1.2.1 From 5d386e1ac4025b4bcc6bad6811e771cb76064dfe Mon Sep 17 00:00:00 2001 From: Kenji Kaneshige Date: Tue, 6 Mar 2007 15:02:26 -0800 Subject: 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 | 616 +++++++++++++++++--------------------- drivers/pci/hotplug/pciehp_hpc.c | 34 ++- 4 files changed, 321 insertions(+), 389 deletions(-) (limited to 'drivers/pci/hotplug') 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++; + p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); /* * 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; - - 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)); - } + info("Button pressed on Slot(%s)\n", p_slot->name); + event_type = INT_BUTTON_PRESS; - 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; - - 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 */ + 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); + + 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 -- cgit v1.2.1 From 9233352628bc8e284f66fc90c4dc74473db1fbc1 Mon Sep 17 00:00:00 2001 From: Kenji Kaneshige Date: Tue, 6 Mar 2007 15:02:32 -0800 Subject: 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(-) (limited to 'drivers/pci/hotplug') 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; - - ctrl = pciehp_ctrl_list; - - while (ctrl) { - cleanup_slots(ctrl); - - ctrl->hpc_ops->release_ctlr(ctrl); - - tctrl = ctrl; - ctrl = ctrl->next; - - kfree(tctrl); - } -} + struct pci_dev *pdev = dev->port; + struct controller *ctrl = pci_get_drvdata(pdev); -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"); } -- cgit v1.2.1 From e325e1f0783382298141c74737712637943c6063 Mon Sep 17 00:00:00 2001 From: Kristen Carlson Accardi Date: Wed, 21 Mar 2007 11:45:31 -0700 Subject: 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(-) (limited to 'drivers/pci/hotplug') 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; -- cgit v1.2.1 From bab41e9be75121c473b00df2ffa33af3c44066a7 Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Thu, 5 Apr 2007 17:19:09 +1000 Subject: 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 --- drivers/pci/hotplug/fakephp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/pci/hotplug') 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; -- cgit v1.2.1 From bf8cbae47559170d2f2947dd547492714f195dd3 Mon Sep 17 00:00:00 2001 From: Linas Vepstas Date: Fri, 13 Apr 2007 15:34:07 -0700 Subject: 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 | 40 +++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) (limited to 'drivers/pci/hotplug') 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 += (strlen(name) + 1), type += (strlen(type) + 1)) { - - 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); + name = (char *) &names[1]; + type = (char *) &types[1]; + for (i = 0; i < indexes[0]; i++) { + + slot = alloc_slot_struct(dn, indexes[i + 1], name, power_domains[i + 1]); + if (!slot) + return -ENOMEM; + + 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; -- cgit v1.2.1 From fa1891596ca252e48e8803738fd8ead5b3082217 Mon Sep 17 00:00:00 2001 From: Linas Vepstas Date: Fri, 13 Apr 2007 15:34:08 -0700 Subject: 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(-) (limited to 'drivers/pci/hotplug') 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: -- cgit v1.2.1 From 31be7586d1122538747519d786408f142f59dd46 Mon Sep 17 00:00:00 2001 From: Linas Vepstas Date: Fri, 13 Apr 2007 15:34:09 -0700 Subject: 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(-) (limited to 'drivers/pci/hotplug') 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; } -- cgit v1.2.1 From 5fd39c35a016150e93b68c472a04b2d4b5574a2b Mon Sep 17 00:00:00 2001 From: Linas Vepstas Date: Fri, 13 Apr 2007 15:34:10 -0700 Subject: 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(-) (limited to 'drivers/pci/hotplug') 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)) -- cgit v1.2.1 From 3499f0726ec179afd19669070681ac457d27033f Mon Sep 17 00:00:00 2001 From: Linas Vepstas Date: Fri, 13 Apr 2007 15:34:11 -0700 Subject: 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(-) (limited to 'drivers/pci/hotplug') 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; } -- cgit v1.2.1 From 517d5a0417e19101eaa769039d1921d626ee546c Mon Sep 17 00:00:00 2001 From: Linas Vepstas Date: Fri, 13 Apr 2007 15:34:12 -0700 Subject: 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(-) (limited to 'drivers/pci/hotplug') 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); } -- cgit v1.2.1 From 427310ff02e80cc80826407c0121cec3694c9e7d Mon Sep 17 00:00:00 2001 From: Linas Vepstas Date: Fri, 13 Apr 2007 15:34:13 -0700 Subject: 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(-) (limited to 'drivers/pci/hotplug') 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; -- cgit v1.2.1 From bf0af511fcc856649a2a39c627828695b580d124 Mon Sep 17 00:00:00 2001 From: Linas Vepstas Date: Fri, 13 Apr 2007 15:34:14 -0700 Subject: 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(-) (limited to 'drivers/pci/hotplug') 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)) -- cgit v1.2.1 From ebf42c0edd5ee325043d4ae8fbb8caebd707e791 Mon Sep 17 00:00:00 2001 From: Linas Vepstas Date: Fri, 13 Apr 2007 15:34:15 -0700 Subject: 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(-) (limited to 'drivers/pci/hotplug') 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) -- cgit v1.2.1 From 03a667559138d47cea487823332c4712fc6fbec7 Mon Sep 17 00:00:00 2001 From: Linas Vepstas Date: Fri, 13 Apr 2007 15:34:16 -0700 Subject: 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(-) (limited to 'drivers/pci/hotplug') 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); } -- cgit v1.2.1 From 307ff12e35526cfab9f09cafcb17239286e6eb85 Mon Sep 17 00:00:00 2001 From: Linas Vepstas Date: Fri, 13 Apr 2007 15:34:17 -0700 Subject: 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(-) (limited to 'drivers/pci/hotplug') 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); -- cgit v1.2.1 From c02929c278f2bca68635e4c2daa00b7825d71061 Mon Sep 17 00:00:00 2001 From: Linas Vepstas Date: Fri, 13 Apr 2007 15:34:18 -0700 Subject: 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(-) (limited to 'drivers/pci/hotplug') 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; -} -- cgit v1.2.1 From 6f79eb749df7f1eea76c947f31603ade7d2b5f6d Mon Sep 17 00:00:00 2001 From: Linas Vepstas Date: Fri, 13 Apr 2007 15:34:19 -0700 Subject: 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(-) (limited to 'drivers/pci/hotplug') 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; } -- cgit v1.2.1 From fea54b8cc9c8290b4c99d481c3e600c46eb18fd5 Mon Sep 17 00:00:00 2001 From: Linas Vepstas Date: Fri, 13 Apr 2007 15:34:20 -0700 Subject: 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(-) (limited to 'drivers/pci/hotplug') 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; -- cgit v1.2.1 From 8485d1a123e0d367bbcbfec36acf134e6895f39a Mon Sep 17 00:00:00 2001 From: Linas Vepstas Date: Fri, 13 Apr 2007 15:34:21 -0700 Subject: 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(-) (limited to 'drivers/pci/hotplug') 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", -- cgit v1.2.1 From da65944be2441191539f50ce71cd1f8030699be1 Mon Sep 17 00:00:00 2001 From: Linas Vepstas Date: Fri, 13 Apr 2007 15:34:22 -0700 Subject: 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(-) (limited to 'drivers/pci/hotplug') 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 + * + * 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. * - * 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. + * 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; -- cgit v1.2.1 From e70ea2634afe7d04ffaf7417df7bfdbfdc460e10 Mon Sep 17 00:00:00 2001 From: Linas Vepstas Date: Fri, 13 Apr 2007 15:34:23 -0700 Subject: 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(-) (limited to 'drivers/pci/hotplug') 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; } -- cgit v1.2.1 From b5661479eeb863749ae28b9ee0dd288464311854 Mon Sep 17 00:00:00 2001 From: Linas Vepstas Date: Fri, 13 Apr 2007 15:34:24 -0700 Subject: 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(-) (limited to 'drivers/pci/hotplug') 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", -- cgit v1.2.1 From ac1f0e9923356652f21756526e194a4a1a37dd38 Mon Sep 17 00:00:00 2001 From: Linas Vepstas Date: Fri, 13 Apr 2007 15:34:25 -0700 Subject: 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(-) (limited to 'drivers/pci/hotplug') 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, -- cgit v1.2.1 From 03555d591d2c8ee9291db171c0d21d3c9cab04d9 Mon Sep 17 00:00:00 2001 From: Scott Murray Date: Fri, 13 Apr 2007 15:34:26 -0700 Subject: 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(-) (limited to 'drivers/pci/hotplug') 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 -- cgit v1.2.1 From d4770143fe72979d463a911d7a1f75f27ce6437b Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Fri, 13 Apr 2007 15:34:27 -0700 Subject: 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(-) (limited to 'drivers/pci/hotplug') 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 -- cgit v1.2.1