summaryrefslogtreecommitdiffstats
path: root/drivers/net/qlge/qlge_main.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/qlge/qlge_main.c')
-rw-r--r--drivers/net/qlge/qlge_main.c89
1 files changed, 46 insertions, 43 deletions
diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c
index 4b2caa6b7ac..b83a9c9b6a9 100644
--- a/drivers/net/qlge/qlge_main.c
+++ b/drivers/net/qlge/qlge_main.c
@@ -577,41 +577,53 @@ static void ql_disable_interrupts(struct ql_adapter *qdev)
* incremented everytime we queue a worker and decremented everytime
* a worker finishes. Once it hits zero we enable the interrupt.
*/
-void ql_enable_completion_interrupt(struct ql_adapter *qdev, u32 intr)
+u32 ql_enable_completion_interrupt(struct ql_adapter *qdev, u32 intr)
{
- if (likely(test_bit(QL_MSIX_ENABLED, &qdev->flags)))
+ u32 var = 0;
+ unsigned long hw_flags = 0;
+ struct intr_context *ctx = qdev->intr_context + intr;
+
+ if (likely(test_bit(QL_MSIX_ENABLED, &qdev->flags) && intr)) {
+ /* Always enable if we're MSIX multi interrupts and
+ * it's not the default (zeroeth) interrupt.
+ */
ql_write32(qdev, INTR_EN,
- qdev->intr_context[intr].intr_en_mask);
- else {
- if (qdev->legacy_check)
- spin_lock(&qdev->legacy_lock);
- if (atomic_dec_and_test(&qdev->intr_context[intr].irq_cnt)) {
- QPRINTK(qdev, INTR, ERR, "Enabling interrupt %d.\n",
- intr);
- ql_write32(qdev, INTR_EN,
- qdev->intr_context[intr].intr_en_mask);
- } else {
- QPRINTK(qdev, INTR, ERR,
- "Skip enable, other queue(s) are active.\n");
- }
- if (qdev->legacy_check)
- spin_unlock(&qdev->legacy_lock);
+ ctx->intr_en_mask);
+ var = ql_read32(qdev, STS);
+ return var;
}
+
+ spin_lock_irqsave(&qdev->hw_lock, hw_flags);
+ if (atomic_dec_and_test(&ctx->irq_cnt)) {
+ ql_write32(qdev, INTR_EN,
+ ctx->intr_en_mask);
+ var = ql_read32(qdev, STS);
+ }
+ spin_unlock_irqrestore(&qdev->hw_lock, hw_flags);
+ return var;
}
static u32 ql_disable_completion_interrupt(struct ql_adapter *qdev, u32 intr)
{
u32 var = 0;
+ unsigned long hw_flags;
+ struct intr_context *ctx;
- if (likely(test_bit(QL_MSIX_ENABLED, &qdev->flags)))
- goto exit;
- else if (!atomic_read(&qdev->intr_context[intr].irq_cnt)) {
+ /* HW disables for us if we're MSIX multi interrupts and
+ * it's not the default (zeroeth) interrupt.
+ */
+ if (likely(test_bit(QL_MSIX_ENABLED, &qdev->flags) && intr))
+ return 0;
+
+ ctx = qdev->intr_context + intr;
+ spin_lock_irqsave(&qdev->hw_lock, hw_flags);
+ if (!atomic_read(&ctx->irq_cnt)) {
ql_write32(qdev, INTR_EN,
- qdev->intr_context[intr].intr_dis_mask);
+ ctx->intr_dis_mask);
var = ql_read32(qdev, STS);
}
- atomic_inc(&qdev->intr_context[intr].irq_cnt);
-exit:
+ atomic_inc(&ctx->irq_cnt);
+ spin_unlock_irqrestore(&qdev->hw_lock, hw_flags);
return var;
}
@@ -623,7 +635,9 @@ static void ql_enable_all_completion_interrupts(struct ql_adapter *qdev)
* and enables only if the result is zero.
* So we precharge it here.
*/
- atomic_set(&qdev->intr_context[i].irq_cnt, 1);
+ if (unlikely(!test_bit(QL_MSIX_ENABLED, &qdev->flags) ||
+ i == 0))
+ atomic_set(&qdev->intr_context[i].irq_cnt, 1);
ql_enable_completion_interrupt(qdev, i);
}
@@ -1725,19 +1739,6 @@ static irqreturn_t qlge_msix_rx_isr(int irq, void *dev_id)
return IRQ_HANDLED;
}
-/* We check here to see if we're already handling a legacy
- * interrupt. If we are, then it must belong to another
- * chip with which we're sharing the interrupt line.
- */
-int ql_legacy_check(struct ql_adapter *qdev)
-{
- int err;
- spin_lock(&qdev->legacy_lock);
- err = atomic_read(&qdev->intr_context[0].irq_cnt);
- spin_unlock(&qdev->legacy_lock);
- return err;
-}
-
/* This handles a fatal error, MPI activity, and the default
* rx_ring in an MSI-X multiple vector environment.
* In MSI/Legacy environment it also process the rest of
@@ -1752,12 +1753,15 @@ static irqreturn_t qlge_isr(int irq, void *dev_id)
int i;
int work_done = 0;
- if (qdev->legacy_check && qdev->legacy_check(qdev)) {
- QPRINTK(qdev, INTR, INFO, "Already busy, not our interrupt.\n");
- return IRQ_NONE; /* Not our interrupt */
+ spin_lock(&qdev->hw_lock);
+ if (atomic_read(&qdev->intr_context[0].irq_cnt)) {
+ QPRINTK(qdev, INTR, DEBUG, "Shared Interrupt, Not ours!\n");
+ spin_unlock(&qdev->hw_lock);
+ return IRQ_NONE;
}
+ spin_unlock(&qdev->hw_lock);
- var = ql_read32(qdev, STS);
+ var = ql_disable_completion_interrupt(qdev, intr_context->intr);
/*
* Check for fatal error.
@@ -1823,6 +1827,7 @@ static irqreturn_t qlge_isr(int irq, void *dev_id)
}
}
}
+ ql_enable_completion_interrupt(qdev, intr_context->intr);
return work_done ? IRQ_HANDLED : IRQ_NONE;
}
@@ -2701,8 +2706,6 @@ msi:
}
}
irq_type = LEG_IRQ;
- spin_lock_init(&qdev->legacy_lock);
- qdev->legacy_check = ql_legacy_check;
QPRINTK(qdev, IFUP, DEBUG, "Running with legacy interrupts.\n");
}