]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blob - drivers/staging/et131x/et131x_isr.c
Staging: add et131x network driver
[linux-2.6-omap-h63xx.git] / drivers / staging / et131x / et131x_isr.c
1 /*
2  * Agere Systems Inc.
3  * 10/100/1000 Base-T Ethernet Driver for the ET1301 and ET131x series MACs
4  *
5  * Copyright © 2005 Agere Systems Inc.
6  * All rights reserved.
7  *   http://www.agere.com
8  *
9  *------------------------------------------------------------------------------
10  *
11  * et131x_isr.c - File which contains the ISR, ISR handler, and related routines
12  *                for processing interrupts from the device.
13  *
14  *------------------------------------------------------------------------------
15  *
16  * SOFTWARE LICENSE
17  *
18  * This software is provided subject to the following terms and conditions,
19  * which you should read carefully before using the software.  Using this
20  * software indicates your acceptance of these terms and conditions.  If you do
21  * not agree with these terms and conditions, do not use the software.
22  *
23  * Copyright © 2005 Agere Systems Inc.
24  * All rights reserved.
25  *
26  * Redistribution and use in source or binary forms, with or without
27  * modifications, are permitted provided that the following conditions are met:
28  *
29  * . Redistributions of source code must retain the above copyright notice, this
30  *    list of conditions and the following Disclaimer as comments in the code as
31  *    well as in the documentation and/or other materials provided with the
32  *    distribution.
33  *
34  * . Redistributions in binary form must reproduce the above copyright notice,
35  *    this list of conditions and the following Disclaimer in the documentation
36  *    and/or other materials provided with the distribution.
37  *
38  * . Neither the name of Agere Systems Inc. nor the names of the contributors
39  *    may be used to endorse or promote products derived from this software
40  *    without specific prior written permission.
41  *
42  * Disclaimer
43  *
44  * THIS SOFTWARE IS PROVIDED \93AS IS\94 AND ANY EXPRESS OR IMPLIED WARRANTIES,
45  * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF
46  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  ANY
47  * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN
48  * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. OR CONTRIBUTORS BE LIABLE FOR ANY
49  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
50  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
51  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
52  * ON ANY THEORY OF LIABILITY, INCLUDING, BUT NOT LIMITED TO, CONTRACT, STRICT
53  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
54  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
55  * DAMAGE.
56  *
57  */
58
59 #include "et131x_version.h"
60 #include "et131x_debug.h"
61 #include "et131x_defs.h"
62
63 #include <linux/init.h>
64 #include <linux/module.h>
65 #include <linux/types.h>
66 #include <linux/kernel.h>
67
68 #include <linux/sched.h>
69 #include <linux/ptrace.h>
70 #include <linux/slab.h>
71 #include <linux/ctype.h>
72 #include <linux/string.h>
73 #include <linux/timer.h>
74 #include <linux/interrupt.h>
75 #include <linux/in.h>
76 #include <linux/delay.h>
77 #include <asm/io.h>
78 #include <asm/system.h>
79 #include <asm/bitops.h>
80
81 #include <linux/netdevice.h>
82 #include <linux/etherdevice.h>
83 #include <linux/skbuff.h>
84 #include <linux/if_arp.h>
85 #include <linux/ioport.h>
86
87 #include "et1310_phy.h"
88 #include "et1310_pm.h"
89 #include "et1310_jagcore.h"
90 #include "et1310_mac.h"
91
92 #include "et131x_adapter.h"
93
94 /* Data for debugging facilities */
95 #ifdef CONFIG_ET131X_DEBUG
96 extern dbg_info_t *et131x_dbginfo;
97 #endif /* CONFIG_ET131X_DEBUG */
98
99 /**
100  * et131x_isr - The Interrupt Service Routine for the driver.
101  * @irq: the IRQ on which the interrupt was received.
102  * @dev_id: device-specific info (here a pointer to a net_device struct)
103  *
104  * Returns a value indicating if the interrupt was handled.
105  */
106 irqreturn_t et131x_isr(int irq, void *dev_id)
107 {
108         bool handled = true;
109         struct net_device *netdev = (struct net_device *)dev_id;
110         struct et131x_adapter *adapter = NULL;
111         INTERRUPT_t status;
112
113         if (netdev == NULL || !netif_device_present(netdev)) {
114                 DBG_WARNING(et131x_dbginfo,
115                             "No net_device struct or device not present\n");
116                 handled = false;
117                 goto out;
118         }
119
120         adapter = netdev_priv(netdev);
121
122         /* If the adapter is in low power state, then it should not
123          * recognize any interrupt
124          */
125
126         /* Disable Device Interrupts */
127         et131x_disable_interrupts(adapter);
128
129         /* Get a copy of the value in the interrupt status register
130          * so we can process the interrupting section
131          */
132         status.value = readl(&adapter->CSRAddress->global.int_status.value);
133
134         if (adapter->FlowControl == TxOnly ||
135             adapter->FlowControl == Both) {
136                 status.value &= ~INT_MASK_ENABLE;
137         } else {
138                 status.value &= ~INT_MASK_ENABLE_NO_FLOW;
139         }
140
141         /* Make sure this is our interrupt */
142         if (!status.value) {
143 #ifdef CONFIG_ET131X_DEBUG
144                 adapter->Stats.UnhandledInterruptsPerSec++;
145 #endif
146                 handled = false;
147                 DBG_VERBOSE(et131x_dbginfo, "NOT OUR INTERRUPT\n");
148                 et131x_enable_interrupts(adapter);
149                 goto out;
150         }
151
152         /* This is our interrupt, so process accordingly */
153 #ifdef CONFIG_ET131X_DEBUG
154         if (status.bits.rxdma_xfr_done) {
155                 adapter->Stats.RxDmaInterruptsPerSec++;
156         }
157
158         if (status.bits.txdma_isr) {
159                 adapter->Stats.TxDmaInterruptsPerSec++;
160         }
161 #endif
162
163         if (status.bits.watchdog_interrupt) {
164                 PMP_TCB pMpTcb = adapter->TxRing.CurrSendHead;
165
166                 if (pMpTcb) {
167                         if (++pMpTcb->PacketStaleCount > 1) {
168                                 status.bits.txdma_isr = 1;
169                         }
170                 }
171
172                 if (adapter->RxRing.UnfinishedReceives) {
173                         status.bits.rxdma_xfr_done = 1;
174                 } else if (pMpTcb == NULL) {
175                         writel(0, &adapter->CSRAddress->global.watchdog_timer);
176                 }
177
178                 status.bits.watchdog_interrupt = 0;
179 #ifdef CONFIG_ET131X_DEBUG
180                 adapter->Stats.WatchDogInterruptsPerSec++;
181 #endif
182         }
183
184         if (status.value == 0) {
185                 /* This interrupt has in some way been "handled" by
186                  * the ISR. Either it was a spurious Rx interrupt, or
187                  * it was a Tx interrupt that has been filtered by
188                  * the ISR.
189                  */
190                 et131x_enable_interrupts(adapter);
191                 goto out;
192         }
193
194         /* We need to save the interrupt status value for use in our
195          * DPC. We will clear the software copy of that in that
196          * routine.
197          */
198         adapter->Stats.InterruptStatus = status;
199
200         /* Schedule the ISR handler as a bottom-half task in the
201          * kernel's tq_immediate queue, and mark the queue for
202          * execution
203          */
204         schedule_work(&adapter->task);
205
206 out:
207         return IRQ_RETVAL(handled);
208 }
209
210 /**
211  * et131x_isr_handler - The ISR handler
212  * @p_adapter, a pointer to the device's private adapter structure
213  *
214  * scheduled to run in a deferred context by the ISR. This is where the ISR's
215  * work actually gets done.
216  */
217 void et131x_isr_handler(struct work_struct *work)
218 {
219         struct et131x_adapter *pAdapter =
220                 container_of(work, struct et131x_adapter, task);
221         INTERRUPT_t GlobStatus = pAdapter->Stats.InterruptStatus;
222         ADDRESS_MAP_t __iomem *iomem = pAdapter->CSRAddress;
223
224         /*
225          * These first two are by far the most common.  Once handled, we clear
226          * their two bits in the status word.  If the word is now zero, we
227          * exit.
228          */
229         /* Handle all the completed Transmit interrupts */
230         if (GlobStatus.bits.txdma_isr) {
231                 DBG_TX(et131x_dbginfo, "TXDMA_ISR interrupt\n");
232                 et131x_handle_send_interrupt(pAdapter);
233         }
234
235         /* Handle all the completed Receives interrupts */
236         if (GlobStatus.bits.rxdma_xfr_done) {
237                 DBG_RX(et131x_dbginfo, "RXDMA_XFR_DONE interrupt\n");
238                 et131x_handle_recv_interrupt(pAdapter);
239         }
240
241         GlobStatus.value &= 0xffffffd7;
242
243         if (GlobStatus.value) {
244                 /* Handle the TXDMA Error interrupt */
245                 if (GlobStatus.bits.txdma_err) {
246                         TXDMA_ERROR_t TxDmaErr;
247
248                         /* Following read also clears the register (COR) */
249                         TxDmaErr.value = readl(&iomem->txdma.TxDmaError.value);
250
251                         DBG_WARNING(et131x_dbginfo,
252                                     "TXDMA_ERR interrupt, error = %d\n",
253                                     TxDmaErr.value);
254                 }
255
256                 /* Handle Free Buffer Ring 0 and 1 Low interrupt */
257                 if (GlobStatus.bits.rxdma_fb_ring0_low ||
258                     GlobStatus.bits.rxdma_fb_ring1_low) {
259                         /*
260                          * This indicates the number of unused buffers in
261                          * RXDMA free buffer ring 0 is <= the limit you
262                          * programmed. Free buffer resources need to be
263                          * returned.  Free buffers are consumed as packets
264                          * are passed from the network to the host. The host
265                          * becomes aware of the packets from the contents of
266                          * the packet status ring. This ring is queried when
267                          * the packet done interrupt occurs. Packets are then
268                          * passed to the OS. When the OS is done with the
269                          * packets the resources can be returned to the
270                          * ET1310 for re-use. This interrupt is one method of
271                          * returning resources.
272                          */
273                         DBG_WARNING(et131x_dbginfo,
274                                     "RXDMA_FB_RING0_LOW or "
275                                     "RXDMA_FB_RING1_LOW interrupt\n");
276
277                         /* If the user has flow control on, then we will
278                          * send a pause packet, otherwise just exit
279                          */
280                         if (pAdapter->FlowControl == TxOnly ||
281                             pAdapter->FlowControl == Both) {
282                                 PM_CSR_t pm_csr;
283
284                                 /* Tell the device to send a pause packet via
285                                  * the back pressure register
286                                  */
287                                 pm_csr.value = readl(&iomem->global.pm_csr.value);
288                                 if (pm_csr.bits.pm_phy_sw_coma == 0) {
289                                         TXMAC_BP_CTRL_t bp_ctrl = { 0 };
290
291                                         bp_ctrl.bits.bp_req = 1;
292                                         bp_ctrl.bits.bp_xonxoff = 1;
293                                         writel(bp_ctrl.value,
294                                                &iomem->txmac.bp_ctrl.value);
295                                 }
296                         }
297                 }
298
299                 /* Handle Packet Status Ring Low Interrupt */
300                 if (GlobStatus.bits.rxdma_pkt_stat_ring_low) {
301                         DBG_WARNING(et131x_dbginfo,
302                                     "RXDMA_PKT_STAT_RING_LOW interrupt\n");
303
304                         /*
305                          * Same idea as with the two Free Buffer Rings.
306                          * Packets going from the network to the host each
307                          * consume a free buffer resource and a packet status
308                          * resource.  These resoures are passed to the OS.
309                          * When the OS is done with the resources, they need
310                          * to be returned to the ET1310. This is one method
311                          * of returning the resources.
312                          */
313                 }
314
315                 /* Handle RXDMA Error Interrupt */
316                 if (GlobStatus.bits.rxdma_err) {
317                         /*
318                          * The rxdma_error interrupt is sent when a time-out
319                          * on a request issued by the JAGCore has occurred or
320                          * a completion is returned with an un-successful
321                          * status.  In both cases the request is considered
322                          * complete. The JAGCore will automatically re-try the
323                          * request in question. Normally information on events
324                          * like these are sent to the host using the "Advanced
325                          * Error Reporting" capability. This interrupt is
326                          * another way of getting similar information. The
327                          * only thing required is to clear the interrupt by
328                          * reading the ISR in the global resources. The
329                          * JAGCore will do a re-try on the request.  Normally
330                          * you should never see this interrupt. If you start
331                          * to see this interrupt occurring frequently then
332                          * something bad has occurred. A reset might be the
333                          * thing to do.
334                          */
335                         // TRAP();
336
337                         pAdapter->TxMacTest.value =
338                                 readl(&iomem->txmac.tx_test.value);
339                         DBG_WARNING(et131x_dbginfo,
340                                     "RxDMA_ERR interrupt, error %x\n",
341                                     pAdapter->TxMacTest.value);
342                 }
343
344                 /* Handle the Wake on LAN Event */
345                 if (GlobStatus.bits.wake_on_lan) {
346                         /*
347                          * This is a secondary interrupt for wake on LAN.
348                          * The driver should never see this, if it does,
349                          * something serious is wrong. We will TRAP the
350                          * message when we are in DBG mode, otherwise we
351                          * will ignore it.
352                          */
353                         DBG_ERROR(et131x_dbginfo, "WAKE_ON_LAN interrupt\n");
354                 }
355
356                 /* Handle the PHY interrupt */
357                 if (GlobStatus.bits.phy_interrupt) {
358                         PM_CSR_t pm_csr;
359                         MI_BMSR_t BmsrInts, BmsrData;
360                         MI_ISR_t myIsr;
361
362                         DBG_VERBOSE(et131x_dbginfo, "PHY interrupt\n");
363
364                         /* If we are in coma mode when we get this interrupt,
365                          * we need to disable it.
366                          */
367                         pm_csr.value = readl(&iomem->global.pm_csr.value);
368                         if (pm_csr.bits.pm_phy_sw_coma == 1) {
369                                 /*
370                                  * Check to see if we are in coma mode and if
371                                  * so, disable it because we will not be able
372                                  * to read PHY values until we are out.
373                                  */
374                                 DBG_VERBOSE(et131x_dbginfo,
375                                             "Device is in COMA mode, "
376                                             "need to wake up\n");
377                                 DisablePhyComa(pAdapter);
378                         }
379
380                         /* Read the PHY ISR to clear the reason for the
381                          * interrupt.
382                          */
383                         MiRead(pAdapter, (uint8_t) offsetof(MI_REGS_t, isr),
384                                &myIsr.value);
385
386                         if (!pAdapter->ReplicaPhyLoopbk) {
387                                 MiRead(pAdapter,
388                                        (uint8_t) offsetof(MI_REGS_t, bmsr),
389                                        &BmsrData.value);
390
391                                 BmsrInts.value =
392                                     pAdapter->Bmsr.value ^ BmsrData.value;
393                                 pAdapter->Bmsr.value = BmsrData.value;
394
395                                 DBG_VERBOSE(et131x_dbginfo,
396                                             "Bmsr.value = 0x%04x,"
397                                             "Bmsr_ints.value = 0x%04x\n",
398                                             BmsrData.value, BmsrInts.value);
399
400                                 /* Do all the cable in / cable out stuff */
401                                 et131x_Mii_check(pAdapter, BmsrData, BmsrInts);
402                         }
403                 }
404
405                 /* Let's move on to the TxMac */
406                 if (GlobStatus.bits.txmac_interrupt) {
407                         pAdapter->TxRing.TxMacErr.value =
408                                 readl(&iomem->txmac.err.value);
409
410                         /*
411                          * When any of the errors occur and TXMAC generates
412                          * an interrupt to report these errors, it usually
413                          * means that TXMAC has detected an error in the data
414                          * stream retrieved from the on-chip Tx Q. All of
415                          * these errors are catastrophic and TXMAC won't be
416                          * able to recover data when these errors occur.  In
417                          * a nutshell, the whole Tx path will have to be reset
418                          * and re-configured afterwards.
419                          */
420                         DBG_WARNING(et131x_dbginfo,
421                                     "TXMAC interrupt, error 0x%08x\n",
422                                     pAdapter->TxRing.TxMacErr.value);
423
424                         /* If we are debugging, we want to see this error,
425                          * otherwise we just want the device to be reset and
426                          * continue
427                          */
428                         //DBG_TRAP();
429                 }
430
431                 /* Handle RXMAC Interrupt */
432                 if (GlobStatus.bits.rxmac_interrupt) {
433                         /*
434                          * These interrupts are catastrophic to the device,
435                          * what we need to do is disable the interrupts and
436                          * set the flag to cause us to reset so we can solve
437                          * this issue.
438                          */
439                         // MP_SET_FLAG( pAdapter, fMP_ADAPTER_HARDWARE_ERROR );
440
441                         DBG_WARNING(et131x_dbginfo,
442                                     "RXMAC interrupt, error 0x%08x.  Requesting reset\n",
443                                     readl(&iomem->rxmac.err_reg.value));
444
445                         DBG_WARNING(et131x_dbginfo,
446                                     "Enable 0x%08x, Diag 0x%08x\n",
447                                     readl(&iomem->rxmac.ctrl.value),
448                                     readl(&iomem->rxmac.rxq_diag.value));
449
450                         /*
451                          * If we are debugging, we want to see this error,
452                          * otherwise we just want the device to be reset and
453                          * continue
454                          */
455                         // TRAP();
456                 }
457
458                 /* Handle MAC_STAT Interrupt */
459                 if (GlobStatus.bits.mac_stat_interrupt) {
460                         /*
461                          * This means at least one of the un-masked counters
462                          * in the MAC_STAT block has rolled over.  Use this
463                          * to maintain the top, software managed bits of the
464                          * counter(s).
465                          */
466                         DBG_VERBOSE(et131x_dbginfo, "MAC_STAT interrupt\n");
467                         HandleMacStatInterrupt(pAdapter);
468                 }
469
470                 /* Handle SLV Timeout Interrupt */
471                 if (GlobStatus.bits.slv_timeout) {
472                         /*
473                          * This means a timeout has occured on a read or
474                          * write request to one of the JAGCore registers. The
475                          * Global Resources block has terminated the request
476                          * and on a read request, returned a "fake" value.
477                          * The most likely reasons are: Bad Address or the
478                          * addressed module is in a power-down state and
479                          * can't respond.
480                          */
481                         DBG_VERBOSE(et131x_dbginfo, "SLV_TIMEOUT interrupt\n");
482                 }
483         }
484
485         if (pAdapter->PoMgmt.PowerState == NdisDeviceStateD0) {
486                 et131x_enable_interrupts(pAdapter);
487         }
488 }