aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/hotplug
diff options
context:
space:
mode:
authorPaul Mackerras <paulus@samba.org>2007-05-07 23:37:51 -0400
committerPaul Mackerras <paulus@samba.org>2007-05-07 23:37:51 -0400
commit02bbc0f09c90cefdb2837605c96a66c5ce4ba2e1 (patch)
tree04ef573cd4de095c500c9fc3477f4278c0b36300 /drivers/pci/hotplug
parent7487a2245b8841c77ba9db406cf99a483b9334e9 (diff)
parent5b94f675f57e4ff16c8fda09088d7480a84dcd91 (diff)
Merge branch 'linux-2.6'
Diffstat (limited to 'drivers/pci/hotplug')
-rw-r--r--drivers/pci/hotplug/Kconfig25
-rw-r--r--drivers/pci/hotplug/acpiphp_ibm.c4
-rw-r--r--drivers/pci/hotplug/cpcihp_zt5550.c6
-rw-r--r--drivers/pci/hotplug/fakephp.c2
-rw-r--r--drivers/pci/hotplug/pci_hotplug_core.c4
-rw-r--r--drivers/pci/hotplug/pciehp.h19
-rw-r--r--drivers/pci/hotplug/pciehp_core.c82
-rw-r--r--drivers/pci/hotplug/pciehp_ctrl.c616
-rw-r--r--drivers/pci/hotplug/pciehp_hpc.c34
-rw-r--r--drivers/pci/hotplug/rpadlpar_core.c27
-rw-r--r--drivers/pci/hotplug/rpaphp.h8
-rw-r--r--drivers/pci/hotplug/rpaphp_core.c200
-rw-r--r--drivers/pci/hotplug/rpaphp_pci.c167
-rw-r--r--drivers/pci/hotplug/rpaphp_slot.c49
-rw-r--r--drivers/pci/hotplug/shpchp.h2
-rw-r--r--drivers/pci/hotplug/shpchp_core.c2
-rw-r--r--drivers/pci/hotplug/shpchp_ctrl.c2
17 files changed, 514 insertions, 735 deletions
diff --git a/drivers/pci/hotplug/Kconfig b/drivers/pci/hotplug/Kconfig
index be92695a7833..63d62752fb91 100644
--- a/drivers/pci/hotplug/Kconfig
+++ b/drivers/pci/hotplug/Kconfig
@@ -2,9 +2,7 @@
2# PCI Hotplug support 2# PCI Hotplug support
3# 3#
4 4
5menu "PCI Hotplug Support" 5menuconfig HOTPLUG_PCI
6
7config HOTPLUG_PCI
8 tristate "Support for PCI Hotplug (EXPERIMENTAL)" 6 tristate "Support for PCI Hotplug (EXPERIMENTAL)"
9 depends on PCI && EXPERIMENTAL && HOTPLUG 7 depends on PCI && EXPERIMENTAL && HOTPLUG
10 ---help--- 8 ---help---
@@ -17,9 +15,10 @@ config HOTPLUG_PCI
17 15
18 When in doubt, say N. 16 When in doubt, say N.
19 17
18if HOTPLUG_PCI
19
20config HOTPLUG_PCI_FAKE 20config HOTPLUG_PCI_FAKE
21 tristate "Fake PCI Hotplug driver" 21 tristate "Fake PCI Hotplug driver"
22 depends on HOTPLUG_PCI
23 help 22 help
24 Say Y here if you want to use the fake PCI hotplug driver. It can 23 Say Y here if you want to use the fake PCI hotplug driver. It can
25 be used to simulate PCI hotplug events if even if your system is 24 be used to simulate PCI hotplug events if even if your system is
@@ -42,7 +41,7 @@ config HOTPLUG_PCI_FAKE
42 41
43config HOTPLUG_PCI_COMPAQ 42config HOTPLUG_PCI_COMPAQ
44 tristate "Compaq PCI Hotplug driver" 43 tristate "Compaq PCI Hotplug driver"
45 depends on HOTPLUG_PCI && X86 && PCI_BIOS 44 depends on X86 && PCI_BIOS
46 help 45 help
47 Say Y here if you have a motherboard with a Compaq PCI Hotplug 46 Say Y here if you have a motherboard with a Compaq PCI Hotplug
48 controller. 47 controller.
@@ -64,7 +63,7 @@ config HOTPLUG_PCI_COMPAQ_NVRAM
64 63
65config HOTPLUG_PCI_IBM 64config HOTPLUG_PCI_IBM
66 tristate "IBM PCI Hotplug driver" 65 tristate "IBM PCI Hotplug driver"
67 depends on HOTPLUG_PCI && X86_IO_APIC && X86 && PCI_BIOS 66 depends on X86_IO_APIC && X86 && PCI_BIOS
68 help 67 help
69 Say Y here if you have a motherboard with a IBM PCI Hotplug 68 Say Y here if you have a motherboard with a IBM PCI Hotplug
70 controller. 69 controller.
@@ -76,7 +75,6 @@ config HOTPLUG_PCI_IBM
76 75
77config HOTPLUG_PCI_ACPI 76config HOTPLUG_PCI_ACPI
78 tristate "ACPI PCI Hotplug driver" 77 tristate "ACPI PCI Hotplug driver"
79 depends on HOTPLUG_PCI
80 depends on (!ACPI_DOCK && ACPI) || (ACPI_DOCK) 78 depends on (!ACPI_DOCK && ACPI) || (ACPI_DOCK)
81 help 79 help
82 Say Y here if you have a system that supports PCI Hotplug using 80 Say Y here if you have a system that supports PCI Hotplug using
@@ -101,7 +99,6 @@ config HOTPLUG_PCI_ACPI_IBM
101 99
102config HOTPLUG_PCI_CPCI 100config HOTPLUG_PCI_CPCI
103 bool "CompactPCI Hotplug driver" 101 bool "CompactPCI Hotplug driver"
104 depends on HOTPLUG_PCI
105 help 102 help
106 Say Y here if you have a CompactPCI system card with CompactPCI 103 Say Y here if you have a CompactPCI system card with CompactPCI
107 hotswap support per the PICMG 2.1 specification. 104 hotswap support per the PICMG 2.1 specification.
@@ -110,7 +107,7 @@ config HOTPLUG_PCI_CPCI
110 107
111config HOTPLUG_PCI_CPCI_ZT5550 108config HOTPLUG_PCI_CPCI_ZT5550
112 tristate "Ziatech ZT5550 CompactPCI Hotplug driver" 109 tristate "Ziatech ZT5550 CompactPCI Hotplug driver"
113 depends on HOTPLUG_PCI && HOTPLUG_PCI_CPCI && X86 110 depends on HOTPLUG_PCI_CPCI && X86
114 help 111 help
115 Say Y here if you have an Performance Technologies (formerly Intel, 112 Say Y here if you have an Performance Technologies (formerly Intel,
116 formerly just Ziatech) Ziatech ZT5550 CompactPCI system card. 113 formerly just Ziatech) Ziatech ZT5550 CompactPCI system card.
@@ -122,7 +119,7 @@ config HOTPLUG_PCI_CPCI_ZT5550
122 119
123config HOTPLUG_PCI_CPCI_GENERIC 120config HOTPLUG_PCI_CPCI_GENERIC
124 tristate "Generic port I/O CompactPCI Hotplug driver" 121 tristate "Generic port I/O CompactPCI Hotplug driver"
125 depends on HOTPLUG_PCI && HOTPLUG_PCI_CPCI && X86 122 depends on HOTPLUG_PCI_CPCI && X86
126 help 123 help
127 Say Y here if you have a CompactPCI system card that exposes the #ENUM 124 Say Y here if you have a CompactPCI system card that exposes the #ENUM
128 hotswap signal as a bit in a system register that can be read through 125 hotswap signal as a bit in a system register that can be read through
@@ -135,7 +132,6 @@ config HOTPLUG_PCI_CPCI_GENERIC
135 132
136config HOTPLUG_PCI_SHPC 133config HOTPLUG_PCI_SHPC
137 tristate "SHPC PCI Hotplug driver" 134 tristate "SHPC PCI Hotplug driver"
138 depends on HOTPLUG_PCI
139 help 135 help
140 Say Y here if you have a motherboard with a SHPC PCI Hotplug 136 Say Y here if you have a motherboard with a SHPC PCI Hotplug
141 controller. 137 controller.
@@ -147,7 +143,7 @@ config HOTPLUG_PCI_SHPC
147 143
148config HOTPLUG_PCI_RPA 144config HOTPLUG_PCI_RPA
149 tristate "RPA PCI Hotplug driver" 145 tristate "RPA PCI Hotplug driver"
150 depends on HOTPLUG_PCI && PPC_PSERIES && PPC64 && !HOTPLUG_PCI_FAKE 146 depends on PPC_PSERIES && PPC64 && !HOTPLUG_PCI_FAKE
151 help 147 help
152 Say Y here if you have a RPA system that supports PCI Hotplug. 148 Say Y here if you have a RPA system that supports PCI Hotplug.
153 149
@@ -170,12 +166,11 @@ config HOTPLUG_PCI_RPA_DLPAR
170 166
171config HOTPLUG_PCI_SGI 167config HOTPLUG_PCI_SGI
172 tristate "SGI PCI Hotplug Support" 168 tristate "SGI PCI Hotplug Support"
173 depends on HOTPLUG_PCI && (IA64_SGI_SN2 || IA64_GENERIC) 169 depends on IA64_SGI_SN2 || IA64_GENERIC
174 help 170 help
175 Say Y here if you want to use the SGI Altix Hotplug 171 Say Y here if you want to use the SGI Altix Hotplug
176 Driver for PCI devices. 172 Driver for PCI devices.
177 173
178 When in doubt, say N. 174 When in doubt, say N.
179 175
180endmenu 176endif # HOTPLUG_PCI
181
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)
424 int retval = 0; 424 int retval = 0;
425 acpi_status status; 425 acpi_status status;
426 struct acpi_device *device; 426 struct acpi_device *device;
427 struct kobject *sysdir = &pci_hotplug_slots_subsys.kset.kobj; 427 struct kobject *sysdir = &pci_hotplug_slots_subsys.kobj;
428 428
429 dbg("%s\n", __FUNCTION__); 429 dbg("%s\n", __FUNCTION__);
430 430
@@ -471,7 +471,7 @@ init_return:
471static void __exit ibm_acpiphp_exit(void) 471static void __exit ibm_acpiphp_exit(void)
472{ 472{
473 acpi_status status; 473 acpi_status status;
474 struct kobject *sysdir = &pci_hotplug_slots_subsys.kset.kobj; 474 struct kobject *sysdir = &pci_hotplug_slots_subsys.kobj;
475 475
476 dbg("%s\n", __FUNCTION__); 476 dbg("%s\n", __FUNCTION__);
477 477
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 = {
296static int __init zt5550_init(void) 296static int __init zt5550_init(void)
297{ 297{
298 struct resource* r; 298 struct resource* r;
299 int rc;
299 300
300 info(DRIVER_DESC " version: " DRIVER_VERSION); 301 info(DRIVER_DESC " version: " DRIVER_VERSION);
301 r = request_region(ENUM_PORT, 1, "#ENUM hotswap signal register"); 302 r = request_region(ENUM_PORT, 1, "#ENUM hotswap signal register");
302 if(!r) 303 if(!r)
303 return -EBUSY; 304 return -EBUSY;
304 305
305 return pci_register_driver(&zt5550_hc_driver); 306 rc = pci_register_driver(&zt5550_hc_driver);
307 if(rc < 0)
308 release_region(ENUM_PORT, 1);
309 return rc;
306} 310}
307 311
308static void __exit 312static void __exit
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)
238{ 238{
239 unsigned int devfn; 239 unsigned int devfn;
240 struct pci_dev *dev; 240 struct pci_dev *dev;
241 dev = kzalloc(sizeof(struct pci_dev), GFP_KERNEL); 241 dev = alloc_pci_dev();
242 if (!dev) 242 if (!dev)
243 return; 243 return;
244 244
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;
62 62
63static LIST_HEAD(pci_hotplug_slot_list); 63static LIST_HEAD(pci_hotplug_slot_list);
64 64
65struct subsystem pci_hotplug_slots_subsys; 65struct kset pci_hotplug_slots_subsys;
66 66
67static ssize_t hotplug_slot_attr_show(struct kobject *kobj, 67static ssize_t hotplug_slot_attr_show(struct kobject *kobj,
68 struct attribute *attr, char *buf) 68 struct attribute *attr, char *buf)
@@ -764,7 +764,7 @@ static int __init pci_hotplug_init (void)
764{ 764{
765 int result; 765 int result;
766 766
767 kset_set_kset_s(&pci_hotplug_slots_subsys, pci_bus_type.subsys); 767 kobj_set_kset_s(&pci_hotplug_slots_subsys, pci_bus_type.subsys);
768 result = subsystem_register(&pci_hotplug_slots_subsys); 768 result = subsystem_register(&pci_hotplug_slots_subsys);
769 if (result) { 769 if (result) {
770 err("Register subsys with error %d\n", result); 770 err("Register subsys with error %d\n", result);
diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h
index d19fcae8a7c0..ccc57627201e 100644
--- a/drivers/pci/hotplug/pciehp.h
+++ b/drivers/pci/hotplug/pciehp.h
@@ -43,6 +43,7 @@ extern int pciehp_poll_mode;
43extern int pciehp_poll_time; 43extern int pciehp_poll_time;
44extern int pciehp_debug; 44extern int pciehp_debug;
45extern int pciehp_force; 45extern int pciehp_force;
46extern struct workqueue_struct *pciehp_wq;
46 47
47#define dbg(format, arg...) \ 48#define dbg(format, arg...) \
48 do { \ 49 do { \
@@ -70,14 +71,16 @@ struct slot {
70 struct list_head slot_list; 71 struct list_head slot_list;
71 char name[SLOT_NAME_SIZE]; 72 char name[SLOT_NAME_SIZE];
72 unsigned long last_emi_toggle; 73 unsigned long last_emi_toggle;
74 struct delayed_work work; /* work for button event */
75 struct mutex lock;
73}; 76};
74 77
75struct event_info { 78struct event_info {
76 u32 event_type; 79 u32 event_type;
77 u8 hp_slot; 80 struct slot *p_slot;
81 struct work_struct work;
78}; 82};
79 83
80#define MAX_EVENTS 10
81struct controller { 84struct controller {
82 struct controller *next; 85 struct controller *next;
83 struct mutex crit_sect; /* critical section mutex */ 86 struct mutex crit_sect; /* critical section mutex */
@@ -86,11 +89,9 @@ struct controller {
86 int slot_num_inc; /* 1 or -1 */ 89 int slot_num_inc; /* 1 or -1 */
87 struct pci_dev *pci_dev; 90 struct pci_dev *pci_dev;
88 struct list_head slot_list; 91 struct list_head slot_list;
89 struct event_info event_queue[MAX_EVENTS];
90 struct slot *slot; 92 struct slot *slot;
91 struct hpc_ops *hpc_ops; 93 struct hpc_ops *hpc_ops;
92 wait_queue_head_t queue; /* sleep & wake process */ 94 wait_queue_head_t queue; /* sleep & wake process */
93 u8 next_event;
94 u8 bus; 95 u8 bus;
95 u8 device; 96 u8 device;
96 u8 function; 97 u8 function;
@@ -149,21 +150,17 @@ struct controller {
149#define HP_SUPR_RM(cap) (cap & HP_SUPR_RM_SUP) 150#define HP_SUPR_RM(cap) (cap & HP_SUPR_RM_SUP)
150#define EMI(cap) (cap & EMI_PRSN) 151#define EMI(cap) (cap & EMI_PRSN)
151 152
152extern int pciehp_event_start_thread(void); 153extern int pciehp_sysfs_enable_slot(struct slot *slot);
153extern void pciehp_event_stop_thread(void); 154extern int pciehp_sysfs_disable_slot(struct slot *slot);
154extern int pciehp_enable_slot(struct slot *slot);
155extern int pciehp_disable_slot(struct slot *slot);
156extern u8 pciehp_handle_attention_button(u8 hp_slot, struct controller *ctrl); 155extern u8 pciehp_handle_attention_button(u8 hp_slot, struct controller *ctrl);
157extern u8 pciehp_handle_switch_change(u8 hp_slot, struct controller *ctrl); 156extern u8 pciehp_handle_switch_change(u8 hp_slot, struct controller *ctrl);
158extern u8 pciehp_handle_presence_change(u8 hp_slot, struct controller *ctrl); 157extern u8 pciehp_handle_presence_change(u8 hp_slot, struct controller *ctrl);
159extern u8 pciehp_handle_power_fault(u8 hp_slot, struct controller *ctrl); 158extern u8 pciehp_handle_power_fault(u8 hp_slot, struct controller *ctrl);
160extern int pciehp_configure_device(struct slot *p_slot); 159extern int pciehp_configure_device(struct slot *p_slot);
161extern int pciehp_unconfigure_device(struct slot *p_slot); 160extern int pciehp_unconfigure_device(struct slot *p_slot);
161extern void pciehp_queue_pushbutton_work(struct work_struct *work);
162int pcie_init(struct controller *ctrl, struct pcie_device *dev); 162int pcie_init(struct controller *ctrl, struct pcie_device *dev);
163 163
164/* Global variables */
165extern struct controller *pciehp_ctrl_list;
166
167static inline struct slot *pciehp_find_slot(struct controller *ctrl, u8 device) 164static inline struct slot *pciehp_find_slot(struct controller *ctrl, u8 device)
168{ 165{
169 struct slot *slot; 166 struct slot *slot;
diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c
index a92eda6e02f6..e5d3f0b4f45a 100644
--- a/drivers/pci/hotplug/pciehp_core.c
+++ b/drivers/pci/hotplug/pciehp_core.c
@@ -41,7 +41,7 @@ int pciehp_debug;
41int pciehp_poll_mode; 41int pciehp_poll_mode;
42int pciehp_poll_time; 42int pciehp_poll_time;
43int pciehp_force; 43int pciehp_force;
44struct controller *pciehp_ctrl_list; 44struct workqueue_struct *pciehp_wq;
45 45
46#define DRIVER_VERSION "0.4" 46#define DRIVER_VERSION "0.4"
47#define DRIVER_AUTHOR "Dan Zink <dan.zink@compaq.com>, Greg Kroah-Hartman <greg@kroah.com>, Dely Sy <dely.l.sy@intel.com>" 47#define DRIVER_AUTHOR "Dan Zink <dan.zink@compaq.com>, Greg Kroah-Hartman <greg@kroah.com>, Dely Sy <dely.l.sy@intel.com>"
@@ -62,7 +62,6 @@ MODULE_PARM_DESC(pciehp_force, "Force pciehp, even if _OSC and OSHP are missing"
62 62
63#define PCIE_MODULE_NAME "pciehp" 63#define PCIE_MODULE_NAME "pciehp"
64 64
65static int pcie_start_thread (void);
66static int set_attention_status (struct hotplug_slot *slot, u8 value); 65static int set_attention_status (struct hotplug_slot *slot, u8 value);
67static int enable_slot (struct hotplug_slot *slot); 66static int enable_slot (struct hotplug_slot *slot);
68static int disable_slot (struct hotplug_slot *slot); 67static int disable_slot (struct hotplug_slot *slot);
@@ -229,6 +228,8 @@ static int init_slots(struct controller *ctrl)
229 slot->device = ctrl->slot_device_offset + i; 228 slot->device = ctrl->slot_device_offset + i;
230 slot->hpc_ops = ctrl->hpc_ops; 229 slot->hpc_ops = ctrl->hpc_ops;
231 slot->number = ctrl->first_slot; 230 slot->number = ctrl->first_slot;
231 mutex_init(&slot->lock);
232 INIT_DELAYED_WORK(&slot->work, pciehp_queue_pushbutton_work);
232 233
233 /* register this slot with the hotplug pci core */ 234 /* register this slot with the hotplug pci core */
234 hotplug_slot->private = slot; 235 hotplug_slot->private = slot;
@@ -286,6 +287,9 @@ static void cleanup_slots(struct controller *ctrl)
286 if (EMI(ctrl->ctrlcap)) 287 if (EMI(ctrl->ctrlcap))
287 sysfs_remove_file(&slot->hotplug_slot->kobj, 288 sysfs_remove_file(&slot->hotplug_slot->kobj,
288 &hotplug_slot_attr_lock.attr); 289 &hotplug_slot_attr_lock.attr);
290 cancel_delayed_work(&slot->work);
291 flush_scheduled_work();
292 flush_workqueue(pciehp_wq);
289 pci_hp_deregister(slot->hotplug_slot); 293 pci_hp_deregister(slot->hotplug_slot);
290 } 294 }
291} 295}
@@ -314,7 +318,7 @@ static int enable_slot(struct hotplug_slot *hotplug_slot)
314 318
315 dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); 319 dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
316 320
317 return pciehp_enable_slot(slot); 321 return pciehp_sysfs_enable_slot(slot);
318} 322}
319 323
320 324
@@ -324,7 +328,7 @@ static int disable_slot(struct hotplug_slot *hotplug_slot)
324 328
325 dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); 329 dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
326 330
327 return pciehp_disable_slot(slot); 331 return pciehp_sysfs_disable_slot(slot);
328} 332}
329 333
330static int get_power_status(struct hotplug_slot *hotplug_slot, u8 *value) 334static int get_power_status(struct hotplug_slot *hotplug_slot, u8 *value)
@@ -466,17 +470,6 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_
466 470
467 t_slot = pciehp_find_slot(ctrl, ctrl->slot_device_offset); 471 t_slot = pciehp_find_slot(ctrl, ctrl->slot_device_offset);
468 472
469 /* Finish setting up the hot plug ctrl device */
470 ctrl->next_event = 0;
471
472 if (!pciehp_ctrl_list) {
473 pciehp_ctrl_list = ctrl;
474 ctrl->next = NULL;
475 } else {
476 ctrl->next = pciehp_ctrl_list;
477 pciehp_ctrl_list = ctrl;
478 }
479
480 t_slot->hpc_ops->get_adapter_status(t_slot, &value); /* Check if slot is occupied */ 473 t_slot->hpc_ops->get_adapter_status(t_slot, &value); /* Check if slot is occupied */
481 if ((POWER_CTRL(ctrl->ctrlcap)) && !value) { 474 if ((POWER_CTRL(ctrl->ctrlcap)) && !value) {
482 rc = t_slot->hpc_ops->power_off_slot(t_slot); /* Power off slot if not occupied*/ 475 rc = t_slot->hpc_ops->power_off_slot(t_slot); /* Power off slot if not occupied*/
@@ -496,48 +489,14 @@ err_out_none:
496 return -ENODEV; 489 return -ENODEV;
497} 490}
498 491
499 492static void pciehp_remove (struct pcie_device *dev)
500static int pcie_start_thread(void)
501{ 493{
502 int retval = 0; 494 struct pci_dev *pdev = dev->port;
503 495 struct controller *ctrl = pci_get_drvdata(pdev);
504 dbg("Initialize + Start the notification/polling mechanism \n");
505
506 retval = pciehp_event_start_thread();
507 if (retval) {
508 dbg("pciehp_event_start_thread() failed\n");
509 return retval;
510 }
511
512 return retval;
513}
514
515static void __exit unload_pciehpd(void)
516{
517 struct controller *ctrl;
518 struct controller *tctrl;
519
520 ctrl = pciehp_ctrl_list;
521
522 while (ctrl) {
523 cleanup_slots(ctrl);
524 496
525 ctrl->hpc_ops->release_ctlr(ctrl); 497 cleanup_slots(ctrl);
526 498 ctrl->hpc_ops->release_ctlr(ctrl);
527 tctrl = ctrl; 499 kfree(ctrl);
528 ctrl = ctrl->next;
529
530 kfree(tctrl);
531 }
532
533 /* Stop the notification mechanism */
534 pciehp_event_stop_thread();
535
536}
537
538static void pciehp_remove (struct pcie_device *device)
539{
540 /* XXX - Needs to be adapted to device driver model */
541} 500}
542 501
543#ifdef CONFIG_PM 502#ifdef CONFIG_PM
@@ -585,31 +544,18 @@ static int __init pcied_init(void)
585 pciehp_poll_mode = 1; 544 pciehp_poll_mode = 1;
586#endif 545#endif
587 546
588 retval = pcie_start_thread();
589 if (retval)
590 goto error_hpc_init;
591
592 retval = pcie_port_service_register(&hpdriver_portdrv); 547 retval = pcie_port_service_register(&hpdriver_portdrv);
593 dbg("pcie_port_service_register = %d\n", retval); 548 dbg("pcie_port_service_register = %d\n", retval);
594 info(DRIVER_DESC " version: " DRIVER_VERSION "\n"); 549 info(DRIVER_DESC " version: " DRIVER_VERSION "\n");
595 if (retval) 550 if (retval)
596 dbg("%s: Failure to register service\n", __FUNCTION__); 551 dbg("%s: Failure to register service\n", __FUNCTION__);
597
598error_hpc_init:
599 if (retval) {
600 pciehp_event_stop_thread();
601 };
602
603 return retval; 552 return retval;
604} 553}
605 554
606static void __exit pcied_cleanup(void) 555static void __exit pcied_cleanup(void)
607{ 556{
608 dbg("unload_pciehpd()\n"); 557 dbg("unload_pciehpd()\n");
609 unload_pciehpd();
610
611 pcie_port_service_unregister(&hpdriver_portdrv); 558 pcie_port_service_unregister(&hpdriver_portdrv);
612
613 info(DRIVER_DESC " version: " DRIVER_VERSION " unloaded\n"); 559 info(DRIVER_DESC " version: " DRIVER_VERSION " unloaded\n");
614} 560}
615 561
diff --git a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c
index 4283ef56dbd9..7f22caa70178 100644
--- a/drivers/pci/hotplug/pciehp_ctrl.c
+++ b/drivers/pci/hotplug/pciehp_ctrl.c
@@ -32,92 +32,61 @@
32#include <linux/types.h> 32#include <linux/types.h>
33#include <linux/smp_lock.h> 33#include <linux/smp_lock.h>
34#include <linux/pci.h> 34#include <linux/pci.h>
35#include <linux/workqueue.h>
35#include "../pci.h" 36#include "../pci.h"
36#include "pciehp.h" 37#include "pciehp.h"
37 38
38static void interrupt_event_handler(struct controller *ctrl); 39static void interrupt_event_handler(struct work_struct *work);
40static int pciehp_enable_slot(struct slot *p_slot);
41static int pciehp_disable_slot(struct slot *p_slot);
39 42
40static struct semaphore event_semaphore; /* mutex for process loop (up if something to process) */ 43static int queue_interrupt_event(struct slot *p_slot, u32 event_type)
41static struct semaphore event_exit; /* guard ensure thread has exited before calling it quits */
42static int event_finished;
43static unsigned long pushbutton_pending; /* = 0 */
44static unsigned long surprise_rm_pending; /* = 0 */
45
46static inline char *slot_name(struct slot *p_slot)
47{ 44{
48 return p_slot->hotplug_slot->name; 45 struct event_info *info;
46
47 info = kmalloc(sizeof(*info), GFP_ATOMIC);
48 if (!info)
49 return -ENOMEM;
50
51 info->event_type = event_type;
52 info->p_slot = p_slot;
53 INIT_WORK(&info->work, interrupt_event_handler);
54
55 schedule_work(&info->work);
56
57 return 0;
49} 58}
50 59
51u8 pciehp_handle_attention_button(u8 hp_slot, struct controller *ctrl) 60u8 pciehp_handle_attention_button(u8 hp_slot, struct controller *ctrl)
52{ 61{
53 struct slot *p_slot; 62 struct slot *p_slot;
54 u8 rc = 0; 63 u32 event_type;
55 u8 getstatus;
56 struct event_info *taskInfo;
57 64
58 /* Attention Button Change */ 65 /* Attention Button Change */
59 dbg("pciehp: Attention button interrupt received.\n"); 66 dbg("pciehp: Attention button interrupt received.\n");
60
61 /* This is the structure that tells the worker thread what to do */
62 taskInfo = &(ctrl->event_queue[ctrl->next_event]);
63 p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
64
65 p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
66
67 ctrl->next_event = (ctrl->next_event + 1) % MAX_EVENTS;
68 taskInfo->hp_slot = hp_slot;
69 67
70 rc++; 68 p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
71 69
72 /* 70 /*
73 * Button pressed - See if need to TAKE ACTION!!! 71 * Button pressed - See if need to TAKE ACTION!!!
74 */ 72 */
75 info("Button pressed on Slot(%s)\n", slot_name(p_slot)); 73 info("Button pressed on Slot(%s)\n", p_slot->name);
76 taskInfo->event_type = INT_BUTTON_PRESS; 74 event_type = INT_BUTTON_PRESS;
77
78 if ((p_slot->state == BLINKINGON_STATE)
79 || (p_slot->state == BLINKINGOFF_STATE)) {
80 /* Cancel if we are still blinking; this means that we press the
81 * attention again before the 5 sec. limit expires to cancel hot-add
82 * or hot-remove
83 */
84 taskInfo->event_type = INT_BUTTON_CANCEL;
85 info("Button cancel on Slot(%s)\n", slot_name(p_slot));
86 } else if ((p_slot->state == POWERON_STATE)
87 || (p_slot->state == POWEROFF_STATE)) {
88 /* Ignore if the slot is on power-on or power-off state; this
89 * means that the previous attention button action to hot-add or
90 * hot-remove is undergoing
91 */
92 taskInfo->event_type = INT_BUTTON_IGNORE;
93 info("Button ignore on Slot(%s)\n", slot_name(p_slot));
94 }
95 75
96 if (rc) 76 queue_interrupt_event(p_slot, event_type);
97 up(&event_semaphore); /* signal event thread that new event is posted */
98 77
99 return 0; 78 return 0;
100
101} 79}
102 80
103u8 pciehp_handle_switch_change(u8 hp_slot, struct controller *ctrl) 81u8 pciehp_handle_switch_change(u8 hp_slot, struct controller *ctrl)
104{ 82{
105 struct slot *p_slot; 83 struct slot *p_slot;
106 u8 rc = 0;
107 u8 getstatus; 84 u8 getstatus;
108 struct event_info *taskInfo; 85 u32 event_type;
109 86
110 /* Switch Change */ 87 /* Switch Change */
111 dbg("pciehp: Switch interrupt received.\n"); 88 dbg("pciehp: Switch interrupt received.\n");
112 89
113 /* This is the structure that tells the worker thread
114 * what to do
115 */
116 taskInfo = &(ctrl->event_queue[ctrl->next_event]);
117 ctrl->next_event = (ctrl->next_event + 1) % MAX_EVENTS;
118 taskInfo->hp_slot = hp_slot;
119
120 rc++;
121 p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); 90 p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
122 p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); 91 p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
123 92
@@ -125,39 +94,30 @@ u8 pciehp_handle_switch_change(u8 hp_slot, struct controller *ctrl)
125 /* 94 /*
126 * Switch opened 95 * Switch opened
127 */ 96 */
128 info("Latch open on Slot(%s)\n", slot_name(p_slot)); 97 info("Latch open on Slot(%s)\n", p_slot->name);
129 taskInfo->event_type = INT_SWITCH_OPEN; 98 event_type = INT_SWITCH_OPEN;
130 } else { 99 } else {
131 /* 100 /*
132 * Switch closed 101 * Switch closed
133 */ 102 */
134 info("Latch close on Slot(%s)\n", slot_name(p_slot)); 103 info("Latch close on Slot(%s)\n", p_slot->name);
135 taskInfo->event_type = INT_SWITCH_CLOSE; 104 event_type = INT_SWITCH_CLOSE;
136 } 105 }
137 106
138 if (rc) 107 queue_interrupt_event(p_slot, event_type);
139 up(&event_semaphore); /* signal event thread that new event is posted */
140 108
141 return rc; 109 return 1;
142} 110}
143 111
144u8 pciehp_handle_presence_change(u8 hp_slot, struct controller *ctrl) 112u8 pciehp_handle_presence_change(u8 hp_slot, struct controller *ctrl)
145{ 113{
146 struct slot *p_slot; 114 struct slot *p_slot;
147 u8 presence_save, rc = 0; 115 u32 event_type;
148 struct event_info *taskInfo; 116 u8 presence_save;
149 117
150 /* Presence Change */ 118 /* Presence Change */
151 dbg("pciehp: Presence/Notify input change.\n"); 119 dbg("pciehp: Presence/Notify input change.\n");
152 120
153 /* This is the structure that tells the worker thread
154 * what to do
155 */
156 taskInfo = &(ctrl->event_queue[ctrl->next_event]);
157 ctrl->next_event = (ctrl->next_event + 1) % MAX_EVENTS;
158 taskInfo->hp_slot = hp_slot;
159
160 rc++;
161 p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); 121 p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
162 122
163 /* Switch is open, assume a presence change 123 /* Switch is open, assume a presence change
@@ -168,59 +128,49 @@ u8 pciehp_handle_presence_change(u8 hp_slot, struct controller *ctrl)
168 /* 128 /*
169 * Card Present 129 * Card Present
170 */ 130 */
171 info("Card present on Slot(%s)\n", slot_name(p_slot)); 131 info("Card present on Slot(%s)\n", p_slot->name);
172 taskInfo->event_type = INT_PRESENCE_ON; 132 event_type = INT_PRESENCE_ON;
173 } else { 133 } else {
174 /* 134 /*
175 * Not Present 135 * Not Present
176 */ 136 */
177 info("Card not present on Slot(%s)\n", slot_name(p_slot)); 137 info("Card not present on Slot(%s)\n", p_slot->name);
178 taskInfo->event_type = INT_PRESENCE_OFF; 138 event_type = INT_PRESENCE_OFF;
179 } 139 }
180 140
181 if (rc) 141 queue_interrupt_event(p_slot, event_type);
182 up(&event_semaphore); /* signal event thread that new event is posted */
183 142
184 return rc; 143 return 1;
185} 144}
186 145
187u8 pciehp_handle_power_fault(u8 hp_slot, struct controller *ctrl) 146u8 pciehp_handle_power_fault(u8 hp_slot, struct controller *ctrl)
188{ 147{
189 struct slot *p_slot; 148 struct slot *p_slot;
190 u8 rc = 0; 149 u32 event_type;
191 struct event_info *taskInfo;
192 150
193 /* power fault */ 151 /* power fault */
194 dbg("pciehp: Power fault interrupt received.\n"); 152 dbg("pciehp: Power fault interrupt received.\n");
195 153
196 /* this is the structure that tells the worker thread
197 * what to do
198 */
199 taskInfo = &(ctrl->event_queue[ctrl->next_event]);
200 ctrl->next_event = (ctrl->next_event + 1) % MAX_EVENTS;
201 taskInfo->hp_slot = hp_slot;
202
203 rc++;
204 p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); 154 p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
205 155
206 if ( !(p_slot->hpc_ops->query_power_fault(p_slot))) { 156 if ( !(p_slot->hpc_ops->query_power_fault(p_slot))) {
207 /* 157 /*
208 * power fault Cleared 158 * power fault Cleared
209 */ 159 */
210 info("Power fault cleared on Slot(%s)\n", slot_name(p_slot)); 160 info("Power fault cleared on Slot(%s)\n", p_slot->name);
211 taskInfo->event_type = INT_POWER_FAULT_CLEAR; 161 event_type = INT_POWER_FAULT_CLEAR;
212 } else { 162 } else {
213 /* 163 /*
214 * power fault 164 * power fault
215 */ 165 */
216 info("Power fault on Slot(%s)\n", slot_name(p_slot)); 166 info("Power fault on Slot(%s)\n", p_slot->name);
217 taskInfo->event_type = INT_POWER_FAULT; 167 event_type = INT_POWER_FAULT;
218 info("power fault bit %x set\n", hp_slot); 168 info("power fault bit %x set\n", hp_slot);
219 } 169 }
220 if (rc)
221 up(&event_semaphore); /* signal event thread that new event is posted */
222 170
223 return rc; 171 queue_interrupt_event(p_slot, event_type);
172
173 return 1;
224} 174}
225 175
226/* The following routines constitute the bulk of the 176/* The following routines constitute the bulk of the
@@ -357,13 +307,10 @@ static int remove_board(struct slot *p_slot)
357 return 0; 307 return 0;
358} 308}
359 309
360 310struct power_work_info {
361static void pushbutton_helper_thread(unsigned long data) 311 struct slot *p_slot;
362{ 312 struct work_struct work;
363 pushbutton_pending = data; 313};
364
365 up(&event_semaphore);
366}
367 314
368/** 315/**
369 * pciehp_pushbutton_thread 316 * pciehp_pushbutton_thread
@@ -372,276 +319,214 @@ static void pushbutton_helper_thread(unsigned long data)
372 * Handles all pending events and exits. 319 * Handles all pending events and exits.
373 * 320 *
374 */ 321 */
375static void pciehp_pushbutton_thread(unsigned long slot) 322static void pciehp_power_thread(struct work_struct *work)
376{ 323{
377 struct slot *p_slot = (struct slot *) slot; 324 struct power_work_info *info =
378 u8 getstatus; 325 container_of(work, struct power_work_info, work);
379 326 struct slot *p_slot = info->p_slot;
380 pushbutton_pending = 0; 327
381 328 mutex_lock(&p_slot->lock);
382 if (!p_slot) { 329 switch (p_slot->state) {
383 dbg("%s: Error! slot NULL\n", __FUNCTION__); 330 case POWEROFF_STATE:
384 return; 331 mutex_unlock(&p_slot->lock);
385 } 332 dbg("%s: disabling bus:device(%x:%x)\n",
386 333 __FUNCTION__, p_slot->bus, p_slot->device);
387 p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
388 if (getstatus) {
389 p_slot->state = POWEROFF_STATE;
390 dbg("%s: disabling bus:device(%x:%x)\n", __FUNCTION__,
391 p_slot->bus, p_slot->device);
392
393 pciehp_disable_slot(p_slot); 334 pciehp_disable_slot(p_slot);
335 mutex_lock(&p_slot->lock);
394 p_slot->state = STATIC_STATE; 336 p_slot->state = STATIC_STATE;
395 } else { 337 break;
396 p_slot->state = POWERON_STATE; 338 case POWERON_STATE:
397 dbg("%s: adding bus:device(%x:%x)\n", __FUNCTION__, 339 mutex_unlock(&p_slot->lock);
398 p_slot->bus, p_slot->device);
399
400 if (pciehp_enable_slot(p_slot) && 340 if (pciehp_enable_slot(p_slot) &&
401 PWR_LED(p_slot->ctrl->ctrlcap)) 341 PWR_LED(p_slot->ctrl->ctrlcap))
402 p_slot->hpc_ops->green_led_off(p_slot); 342 p_slot->hpc_ops->green_led_off(p_slot);
403 343 mutex_lock(&p_slot->lock);
404 p_slot->state = STATIC_STATE; 344 p_slot->state = STATIC_STATE;
345 break;
346 default:
347 break;
405 } 348 }
349 mutex_unlock(&p_slot->lock);
406 350
407 return; 351 kfree(info);
408} 352}
409 353
410/** 354void pciehp_queue_pushbutton_work(struct work_struct *work)
411 * pciehp_surprise_rm_thread
412 *
413 * Scheduled procedure to handle blocking stuff for the surprise removal
414 * Handles all pending events and exits.
415 *
416 */
417static void pciehp_surprise_rm_thread(unsigned long slot)
418{ 355{
419 struct slot *p_slot = (struct slot *) slot; 356 struct slot *p_slot = container_of(work, struct slot, work.work);
420 u8 getstatus; 357 struct power_work_info *info;
421
422 surprise_rm_pending = 0;
423 358
424 if (!p_slot) { 359 info = kmalloc(sizeof(*info), GFP_KERNEL);
425 dbg("%s: Error! slot NULL\n", __FUNCTION__); 360 if (!info) {
361 err("%s: Cannot allocate memory\n", __FUNCTION__);
426 return; 362 return;
427 } 363 }
364 info->p_slot = p_slot;
365 INIT_WORK(&info->work, pciehp_power_thread);
428 366
429 p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus); 367 mutex_lock(&p_slot->lock);
430 if (!getstatus) { 368 switch (p_slot->state) {
369 case BLINKINGOFF_STATE:
431 p_slot->state = POWEROFF_STATE; 370 p_slot->state = POWEROFF_STATE;
432 dbg("%s: removing bus:device(%x:%x)\n", 371 break;
433 __FUNCTION__, p_slot->bus, p_slot->device); 372 case BLINKINGON_STATE:
434
435 pciehp_disable_slot(p_slot);
436 p_slot->state = STATIC_STATE;
437 } else {
438 p_slot->state = POWERON_STATE; 373 p_slot->state = POWERON_STATE;
439 dbg("%s: adding bus:device(%x:%x)\n", 374 break;
440 __FUNCTION__, p_slot->bus, p_slot->device); 375 default:
441 376 goto out;
442 if (pciehp_enable_slot(p_slot) &&
443 PWR_LED(p_slot->ctrl->ctrlcap))
444 p_slot->hpc_ops->green_led_off(p_slot);
445
446 p_slot->state = STATIC_STATE;
447 } 377 }
448 378 queue_work(pciehp_wq, &info->work);
449 return; 379 out:
380 mutex_unlock(&p_slot->lock);
450} 381}
451 382
452
453
454/* this is the main worker thread */
455static int event_thread(void* data)
456{
457 struct controller *ctrl;
458 lock_kernel();
459 daemonize("pciehpd_event");
460
461 unlock_kernel();
462
463 while (1) {
464 dbg("!!!!event_thread sleeping\n");
465 down_interruptible (&event_semaphore);
466 dbg("event_thread woken finished = %d\n", event_finished);
467 if (event_finished || signal_pending(current))
468 break;
469 /* Do stuff here */
470 if (pushbutton_pending)
471 pciehp_pushbutton_thread(pushbutton_pending);
472 else if (surprise_rm_pending)
473 pciehp_surprise_rm_thread(surprise_rm_pending);
474 else
475 for (ctrl = pciehp_ctrl_list; ctrl; ctrl=ctrl->next)
476 interrupt_event_handler(ctrl);
477 }
478 dbg("event_thread signals exit\n");
479 up(&event_exit);
480 return 0;
481}
482
483int pciehp_event_start_thread(void)
484{
485 int pid;
486
487 /* initialize our semaphores */
488 init_MUTEX_LOCKED(&event_exit);
489 event_finished=0;
490
491 init_MUTEX_LOCKED(&event_semaphore);
492 pid = kernel_thread(event_thread, NULL, 0);
493
494 if (pid < 0) {
495 err ("Can't start up our event thread\n");
496 return -1;
497 }
498 return 0;
499}
500
501
502void pciehp_event_stop_thread(void)
503{
504 event_finished = 1;
505 up(&event_semaphore);
506 down(&event_exit);
507}
508
509
510static int update_slot_info(struct slot *slot) 383static int update_slot_info(struct slot *slot)
511{ 384{
512 struct hotplug_slot_info *info; 385 struct hotplug_slot_info *info;
513 /* char buffer[SLOT_NAME_SIZE]; */
514 int result; 386 int result;
515 387
516 info = kmalloc(sizeof(struct hotplug_slot_info), GFP_KERNEL); 388 info = kmalloc(sizeof(*info), GFP_KERNEL);
517 if (!info) 389 if (!info)
518 return -ENOMEM; 390 return -ENOMEM;
519 391
520 /* make_slot_name (&buffer[0], SLOT_NAME_SIZE, slot); */
521
522 slot->hpc_ops->get_power_status(slot, &(info->power_status)); 392 slot->hpc_ops->get_power_status(slot, &(info->power_status));
523 slot->hpc_ops->get_attention_status(slot, &(info->attention_status)); 393 slot->hpc_ops->get_attention_status(slot, &(info->attention_status));
524 slot->hpc_ops->get_latch_status(slot, &(info->latch_status)); 394 slot->hpc_ops->get_latch_status(slot, &(info->latch_status));
525 slot->hpc_ops->get_adapter_status(slot, &(info->adapter_status)); 395 slot->hpc_ops->get_adapter_status(slot, &(info->adapter_status));
526 396
527 /* result = pci_hp_change_slot_info(buffer, info); */
528 result = pci_hp_change_slot_info(slot->hotplug_slot, info); 397 result = pci_hp_change_slot_info(slot->hotplug_slot, info);
529 kfree (info); 398 kfree (info);
530 return result; 399 return result;
531} 400}
532 401
533static void interrupt_event_handler(struct controller *ctrl) 402/*
403 * Note: This function must be called with slot->lock held
404 */
405static void handle_button_press_event(struct slot *p_slot)
534{ 406{
535 int loop = 0; 407 struct controller *ctrl = p_slot->ctrl;
536 int change = 1;
537 u8 hp_slot;
538 u8 getstatus; 408 u8 getstatus;
539 struct slot *p_slot;
540 409
541 while (change) { 410 switch (p_slot->state) {
542 change = 0; 411 case STATIC_STATE:
543 412 p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
544 for (loop = 0; loop < MAX_EVENTS; loop++) { 413 if (getstatus) {
545 if (ctrl->event_queue[loop].event_type != 0) { 414 p_slot->state = BLINKINGOFF_STATE;
546 hp_slot = ctrl->event_queue[loop].hp_slot; 415 info("PCI slot #%s - powering off due to button "
547 416 "press.\n", p_slot->name);
548 p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); 417 } else {
549 418 p_slot->state = BLINKINGON_STATE;
550 if (ctrl->event_queue[loop].event_type == INT_BUTTON_CANCEL) { 419 info("PCI slot #%s - powering on due to button "
551 dbg("button cancel\n"); 420 "press.\n", p_slot->name);
552 del_timer(&p_slot->task_event); 421 }
553 422 /* blink green LED and turn off amber */
554 switch (p_slot->state) { 423 if (PWR_LED(ctrl->ctrlcap))
555 case BLINKINGOFF_STATE: 424 p_slot->hpc_ops->green_led_blink(p_slot);
556 if (PWR_LED(ctrl->ctrlcap)) 425 if (ATTN_LED(ctrl->ctrlcap))
557 p_slot->hpc_ops->green_led_on(p_slot); 426 p_slot->hpc_ops->set_attention_status(p_slot, 0);
558 427
559 if (ATTN_LED(ctrl->ctrlcap)) 428 schedule_delayed_work(&p_slot->work, 5*HZ);
560 p_slot->hpc_ops->set_attention_status(p_slot, 0); 429 break;
561 break; 430 case BLINKINGOFF_STATE:
562 case BLINKINGON_STATE: 431 case BLINKINGON_STATE:
563 if (PWR_LED(ctrl->ctrlcap)) 432 /*
564 p_slot->hpc_ops->green_led_off(p_slot); 433 * Cancel if we are still blinking; this means that we
565 434 * press the attention again before the 5 sec. limit
566 if (ATTN_LED(ctrl->ctrlcap)) 435 * expires to cancel hot-add or hot-remove
567 p_slot->hpc_ops->set_attention_status(p_slot, 0); 436 */
568 break; 437 info("Button cancel on Slot(%s)\n", p_slot->name);
569 default: 438 dbg("%s: button cancel\n", __FUNCTION__);
570 warn("Not a valid state\n"); 439 cancel_delayed_work(&p_slot->work);
571 return; 440 if (p_slot->state == BLINKINGOFF_STATE) {
572 } 441 if (PWR_LED(ctrl->ctrlcap))
573 info("PCI slot #%s - action canceled due to button press.\n", slot_name(p_slot)); 442 p_slot->hpc_ops->green_led_on(p_slot);
574 p_slot->state = STATIC_STATE; 443 } else {
575 } 444 if (PWR_LED(ctrl->ctrlcap))
576 /* ***********Button Pressed (No action on 1st press...) */ 445 p_slot->hpc_ops->green_led_off(p_slot);
577 else if (ctrl->event_queue[loop].event_type == INT_BUTTON_PRESS) { 446 }
578 447 if (ATTN_LED(ctrl->ctrlcap))
579 if (ATTN_BUTTN(ctrl->ctrlcap)) { 448 p_slot->hpc_ops->set_attention_status(p_slot, 0);
580 dbg("Button pressed\n"); 449 info("PCI slot #%s - action canceled due to button press\n",
581 p_slot->hpc_ops->get_power_status(p_slot, &getstatus); 450 p_slot->name);
582 if (getstatus) { 451 p_slot->state = STATIC_STATE;
583 /* slot is on */ 452 break;
584 dbg("slot is on\n"); 453 case POWEROFF_STATE:
585 p_slot->state = BLINKINGOFF_STATE; 454 case POWERON_STATE:
586 info("PCI slot #%s - powering off due to button press.\n", slot_name(p_slot)); 455 /*
587 } else { 456 * Ignore if the slot is on power-on or power-off state;
588 /* slot is off */ 457 * this means that the previous attention button action
589 dbg("slot is off\n"); 458 * to hot-add or hot-remove is undergoing
590 p_slot->state = BLINKINGON_STATE; 459 */
591 info("PCI slot #%s - powering on due to button press.\n", slot_name(p_slot)); 460 info("Button ignore on Slot(%s)\n", p_slot->name);
592 } 461 update_slot_info(p_slot);
593 462 break;
594 /* blink green LED and turn off amber */ 463 default:
595 if (PWR_LED(ctrl->ctrlcap)) 464 warn("Not a valid state\n");
596 p_slot->hpc_ops->green_led_blink(p_slot); 465 break;
597
598 if (ATTN_LED(ctrl->ctrlcap))
599 p_slot->hpc_ops->set_attention_status(p_slot, 0);
600
601 init_timer(&p_slot->task_event);
602 p_slot->task_event.expires = jiffies + 5 * HZ; /* 5 second delay */
603 p_slot->task_event.function = (void (*)(unsigned long)) pushbutton_helper_thread;
604 p_slot->task_event.data = (unsigned long) p_slot;
605
606 add_timer(&p_slot->task_event);
607 }
608 }
609 /***********POWER FAULT********************/
610 else if (ctrl->event_queue[loop].event_type == INT_POWER_FAULT) {
611 if (POWER_CTRL(ctrl->ctrlcap)) {
612 dbg("power fault\n");
613 if (ATTN_LED(ctrl->ctrlcap))
614 p_slot->hpc_ops->set_attention_status(p_slot, 1);
615
616 if (PWR_LED(ctrl->ctrlcap))
617 p_slot->hpc_ops->green_led_off(p_slot);
618 }
619 }
620 /***********SURPRISE REMOVAL********************/
621 else if ((ctrl->event_queue[loop].event_type == INT_PRESENCE_ON) ||
622 (ctrl->event_queue[loop].event_type == INT_PRESENCE_OFF)) {
623 if (HP_SUPR_RM(ctrl->ctrlcap)) {
624 dbg("Surprise Removal\n");
625 if (p_slot) {
626 surprise_rm_pending = (unsigned long) p_slot;
627 up(&event_semaphore);
628 update_slot_info(p_slot);
629 }
630 }
631 } else {
632 /* refresh notification */
633 if (p_slot)
634 update_slot_info(p_slot);
635 }
636
637 ctrl->event_queue[loop].event_type = 0;
638
639 change = 1;
640 }
641 } /* End of FOR loop */
642 } 466 }
643} 467}
644 468
469/*
470 * Note: This function must be called with slot->lock held
471 */
472static void handle_surprise_event(struct slot *p_slot)
473{
474 u8 getstatus;
475 struct power_work_info *info;
476
477 info = kmalloc(sizeof(*info), GFP_KERNEL);
478 if (!info) {
479 err("%s: Cannot allocate memory\n", __FUNCTION__);
480 return;
481 }
482 info->p_slot = p_slot;
483 INIT_WORK(&info->work, pciehp_power_thread);
484
485 p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus);
486 if (!getstatus)
487 p_slot->state = POWEROFF_STATE;
488 else
489 p_slot->state = POWERON_STATE;
490
491 queue_work(pciehp_wq, &info->work);
492}
493
494static void interrupt_event_handler(struct work_struct *work)
495{
496 struct event_info *info = container_of(work, struct event_info, work);
497 struct slot *p_slot = info->p_slot;
498 struct controller *ctrl = p_slot->ctrl;
499
500 mutex_lock(&p_slot->lock);
501 switch (info->event_type) {
502 case INT_BUTTON_PRESS:
503 handle_button_press_event(p_slot);
504 break;
505 case INT_POWER_FAULT:
506 if (!POWER_CTRL(ctrl->ctrlcap))
507 break;
508 if (ATTN_LED(ctrl->ctrlcap))
509 p_slot->hpc_ops->set_attention_status(p_slot, 1);
510 if (PWR_LED(ctrl->ctrlcap))
511 p_slot->hpc_ops->green_led_off(p_slot);
512 break;
513 case INT_PRESENCE_ON:
514 case INT_PRESENCE_OFF:
515 if (!HP_SUPR_RM(ctrl->ctrlcap))
516 break;
517 dbg("Surprise Removal\n");
518 update_slot_info(p_slot);
519 handle_surprise_event(p_slot);
520 break;
521 default:
522 update_slot_info(p_slot);
523 break;
524 }
525 mutex_unlock(&p_slot->lock);
526
527 kfree(info);
528}
529
645int pciehp_enable_slot(struct slot *p_slot) 530int pciehp_enable_slot(struct slot *p_slot)
646{ 531{
647 u8 getstatus = 0; 532 u8 getstatus = 0;
@@ -653,7 +538,7 @@ int pciehp_enable_slot(struct slot *p_slot)
653 rc = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus); 538 rc = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus);
654 if (rc || !getstatus) { 539 if (rc || !getstatus) {
655 info("%s: no adapter on slot(%s)\n", __FUNCTION__, 540 info("%s: no adapter on slot(%s)\n", __FUNCTION__,
656 slot_name(p_slot)); 541 p_slot->name);
657 mutex_unlock(&p_slot->ctrl->crit_sect); 542 mutex_unlock(&p_slot->ctrl->crit_sect);
658 return -ENODEV; 543 return -ENODEV;
659 } 544 }
@@ -661,7 +546,7 @@ int pciehp_enable_slot(struct slot *p_slot)
661 rc = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); 546 rc = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
662 if (rc || getstatus) { 547 if (rc || getstatus) {
663 info("%s: latch open on slot(%s)\n", __FUNCTION__, 548 info("%s: latch open on slot(%s)\n", __FUNCTION__,
664 slot_name(p_slot)); 549 p_slot->name);
665 mutex_unlock(&p_slot->ctrl->crit_sect); 550 mutex_unlock(&p_slot->ctrl->crit_sect);
666 return -ENODEV; 551 return -ENODEV;
667 } 552 }
@@ -671,7 +556,7 @@ int pciehp_enable_slot(struct slot *p_slot)
671 rc = p_slot->hpc_ops->get_power_status(p_slot, &getstatus); 556 rc = p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
672 if (rc || getstatus) { 557 if (rc || getstatus) {
673 info("%s: already enabled on slot(%s)\n", __FUNCTION__, 558 info("%s: already enabled on slot(%s)\n", __FUNCTION__,
674 slot_name(p_slot)); 559 p_slot->name);
675 mutex_unlock(&p_slot->ctrl->crit_sect); 560 mutex_unlock(&p_slot->ctrl->crit_sect);
676 return -EINVAL; 561 return -EINVAL;
677 } 562 }
@@ -706,7 +591,7 @@ int pciehp_disable_slot(struct slot *p_slot)
706 ret = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus); 591 ret = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus);
707 if (ret || !getstatus) { 592 if (ret || !getstatus) {
708 info("%s: no adapter on slot(%s)\n", __FUNCTION__, 593 info("%s: no adapter on slot(%s)\n", __FUNCTION__,
709 slot_name(p_slot)); 594 p_slot->name);
710 mutex_unlock(&p_slot->ctrl->crit_sect); 595 mutex_unlock(&p_slot->ctrl->crit_sect);
711 return -ENODEV; 596 return -ENODEV;
712 } 597 }
@@ -716,7 +601,7 @@ int pciehp_disable_slot(struct slot *p_slot)
716 ret = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); 601 ret = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
717 if (ret || getstatus) { 602 if (ret || getstatus) {
718 info("%s: latch open on slot(%s)\n", __FUNCTION__, 603 info("%s: latch open on slot(%s)\n", __FUNCTION__,
719 slot_name(p_slot)); 604 p_slot->name);
720 mutex_unlock(&p_slot->ctrl->crit_sect); 605 mutex_unlock(&p_slot->ctrl->crit_sect);
721 return -ENODEV; 606 return -ENODEV;
722 } 607 }
@@ -726,7 +611,7 @@ int pciehp_disable_slot(struct slot *p_slot)
726 ret = p_slot->hpc_ops->get_power_status(p_slot, &getstatus); 611 ret = p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
727 if (ret || !getstatus) { 612 if (ret || !getstatus) {
728 info("%s: already disabled slot(%s)\n", __FUNCTION__, 613 info("%s: already disabled slot(%s)\n", __FUNCTION__,
729 slot_name(p_slot)); 614 p_slot->name);
730 mutex_unlock(&p_slot->ctrl->crit_sect); 615 mutex_unlock(&p_slot->ctrl->crit_sect);
731 return -EINVAL; 616 return -EINVAL;
732 } 617 }
@@ -739,3 +624,66 @@ int pciehp_disable_slot(struct slot *p_slot)
739 return ret; 624 return ret;
740} 625}
741 626
627int pciehp_sysfs_enable_slot(struct slot *p_slot)
628{
629 int retval = -ENODEV;
630
631 mutex_lock(&p_slot->lock);
632 switch (p_slot->state) {
633 case BLINKINGON_STATE:
634 cancel_delayed_work(&p_slot->work);
635 case STATIC_STATE:
636 p_slot->state = POWERON_STATE;
637 mutex_unlock(&p_slot->lock);
638 retval = pciehp_enable_slot(p_slot);
639 mutex_lock(&p_slot->lock);
640 p_slot->state = STATIC_STATE;
641 break;
642 case POWERON_STATE:
643 info("Slot %s is already in powering on state\n",
644 p_slot->name);
645 break;
646 case BLINKINGOFF_STATE:
647 case POWEROFF_STATE:
648 info("Already enabled on slot %s\n", p_slot->name);
649 break;
650 default:
651 err("Not a valid state on slot %s\n", p_slot->name);
652 break;
653 }
654 mutex_unlock(&p_slot->lock);
655
656 return retval;
657}
658
659int pciehp_sysfs_disable_slot(struct slot *p_slot)
660{
661 int retval = -ENODEV;
662
663 mutex_lock(&p_slot->lock);
664 switch (p_slot->state) {
665 case BLINKINGOFF_STATE:
666 cancel_delayed_work(&p_slot->work);
667 case STATIC_STATE:
668 p_slot->state = POWEROFF_STATE;
669 mutex_unlock(&p_slot->lock);
670 retval = pciehp_disable_slot(p_slot);
671 mutex_lock(&p_slot->lock);
672 p_slot->state = STATIC_STATE;
673 break;
674 case POWEROFF_STATE:
675 info("Slot %s is already in powering off state\n",
676 p_slot->name);
677 break;
678 case BLINKINGON_STATE:
679 case POWERON_STATE:
680 info("Already disabled on slot %s\n", p_slot->name);
681 break;
682 default:
683 err("Not a valid state on slot %s\n", p_slot->name);
684 break;
685 }
686 mutex_unlock(&p_slot->lock);
687
688 return retval;
689}
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 @@
71#define DBG_LEAVE_ROUTINE 71#define DBG_LEAVE_ROUTINE
72#endif /* DEBUG */ 72#endif /* DEBUG */
73 73
74static atomic_t pciehp_num_controllers = ATOMIC_INIT(0);
75
74struct ctrl_reg { 76struct ctrl_reg {
75 u8 cap_id; 77 u8 cap_id;
76 u8 nxt_ptr; 78 u8 nxt_ptr;
@@ -219,10 +221,7 @@ static inline int pciehp_writel(struct controller *ctrl, int reg, u32 value)
219#define EMI_STATE 0x0080 221#define EMI_STATE 0x0080
220#define EMI_STATUS_BIT 7 222#define EMI_STATUS_BIT 7
221 223
222static spinlock_t hpc_event_lock;
223
224DEFINE_DBG_BUFFER /* Debug string buffer for entire HPC defined here */ 224DEFINE_DBG_BUFFER /* Debug string buffer for entire HPC defined here */
225static int ctlr_seq_num = 0; /* Controller sequence # */
226 225
227static irqreturn_t pcie_isr(int irq, void *dev_id); 226static irqreturn_t pcie_isr(int irq, void *dev_id);
228static void start_int_poll_timer(struct controller *ctrl, int sec); 227static void start_int_poll_timer(struct controller *ctrl, int sec);
@@ -656,6 +655,13 @@ static void hpc_release_ctlr(struct controller *ctrl)
656 else 655 else
657 free_irq(ctrl->pci_dev->irq, ctrl); 656 free_irq(ctrl->pci_dev->irq, ctrl);
658 657
658 /*
659 * If this is the last controller to be released, destroy the
660 * pciehp work queue
661 */
662 if (atomic_dec_and_test(&pciehp_num_controllers))
663 destroy_workqueue(pciehp_wq);
664
659 DBG_LEAVE_ROUTINE 665 DBG_LEAVE_ROUTINE
660} 666}
661 667
@@ -1152,7 +1158,6 @@ int pciehp_acpi_get_hp_hw_control_from_firmware(struct pci_dev *dev)
1152int pcie_init(struct controller * ctrl, struct pcie_device *dev) 1158int pcie_init(struct controller * ctrl, struct pcie_device *dev)
1153{ 1159{
1154 int rc; 1160 int rc;
1155 static int first = 1;
1156 u16 temp_word; 1161 u16 temp_word;
1157 u16 cap_reg; 1162 u16 cap_reg;
1158 u16 intr_enable = 0; 1163 u16 intr_enable = 0;
@@ -1221,11 +1226,6 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev)
1221 dbg("%s: SLOTCTRL offset %x slot_ctrl %x\n", 1226 dbg("%s: SLOTCTRL offset %x slot_ctrl %x\n",
1222 __FUNCTION__, ctrl->cap_base + SLOTCTRL, slot_ctrl); 1227 __FUNCTION__, ctrl->cap_base + SLOTCTRL, slot_ctrl);
1223 1228
1224 if (first) {
1225 spin_lock_init(&hpc_event_lock);
1226 first = 0;
1227 }
1228
1229 for ( rc = 0; rc < DEVICE_COUNT_RESOURCE; rc++) 1229 for ( rc = 0; rc < DEVICE_COUNT_RESOURCE; rc++)
1230 if (pci_resource_len(pdev, rc) > 0) 1230 if (pci_resource_len(pdev, rc) > 0)
1231 dbg("pci resource[%d] start=0x%llx(len=0x%llx)\n", rc, 1231 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)
1286 rc = request_irq(ctrl->pci_dev->irq, pcie_isr, IRQF_SHARED, 1286 rc = request_irq(ctrl->pci_dev->irq, pcie_isr, IRQF_SHARED,
1287 MY_NAME, (void *)ctrl); 1287 MY_NAME, (void *)ctrl);
1288 dbg("%s: request_irq %d for hpc%d (returns %d)\n", 1288 dbg("%s: request_irq %d for hpc%d (returns %d)\n",
1289 __FUNCTION__, ctrl->pci_dev->irq, ctlr_seq_num, rc); 1289 __FUNCTION__, ctrl->pci_dev->irq,
1290 atomic_read(&pciehp_num_controllers), rc);
1290 if (rc) { 1291 if (rc) {
1291 err("Can't get irq %d for the hotplug controller\n", 1292 err("Can't get irq %d for the hotplug controller\n",
1292 ctrl->pci_dev->irq); 1293 ctrl->pci_dev->irq);
@@ -1296,6 +1297,18 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev)
1296 dbg("pciehp ctrl b:d:f:irq=0x%x:%x:%x:%x\n", pdev->bus->number, 1297 dbg("pciehp ctrl b:d:f:irq=0x%x:%x:%x:%x\n", pdev->bus->number,
1297 PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn), dev->irq); 1298 PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn), dev->irq);
1298 1299
1300 /*
1301 * If this is the first controller to be initialized,
1302 * initialize the pciehp work queue
1303 */
1304 if (atomic_add_return(1, &pciehp_num_controllers) == 1) {
1305 pciehp_wq = create_singlethread_workqueue("pciehpd");
1306 if (!pciehp_wq) {
1307 rc = -ENOMEM;
1308 goto abort_free_irq;
1309 }
1310 }
1311
1299 rc = pciehp_readw(ctrl, SLOTCTRL, &temp_word); 1312 rc = pciehp_readw(ctrl, SLOTCTRL, &temp_word);
1300 if (rc) { 1313 if (rc) {
1301 err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__); 1314 err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__);
@@ -1349,7 +1362,6 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev)
1349 goto abort_disable_intr; 1362 goto abort_disable_intr;
1350 } 1363 }
1351 1364
1352 ctlr_seq_num++;
1353 ctrl->hpc_ops = &pciehp_hpc_ops; 1365 ctrl->hpc_ops = &pciehp_hpc_ops;
1354 1366
1355 DBG_LEAVE_ROUTINE 1367 DBG_LEAVE_ROUTINE
diff --git a/drivers/pci/hotplug/rpadlpar_core.c b/drivers/pci/hotplug/rpadlpar_core.c
index 72383467a0d5..bb3c101c2c5a 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)
98 return NULL; 98 return NULL;
99} 99}
100 100
101static struct slot *find_slot(struct device_node *dn) 101/**
102 * find_php_slot - return hotplug slot structure for device node
103 *
104 * This routine will return the hotplug slot structure
105 * for a given device node. Note that built-in PCI slots
106 * may be dlpar-able, but not hot-pluggable, so this routine
107 * will return NULL for built-in PCI slots.
108 */
109static struct slot *find_php_slot(struct device_node *dn)
102{ 110{
103 struct list_head *tmp, *n; 111 struct list_head *tmp, *n;
104 struct slot *slot; 112 struct slot *slot;
@@ -224,9 +232,9 @@ static int dlpar_remove_phb(char *drc_name, struct device_node *dn)
224 if (!pcibios_find_pci_bus(dn)) 232 if (!pcibios_find_pci_bus(dn))
225 return -EINVAL; 233 return -EINVAL;
226 234
227 slot = find_slot(dn); 235 /* If pci slot is hotplugable, use hotplug to remove it */
236 slot = find_php_slot(dn);
228 if (slot) { 237 if (slot) {
229 /* Remove hotplug slot */
230 if (rpaphp_deregister_slot(slot)) { 238 if (rpaphp_deregister_slot(slot)) {
231 printk(KERN_ERR 239 printk(KERN_ERR
232 "%s: unable to remove hotplug slot %s\n", 240 "%s: unable to remove hotplug slot %s\n",
@@ -370,22 +378,17 @@ int dlpar_remove_pci_slot(char *drc_name, struct device_node *dn)
370 if (!bus) 378 if (!bus)
371 return -EINVAL; 379 return -EINVAL;
372 380
373 slot = find_slot(dn); 381 /* If pci slot is hotplugable, use hotplug to remove it */
382 slot = find_php_slot(dn);
374 if (slot) { 383 if (slot) {
375 /* Remove hotplug slot */
376 if (rpaphp_deregister_slot(slot)) { 384 if (rpaphp_deregister_slot(slot)) {
377 printk(KERN_ERR 385 printk(KERN_ERR
378 "%s: unable to remove hotplug slot %s\n", 386 "%s: unable to remove hotplug slot %s\n",
379 __FUNCTION__, drc_name); 387 __FUNCTION__, drc_name);
380 return -EIO; 388 return -EIO;
381 } 389 }
382 } else { 390 } else
383 struct pci_dev *dev, *tmp; 391 pcibios_remove_pci_devices(bus);
384 list_for_each_entry_safe(dev, tmp, &bus->devices, bus_list) {
385 eeh_remove_bus_device(dev);
386 pci_remove_bus_device(dev);
387 }
388 }
389 392
390 if (unmap_bus_range(bus)) { 393 if (unmap_bus_range(bus)) {
391 printk(KERN_ERR "%s: failed to unmap bus range\n", 394 printk(KERN_ERR "%s: failed to unmap bus range\n",
diff --git a/drivers/pci/hotplug/rpaphp.h b/drivers/pci/hotplug/rpaphp.h
index 2e7accf0f734..c822a779653f 100644
--- a/drivers/pci/hotplug/rpaphp.h
+++ b/drivers/pci/hotplug/rpaphp.h
@@ -83,19 +83,15 @@ struct slot {
83 83
84extern struct hotplug_slot_ops rpaphp_hotplug_slot_ops; 84extern struct hotplug_slot_ops rpaphp_hotplug_slot_ops;
85extern struct list_head rpaphp_slot_head; 85extern struct list_head rpaphp_slot_head;
86extern int num_slots;
87 86
88/* function prototypes */ 87/* function prototypes */
89 88
90/* rpaphp_pci.c */ 89/* rpaphp_pci.c */
91extern int rpaphp_enable_pci_slot(struct slot *slot); 90extern int rpaphp_enable_slot(struct slot *slot);
92extern int rpaphp_register_pci_slot(struct slot *slot);
93extern int rpaphp_get_pci_adapter_status(struct slot *slot, int is_init, u8 * value);
94extern int rpaphp_get_sensor_state(struct slot *slot, int *state); 91extern int rpaphp_get_sensor_state(struct slot *slot, int *state);
95 92
96/* rpaphp_core.c */ 93/* rpaphp_core.c */
97extern int rpaphp_add_slot(struct device_node *dn); 94extern int rpaphp_add_slot(struct device_node *dn);
98extern int rpaphp_remove_slot(struct slot *slot);
99extern int rpaphp_get_drc_props(struct device_node *dn, int *drc_index, 95extern int rpaphp_get_drc_props(struct device_node *dn, int *drc_index,
100 char **drc_name, char **drc_type, int *drc_power_domain); 96 char **drc_name, char **drc_type, int *drc_power_domain);
101 97
@@ -104,7 +100,5 @@ extern void dealloc_slot_struct(struct slot *slot);
104extern struct slot *alloc_slot_struct(struct device_node *dn, int drc_index, char *drc_name, int power_domain); 100extern struct slot *alloc_slot_struct(struct device_node *dn, int drc_index, char *drc_name, int power_domain);
105extern int rpaphp_register_slot(struct slot *slot); 101extern int rpaphp_register_slot(struct slot *slot);
106extern int rpaphp_deregister_slot(struct slot *slot); 102extern int rpaphp_deregister_slot(struct slot *slot);
107extern int rpaphp_get_power_status(struct slot *slot, u8 * value);
108extern int rpaphp_set_attention_status(struct slot *slot, u8 status);
109 103
110#endif /* _PPC64PHP_H */ 104#endif /* _PPC64PHP_H */
diff --git a/drivers/pci/hotplug/rpaphp_core.c b/drivers/pci/hotplug/rpaphp_core.c
index 353da5b296ef..899eed002748 100644
--- a/drivers/pci/hotplug/rpaphp_core.c
+++ b/drivers/pci/hotplug/rpaphp_core.c
@@ -39,9 +39,7 @@
39#include "rpaphp.h" 39#include "rpaphp.h"
40 40
41int debug; 41int debug;
42static struct semaphore rpaphp_sem;
43LIST_HEAD(rpaphp_slot_head); 42LIST_HEAD(rpaphp_slot_head);
44int num_slots;
45 43
46#define DRIVER_VERSION "0.1" 44#define DRIVER_VERSION "0.1"
47#define DRIVER_AUTHOR "Linda Xie <lxie@us.ibm.com>" 45#define DRIVER_AUTHOR "Linda Xie <lxie@us.ibm.com>"
@@ -55,11 +53,6 @@ MODULE_LICENSE("GPL");
55 53
56module_param(debug, bool, 0644); 54module_param(debug, bool, 0644);
57 55
58static int rpaphp_get_attention_status(struct slot *slot)
59{
60 return slot->hotplug_slot->info->attention_status;
61}
62
63/** 56/**
64 * set_attention_status - set attention LED 57 * set_attention_status - set attention LED
65 * echo 0 > attention -- set LED OFF 58 * echo 0 > attention -- set LED OFF
@@ -69,79 +62,75 @@ static int rpaphp_get_attention_status(struct slot *slot)
69 */ 62 */
70static int set_attention_status(struct hotplug_slot *hotplug_slot, u8 value) 63static int set_attention_status(struct hotplug_slot *hotplug_slot, u8 value)
71{ 64{
72 int retval = 0; 65 int rc;
73 struct slot *slot = (struct slot *)hotplug_slot->private; 66 struct slot *slot = (struct slot *)hotplug_slot->private;
74 67
75 down(&rpaphp_sem);
76 switch (value) { 68 switch (value) {
77 case 0: 69 case 0:
78 retval = rpaphp_set_attention_status(slot, LED_OFF);
79 hotplug_slot->info->attention_status = 0;
80 break;
81 case 1: 70 case 1:
82 default:
83 retval = rpaphp_set_attention_status(slot, LED_ON);
84 hotplug_slot->info->attention_status = 1;
85 break;
86 case 2: 71 case 2:
87 retval = rpaphp_set_attention_status(slot, LED_ID); 72 break;
88 hotplug_slot->info->attention_status = 2; 73 default:
74 value = 1;
89 break; 75 break;
90 } 76 }
91 up(&rpaphp_sem); 77
92 return retval; 78 rc = rtas_set_indicator(DR_INDICATOR, slot->index, value);
79 if (!rc)
80 hotplug_slot->info->attention_status = value;
81
82 return rc;
93} 83}
94 84
95/** 85/**
96 * get_power_status - get power status of a slot 86 * get_power_status - get power status of a slot
97 * @hotplug_slot: slot to get status 87 * @hotplug_slot: slot to get status
98 * @value: pointer to store status 88 * @value: pointer to store status
99 *
100 *
101 */ 89 */
102static int get_power_status(struct hotplug_slot *hotplug_slot, u8 * value) 90static int get_power_status(struct hotplug_slot *hotplug_slot, u8 * value)
103{ 91{
104 int retval; 92 int retval, level;
105 struct slot *slot = (struct slot *)hotplug_slot->private; 93 struct slot *slot = (struct slot *)hotplug_slot->private;
106 94
107 down(&rpaphp_sem); 95 retval = rtas_get_power_level (slot->power_domain, &level);
108 retval = rpaphp_get_power_status(slot, value); 96 if (!retval)
109 up(&rpaphp_sem); 97 *value = level;
110 return retval; 98 return retval;
111} 99}
112 100
113/** 101/**
114 * get_attention_status - get attention LED status 102 * get_attention_status - get attention LED status
115 *
116 *
117 */ 103 */
118static int get_attention_status(struct hotplug_slot *hotplug_slot, u8 * value) 104static int get_attention_status(struct hotplug_slot *hotplug_slot, u8 * value)
119{ 105{
120 int retval = 0;
121 struct slot *slot = (struct slot *)hotplug_slot->private; 106 struct slot *slot = (struct slot *)hotplug_slot->private;
122 107 *value = slot->hotplug_slot->info->attention_status;
123 down(&rpaphp_sem); 108 return 0;
124 *value = rpaphp_get_attention_status(slot);
125 up(&rpaphp_sem);
126 return retval;
127} 109}
128 110
129static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 * value) 111static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 * value)
130{ 112{
131 struct slot *slot = (struct slot *)hotplug_slot->private; 113 struct slot *slot = (struct slot *)hotplug_slot->private;
132 int retval = 0; 114 int rc, state;
133 115
134 down(&rpaphp_sem); 116 rc = rpaphp_get_sensor_state(slot, &state);
135 retval = rpaphp_get_pci_adapter_status(slot, 0, value); 117
136 up(&rpaphp_sem); 118 *value = NOT_VALID;
137 return retval; 119 if (rc)
120 return rc;
121
122 if (state == EMPTY)
123 *value = EMPTY;
124 else if (state == PRESENT)
125 *value = slot->state;
126
127 return 0;
138} 128}
139 129
140static int get_max_bus_speed(struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value) 130static int get_max_bus_speed(struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value)
141{ 131{
142 struct slot *slot = (struct slot *)hotplug_slot->private; 132 struct slot *slot = (struct slot *)hotplug_slot->private;
143 133
144 down(&rpaphp_sem);
145 switch (slot->type) { 134 switch (slot->type) {
146 case 1: 135 case 1:
147 case 2: 136 case 2:
@@ -172,7 +161,6 @@ static int get_max_bus_speed(struct hotplug_slot *hotplug_slot, enum pci_bus_spe
172 break; 161 break;
173 162
174 } 163 }
175 up(&rpaphp_sem);
176 return 0; 164 return 0;
177} 165}
178 166
@@ -265,6 +253,14 @@ static int is_php_type(char *drc_type)
265 return 1; 253 return 1;
266} 254}
267 255
256/**
257 * is_php_dn() - return 1 if this is a hotpluggable pci slot, else 0
258 *
259 * This routine will return true only if the device node is
260 * a hotpluggable slot. This routine will return false
261 * for built-in pci slots (even when the built-in slots are
262 * dlparable.)
263 */
268static int is_php_dn(struct device_node *dn, const int **indexes, 264static int is_php_dn(struct device_node *dn, const int **indexes,
269 const int **names, const int **types, const int **power_domains) 265 const int **names, const int **types, const int **power_domains)
270{ 266{
@@ -272,24 +268,31 @@ static int is_php_dn(struct device_node *dn, const int **indexes,
272 int rc; 268 int rc;
273 269
274 rc = get_children_props(dn, indexes, names, &drc_types, power_domains); 270 rc = get_children_props(dn, indexes, names, &drc_types, power_domains);
275 if (rc >= 0) { 271 if (rc < 0)
276 if (is_php_type((char *) &drc_types[1])) { 272 return 0;
277 *types = drc_types;
278 return 1;
279 }
280 }
281 273
282 return 0; 274 if (!is_php_type((char *) &drc_types[1]))
275 return 0;
276
277 *types = drc_types;
278 return 1;
283} 279}
284 280
285/** 281/**
286 * rpaphp_add_slot -- add hotplug or dlpar slot 282 * rpaphp_add_slot -- declare a hotplug slot to the hotplug subsystem.
283 * @dn device node of slot
284 *
285 * This subroutine will register a hotplugable slot with the
286 * PCI hotplug infrastructure. This routine is typicaly called
287 * during boot time, if the hotplug slots are present at boot time,
288 * or is called later, by the dlpar add code, if the slot is
289 * being dynamically added during runtime.
290 *
291 * If the device node points at an embedded (built-in) slot, this
292 * routine will just return without doing anything, since embedded
293 * slots cannot be hotplugged.
287 * 294 *
288 * rpaphp not only registers PCI hotplug slots(HOTPLUG), 295 * To remove a slot, it suffices to call rpaphp_deregister_slot()
289 * but also logical DR slots(EMBEDDED).
290 * HOTPLUG slot: An adapter can be physically added/removed.
291 * EMBEDDED slot: An adapter can be logically removed/added
292 * from/to a partition with the slot.
293 */ 296 */
294int rpaphp_add_slot(struct device_node *dn) 297int rpaphp_add_slot(struct device_node *dn)
295{ 298{
@@ -299,34 +302,42 @@ int rpaphp_add_slot(struct device_node *dn)
299 const int *indexes, *names, *types, *power_domains; 302 const int *indexes, *names, *types, *power_domains;
300 char *name, *type; 303 char *name, *type;
301 304
305 if (!dn->name || strcmp(dn->name, "pci"))
306 return 0;
307
308 /* If this is not a hotplug slot, return without doing anything. */
309 if (!is_php_dn(dn, &indexes, &names, &types, &power_domains))
310 return 0;
311
302 dbg("Entry %s: dn->full_name=%s\n", __FUNCTION__, dn->full_name); 312 dbg("Entry %s: dn->full_name=%s\n", __FUNCTION__, dn->full_name);
303 313
304 /* register PCI devices */ 314 /* register PCI devices */
305 if (dn->name != 0 && strcmp(dn->name, "pci") == 0) { 315 name = (char *) &names[1];
306 if (!is_php_dn(dn, &indexes, &names, &types, &power_domains)) 316 type = (char *) &types[1];
307 goto exit; 317 for (i = 0; i < indexes[0]; i++) {
308 318
309 name = (char *) &names[1]; 319 slot = alloc_slot_struct(dn, indexes[i + 1], name, power_domains[i + 1]);
310 type = (char *) &types[1]; 320 if (!slot)
311 for (i = 0; i < indexes[0]; i++, 321 return -ENOMEM;
312 name += (strlen(name) + 1), type += (strlen(type) + 1)) { 322
313 323 slot->type = simple_strtoul(type, NULL, 10);
314 if (!(slot = alloc_slot_struct(dn, indexes[i + 1], name,
315 power_domains[i + 1]))) {
316 retval = -ENOMEM;
317 goto exit;
318 }
319 slot->type = simple_strtoul(type, NULL, 10);
320 324
321 dbg("Found drc-index:0x%x drc-name:%s drc-type:%s\n", 325 dbg("Found drc-index:0x%x drc-name:%s drc-type:%s\n",
322 indexes[i + 1], name, type); 326 indexes[i + 1], name, type);
323 327
324 retval = rpaphp_register_pci_slot(slot); 328 retval = rpaphp_enable_slot(slot);
325 } 329 if (!retval)
330 retval = rpaphp_register_slot(slot);
331
332 if (retval)
333 dealloc_slot_struct(slot);
334
335 name += strlen(name) + 1;
336 type += strlen(type) + 1;
326 } 337 }
327exit: 338 dbg("%s - Exit: rc[%d]\n", __FUNCTION__, retval);
328 dbg("%s - Exit: num_slots=%d rc[%d]\n", 339
329 __FUNCTION__, num_slots, retval); 340 /* XXX FIXME: reports a failure only if last entry in loop failed */
330 return retval; 341 return retval;
331} 342}
332 343
@@ -354,7 +365,6 @@ static int __init rpaphp_init(void)
354 struct device_node *dn = NULL; 365 struct device_node *dn = NULL;
355 366
356 info(DRIVER_DESC " version: " DRIVER_VERSION "\n"); 367 info(DRIVER_DESC " version: " DRIVER_VERSION "\n");
357 init_MUTEX(&rpaphp_sem);
358 368
359 while ((dn = of_find_node_by_name(dn, "pci"))) 369 while ((dn = of_find_node_by_name(dn, "pci")))
360 rpaphp_add_slot(dn); 370 rpaphp_add_slot(dn);
@@ -367,8 +377,9 @@ static void __exit rpaphp_exit(void)
367 cleanup_slots(); 377 cleanup_slots();
368} 378}
369 379
370static int __enable_slot(struct slot *slot) 380static int enable_slot(struct hotplug_slot *hotplug_slot)
371{ 381{
382 struct slot *slot = (struct slot *)hotplug_slot->private;
372 int state; 383 int state;
373 int retval; 384 int retval;
374 385
@@ -392,46 +403,17 @@ static int __enable_slot(struct slot *slot)
392 return 0; 403 return 0;
393} 404}
394 405
395static int enable_slot(struct hotplug_slot *hotplug_slot) 406static int disable_slot(struct hotplug_slot *hotplug_slot)
396{ 407{
397 int retval;
398 struct slot *slot = (struct slot *)hotplug_slot->private; 408 struct slot *slot = (struct slot *)hotplug_slot->private;
399
400 down(&rpaphp_sem);
401 retval = __enable_slot(slot);
402 up(&rpaphp_sem);
403
404 return retval;
405}
406
407static int __disable_slot(struct slot *slot)
408{
409 struct pci_dev *dev, *tmp;
410
411 if (slot->state == NOT_CONFIGURED) 409 if (slot->state == NOT_CONFIGURED)
412 return -EINVAL; 410 return -EINVAL;
413 411
414 list_for_each_entry_safe(dev, tmp, &slot->bus->devices, bus_list) { 412 pcibios_remove_pci_devices(slot->bus);
415 eeh_remove_bus_device(dev);
416 pci_remove_bus_device(dev);
417 }
418
419 slot->state = NOT_CONFIGURED; 413 slot->state = NOT_CONFIGURED;
420 return 0; 414 return 0;
421} 415}
422 416
423static int disable_slot(struct hotplug_slot *hotplug_slot)
424{
425 struct slot *slot = (struct slot *)hotplug_slot->private;
426 int retval;
427
428 down(&rpaphp_sem);
429 retval = __disable_slot (slot);
430 up(&rpaphp_sem);
431
432 return retval;
433}
434
435struct hotplug_slot_ops rpaphp_hotplug_slot_ops = { 417struct hotplug_slot_ops rpaphp_hotplug_slot_ops = {
436 .owner = THIS_MODULE, 418 .owner = THIS_MODULE,
437 .enable_slot = enable_slot, 419 .enable_slot = enable_slot,
diff --git a/drivers/pci/hotplug/rpaphp_pci.c b/drivers/pci/hotplug/rpaphp_pci.c
index 6f6cbede5135..54ca8650d511 100644
--- a/drivers/pci/hotplug/rpaphp_pci.c
+++ b/drivers/pci/hotplug/rpaphp_pci.c
@@ -64,75 +64,6 @@ int rpaphp_get_sensor_state(struct slot *slot, int *state)
64 return rc; 64 return rc;
65} 65}
66 66
67/**
68 * get_pci_adapter_status - get the status of a slot
69 *
70 * 0-- slot is empty
71 * 1-- adapter is configured
72 * 2-- adapter is not configured
73 * 3-- not valid
74 */
75int rpaphp_get_pci_adapter_status(struct slot *slot, int is_init, u8 * value)
76{
77 struct pci_bus *bus;
78 int state, rc;
79
80 *value = NOT_VALID;
81 rc = rpaphp_get_sensor_state(slot, &state);
82 if (rc)
83 goto exit;
84
85 if (state == EMPTY)
86 *value = EMPTY;
87 else if (state == PRESENT) {
88 if (!is_init) {
89 /* at run-time slot->state can be changed by */
90 /* config/unconfig adapter */
91 *value = slot->state;
92 } else {
93 bus = pcibios_find_pci_bus(slot->dn);
94 if (bus && !list_empty(&bus->devices))
95 *value = CONFIGURED;
96 else
97 *value = NOT_CONFIGURED;
98 }
99 }
100exit:
101 return rc;
102}
103
104static void print_slot_pci_funcs(struct pci_bus *bus)
105{
106 struct device_node *dn;
107 struct pci_dev *dev;
108
109 dn = pci_bus_to_OF_node(bus);
110 if (!dn)
111 return;
112
113 dbg("%s: pci_devs of slot[%s]\n", __FUNCTION__, dn->full_name);
114 list_for_each_entry (dev, &bus->devices, bus_list)
115 dbg("\t%s\n", pci_name(dev));
116 return;
117}
118
119static int setup_pci_hotplug_slot_info(struct slot *slot)
120{
121 struct hotplug_slot_info *hotplug_slot_info = slot->hotplug_slot->info;
122
123 dbg("%s Initilize the PCI slot's hotplug->info structure ...\n",
124 __FUNCTION__);
125 rpaphp_get_power_status(slot, &hotplug_slot_info->power_status);
126 rpaphp_get_pci_adapter_status(slot, 1,
127 &hotplug_slot_info->adapter_status);
128 if (hotplug_slot_info->adapter_status == NOT_VALID) {
129 err("%s: NOT_VALID: skip dn->full_name=%s\n",
130 __FUNCTION__, slot->dn->full_name);
131 return -EINVAL;
132 }
133 return 0;
134}
135
136static void set_slot_name(struct slot *slot) 67static void set_slot_name(struct slot *slot)
137{ 68{
138 struct pci_bus *bus = slot->bus; 69 struct pci_bus *bus = slot->bus;
@@ -146,69 +77,73 @@ static void set_slot_name(struct slot *slot)
146 bus->number); 77 bus->number);
147} 78}
148 79
149static int setup_pci_slot(struct slot *slot) 80/**
81 * rpaphp_enable_slot - record slot state, config pci device
82 *
83 * Initialize values in the slot, and the hotplug_slot info
84 * structures to indicate if there is a pci card plugged into
85 * the slot. If the slot is not empty, run the pcibios routine
86 * to get pcibios stuff correctly set up.
87 */
88int rpaphp_enable_slot(struct slot *slot)
150{ 89{
151 struct device_node *dn = slot->dn; 90 int rc, level, state;
152 struct pci_bus *bus; 91 struct pci_bus *bus;
92 struct hotplug_slot_info *info = slot->hotplug_slot->info;
93
94 info->adapter_status = NOT_VALID;
95 slot->state = EMPTY;
96
97 /* Find out if the power is turned on for the slot */
98 rc = rtas_get_power_level(slot->power_domain, &level);
99 if (rc)
100 return rc;
101 info->power_status = level;
102
103 /* Figure out if there is an adapter in the slot */
104 rc = rpaphp_get_sensor_state(slot, &state);
105 if (rc)
106 return rc;
153 107
154 BUG_ON(!dn); 108 bus = pcibios_find_pci_bus(slot->dn);
155 bus = pcibios_find_pci_bus(dn);
156 if (!bus) { 109 if (!bus) {
157 err("%s: no pci_bus for dn %s\n", __FUNCTION__, dn->full_name); 110 err("%s: no pci_bus for dn %s\n", __FUNCTION__, slot->dn->full_name);
158 goto exit_rc; 111 return -EINVAL;
159 } 112 }
160 113
114 info->adapter_status = EMPTY;
161 slot->bus = bus; 115 slot->bus = bus;
162 slot->pci_devs = &bus->devices; 116 slot->pci_devs = &bus->devices;
163 set_slot_name(slot); 117 set_slot_name(slot);
164 118
165 /* find slot's pci_dev if it's not empty */ 119 /* if there's an adapter in the slot, go add the pci devices */
166 if (slot->hotplug_slot->info->adapter_status == EMPTY) { 120 if (state == PRESENT) {
167 slot->state = EMPTY; /* slot is empty */ 121 info->adapter_status = NOT_CONFIGURED;
168 } else { 122 slot->state = NOT_CONFIGURED;
169 /* slot is occupied */ 123
170 if (!dn->child) { 124 /* non-empty slot has to have child */
171 /* non-empty slot has to have child */ 125 if (!slot->dn->child) {
172 err("%s: slot[%s]'s device_node doesn't have child for adapter\n", 126 err("%s: slot[%s]'s device_node doesn't have child for adapter\n",
173 __FUNCTION__, slot->name); 127 __FUNCTION__, slot->name);
174 goto exit_rc; 128 return -EINVAL;
175 } 129 }
176 130
177 if (slot->hotplug_slot->info->adapter_status == NOT_CONFIGURED) { 131 if (list_empty(&bus->devices))
178 dbg("%s CONFIGURING pci adapter in slot[%s]\n", 132 pcibios_add_pci_devices(bus);
179 __FUNCTION__, slot->name);
180 pcibios_add_pci_devices(slot->bus);
181 133
182 } else if (slot->hotplug_slot->info->adapter_status != CONFIGURED) { 134 if (!list_empty(&bus->devices)) {
183 err("%s: slot[%s]'s adapter_status is NOT_VALID.\n", 135 info->adapter_status = CONFIGURED;
184 __FUNCTION__, slot->name);
185 goto exit_rc;
186 }
187 print_slot_pci_funcs(slot->bus);
188 if (!list_empty(slot->pci_devs)) {
189 slot->state = CONFIGURED; 136 slot->state = CONFIGURED;
190 } else { 137 }
191 /* DLPAR add as opposed to 138
192 * boot time */ 139 if (debug) {
193 slot->state = NOT_CONFIGURED; 140 struct pci_dev *dev;
141 dbg("%s: pci_devs of slot[%s]\n", __FUNCTION__, slot->dn->full_name);
142 list_for_each_entry (dev, &bus->devices, bus_list)
143 dbg("\t%s\n", pci_name(dev));
194 } 144 }
195 } 145 }
196 return 0;
197exit_rc:
198 dealloc_slot_struct(slot);
199 return -EINVAL;
200}
201 146
202int rpaphp_register_pci_slot(struct slot *slot) 147 return 0;
203{
204 int rc = -EINVAL;
205
206 if (setup_pci_hotplug_slot_info(slot))
207 goto exit_rc;
208 if (setup_pci_slot(slot))
209 goto exit_rc;
210 rc = rpaphp_register_slot(slot);
211exit_rc:
212 return rc;
213} 148}
214 149
diff --git a/drivers/pci/hotplug/rpaphp_slot.c b/drivers/pci/hotplug/rpaphp_slot.c
index 3009193f0058..d4ee8723fcb3 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 = {
56static void rpaphp_release_slot(struct hotplug_slot *hotplug_slot) 56static void rpaphp_release_slot(struct hotplug_slot *hotplug_slot)
57{ 57{
58 struct slot *slot = (struct slot *) hotplug_slot->private; 58 struct slot *slot = (struct slot *) hotplug_slot->private;
59
60 dealloc_slot_struct(slot); 59 dealloc_slot_struct(slot);
61} 60}
62 61
@@ -65,12 +64,12 @@ void dealloc_slot_struct(struct slot *slot)
65 kfree(slot->hotplug_slot->info); 64 kfree(slot->hotplug_slot->info);
66 kfree(slot->hotplug_slot->name); 65 kfree(slot->hotplug_slot->name);
67 kfree(slot->hotplug_slot); 66 kfree(slot->hotplug_slot);
67 kfree(slot->location);
68 kfree(slot); 68 kfree(slot);
69 return;
70} 69}
71 70
72struct slot *alloc_slot_struct(struct device_node *dn, int drc_index, char *drc_name, 71struct slot *alloc_slot_struct(struct device_node *dn,
73 int power_domain) 72 int drc_index, char *drc_name, int power_domain)
74{ 73{
75 struct slot *slot; 74 struct slot *slot;
76 75
@@ -115,7 +114,7 @@ error_nomem:
115 114
116static int is_registered(struct slot *slot) 115static int is_registered(struct slot *slot)
117{ 116{
118 struct slot *tmp_slot; 117 struct slot *tmp_slot;
119 118
120 list_for_each_entry(tmp_slot, &rpaphp_slot_head, rpaphp_slot_list) { 119 list_for_each_entry(tmp_slot, &rpaphp_slot_head, rpaphp_slot_list) {
121 if (!strcmp(tmp_slot->name, slot->name)) 120 if (!strcmp(tmp_slot->name, slot->name))
@@ -140,8 +139,6 @@ int rpaphp_deregister_slot(struct slot *slot)
140 retval = pci_hp_deregister(php_slot); 139 retval = pci_hp_deregister(php_slot);
141 if (retval) 140 if (retval)
142 err("Problem unregistering a slot %s\n", slot->name); 141 err("Problem unregistering a slot %s\n", slot->name);
143 else
144 num_slots--;
145 142
146 dbg("%s - Exit: rc[%d]\n", __FUNCTION__, retval); 143 dbg("%s - Exit: rc[%d]\n", __FUNCTION__, retval);
147 return retval; 144 return retval;
@@ -160,14 +157,13 @@ int rpaphp_register_slot(struct slot *slot)
160 /* should not try to register the same slot twice */ 157 /* should not try to register the same slot twice */
161 if (is_registered(slot)) { 158 if (is_registered(slot)) {
162 err("rpaphp_register_slot: slot[%s] is already registered\n", slot->name); 159 err("rpaphp_register_slot: slot[%s] is already registered\n", slot->name);
163 retval = -EAGAIN; 160 return -EAGAIN;
164 goto register_fail;
165 } 161 }
166 162
167 retval = pci_hp_register(php_slot); 163 retval = pci_hp_register(php_slot);
168 if (retval) { 164 if (retval) {
169 err("pci_hp_register failed with error %d\n", retval); 165 err("pci_hp_register failed with error %d\n", retval);
170 goto register_fail; 166 return retval;
171 } 167 }
172 168
173 /* create "phy_location" file */ 169 /* create "phy_location" file */
@@ -181,43 +177,10 @@ int rpaphp_register_slot(struct slot *slot)
181 list_add(&slot->rpaphp_slot_list, &rpaphp_slot_head); 177 list_add(&slot->rpaphp_slot_list, &rpaphp_slot_head);
182 info("Slot [%s](PCI location=%s) registered\n", slot->name, 178 info("Slot [%s](PCI location=%s) registered\n", slot->name,
183 slot->location); 179 slot->location);
184 num_slots++;
185 return 0; 180 return 0;
186 181
187sysfs_fail: 182sysfs_fail:
188 pci_hp_deregister(php_slot); 183 pci_hp_deregister(php_slot);
189register_fail:
190 rpaphp_release_slot(php_slot);
191 return retval; 184 return retval;
192} 185}
193 186
194int rpaphp_get_power_status(struct slot *slot, u8 * value)
195{
196 int rc = 0, level;
197
198 rc = rtas_get_power_level(slot->power_domain, &level);
199 if (rc < 0) {
200 err("failed to get power-level for slot(%s), rc=0x%x\n",
201 slot->location, rc);
202 return rc;
203 }
204
205 dbg("%s the power level of slot %s(pwd-domain:0x%x) is %d\n",
206 __FUNCTION__, slot->name, slot->power_domain, level);
207 *value = level;
208
209 return rc;
210}
211
212int rpaphp_set_attention_status(struct slot *slot, u8 status)
213{
214 int rc;
215
216 /* status: LED_OFF or LED_ON */
217 rc = rtas_set_indicator(DR_INDICATOR, slot->index, status);
218 if (rc < 0)
219 err("slot(name=%s location=%s index=0x%x) set attention-status(%d) failed! rc=0x%x\n",
220 slot->name, slot->location, slot->index, status, rc);
221
222 return rc;
223}
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);
166extern int shpchp_configure_device(struct slot *p_slot); 166extern int shpchp_configure_device(struct slot *p_slot);
167extern int shpchp_unconfigure_device(struct slot *p_slot); 167extern int shpchp_unconfigure_device(struct slot *p_slot);
168extern void cleanup_slots(struct controller *ctrl); 168extern void cleanup_slots(struct controller *ctrl);
169extern void queue_pushbutton_work(struct work_struct *work); 169extern void shpchp_queue_pushbutton_work(struct work_struct *work);
170extern int shpc_init( struct controller *ctrl, struct pci_dev *pdev); 170extern int shpc_init( struct controller *ctrl, struct pci_dev *pdev);
171 171
172#ifdef CONFIG_ACPI 172#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)
136 slot->hpc_ops = ctrl->hpc_ops; 136 slot->hpc_ops = ctrl->hpc_ops;
137 slot->number = ctrl->first_slot + (ctrl->slot_num_inc * i); 137 slot->number = ctrl->first_slot + (ctrl->slot_num_inc * i);
138 mutex_init(&slot->lock); 138 mutex_init(&slot->lock);
139 INIT_DELAYED_WORK(&slot->work, queue_pushbutton_work); 139 INIT_DELAYED_WORK(&slot->work, shpchp_queue_pushbutton_work);
140 140
141 /* register this slot with the hotplug pci core */ 141 /* register this slot with the hotplug pci core */
142 hotplug_slot->private = slot; 142 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)
433 kfree(info); 433 kfree(info);
434} 434}
435 435
436void queue_pushbutton_work(struct work_struct *work) 436void shpchp_queue_pushbutton_work(struct work_struct *work)
437{ 437{
438 struct slot *p_slot = container_of(work, struct slot, work.work); 438 struct slot *p_slot = container_of(work, struct slot, work.work);
439 struct pushbutton_work_info *info; 439 struct pushbutton_work_info *info;