#define DBG_LEAVE_ROUTINE
#endif /* DEBUG */
+static atomic_t pciehp_num_controllers = ATOMIC_INIT(0);
+
struct ctrl_reg {
u8 cap_id;
u8 nxt_ptr;
#define EMI_STATE 0x0080
#define EMI_STATUS_BIT 7
-static spinlock_t hpc_event_lock;
-
DEFINE_DBG_BUFFER /* Debug string buffer for entire HPC defined here */
-static int ctlr_seq_num = 0; /* Controller sequence # */
static irqreturn_t pcie_isr(int irq, void *dev_id);
static void start_int_poll_timer(struct controller *ctrl, int sec);
else
free_irq(ctrl->pci_dev->irq, ctrl);
+ /*
+ * If this is the last controller to be released, destroy the
+ * pciehp work queue
+ */
+ if (atomic_dec_and_test(&pciehp_num_controllers))
+ destroy_workqueue(pciehp_wq);
+
DBG_LEAVE_ROUTINE
}
int pcie_init(struct controller * ctrl, struct pcie_device *dev)
{
int rc;
- static int first = 1;
u16 temp_word;
u16 cap_reg;
u16 intr_enable = 0;
dbg("%s: SLOTCTRL offset %x slot_ctrl %x\n",
__FUNCTION__, ctrl->cap_base + SLOTCTRL, slot_ctrl);
- if (first) {
- spin_lock_init(&hpc_event_lock);
- first = 0;
- }
-
for ( rc = 0; rc < DEVICE_COUNT_RESOURCE; rc++)
if (pci_resource_len(pdev, rc) > 0)
dbg("pci resource[%d] start=0x%llx(len=0x%llx)\n", rc,
rc = request_irq(ctrl->pci_dev->irq, pcie_isr, IRQF_SHARED,
MY_NAME, (void *)ctrl);
dbg("%s: request_irq %d for hpc%d (returns %d)\n",
- __FUNCTION__, ctrl->pci_dev->irq, ctlr_seq_num, rc);
+ __FUNCTION__, ctrl->pci_dev->irq,
+ atomic_read(&pciehp_num_controllers), rc);
if (rc) {
err("Can't get irq %d for the hotplug controller\n",
ctrl->pci_dev->irq);
dbg("pciehp ctrl b:d:f:irq=0x%x:%x:%x:%x\n", pdev->bus->number,
PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn), dev->irq);
+ /*
+ * If this is the first controller to be initialized,
+ * initialize the pciehp work queue
+ */
+ if (atomic_add_return(1, &pciehp_num_controllers) == 1) {
+ pciehp_wq = create_singlethread_workqueue("pciehpd");
+ if (!pciehp_wq) {
+ rc = -ENOMEM;
+ goto abort_free_irq;
+ }
+ }
+
rc = pciehp_readw(ctrl, SLOTCTRL, &temp_word);
if (rc) {
err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__);
goto abort_disable_intr;
}
- ctlr_seq_num++;
ctrl->hpc_ops = &pciehp_hpc_ops;
DBG_LEAVE_ROUTINE