diff options
author | Amit S. Kale <amitkale@netxen.com> | 2006-10-21 15:33:03 -0400 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2006-12-02 00:11:58 -0500 |
commit | 3d396eb17e9f8c5f59314078b45b88647591378d (patch) | |
tree | d0c54e4555c1bee13d403f6dad36b40ae26d74a2 /drivers/net/netxen/netxen_nic_isr.c | |
parent | f3d1fca3eb05cf6ff3879a385a15d24fbf556c57 (diff) |
Add NetXen 1G/10G ethernet driver.
Signed-off-by: Amit S. Kale <amitkale@netxen.com>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers/net/netxen/netxen_nic_isr.c')
-rw-r--r-- | drivers/net/netxen/netxen_nic_isr.c | 221 |
1 files changed, 221 insertions, 0 deletions
diff --git a/drivers/net/netxen/netxen_nic_isr.c b/drivers/net/netxen/netxen_nic_isr.c new file mode 100644 index 000000000000..f1c3e5af03a9 --- /dev/null +++ b/drivers/net/netxen/netxen_nic_isr.c | |||
@@ -0,0 +1,221 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2003 - 2006 NetXen, Inc. | ||
3 | * All rights reserved. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or | ||
6 | * modify it under the terms of the GNU General Public License | ||
7 | * as published by the Free Software Foundation; either version 2 | ||
8 | * of the License, or (at your option) any later version. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, but | ||
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, | ||
18 | * MA 02111-1307, USA. | ||
19 | * | ||
20 | * The full GNU General Public License is included in this distribution | ||
21 | * in the file called LICENSE. | ||
22 | * | ||
23 | * Contact Information: | ||
24 | * info@netxen.com | ||
25 | * NetXen, | ||
26 | * 3965 Freedom Circle, Fourth floor, | ||
27 | * Santa Clara, CA 95054 | ||
28 | */ | ||
29 | |||
30 | #include <linux/netdevice.h> | ||
31 | #include <linux/delay.h> | ||
32 | |||
33 | #include "netxen_nic.h" | ||
34 | #include "netxen_nic_hw.h" | ||
35 | #include "netxen_nic_phan_reg.h" | ||
36 | |||
37 | /* | ||
38 | * netxen_nic_get_stats - Get System Network Statistics | ||
39 | * @netdev: network interface device structure | ||
40 | */ | ||
41 | struct net_device_stats *netxen_nic_get_stats(struct net_device *netdev) | ||
42 | { | ||
43 | struct netxen_port *port = netdev_priv(netdev); | ||
44 | struct net_device_stats *stats = &port->net_stats; | ||
45 | |||
46 | memset(stats, 0, sizeof(*stats)); | ||
47 | |||
48 | /* total packets received */ | ||
49 | stats->rx_packets = port->stats.no_rcv; | ||
50 | /* total packets transmitted */ | ||
51 | stats->tx_packets = port->stats.xmitedframes + port->stats.xmitfinished; | ||
52 | /* total bytes received */ | ||
53 | stats->rx_bytes = port->stats.rxbytes; | ||
54 | /* total bytes transmitted */ | ||
55 | stats->tx_bytes = port->stats.txbytes; | ||
56 | /* bad packets received */ | ||
57 | stats->rx_errors = port->stats.rcvdbadskb; | ||
58 | /* packet transmit problems */ | ||
59 | stats->tx_errors = port->stats.nocmddescriptor; | ||
60 | /* no space in linux buffers */ | ||
61 | stats->rx_dropped = port->stats.updropped; | ||
62 | /* no space available in linux */ | ||
63 | stats->tx_dropped = port->stats.txdropped; | ||
64 | |||
65 | return stats; | ||
66 | } | ||
67 | |||
68 | void netxen_indicate_link_status(struct netxen_adapter *adapter, u32 portno, | ||
69 | u32 link) | ||
70 | { | ||
71 | struct netxen_port *pport = adapter->port[portno]; | ||
72 | struct net_device *netdev = pport->netdev; | ||
73 | |||
74 | if (link) | ||
75 | netif_carrier_on(netdev); | ||
76 | else | ||
77 | netif_carrier_off(netdev); | ||
78 | } | ||
79 | |||
80 | void netxen_handle_port_int(struct netxen_adapter *adapter, u32 portno, | ||
81 | u32 enable) | ||
82 | { | ||
83 | __le32 int_src; | ||
84 | struct netxen_port *port; | ||
85 | |||
86 | /* This should clear the interrupt source */ | ||
87 | if (adapter->ops->phy_read) | ||
88 | adapter->ops->phy_read(adapter, portno, | ||
89 | NETXEN_NIU_GB_MII_MGMT_ADDR_INT_STATUS, | ||
90 | &int_src); | ||
91 | if (int_src == 0) { | ||
92 | DPRINTK(INFO, "No phy interrupts for port #%d\n", portno); | ||
93 | return; | ||
94 | } | ||
95 | if (adapter->ops->disable_phy_interrupts) | ||
96 | adapter->ops->disable_phy_interrupts(adapter, portno); | ||
97 | |||
98 | port = adapter->port[portno]; | ||
99 | |||
100 | if (netxen_get_phy_int_jabber(int_src)) | ||
101 | DPRINTK(INFO, "NetXen: %s Jabber interrupt \n", | ||
102 | port->netdev->name); | ||
103 | |||
104 | if (netxen_get_phy_int_polarity_changed(int_src)) | ||
105 | DPRINTK(INFO, "NetXen: %s POLARITY CHANGED int \n", | ||
106 | port->netdev->name); | ||
107 | |||
108 | if (netxen_get_phy_int_energy_detect(int_src)) | ||
109 | DPRINTK(INFO, "NetXen: %s ENERGY DETECT INT \n", | ||
110 | port->netdev->name); | ||
111 | |||
112 | if (netxen_get_phy_int_downshift(int_src)) | ||
113 | DPRINTK(INFO, "NetXen: %s DOWNSHIFT INT \n", | ||
114 | port->netdev->name); | ||
115 | /* write it down later.. */ | ||
116 | if ((netxen_get_phy_int_speed_changed(int_src)) | ||
117 | || (netxen_get_phy_int_link_status_changed(int_src))) { | ||
118 | __le32 status; | ||
119 | |||
120 | DPRINTK(INFO, "NetXen: %s SPEED CHANGED OR" | ||
121 | " LINK STATUS CHANGED \n", port->netdev->name); | ||
122 | |||
123 | if (adapter->ops->phy_read | ||
124 | && adapter->ops->phy_read(adapter, portno, | ||
125 | NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_STATUS, | ||
126 | &status) == 0) { | ||
127 | if (netxen_get_phy_int_link_status_changed(int_src)) { | ||
128 | if (netxen_get_phy_link(status)) { | ||
129 | netxen_niu_gbe_init_port(adapter, | ||
130 | portno); | ||
131 | printk("%s: %s Link UP\n", | ||
132 | netxen_nic_driver_name, | ||
133 | port->netdev->name); | ||
134 | |||
135 | } else { | ||
136 | printk("%s: %s Link DOWN\n", | ||
137 | netxen_nic_driver_name, | ||
138 | port->netdev->name); | ||
139 | } | ||
140 | netxen_indicate_link_status(adapter, portno, | ||
141 | netxen_get_phy_link | ||
142 | (status)); | ||
143 | } | ||
144 | } | ||
145 | } | ||
146 | if (adapter->ops->enable_phy_interrupts) | ||
147 | adapter->ops->enable_phy_interrupts(adapter, portno); | ||
148 | } | ||
149 | |||
150 | void netxen_nic_isr_other(struct netxen_adapter *adapter) | ||
151 | { | ||
152 | u32 enable, portno; | ||
153 | u32 i2qhi; | ||
154 | |||
155 | /* | ||
156 | * bit 3 is for i2qInt, if high its enabled | ||
157 | * check for phy interrupts | ||
158 | * read vector and check for bit 45 for phy | ||
159 | * clear int by writing the same value into ISR_INT_VECTOR REG | ||
160 | */ | ||
161 | |||
162 | DPRINTK(INFO, "I2Q is the source of INT \n"); | ||
163 | |||
164 | /* verify the offset */ | ||
165 | i2qhi = readl(NETXEN_CRB_NORMALIZE(adapter, NETXEN_I2Q_CLR_PCI_HI)); | ||
166 | |||
167 | DPRINTK(INFO, "isr NETXEN_I2Q_CLR_PCI_HI = 0x%x \n", i2qhi); | ||
168 | |||
169 | if (i2qhi & 0x4000) { | ||
170 | for (portno = 0; portno < NETXEN_NIU_MAX_GBE_PORTS; portno++) { | ||
171 | DPRINTK(INFO, "External PHY interrupt ON PORT %d\n", | ||
172 | portno); | ||
173 | |||
174 | enable = 1; | ||
175 | netxen_handle_port_int(adapter, portno, enable); | ||
176 | } | ||
177 | |||
178 | /* Clear the interrupt on I2Q */ | ||
179 | writel((u32) i2qhi, | ||
180 | NETXEN_CRB_NORMALIZE(adapter, NETXEN_I2Q_CLR_PCI_HI)); | ||
181 | |||
182 | } | ||
183 | } | ||
184 | |||
185 | void netxen_nic_gbe_handle_phy_intr(struct netxen_adapter *adapter) | ||
186 | { | ||
187 | u32 val; | ||
188 | val = readl(NETXEN_CRB_NORMALIZE(adapter, ISR_INT_VECTOR)); | ||
189 | if (val & 0x4) { | ||
190 | adapter->stats.otherints++; | ||
191 | netxen_nic_isr_other(adapter); | ||
192 | } | ||
193 | } | ||
194 | |||
195 | void netxen_nic_xgbe_handle_phy_intr(struct netxen_adapter *adapter) | ||
196 | { | ||
197 | struct net_device *netdev = adapter->port[0]->netdev; | ||
198 | u32 val; | ||
199 | |||
200 | /* WINDOW = 1 */ | ||
201 | val = readl(NETXEN_CRB_NORMALIZE(adapter, CRB_XG_STATE)); | ||
202 | |||
203 | if (adapter->ahw.xg_linkup == 1 && val != XG_LINK_UP) { | ||
204 | printk(KERN_INFO "%s: %s NIC Link is down\n", | ||
205 | netxen_nic_driver_name, netdev->name); | ||
206 | adapter->ahw.xg_linkup = 0; | ||
207 | /* read twice to clear sticky bits */ | ||
208 | /* WINDOW = 0 */ | ||
209 | netxen_nic_read_w0(adapter, NETXEN_NIU_XG_STATUS, &val); | ||
210 | netxen_nic_read_w0(adapter, NETXEN_NIU_XG_STATUS, &val); | ||
211 | |||
212 | if ((val & 0xffb) != 0xffb) { | ||
213 | printk(KERN_INFO "%s ISR: Sync/Align BAD: 0x%08x\n", | ||
214 | netxen_nic_driver_name, val); | ||
215 | } | ||
216 | } else if (adapter->ahw.xg_linkup == 0 && val == XG_LINK_UP) { | ||
217 | printk(KERN_INFO "%s: %s NIC Link is up\n", | ||
218 | netxen_nic_driver_name, netdev->name); | ||
219 | adapter->ahw.xg_linkup = 1; | ||
220 | } | ||
221 | } | ||