diff options
Diffstat (limited to 'drivers/pci/hotplug/pciehp_hpc.c')
-rw-r--r-- | drivers/pci/hotplug/pciehp_hpc.c | 34 |
1 files changed, 23 insertions, 11 deletions
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 | ||
74 | static atomic_t pciehp_num_controllers = ATOMIC_INIT(0); | ||
75 | |||
74 | struct ctrl_reg { | 76 | struct 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 | ||
222 | static spinlock_t hpc_event_lock; | ||
223 | |||
224 | DEFINE_DBG_BUFFER /* Debug string buffer for entire HPC defined here */ | 224 | DEFINE_DBG_BUFFER /* Debug string buffer for entire HPC defined here */ |
225 | static int ctlr_seq_num = 0; /* Controller sequence # */ | ||
226 | 225 | ||
227 | static irqreturn_t pcie_isr(int irq, void *dev_id); | 226 | static irqreturn_t pcie_isr(int irq, void *dev_id); |
228 | static void start_int_poll_timer(struct controller *ctrl, int sec); | 227 | static 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) | |||
1152 | int pcie_init(struct controller * ctrl, struct pcie_device *dev) | 1158 | int 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 |