aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/qlcnic/qlcnic_main.c
diff options
context:
space:
mode:
authorAmit Kumar Salecha <amit.salecha@qlogic.com>2010-02-01 00:24:59 -0500
committerDavid S. Miller <davem@davemloft.net>2010-02-02 18:55:46 -0500
commit7eb9855d68faabe0004ed18c2af1f0974d3c2c63 (patch)
tree750382ba8db5b390847ce05fc4f216d1d7d7d533 /drivers/net/qlcnic/qlcnic_main.c
parent897d3596e0dfc4c25963cff00f1159c79eaf38d3 (diff)
qlcnic: add interrupt diagnostic test
Interrupt test (offline) added in ethtool self test. Register a temporary interrupt handler and then send command to fw to raise an interrupt. Signed-off-by: Sucheta Chakraborty <sucheta.chakraborty@qlogic.com> Signed-off-by: Amit Kumar Salecha <amit.salecha@qlogic.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/qlcnic/qlcnic_main.c')
-rw-r--r--drivers/net/qlcnic/qlcnic_main.c112
1 files changed, 102 insertions, 10 deletions
diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c
index 7259adc32631..a8b07120d362 100644
--- a/drivers/net/qlcnic/qlcnic_main.c
+++ b/drivers/net/qlcnic/qlcnic_main.c
@@ -88,6 +88,7 @@ static void qlcnic_remove_diag_entries(struct qlcnic_adapter *adapter);
88static void qlcnic_clr_all_drv_state(struct qlcnic_adapter *adapter); 88static void qlcnic_clr_all_drv_state(struct qlcnic_adapter *adapter);
89static int qlcnic_can_start_firmware(struct qlcnic_adapter *adapter); 89static int qlcnic_can_start_firmware(struct qlcnic_adapter *adapter);
90 90
91static irqreturn_t qlcnic_tmp_intr(int irq, void *data);
91static irqreturn_t qlcnic_intr(int irq, void *data); 92static irqreturn_t qlcnic_intr(int irq, void *data);
92static irqreturn_t qlcnic_msi_intr(int irq, void *data); 93static irqreturn_t qlcnic_msi_intr(int irq, void *data);
93static irqreturn_t qlcnic_msix_intr(int irq, void *data); 94static irqreturn_t qlcnic_msix_intr(int irq, void *data);
@@ -720,13 +721,20 @@ qlcnic_request_irq(struct qlcnic_adapter *adapter)
720 struct net_device *netdev = adapter->netdev; 721 struct net_device *netdev = adapter->netdev;
721 struct qlcnic_recv_context *recv_ctx = &adapter->recv_ctx; 722 struct qlcnic_recv_context *recv_ctx = &adapter->recv_ctx;
722 723
723 if (adapter->flags & QLCNIC_MSIX_ENABLED) 724 if (adapter->diag_test == QLCNIC_INTERRUPT_TEST) {
724 handler = qlcnic_msix_intr; 725 handler = qlcnic_tmp_intr;
725 else if (adapter->flags & QLCNIC_MSI_ENABLED) 726 if (!QLCNIC_IS_MSI_FAMILY(adapter))
726 handler = qlcnic_msi_intr; 727 flags |= IRQF_SHARED;
727 else { 728
728 flags |= IRQF_SHARED; 729 } else {
729 handler = qlcnic_intr; 730 if (adapter->flags & QLCNIC_MSIX_ENABLED)
731 handler = qlcnic_msix_intr;
732 else if (adapter->flags & QLCNIC_MSI_ENABLED)
733 handler = qlcnic_msi_intr;
734 else {
735 flags |= IRQF_SHARED;
736 handler = qlcnic_intr;
737 }
730 } 738 }
731 adapter->irq = netdev->irq; 739 adapter->irq = netdev->irq;
732 740
@@ -923,6 +931,60 @@ qlcnic_detach(struct qlcnic_adapter *adapter)
923 adapter->is_up = 0; 931 adapter->is_up = 0;
924} 932}
925 933
934void qlcnic_diag_free_res(struct net_device *netdev, int max_sds_rings)
935{
936 struct qlcnic_adapter *adapter = netdev_priv(netdev);
937 struct qlcnic_host_sds_ring *sds_ring;
938 int ring;
939
940 for (ring = 0; ring < adapter->max_sds_rings; ring++) {
941 sds_ring = &adapter->recv_ctx.sds_rings[ring];
942 qlcnic_disable_int(sds_ring);
943 }
944
945 qlcnic_detach(adapter);
946
947 adapter->diag_test = 0;
948 adapter->max_sds_rings = max_sds_rings;
949
950 if (qlcnic_attach(adapter))
951 return;
952
953 if (netif_running(netdev))
954 __qlcnic_up(adapter, netdev);
955
956 netif_device_attach(netdev);
957}
958
959int qlcnic_diag_alloc_res(struct net_device *netdev, int test)
960{
961 struct qlcnic_adapter *adapter = netdev_priv(netdev);
962 struct qlcnic_host_sds_ring *sds_ring;
963 int ring;
964 int ret;
965
966 netif_device_detach(netdev);
967
968 if (netif_running(netdev))
969 __qlcnic_down(adapter, netdev);
970
971 qlcnic_detach(adapter);
972
973 adapter->max_sds_rings = 1;
974 adapter->diag_test = test;
975
976 ret = qlcnic_attach(adapter);
977 if (ret)
978 return ret;
979
980 for (ring = 0; ring < adapter->max_sds_rings; ring++) {
981 sds_ring = &adapter->recv_ctx.sds_rings[ring];
982 qlcnic_enable_int(sds_ring);
983 }
984
985 return 0;
986}
987
926int 988int
927qlcnic_reset_context(struct qlcnic_adapter *adapter) 989qlcnic_reset_context(struct qlcnic_adapter *adapter)
928{ 990{
@@ -1689,10 +1751,8 @@ static struct net_device_stats *qlcnic_get_stats(struct net_device *netdev)
1689 return stats; 1751 return stats;
1690} 1752}
1691 1753
1692static irqreturn_t qlcnic_intr(int irq, void *data) 1754static irqreturn_t qlcnic_clear_legacy_intr(struct qlcnic_adapter *adapter)
1693{ 1755{
1694 struct qlcnic_host_sds_ring *sds_ring = data;
1695 struct qlcnic_adapter *adapter = sds_ring->adapter;
1696 u32 status; 1756 u32 status;
1697 1757
1698 status = readl(adapter->isr_int_vec); 1758 status = readl(adapter->isr_int_vec);
@@ -1710,6 +1770,38 @@ static irqreturn_t qlcnic_intr(int irq, void *data)
1710 readl(adapter->isr_int_vec); 1770 readl(adapter->isr_int_vec);
1711 readl(adapter->isr_int_vec); 1771 readl(adapter->isr_int_vec);
1712 1772
1773 return IRQ_HANDLED;
1774}
1775
1776static irqreturn_t qlcnic_tmp_intr(int irq, void *data)
1777{
1778 struct qlcnic_host_sds_ring *sds_ring = data;
1779 struct qlcnic_adapter *adapter = sds_ring->adapter;
1780
1781 if (adapter->flags & QLCNIC_MSIX_ENABLED)
1782 goto done;
1783 else if (adapter->flags & QLCNIC_MSI_ENABLED) {
1784 writel(0xffffffff, adapter->tgt_status_reg);
1785 goto done;
1786 }
1787
1788 if (qlcnic_clear_legacy_intr(adapter) == IRQ_NONE)
1789 return IRQ_NONE;
1790
1791done:
1792 adapter->diag_cnt++;
1793 qlcnic_enable_int(sds_ring);
1794 return IRQ_HANDLED;
1795}
1796
1797static irqreturn_t qlcnic_intr(int irq, void *data)
1798{
1799 struct qlcnic_host_sds_ring *sds_ring = data;
1800 struct qlcnic_adapter *adapter = sds_ring->adapter;
1801
1802 if (qlcnic_clear_legacy_intr(adapter) == IRQ_NONE)
1803 return IRQ_NONE;
1804
1713 napi_schedule(&sds_ring->napi); 1805 napi_schedule(&sds_ring->napi);
1714 1806
1715 return IRQ_HANDLED; 1807 return IRQ_HANDLED;