aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/hotplug
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@woody.linux-foundation.org>2007-07-12 16:40:57 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-07-12 16:40:57 -0400
commit21ba0f88ae56da82a3a15fe54d729208b64c4f4b (patch)
tree17ce67f276fe3ea7284c3dc730bdd6a2ec7dfe2f /drivers/pci/hotplug
parentdc690d8ef842b464f1c429a376ca16cb8dbee6ae (diff)
parent36e235901f90fb83215be43cbd8f1ca14661ea40 (diff)
Merge master.kernel.org:/pub/scm/linux/kernel/git/gregkh/pci-2.6
* master.kernel.org:/pub/scm/linux/kernel/git/gregkh/pci-2.6: (34 commits) PCI: Only build PCI syscalls on architectures that want them PCI: limit pci_get_bus_and_slot to domain 0 PCI: hotplug: acpiphp: avoid acpiphp "cannot get bridge info" PCI hotplug failure PCI: hotplug: acpiphp: remove hot plug parameter write to PCI host bridge PCI: hotplug: acpiphp: fix slot poweroff problem on systems without _PS3 PCI: hotplug: pciehp: wait for 1 second after power off slot PCI: pci_set_power_state(): check for PM capabilities earlier PCI: cpci_hotplug: Convert to use the kthread API PCI: add pci_try_set_mwi PCI: pcie: remove SPIN_LOCK_UNLOCKED PCI: ROUND_UP macro cleanup in drivers/pci PCI: remove pci_dac_dma_... APIs PCI: pci-x-pci-express-read-control-interfaces cleanups PCI: Fix typo in include/linux/pci.h PCI: pci_ids, remove double or more empty lines PCI: pci_ids, add atheros and 3com_2 vendors PCI: pci_ids, reorder some entries PCI: i386: traps, change VENDOR to DEVICE PCI: ATM: lanai, change VENDOR to DEVICE PCI: Change all drivers to use pci_device->revision ...
Diffstat (limited to 'drivers/pci/hotplug')
-rw-r--r--drivers/pci/hotplug/acpiphp.h1
-rw-r--r--drivers/pci/hotplug/acpiphp_core.c6
-rw-r--r--drivers/pci/hotplug/acpiphp_glue.c53
-rw-r--r--drivers/pci/hotplug/cpci_hotplug_core.c66
-rw-r--r--drivers/pci/hotplug/cpci_hotplug_pci.c2
-rw-r--r--drivers/pci/hotplug/cpqphp_core.c12
-rw-r--r--drivers/pci/hotplug/pciehp.h1
-rw-r--r--drivers/pci/hotplug/pciehp_ctrl.c12
-rw-r--r--drivers/pci/hotplug/pciehp_hpc.c191
9 files changed, 196 insertions, 148 deletions
diff --git a/drivers/pci/hotplug/acpiphp.h b/drivers/pci/hotplug/acpiphp.h
index ddbadd95387e..f6cc0c5b5657 100644
--- a/drivers/pci/hotplug/acpiphp.h
+++ b/drivers/pci/hotplug/acpiphp.h
@@ -211,6 +211,7 @@ typedef int (*acpiphp_callback)(struct acpiphp_slot *slot, void *data);
211 211
212extern int acpiphp_enable_slot (struct acpiphp_slot *slot); 212extern int acpiphp_enable_slot (struct acpiphp_slot *slot);
213extern int acpiphp_disable_slot (struct acpiphp_slot *slot); 213extern int acpiphp_disable_slot (struct acpiphp_slot *slot);
214extern int acpiphp_eject_slot (struct acpiphp_slot *slot);
214extern u8 acpiphp_get_power_status (struct acpiphp_slot *slot); 215extern u8 acpiphp_get_power_status (struct acpiphp_slot *slot);
215extern u8 acpiphp_get_attention_status (struct acpiphp_slot *slot); 216extern u8 acpiphp_get_attention_status (struct acpiphp_slot *slot);
216extern u8 acpiphp_get_latch_status (struct acpiphp_slot *slot); 217extern u8 acpiphp_get_latch_status (struct acpiphp_slot *slot);
diff --git a/drivers/pci/hotplug/acpiphp_core.c b/drivers/pci/hotplug/acpiphp_core.c
index fa5c0197d571..a0ca63adad5a 100644
--- a/drivers/pci/hotplug/acpiphp_core.c
+++ b/drivers/pci/hotplug/acpiphp_core.c
@@ -156,11 +156,15 @@ static int enable_slot(struct hotplug_slot *hotplug_slot)
156static int disable_slot(struct hotplug_slot *hotplug_slot) 156static int disable_slot(struct hotplug_slot *hotplug_slot)
157{ 157{
158 struct slot *slot = hotplug_slot->private; 158 struct slot *slot = hotplug_slot->private;
159 int retval;
159 160
160 dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); 161 dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
161 162
162 /* disable the specified slot */ 163 /* disable the specified slot */
163 return acpiphp_disable_slot(slot->acpi_slot); 164 retval = acpiphp_disable_slot(slot->acpi_slot);
165 if (!retval)
166 retval = acpiphp_eject_slot(slot->acpi_slot);
167 return retval;
164} 168}
165 169
166 170
diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c
index 9ef4e989afc4..1e125b56c9a9 100644
--- a/drivers/pci/hotplug/acpiphp_glue.c
+++ b/drivers/pci/hotplug/acpiphp_glue.c
@@ -1282,7 +1282,7 @@ static unsigned int get_slot_status(struct acpiphp_slot *slot)
1282/** 1282/**
1283 * acpiphp_eject_slot - physically eject the slot 1283 * acpiphp_eject_slot - physically eject the slot
1284 */ 1284 */
1285static int acpiphp_eject_slot(struct acpiphp_slot *slot) 1285int acpiphp_eject_slot(struct acpiphp_slot *slot)
1286{ 1286{
1287 acpi_status status; 1287 acpi_status status;
1288 struct acpiphp_func *func; 1288 struct acpiphp_func *func;
@@ -1368,6 +1368,9 @@ static void program_hpp(struct pci_dev *dev, struct acpiphp_bridge *bridge)
1368 (dev->class >> 8) == PCI_CLASS_BRIDGE_PCI))) 1368 (dev->class >> 8) == PCI_CLASS_BRIDGE_PCI)))
1369 return; 1369 return;
1370 1370
1371 if ((dev->class >> 8) == PCI_CLASS_BRIDGE_HOST)
1372 return;
1373
1371 pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, 1374 pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE,
1372 bridge->hpp.t0->cache_line_size); 1375 bridge->hpp.t0->cache_line_size);
1373 pci_write_config_byte(dev, PCI_LATENCY_TIMER, 1376 pci_write_config_byte(dev, PCI_LATENCY_TIMER,
@@ -1502,6 +1505,37 @@ static void handle_bridge_insertion(acpi_handle handle, u32 type)
1502 * ACPI event handlers 1505 * ACPI event handlers
1503 */ 1506 */
1504 1507
1508static acpi_status
1509count_sub_bridges(acpi_handle handle, u32 lvl, void *context, void **rv)
1510{
1511 int *count = (int *)context;
1512 struct acpiphp_bridge *bridge;
1513
1514 bridge = acpiphp_handle_to_bridge(handle);
1515 if (bridge)
1516 (*count)++;
1517 return AE_OK ;
1518}
1519
1520static acpi_status
1521check_sub_bridges(acpi_handle handle, u32 lvl, void *context, void **rv)
1522{
1523 struct acpiphp_bridge *bridge;
1524 char objname[64];
1525 struct acpi_buffer buffer = { .length = sizeof(objname),
1526 .pointer = objname };
1527
1528 bridge = acpiphp_handle_to_bridge(handle);
1529 if (bridge) {
1530 acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
1531 dbg("%s: re-enumerating slots under %s\n",
1532 __FUNCTION__, objname);
1533 acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
1534 acpiphp_check_bridge(bridge);
1535 }
1536 return AE_OK ;
1537}
1538
1505/** 1539/**
1506 * handle_hotplug_event_bridge - handle ACPI event on bridges 1540 * handle_hotplug_event_bridge - handle ACPI event on bridges
1507 * 1541 *
@@ -1519,6 +1553,7 @@ static void handle_hotplug_event_bridge(acpi_handle handle, u32 type, void *cont
1519 struct acpi_buffer buffer = { .length = sizeof(objname), 1553 struct acpi_buffer buffer = { .length = sizeof(objname),
1520 .pointer = objname }; 1554 .pointer = objname };
1521 struct acpi_device *device; 1555 struct acpi_device *device;
1556 int num_sub_bridges = 0;
1522 1557
1523 if (acpi_bus_get_device(handle, &device)) { 1558 if (acpi_bus_get_device(handle, &device)) {
1524 /* This bridge must have just been physically inserted */ 1559 /* This bridge must have just been physically inserted */
@@ -1527,7 +1562,12 @@ static void handle_hotplug_event_bridge(acpi_handle handle, u32 type, void *cont
1527 } 1562 }
1528 1563
1529 bridge = acpiphp_handle_to_bridge(handle); 1564 bridge = acpiphp_handle_to_bridge(handle);
1530 if (!bridge) { 1565 if (type == ACPI_NOTIFY_BUS_CHECK) {
1566 acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, ACPI_UINT32_MAX,
1567 count_sub_bridges, &num_sub_bridges, NULL);
1568 }
1569
1570 if (!bridge && !num_sub_bridges) {
1531 err("cannot get bridge info\n"); 1571 err("cannot get bridge info\n");
1532 return; 1572 return;
1533 } 1573 }
@@ -1538,7 +1578,14 @@ static void handle_hotplug_event_bridge(acpi_handle handle, u32 type, void *cont
1538 case ACPI_NOTIFY_BUS_CHECK: 1578 case ACPI_NOTIFY_BUS_CHECK:
1539 /* bus re-enumerate */ 1579 /* bus re-enumerate */
1540 dbg("%s: Bus check notify on %s\n", __FUNCTION__, objname); 1580 dbg("%s: Bus check notify on %s\n", __FUNCTION__, objname);
1541 acpiphp_check_bridge(bridge); 1581 if (bridge) {
1582 dbg("%s: re-enumerating slots under %s\n",
1583 __FUNCTION__, objname);
1584 acpiphp_check_bridge(bridge);
1585 }
1586 if (num_sub_bridges)
1587 acpi_walk_namespace(ACPI_TYPE_DEVICE, handle,
1588 ACPI_UINT32_MAX, check_sub_bridges, NULL, NULL);
1542 break; 1589 break;
1543 1590
1544 case ACPI_NOTIFY_DEVICE_CHECK: 1591 case ACPI_NOTIFY_DEVICE_CHECK:
diff --git a/drivers/pci/hotplug/cpci_hotplug_core.c b/drivers/pci/hotplug/cpci_hotplug_core.c
index 684551559d44..ed4d44e3332c 100644
--- a/drivers/pci/hotplug/cpci_hotplug_core.c
+++ b/drivers/pci/hotplug/cpci_hotplug_core.c
@@ -35,6 +35,7 @@
35#include <linux/smp_lock.h> 35#include <linux/smp_lock.h>
36#include <asm/atomic.h> 36#include <asm/atomic.h>
37#include <linux/delay.h> 37#include <linux/delay.h>
38#include <linux/kthread.h>
38#include "cpci_hotplug.h" 39#include "cpci_hotplug.h"
39 40
40#define DRIVER_AUTHOR "Scott Murray <scottm@somanetworks.com>" 41#define DRIVER_AUTHOR "Scott Murray <scottm@somanetworks.com>"
@@ -59,9 +60,8 @@ static int slots;
59static atomic_t extracting; 60static atomic_t extracting;
60int cpci_debug; 61int cpci_debug;
61static struct cpci_hp_controller *controller; 62static struct cpci_hp_controller *controller;
62static struct semaphore event_semaphore; /* mutex for process loop (up if something to process) */ 63static struct task_struct *cpci_thread;
63static struct semaphore thread_exit; /* guard ensure thread has exited before calling it quits */ 64static int thread_finished;
64static int thread_finished = 1;
65 65
66static int enable_slot(struct hotplug_slot *slot); 66static int enable_slot(struct hotplug_slot *slot);
67static int disable_slot(struct hotplug_slot *slot); 67static int disable_slot(struct hotplug_slot *slot);
@@ -357,9 +357,7 @@ cpci_hp_intr(int irq, void *data)
357 controller->ops->disable_irq(); 357 controller->ops->disable_irq();
358 358
359 /* Trigger processing by the event thread */ 359 /* Trigger processing by the event thread */
360 dbg("Signal event_semaphore"); 360 wake_up_process(cpci_thread);
361 up(&event_semaphore);
362 dbg("exited cpci_hp_intr");
363 return IRQ_HANDLED; 361 return IRQ_HANDLED;
364} 362}
365 363
@@ -521,17 +519,12 @@ event_thread(void *data)
521{ 519{
522 int rc; 520 int rc;
523 521
524 lock_kernel();
525 daemonize("cpci_hp_eventd");
526 unlock_kernel();
527
528 dbg("%s - event thread started", __FUNCTION__); 522 dbg("%s - event thread started", __FUNCTION__);
529 while (1) { 523 while (1) {
530 dbg("event thread sleeping"); 524 dbg("event thread sleeping");
531 down_interruptible(&event_semaphore); 525 set_current_state(TASK_INTERRUPTIBLE);
532 dbg("event thread woken, thread_finished = %d", 526 schedule();
533 thread_finished); 527 if (kthread_should_stop())
534 if (thread_finished || signal_pending(current))
535 break; 528 break;
536 do { 529 do {
537 rc = check_slots(); 530 rc = check_slots();
@@ -541,18 +534,17 @@ event_thread(void *data)
541 } else if (rc < 0) { 534 } else if (rc < 0) {
542 dbg("%s - error checking slots", __FUNCTION__); 535 dbg("%s - error checking slots", __FUNCTION__);
543 thread_finished = 1; 536 thread_finished = 1;
544 break; 537 goto out;
545 } 538 }
546 } while (atomic_read(&extracting) && !thread_finished); 539 } while (atomic_read(&extracting) && !kthread_should_stop());
547 if (thread_finished) 540 if (kthread_should_stop())
548 break; 541 break;
549 542
550 /* Re-enable ENUM# interrupt */ 543 /* Re-enable ENUM# interrupt */
551 dbg("%s - re-enabling irq", __FUNCTION__); 544 dbg("%s - re-enabling irq", __FUNCTION__);
552 controller->ops->enable_irq(); 545 controller->ops->enable_irq();
553 } 546 }
554 dbg("%s - event thread signals exit", __FUNCTION__); 547 out:
555 up(&thread_exit);
556 return 0; 548 return 0;
557} 549}
558 550
@@ -562,12 +554,8 @@ poll_thread(void *data)
562{ 554{
563 int rc; 555 int rc;
564 556
565 lock_kernel();
566 daemonize("cpci_hp_polld");
567 unlock_kernel();
568
569 while (1) { 557 while (1) {
570 if (thread_finished || signal_pending(current)) 558 if (kthread_should_stop() || signal_pending(current))
571 break; 559 break;
572 if (controller->ops->query_enum()) { 560 if (controller->ops->query_enum()) {
573 do { 561 do {
@@ -578,48 +566,36 @@ poll_thread(void *data)
578 } else if (rc < 0) { 566 } else if (rc < 0) {
579 dbg("%s - error checking slots", __FUNCTION__); 567 dbg("%s - error checking slots", __FUNCTION__);
580 thread_finished = 1; 568 thread_finished = 1;
581 break; 569 goto out;
582 } 570 }
583 } while (atomic_read(&extracting) && !thread_finished); 571 } while (atomic_read(&extracting) && !kthread_should_stop());
584 } 572 }
585 msleep(100); 573 msleep(100);
586 } 574 }
587 dbg("poll thread signals exit"); 575 out:
588 up(&thread_exit);
589 return 0; 576 return 0;
590} 577}
591 578
592static int 579static int
593cpci_start_thread(void) 580cpci_start_thread(void)
594{ 581{
595 int pid;
596
597 /* initialize our semaphores */
598 init_MUTEX_LOCKED(&event_semaphore);
599 init_MUTEX_LOCKED(&thread_exit);
600 thread_finished = 0;
601
602 if (controller->irq) 582 if (controller->irq)
603 pid = kernel_thread(event_thread, NULL, 0); 583 cpci_thread = kthread_run(event_thread, NULL, "cpci_hp_eventd");
604 else 584 else
605 pid = kernel_thread(poll_thread, NULL, 0); 585 cpci_thread = kthread_run(poll_thread, NULL, "cpci_hp_polld");
606 if (pid < 0) { 586 if (IS_ERR(cpci_thread)) {
607 err("Can't start up our thread"); 587 err("Can't start up our thread");
608 return -1; 588 return PTR_ERR(cpci_thread);
609 } 589 }
610 dbg("Our thread pid = %d", pid); 590 thread_finished = 0;
611 return 0; 591 return 0;
612} 592}
613 593
614static void 594static void
615cpci_stop_thread(void) 595cpci_stop_thread(void)
616{ 596{
597 kthread_stop(cpci_thread);
617 thread_finished = 1; 598 thread_finished = 1;
618 dbg("thread finish command given");
619 if (controller->irq)
620 up(&event_semaphore);
621 dbg("wait for thread to exit");
622 down(&thread_exit);
623} 599}
624 600
625int 601int
diff --git a/drivers/pci/hotplug/cpci_hotplug_pci.c b/drivers/pci/hotplug/cpci_hotplug_pci.c
index 7b1beaad2752..5e9be44817cb 100644
--- a/drivers/pci/hotplug/cpci_hotplug_pci.c
+++ b/drivers/pci/hotplug/cpci_hotplug_pci.c
@@ -45,8 +45,6 @@ extern int cpci_debug;
45#define info(format, arg...) printk(KERN_INFO "%s: " format "\n", MY_NAME , ## arg) 45#define info(format, arg...) printk(KERN_INFO "%s: " format "\n", MY_NAME , ## arg)
46#define warn(format, arg...) printk(KERN_WARNING "%s: " format "\n", MY_NAME , ## arg) 46#define warn(format, arg...) printk(KERN_WARNING "%s: " format "\n", MY_NAME , ## arg)
47 47
48#define ROUND_UP(x, a) (((x) + (a) - 1) & ~((a) - 1))
49
50 48
51u8 cpci_get_attention_status(struct slot* slot) 49u8 cpci_get_attention_status(struct slot* slot)
52{ 50{
diff --git a/drivers/pci/hotplug/cpqphp_core.c b/drivers/pci/hotplug/cpqphp_core.c
index 5617cfdadc5c..d590a99930fa 100644
--- a/drivers/pci/hotplug/cpqphp_core.c
+++ b/drivers/pci/hotplug/cpqphp_core.c
@@ -796,7 +796,6 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
796 u8 num_of_slots = 0; 796 u8 num_of_slots = 0;
797 u8 hp_slot = 0; 797 u8 hp_slot = 0;
798 u8 device; 798 u8 device;
799 u8 rev;
800 u8 bus_cap; 799 u8 bus_cap;
801 u16 temp_word; 800 u16 temp_word;
802 u16 vendor_id; 801 u16 vendor_id;
@@ -823,9 +822,8 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
823 } 822 }
824 dbg("Vendor ID: %x\n", vendor_id); 823 dbg("Vendor ID: %x\n", vendor_id);
825 824
826 rc = pci_read_config_byte(pdev, PCI_REVISION_ID, &rev); 825 dbg("revision: %d\n", pdev->revision);
827 dbg("revision: %d\n", rev); 826 if ((vendor_id == PCI_VENDOR_ID_COMPAQ) && (!pdev->revision)) {
828 if (rc || ((vendor_id == PCI_VENDOR_ID_COMPAQ) && (!rev))) {
829 err(msg_HPC_rev_error); 827 err(msg_HPC_rev_error);
830 rc = -ENODEV; 828 rc = -ENODEV;
831 goto err_disable_device; 829 goto err_disable_device;
@@ -836,7 +834,7 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
836 * For Intel, each SSID bit identifies a PHP capability. 834 * For Intel, each SSID bit identifies a PHP capability.
837 * Also Intel HPC's may have RID=0. 835 * Also Intel HPC's may have RID=0.
838 */ 836 */
839 if ((rev > 2) || (vendor_id == PCI_VENDOR_ID_INTEL)) { 837 if ((pdev->revision > 2) || (vendor_id == PCI_VENDOR_ID_INTEL)) {
840 // TODO: This code can be made to support non-Compaq or Intel subsystem IDs 838 // TODO: This code can be made to support non-Compaq or Intel subsystem IDs
841 rc = pci_read_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID, &subsystem_vid); 839 rc = pci_read_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID, &subsystem_vid);
842 if (rc) { 840 if (rc) {
@@ -870,7 +868,7 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
870 868
871 switch (subsystem_vid) { 869 switch (subsystem_vid) {
872 case PCI_VENDOR_ID_COMPAQ: 870 case PCI_VENDOR_ID_COMPAQ:
873 if (rev >= 0x13) { /* CIOBX */ 871 if (pdev->revision >= 0x13) { /* CIOBX */
874 ctrl->push_flag = 1; 872 ctrl->push_flag = 1;
875 ctrl->slot_switch_type = 1; 873 ctrl->slot_switch_type = 1;
876 ctrl->push_button = 1; 874 ctrl->push_button = 1;
@@ -1075,7 +1073,7 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
1075 memcpy(ctrl->pci_bus, pdev->bus, sizeof(*ctrl->pci_bus)); 1073 memcpy(ctrl->pci_bus, pdev->bus, sizeof(*ctrl->pci_bus));
1076 1074
1077 ctrl->bus = pdev->bus->number; 1075 ctrl->bus = pdev->bus->number;
1078 ctrl->rev = rev; 1076 ctrl->rev = pdev->revision;
1079 dbg("bus device function rev: %d %d %d %d\n", ctrl->bus, 1077 dbg("bus device function rev: %d %d %d %d\n", ctrl->bus,
1080 PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn), ctrl->rev); 1078 PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn), ctrl->rev);
1081 1079
diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h
index ccc57627201e..7959c222dc24 100644
--- a/drivers/pci/hotplug/pciehp.h
+++ b/drivers/pci/hotplug/pciehp.h
@@ -103,6 +103,7 @@ struct controller {
103 u8 cap_base; 103 u8 cap_base;
104 struct timer_list poll_timer; 104 struct timer_list poll_timer;
105 volatile int cmd_busy; 105 volatile int cmd_busy;
106 spinlock_t lock;
106}; 107};
107 108
108#define INT_BUTTON_IGNORE 0 109#define INT_BUTTON_IGNORE 0
diff --git a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c
index 7f22caa70178..98e541ffef3d 100644
--- a/drivers/pci/hotplug/pciehp_ctrl.c
+++ b/drivers/pci/hotplug/pciehp_ctrl.c
@@ -197,6 +197,12 @@ static void set_slot_off(struct controller *ctrl, struct slot * pslot)
197 __FUNCTION__); 197 __FUNCTION__);
198 return; 198 return;
199 } 199 }
200 /*
201 * After turning power off, we must wait for at least
202 * 1 second before taking any action that relies on
203 * power having been removed from the slot/adapter.
204 */
205 msleep(1000);
200 } 206 }
201} 207}
202 208
@@ -615,6 +621,12 @@ int pciehp_disable_slot(struct slot *p_slot)
615 mutex_unlock(&p_slot->ctrl->crit_sect); 621 mutex_unlock(&p_slot->ctrl->crit_sect);
616 return -EINVAL; 622 return -EINVAL;
617 } 623 }
624 /*
625 * After turning power off, we must wait for at least
626 * 1 second before taking any action that relies on
627 * power having been removed from the slot/adapter.
628 */
629 msleep(1000);
618 } 630 }
619 631
620 ret = remove_board(p_slot); 632 ret = remove_board(p_slot);
diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c
index 9aac6a87eb53..016eea94a8a5 100644
--- a/drivers/pci/hotplug/pciehp_hpc.c
+++ b/drivers/pci/hotplug/pciehp_hpc.c
@@ -275,11 +275,19 @@ static inline int pcie_wait_cmd(struct controller *ctrl)
275 return retval; 275 return retval;
276} 276}
277 277
278static int pcie_write_cmd(struct slot *slot, u16 cmd) 278/**
279 * pcie_write_cmd - Issue controller command
280 * @slot: slot to which the command is issued
281 * @cmd: command value written to slot control register
282 * @mask: bitmask of slot control register to be modified
283 */
284static int pcie_write_cmd(struct slot *slot, u16 cmd, u16 mask)
279{ 285{
280 struct controller *ctrl = slot->ctrl; 286 struct controller *ctrl = slot->ctrl;
281 int retval = 0; 287 int retval = 0;
282 u16 slot_status; 288 u16 slot_status;
289 u16 slot_ctrl;
290 unsigned long flags;
283 291
284 DBG_ENTER_ROUTINE 292 DBG_ENTER_ROUTINE
285 293
@@ -299,17 +307,29 @@ static int pcie_write_cmd(struct slot *slot, u16 cmd)
299 __FUNCTION__); 307 __FUNCTION__);
300 } 308 }
301 309
302 ctrl->cmd_busy = 1; 310 spin_lock_irqsave(&ctrl->lock, flags);
303 retval = pciehp_writew(ctrl, SLOTCTRL, (cmd | CMD_CMPL_INTR_ENABLE)); 311 retval = pciehp_readw(ctrl, SLOTCTRL, &slot_ctrl);
304 if (retval) { 312 if (retval) {
305 err("%s: Cannot write to SLOTCTRL register\n", __FUNCTION__); 313 err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__);
306 goto out; 314 goto out_spin_unlock;
307 } 315 }
308 316
317 slot_ctrl &= ~mask;
318 slot_ctrl |= ((cmd & mask) | CMD_CMPL_INTR_ENABLE);
319
320 ctrl->cmd_busy = 1;
321 retval = pciehp_writew(ctrl, SLOTCTRL, slot_ctrl);
322 if (retval)
323 err("%s: Cannot write to SLOTCTRL register\n", __FUNCTION__);
324
325 out_spin_unlock:
326 spin_unlock_irqrestore(&ctrl->lock, flags);
327
309 /* 328 /*
310 * Wait for command completion. 329 * Wait for command completion.
311 */ 330 */
312 retval = pcie_wait_cmd(ctrl); 331 if (!retval)
332 retval = pcie_wait_cmd(ctrl);
313 out: 333 out:
314 mutex_unlock(&ctrl->ctrl_lock); 334 mutex_unlock(&ctrl->ctrl_lock);
315 DBG_LEAVE_ROUTINE 335 DBG_LEAVE_ROUTINE
@@ -502,25 +522,20 @@ static int hpc_get_emi_status(struct slot *slot, u8 *status)
502 522
503static int hpc_toggle_emi(struct slot *slot) 523static int hpc_toggle_emi(struct slot *slot)
504{ 524{
505 struct controller *ctrl = slot->ctrl; 525 u16 slot_cmd;
506 u16 slot_cmd = 0; 526 u16 cmd_mask;
507 u16 slot_ctrl; 527 int rc;
508 int rc = 0;
509 528
510 DBG_ENTER_ROUTINE 529 DBG_ENTER_ROUTINE
511 530
512 rc = pciehp_readw(ctrl, SLOTCTRL, &slot_ctrl); 531 slot_cmd = EMI_CTRL;
513 if (rc) { 532 cmd_mask = EMI_CTRL;
514 err("%s : hp_register_read_word SLOT_CTRL failed\n", 533 if (!pciehp_poll_mode) {
515 __FUNCTION__);
516 return rc;
517 }
518
519 slot_cmd = (slot_ctrl | EMI_CTRL);
520 if (!pciehp_poll_mode)
521 slot_cmd = slot_cmd | HP_INTR_ENABLE; 534 slot_cmd = slot_cmd | HP_INTR_ENABLE;
535 cmd_mask = cmd_mask | HP_INTR_ENABLE;
536 }
522 537
523 pcie_write_cmd(slot, slot_cmd); 538 rc = pcie_write_cmd(slot, slot_cmd, cmd_mask);
524 slot->last_emi_toggle = get_seconds(); 539 slot->last_emi_toggle = get_seconds();
525 DBG_LEAVE_ROUTINE 540 DBG_LEAVE_ROUTINE
526 return rc; 541 return rc;
@@ -529,35 +544,32 @@ static int hpc_toggle_emi(struct slot *slot)
529static int hpc_set_attention_status(struct slot *slot, u8 value) 544static int hpc_set_attention_status(struct slot *slot, u8 value)
530{ 545{
531 struct controller *ctrl = slot->ctrl; 546 struct controller *ctrl = slot->ctrl;
532 u16 slot_cmd = 0; 547 u16 slot_cmd;
533 u16 slot_ctrl; 548 u16 cmd_mask;
534 int rc = 0; 549 int rc;
535 550
536 DBG_ENTER_ROUTINE 551 DBG_ENTER_ROUTINE
537 552
538 rc = pciehp_readw(ctrl, SLOTCTRL, &slot_ctrl); 553 cmd_mask = ATTN_LED_CTRL;
539 if (rc) {
540 err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__);
541 return rc;
542 }
543
544 switch (value) { 554 switch (value) {
545 case 0 : /* turn off */ 555 case 0 : /* turn off */
546 slot_cmd = (slot_ctrl & ~ATTN_LED_CTRL) | 0x00C0; 556 slot_cmd = 0x00C0;
547 break; 557 break;
548 case 1: /* turn on */ 558 case 1: /* turn on */
549 slot_cmd = (slot_ctrl & ~ATTN_LED_CTRL) | 0x0040; 559 slot_cmd = 0x0040;
550 break; 560 break;
551 case 2: /* turn blink */ 561 case 2: /* turn blink */
552 slot_cmd = (slot_ctrl & ~ATTN_LED_CTRL) | 0x0080; 562 slot_cmd = 0x0080;
553 break; 563 break;
554 default: 564 default:
555 return -1; 565 return -1;
556 } 566 }
557 if (!pciehp_poll_mode) 567 if (!pciehp_poll_mode) {
558 slot_cmd = slot_cmd | HP_INTR_ENABLE; 568 slot_cmd = slot_cmd | HP_INTR_ENABLE;
569 cmd_mask = cmd_mask | HP_INTR_ENABLE;
570 }
559 571
560 pcie_write_cmd(slot, slot_cmd); 572 rc = pcie_write_cmd(slot, slot_cmd, cmd_mask);
561 dbg("%s: SLOTCTRL %x write cmd %x\n", 573 dbg("%s: SLOTCTRL %x write cmd %x\n",
562 __FUNCTION__, ctrl->cap_base + SLOTCTRL, slot_cmd); 574 __FUNCTION__, ctrl->cap_base + SLOTCTRL, slot_cmd);
563 575
@@ -570,21 +582,18 @@ static void hpc_set_green_led_on(struct slot *slot)
570{ 582{
571 struct controller *ctrl = slot->ctrl; 583 struct controller *ctrl = slot->ctrl;
572 u16 slot_cmd; 584 u16 slot_cmd;
573 u16 slot_ctrl; 585 u16 cmd_mask;
574 int rc = 0;
575 586
576 DBG_ENTER_ROUTINE 587 DBG_ENTER_ROUTINE
577 588
578 rc = pciehp_readw(ctrl, SLOTCTRL, &slot_ctrl); 589 slot_cmd = 0x0100;
579 if (rc) { 590 cmd_mask = PWR_LED_CTRL;
580 err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__); 591 if (!pciehp_poll_mode) {
581 return; 592 slot_cmd = slot_cmd | HP_INTR_ENABLE;
593 cmd_mask = cmd_mask | HP_INTR_ENABLE;
582 } 594 }
583 slot_cmd = (slot_ctrl & ~PWR_LED_CTRL) | 0x0100;
584 if (!pciehp_poll_mode)
585 slot_cmd = slot_cmd | HP_INTR_ENABLE;
586 595
587 pcie_write_cmd(slot, slot_cmd); 596 pcie_write_cmd(slot, slot_cmd, cmd_mask);
588 597
589 dbg("%s: SLOTCTRL %x write cmd %x\n", 598 dbg("%s: SLOTCTRL %x write cmd %x\n",
590 __FUNCTION__, ctrl->cap_base + SLOTCTRL, slot_cmd); 599 __FUNCTION__, ctrl->cap_base + SLOTCTRL, slot_cmd);
@@ -596,22 +605,18 @@ static void hpc_set_green_led_off(struct slot *slot)
596{ 605{
597 struct controller *ctrl = slot->ctrl; 606 struct controller *ctrl = slot->ctrl;
598 u16 slot_cmd; 607 u16 slot_cmd;
599 u16 slot_ctrl; 608 u16 cmd_mask;
600 int rc = 0;
601 609
602 DBG_ENTER_ROUTINE 610 DBG_ENTER_ROUTINE
603 611
604 rc = pciehp_readw(ctrl, SLOTCTRL, &slot_ctrl); 612 slot_cmd = 0x0300;
605 if (rc) { 613 cmd_mask = PWR_LED_CTRL;
606 err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__); 614 if (!pciehp_poll_mode) {
607 return; 615 slot_cmd = slot_cmd | HP_INTR_ENABLE;
616 cmd_mask = cmd_mask | HP_INTR_ENABLE;
608 } 617 }
609 618
610 slot_cmd = (slot_ctrl & ~PWR_LED_CTRL) | 0x0300; 619 pcie_write_cmd(slot, slot_cmd, cmd_mask);
611
612 if (!pciehp_poll_mode)
613 slot_cmd = slot_cmd | HP_INTR_ENABLE;
614 pcie_write_cmd(slot, slot_cmd);
615 dbg("%s: SLOTCTRL %x write cmd %x\n", 620 dbg("%s: SLOTCTRL %x write cmd %x\n",
616 __FUNCTION__, ctrl->cap_base + SLOTCTRL, slot_cmd); 621 __FUNCTION__, ctrl->cap_base + SLOTCTRL, slot_cmd);
617 622
@@ -623,22 +628,18 @@ static void hpc_set_green_led_blink(struct slot *slot)
623{ 628{
624 struct controller *ctrl = slot->ctrl; 629 struct controller *ctrl = slot->ctrl;
625 u16 slot_cmd; 630 u16 slot_cmd;
626 u16 slot_ctrl; 631 u16 cmd_mask;
627 int rc = 0;
628 632
629 DBG_ENTER_ROUTINE 633 DBG_ENTER_ROUTINE
630 634
631 rc = pciehp_readw(ctrl, SLOTCTRL, &slot_ctrl); 635 slot_cmd = 0x0200;
632 if (rc) { 636 cmd_mask = PWR_LED_CTRL;
633 err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__); 637 if (!pciehp_poll_mode) {
634 return; 638 slot_cmd = slot_cmd | HP_INTR_ENABLE;
639 cmd_mask = cmd_mask | HP_INTR_ENABLE;
635 } 640 }
636 641
637 slot_cmd = (slot_ctrl & ~PWR_LED_CTRL) | 0x0200; 642 pcie_write_cmd(slot, slot_cmd, cmd_mask);
638
639 if (!pciehp_poll_mode)
640 slot_cmd = slot_cmd | HP_INTR_ENABLE;
641 pcie_write_cmd(slot, slot_cmd);
642 643
643 dbg("%s: SLOTCTRL %x write cmd %x\n", 644 dbg("%s: SLOTCTRL %x write cmd %x\n",
644 __FUNCTION__, ctrl->cap_base + SLOTCTRL, slot_cmd); 645 __FUNCTION__, ctrl->cap_base + SLOTCTRL, slot_cmd);
@@ -669,7 +670,8 @@ static int hpc_power_on_slot(struct slot * slot)
669{ 670{
670 struct controller *ctrl = slot->ctrl; 671 struct controller *ctrl = slot->ctrl;
671 u16 slot_cmd; 672 u16 slot_cmd;
672 u16 slot_ctrl, slot_status; 673 u16 cmd_mask;
674 u16 slot_status;
673 int retval = 0; 675 int retval = 0;
674 676
675 DBG_ENTER_ROUTINE 677 DBG_ENTER_ROUTINE
@@ -692,23 +694,23 @@ static int hpc_power_on_slot(struct slot * slot)
692 } 694 }
693 } 695 }
694 696
695 retval = pciehp_readw(ctrl, SLOTCTRL, &slot_ctrl); 697 slot_cmd = POWER_ON;
696 if (retval) { 698 cmd_mask = PWR_CTRL;
697 err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__);
698 return retval;
699 }
700
701 slot_cmd = (slot_ctrl & ~PWR_CTRL) | POWER_ON;
702
703 /* Enable detection that we turned off at slot power-off time */ 699 /* Enable detection that we turned off at slot power-off time */
704 if (!pciehp_poll_mode) 700 if (!pciehp_poll_mode) {
705 slot_cmd = slot_cmd | 701 slot_cmd = slot_cmd |
706 PWR_FAULT_DETECT_ENABLE | 702 PWR_FAULT_DETECT_ENABLE |
707 MRL_DETECT_ENABLE | 703 MRL_DETECT_ENABLE |
708 PRSN_DETECT_ENABLE | 704 PRSN_DETECT_ENABLE |
709 HP_INTR_ENABLE; 705 HP_INTR_ENABLE;
706 cmd_mask = cmd_mask |
707 PWR_FAULT_DETECT_ENABLE |
708 MRL_DETECT_ENABLE |
709 PRSN_DETECT_ENABLE |
710 HP_INTR_ENABLE;
711 }
710 712
711 retval = pcie_write_cmd(slot, slot_cmd); 713 retval = pcie_write_cmd(slot, slot_cmd, cmd_mask);
712 714
713 if (retval) { 715 if (retval) {
714 err("%s: Write %x command failed!\n", __FUNCTION__, slot_cmd); 716 err("%s: Write %x command failed!\n", __FUNCTION__, slot_cmd);
@@ -726,21 +728,15 @@ static int hpc_power_off_slot(struct slot * slot)
726{ 728{
727 struct controller *ctrl = slot->ctrl; 729 struct controller *ctrl = slot->ctrl;
728 u16 slot_cmd; 730 u16 slot_cmd;
729 u16 slot_ctrl; 731 u16 cmd_mask;
730 int retval = 0; 732 int retval = 0;
731 733
732 DBG_ENTER_ROUTINE 734 DBG_ENTER_ROUTINE
733 735
734 dbg("%s: slot->hp_slot %x\n", __FUNCTION__, slot->hp_slot); 736 dbg("%s: slot->hp_slot %x\n", __FUNCTION__, slot->hp_slot);
735 737
736 retval = pciehp_readw(ctrl, SLOTCTRL, &slot_ctrl); 738 slot_cmd = POWER_OFF;
737 if (retval) { 739 cmd_mask = PWR_CTRL;
738 err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__);
739 return retval;
740 }
741
742 slot_cmd = (slot_ctrl & ~PWR_CTRL) | POWER_OFF;
743
744 /* 740 /*
745 * If we get MRL or presence detect interrupts now, the isr 741 * If we get MRL or presence detect interrupts now, the isr
746 * will notice the sticky power-fault bit too and issue power 742 * will notice the sticky power-fault bit too and issue power
@@ -748,14 +744,19 @@ static int hpc_power_off_slot(struct slot * slot)
748 * of command completions, since the power-fault bit remains on 744 * of command completions, since the power-fault bit remains on
749 * till the slot is powered on again. 745 * till the slot is powered on again.
750 */ 746 */
751 if (!pciehp_poll_mode) 747 if (!pciehp_poll_mode) {
752 slot_cmd = (slot_cmd & 748 slot_cmd = (slot_cmd &
753 ~PWR_FAULT_DETECT_ENABLE & 749 ~PWR_FAULT_DETECT_ENABLE &
754 ~MRL_DETECT_ENABLE & 750 ~MRL_DETECT_ENABLE &
755 ~PRSN_DETECT_ENABLE) | HP_INTR_ENABLE; 751 ~PRSN_DETECT_ENABLE) | HP_INTR_ENABLE;
752 cmd_mask = cmd_mask |
753 PWR_FAULT_DETECT_ENABLE |
754 MRL_DETECT_ENABLE |
755 PRSN_DETECT_ENABLE |
756 HP_INTR_ENABLE;
757 }
756 758
757 retval = pcie_write_cmd(slot, slot_cmd); 759 retval = pcie_write_cmd(slot, slot_cmd, cmd_mask);
758
759 if (retval) { 760 if (retval) {
760 err("%s: Write command failed!\n", __FUNCTION__); 761 err("%s: Write command failed!\n", __FUNCTION__);
761 return -1; 762 return -1;
@@ -775,6 +776,7 @@ static irqreturn_t pcie_isr(int irq, void *dev_id)
775 u16 temp_word; 776 u16 temp_word;
776 int hp_slot = 0; /* only 1 slot per PCI Express port */ 777 int hp_slot = 0; /* only 1 slot per PCI Express port */
777 int rc = 0; 778 int rc = 0;
779 unsigned long flags;
778 780
779 rc = pciehp_readw(ctrl, SLOTSTATUS, &slot_status); 781 rc = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
780 if (rc) { 782 if (rc) {
@@ -794,10 +796,12 @@ static irqreturn_t pcie_isr(int irq, void *dev_id)
794 dbg("%s: intr_loc %x\n", __FUNCTION__, intr_loc); 796 dbg("%s: intr_loc %x\n", __FUNCTION__, intr_loc);
795 /* Mask Hot-plug Interrupt Enable */ 797 /* Mask Hot-plug Interrupt Enable */
796 if (!pciehp_poll_mode) { 798 if (!pciehp_poll_mode) {
799 spin_lock_irqsave(&ctrl->lock, flags);
797 rc = pciehp_readw(ctrl, SLOTCTRL, &temp_word); 800 rc = pciehp_readw(ctrl, SLOTCTRL, &temp_word);
798 if (rc) { 801 if (rc) {
799 err("%s: Cannot read SLOT_CTRL register\n", 802 err("%s: Cannot read SLOT_CTRL register\n",
800 __FUNCTION__); 803 __FUNCTION__);
804 spin_unlock_irqrestore(&ctrl->lock, flags);
801 return IRQ_NONE; 805 return IRQ_NONE;
802 } 806 }
803 807
@@ -808,8 +812,10 @@ static irqreturn_t pcie_isr(int irq, void *dev_id)
808 if (rc) { 812 if (rc) {
809 err("%s: Cannot write to SLOTCTRL register\n", 813 err("%s: Cannot write to SLOTCTRL register\n",
810 __FUNCTION__); 814 __FUNCTION__);
815 spin_unlock_irqrestore(&ctrl->lock, flags);
811 return IRQ_NONE; 816 return IRQ_NONE;
812 } 817 }
818 spin_unlock_irqrestore(&ctrl->lock, flags);
813 819
814 rc = pciehp_readw(ctrl, SLOTSTATUS, &slot_status); 820 rc = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
815 if (rc) { 821 if (rc) {
@@ -859,10 +865,12 @@ static irqreturn_t pcie_isr(int irq, void *dev_id)
859 } 865 }
860 /* Unmask Hot-plug Interrupt Enable */ 866 /* Unmask Hot-plug Interrupt Enable */
861 if (!pciehp_poll_mode) { 867 if (!pciehp_poll_mode) {
868 spin_lock_irqsave(&ctrl->lock, flags);
862 rc = pciehp_readw(ctrl, SLOTCTRL, &temp_word); 869 rc = pciehp_readw(ctrl, SLOTCTRL, &temp_word);
863 if (rc) { 870 if (rc) {
864 err("%s: Cannot read SLOTCTRL register\n", 871 err("%s: Cannot read SLOTCTRL register\n",
865 __FUNCTION__); 872 __FUNCTION__);
873 spin_unlock_irqrestore(&ctrl->lock, flags);
866 return IRQ_NONE; 874 return IRQ_NONE;
867 } 875 }
868 876
@@ -873,8 +881,10 @@ static irqreturn_t pcie_isr(int irq, void *dev_id)
873 if (rc) { 881 if (rc) {
874 err("%s: Cannot write to SLOTCTRL register\n", 882 err("%s: Cannot write to SLOTCTRL register\n",
875 __FUNCTION__); 883 __FUNCTION__);
884 spin_unlock_irqrestore(&ctrl->lock, flags);
876 return IRQ_NONE; 885 return IRQ_NONE;
877 } 886 }
887 spin_unlock_irqrestore(&ctrl->lock, flags);
878 888
879 rc = pciehp_readw(ctrl, SLOTSTATUS, &slot_status); 889 rc = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
880 if (rc) { 890 if (rc) {
@@ -1237,6 +1247,7 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev)
1237 1247
1238 mutex_init(&ctrl->crit_sect); 1248 mutex_init(&ctrl->crit_sect);
1239 mutex_init(&ctrl->ctrl_lock); 1249 mutex_init(&ctrl->ctrl_lock);
1250 spin_lock_init(&ctrl->lock);
1240 1251
1241 /* setup wait queue */ 1252 /* setup wait queue */
1242 init_waitqueue_head(&ctrl->queue); 1253 init_waitqueue_head(&ctrl->queue);