diff options
-rw-r--r-- | drivers/net/qlge/qlge.h | 5 | ||||
-rw-r--r-- | drivers/net/qlge/qlge_main.c | 89 |
2 files changed, 47 insertions, 47 deletions
diff --git a/drivers/net/qlge/qlge.h b/drivers/net/qlge/qlge.h index 38116f9d4163..ba2e1c5b6bcf 100644 --- a/drivers/net/qlge/qlge.h +++ b/drivers/net/qlge/qlge.h | |||
@@ -1375,7 +1375,6 @@ struct ql_adapter { | |||
1375 | spinlock_t adapter_lock; | 1375 | spinlock_t adapter_lock; |
1376 | spinlock_t hw_lock; | 1376 | spinlock_t hw_lock; |
1377 | spinlock_t stats_lock; | 1377 | spinlock_t stats_lock; |
1378 | spinlock_t legacy_lock; /* used for maintaining legacy intr sync */ | ||
1379 | 1378 | ||
1380 | /* PCI Bus Relative Register Addresses */ | 1379 | /* PCI Bus Relative Register Addresses */ |
1381 | void __iomem *reg_base; | 1380 | void __iomem *reg_base; |
@@ -1399,8 +1398,6 @@ struct ql_adapter { | |||
1399 | struct msix_entry *msi_x_entry; | 1398 | struct msix_entry *msi_x_entry; |
1400 | struct intr_context intr_context[MAX_RX_RINGS]; | 1399 | struct intr_context intr_context[MAX_RX_RINGS]; |
1401 | 1400 | ||
1402 | int (*legacy_check) (struct ql_adapter *); | ||
1403 | |||
1404 | int tx_ring_count; /* One per online CPU. */ | 1401 | int tx_ring_count; /* One per online CPU. */ |
1405 | u32 rss_ring_first_cq_id;/* index of first inbound (rss) rx_ring */ | 1402 | u32 rss_ring_first_cq_id;/* index of first inbound (rss) rx_ring */ |
1406 | u32 rss_ring_count; /* One per online CPU. */ | 1403 | u32 rss_ring_count; /* One per online CPU. */ |
@@ -1502,7 +1499,7 @@ void ql_mpi_work(struct work_struct *work); | |||
1502 | void ql_mpi_reset_work(struct work_struct *work); | 1499 | void ql_mpi_reset_work(struct work_struct *work); |
1503 | int ql_wait_reg_rdy(struct ql_adapter *qdev, u32 reg, u32 bit, u32 ebit); | 1500 | int ql_wait_reg_rdy(struct ql_adapter *qdev, u32 reg, u32 bit, u32 ebit); |
1504 | void ql_queue_asic_error(struct ql_adapter *qdev); | 1501 | void ql_queue_asic_error(struct ql_adapter *qdev); |
1505 | void ql_enable_completion_interrupt(struct ql_adapter *qdev, u32 intr); | 1502 | u32 ql_enable_completion_interrupt(struct ql_adapter *qdev, u32 intr); |
1506 | void ql_set_ethtool_ops(struct net_device *ndev); | 1503 | void ql_set_ethtool_ops(struct net_device *ndev); |
1507 | int ql_read_xgmac_reg64(struct ql_adapter *qdev, u32 reg, u64 *data); | 1504 | int ql_read_xgmac_reg64(struct ql_adapter *qdev, u32 reg, u64 *data); |
1508 | 1505 | ||
diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c index 4b2caa6b7ac5..b83a9c9b6a97 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) | |||
577 | * incremented everytime we queue a worker and decremented everytime | 577 | * incremented everytime we queue a worker and decremented everytime |
578 | * a worker finishes. Once it hits zero we enable the interrupt. | 578 | * a worker finishes. Once it hits zero we enable the interrupt. |
579 | */ | 579 | */ |
580 | void ql_enable_completion_interrupt(struct ql_adapter *qdev, u32 intr) | 580 | u32 ql_enable_completion_interrupt(struct ql_adapter *qdev, u32 intr) |
581 | { | 581 | { |
582 | if (likely(test_bit(QL_MSIX_ENABLED, &qdev->flags))) | 582 | u32 var = 0; |
583 | unsigned long hw_flags = 0; | ||
584 | struct intr_context *ctx = qdev->intr_context + intr; | ||
585 | |||
586 | if (likely(test_bit(QL_MSIX_ENABLED, &qdev->flags) && intr)) { | ||
587 | /* Always enable if we're MSIX multi interrupts and | ||
588 | * it's not the default (zeroeth) interrupt. | ||
589 | */ | ||
583 | ql_write32(qdev, INTR_EN, | 590 | ql_write32(qdev, INTR_EN, |
584 | qdev->intr_context[intr].intr_en_mask); | 591 | ctx->intr_en_mask); |
585 | else { | 592 | var = ql_read32(qdev, STS); |
586 | if (qdev->legacy_check) | 593 | return var; |
587 | spin_lock(&qdev->legacy_lock); | ||
588 | if (atomic_dec_and_test(&qdev->intr_context[intr].irq_cnt)) { | ||
589 | QPRINTK(qdev, INTR, ERR, "Enabling interrupt %d.\n", | ||
590 | intr); | ||
591 | ql_write32(qdev, INTR_EN, | ||
592 | qdev->intr_context[intr].intr_en_mask); | ||
593 | } else { | ||
594 | QPRINTK(qdev, INTR, ERR, | ||
595 | "Skip enable, other queue(s) are active.\n"); | ||
596 | } | ||
597 | if (qdev->legacy_check) | ||
598 | spin_unlock(&qdev->legacy_lock); | ||
599 | } | 594 | } |
595 | |||
596 | spin_lock_irqsave(&qdev->hw_lock, hw_flags); | ||
597 | if (atomic_dec_and_test(&ctx->irq_cnt)) { | ||
598 | ql_write32(qdev, INTR_EN, | ||
599 | ctx->intr_en_mask); | ||
600 | var = ql_read32(qdev, STS); | ||
601 | } | ||
602 | spin_unlock_irqrestore(&qdev->hw_lock, hw_flags); | ||
603 | return var; | ||
600 | } | 604 | } |
601 | 605 | ||
602 | static u32 ql_disable_completion_interrupt(struct ql_adapter *qdev, u32 intr) | 606 | static u32 ql_disable_completion_interrupt(struct ql_adapter *qdev, u32 intr) |
603 | { | 607 | { |
604 | u32 var = 0; | 608 | u32 var = 0; |
609 | unsigned long hw_flags; | ||
610 | struct intr_context *ctx; | ||
605 | 611 | ||
606 | if (likely(test_bit(QL_MSIX_ENABLED, &qdev->flags))) | 612 | /* HW disables for us if we're MSIX multi interrupts and |
607 | goto exit; | 613 | * it's not the default (zeroeth) interrupt. |
608 | else if (!atomic_read(&qdev->intr_context[intr].irq_cnt)) { | 614 | */ |
615 | if (likely(test_bit(QL_MSIX_ENABLED, &qdev->flags) && intr)) | ||
616 | return 0; | ||
617 | |||
618 | ctx = qdev->intr_context + intr; | ||
619 | spin_lock_irqsave(&qdev->hw_lock, hw_flags); | ||
620 | if (!atomic_read(&ctx->irq_cnt)) { | ||
609 | ql_write32(qdev, INTR_EN, | 621 | ql_write32(qdev, INTR_EN, |
610 | qdev->intr_context[intr].intr_dis_mask); | 622 | ctx->intr_dis_mask); |
611 | var = ql_read32(qdev, STS); | 623 | var = ql_read32(qdev, STS); |
612 | } | 624 | } |
613 | atomic_inc(&qdev->intr_context[intr].irq_cnt); | 625 | atomic_inc(&ctx->irq_cnt); |
614 | exit: | 626 | spin_unlock_irqrestore(&qdev->hw_lock, hw_flags); |
615 | return var; | 627 | return var; |
616 | } | 628 | } |
617 | 629 | ||
@@ -623,7 +635,9 @@ static void ql_enable_all_completion_interrupts(struct ql_adapter *qdev) | |||
623 | * and enables only if the result is zero. | 635 | * and enables only if the result is zero. |
624 | * So we precharge it here. | 636 | * So we precharge it here. |
625 | */ | 637 | */ |
626 | atomic_set(&qdev->intr_context[i].irq_cnt, 1); | 638 | if (unlikely(!test_bit(QL_MSIX_ENABLED, &qdev->flags) || |
639 | i == 0)) | ||
640 | atomic_set(&qdev->intr_context[i].irq_cnt, 1); | ||
627 | ql_enable_completion_interrupt(qdev, i); | 641 | ql_enable_completion_interrupt(qdev, i); |
628 | } | 642 | } |
629 | 643 | ||
@@ -1725,19 +1739,6 @@ static irqreturn_t qlge_msix_rx_isr(int irq, void *dev_id) | |||
1725 | return IRQ_HANDLED; | 1739 | return IRQ_HANDLED; |
1726 | } | 1740 | } |
1727 | 1741 | ||
1728 | /* We check here to see if we're already handling a legacy | ||
1729 | * interrupt. If we are, then it must belong to another | ||
1730 | * chip with which we're sharing the interrupt line. | ||
1731 | */ | ||
1732 | int ql_legacy_check(struct ql_adapter *qdev) | ||
1733 | { | ||
1734 | int err; | ||
1735 | spin_lock(&qdev->legacy_lock); | ||
1736 | err = atomic_read(&qdev->intr_context[0].irq_cnt); | ||
1737 | spin_unlock(&qdev->legacy_lock); | ||
1738 | return err; | ||
1739 | } | ||
1740 | |||
1741 | /* This handles a fatal error, MPI activity, and the default | 1742 | /* This handles a fatal error, MPI activity, and the default |
1742 | * rx_ring in an MSI-X multiple vector environment. | 1743 | * rx_ring in an MSI-X multiple vector environment. |
1743 | * In MSI/Legacy environment it also process the rest of | 1744 | * In MSI/Legacy environment it also process the rest of |
@@ -1752,12 +1753,15 @@ static irqreturn_t qlge_isr(int irq, void *dev_id) | |||
1752 | int i; | 1753 | int i; |
1753 | int work_done = 0; | 1754 | int work_done = 0; |
1754 | 1755 | ||
1755 | if (qdev->legacy_check && qdev->legacy_check(qdev)) { | 1756 | spin_lock(&qdev->hw_lock); |
1756 | QPRINTK(qdev, INTR, INFO, "Already busy, not our interrupt.\n"); | 1757 | if (atomic_read(&qdev->intr_context[0].irq_cnt)) { |
1757 | return IRQ_NONE; /* Not our interrupt */ | 1758 | QPRINTK(qdev, INTR, DEBUG, "Shared Interrupt, Not ours!\n"); |
1759 | spin_unlock(&qdev->hw_lock); | ||
1760 | return IRQ_NONE; | ||
1758 | } | 1761 | } |
1762 | spin_unlock(&qdev->hw_lock); | ||
1759 | 1763 | ||
1760 | var = ql_read32(qdev, STS); | 1764 | var = ql_disable_completion_interrupt(qdev, intr_context->intr); |
1761 | 1765 | ||
1762 | /* | 1766 | /* |
1763 | * Check for fatal error. | 1767 | * Check for fatal error. |
@@ -1823,6 +1827,7 @@ static irqreturn_t qlge_isr(int irq, void *dev_id) | |||
1823 | } | 1827 | } |
1824 | } | 1828 | } |
1825 | } | 1829 | } |
1830 | ql_enable_completion_interrupt(qdev, intr_context->intr); | ||
1826 | return work_done ? IRQ_HANDLED : IRQ_NONE; | 1831 | return work_done ? IRQ_HANDLED : IRQ_NONE; |
1827 | } | 1832 | } |
1828 | 1833 | ||
@@ -2701,8 +2706,6 @@ msi: | |||
2701 | } | 2706 | } |
2702 | } | 2707 | } |
2703 | irq_type = LEG_IRQ; | 2708 | irq_type = LEG_IRQ; |
2704 | spin_lock_init(&qdev->legacy_lock); | ||
2705 | qdev->legacy_check = ql_legacy_check; | ||
2706 | QPRINTK(qdev, IFUP, DEBUG, "Running with legacy interrupts.\n"); | 2709 | QPRINTK(qdev, IFUP, DEBUG, "Running with legacy interrupts.\n"); |
2707 | } | 2710 | } |
2708 | 2711 | ||