📄 lmc_main.c
字号:
* - Transmit underflow CSR5<5> * - Transmit Receiver buffer unavailable CSR5<7> * - Receive process stopped CSR5<8> * - Receive watchdog timeout CSR5<9> * - Early transmit interrupt CSR5<10> * * Is this really right? Should we do a running reset for jabber? * (being a WAN card and all) */ if (csr & TULIP_STS_ABNRMLINTR){ lmc_running_reset (dev); break; } if (csr & TULIP_STS_RXINTR){ lmc_trace(dev, "rx interrupt"); lmc_rx (dev); } if (csr & (TULIP_STS_TXINTR | TULIP_STS_TXNOBUF | TULIP_STS_TXSTOPPED)) { int n_compl = 0 ; /* reset the transmit timeout detection flag -baz */ sc->stats.tx_NoCompleteCnt = 0; badtx = sc->lmc_taint_tx; i = badtx % LMC_TXDESCS; while ((badtx < sc->lmc_next_tx)) { stat = sc->lmc_txring[i].status; LMC_EVENT_LOG (LMC_EVENT_XMTINT, stat, sc->lmc_txring[i].length); /* * If bit 31 is 1 the tulip owns it break out of the loop */ if (stat & 0x80000000) break; n_compl++ ; /* i.e., have an empty slot in ring */ /* * If we have no skbuff or have cleared it * Already continue to the next buffer */ if (sc->lmc_txq[i] == NULL) continue; /* * Check the total error summary to look for any errors */ if (stat & 0x8000) { sc->stats.tx_errors++; if (stat & 0x4104) sc->stats.tx_aborted_errors++; if (stat & 0x0C00) sc->stats.tx_carrier_errors++; if (stat & 0x0200) sc->stats.tx_window_errors++; if (stat & 0x0002) sc->stats.tx_fifo_errors++; } else { sc->stats.tx_bytes += sc->lmc_txring[i].length & 0x7ff; sc->stats.tx_packets++; } // dev_kfree_skb(sc->lmc_txq[i]); dev_kfree_skb_irq(sc->lmc_txq[i]); sc->lmc_txq[i] = NULL; badtx++; i = badtx % LMC_TXDESCS; } if (sc->lmc_next_tx - badtx > LMC_TXDESCS) { printk ("%s: out of sync pointer\n", dev->name); badtx += LMC_TXDESCS; } LMC_EVENT_LOG(LMC_EVENT_TBUSY0, n_compl, 0); sc->lmc_txfull = 0; netif_wake_queue(dev); sc->stats.tx_tbusy0++ ;#ifdef DEBUG sc->stats.dirtyTx = badtx; sc->stats.lmc_next_tx = sc->lmc_next_tx; sc->stats.lmc_txfull = sc->lmc_txfull;#endif sc->lmc_taint_tx = badtx; /* * Why was there a break here??? */ } /* end handle transmit interrupt */ if (csr & TULIP_STS_SYSERROR) { u32 error; printk (KERN_WARNING "%s: system bus error csr: %#8.8x\n", dev->name, csr); error = csr>>23 & 0x7; switch(error){ case 0x000: printk(KERN_WARNING "%s: Parity Fault (bad)\n", dev->name); break; case 0x001: printk(KERN_WARNING "%s: Master Abort (naughty)\n", dev->name); break; case 0x010: printk(KERN_WARNING "%s: Target Abort (not so naughty)\n", dev->name); break; default: printk(KERN_WARNING "%s: This bus error code was supposed to be reserved!\n", dev->name); } lmc_dec_reset (sc); lmc_reset (sc); LMC_EVENT_LOG(LMC_EVENT_RESET1, LMC_CSR_READ (sc, csr_status), 0); LMC_EVENT_LOG(LMC_EVENT_RESET2, lmc_mii_readreg (sc, 0, 16), lmc_mii_readreg (sc, 0, 17)); } if(max_work-- <= 0) break; /* * Get current csr status to make sure * we've cleared all interrupts */ csr = LMC_CSR_READ (sc, csr_status); } /* end interrupt loop */ LMC_EVENT_LOG(LMC_EVENT_INT, firstcsr, csr);lmc_int_fail_out: spin_unlock(&sc->lmc_lock); lmc_trace(dev, "lmc_interrupt out"); return IRQ_RETVAL(handled);}static int lmc_start_xmit (struct sk_buff *skb, struct net_device *dev) /*fold00*/{ lmc_softc_t *sc; u32 flag; int entry; int ret = 0; unsigned long flags; lmc_trace(dev, "lmc_start_xmit in"); sc = dev->priv; spin_lock_irqsave(&sc->lmc_lock, flags); /* normal path, tbusy known to be zero */ entry = sc->lmc_next_tx % LMC_TXDESCS; sc->lmc_txq[entry] = skb; sc->lmc_txring[entry].buffer1 = virt_to_bus (skb->data); LMC_CONSOLE_LOG("xmit", skb->data, skb->len);#ifndef GCOM /* If the queue is less than half full, don't interrupt */ if (sc->lmc_next_tx - sc->lmc_taint_tx < LMC_TXDESCS / 2) { /* Do not interrupt on completion of this packet */ flag = 0x60000000; netif_wake_queue(dev); } else if (sc->lmc_next_tx - sc->lmc_taint_tx == LMC_TXDESCS / 2) { /* This generates an interrupt on completion of this packet */ flag = 0xe0000000; netif_wake_queue(dev); } else if (sc->lmc_next_tx - sc->lmc_taint_tx < LMC_TXDESCS - 1) { /* Do not interrupt on completion of this packet */ flag = 0x60000000; netif_wake_queue(dev); } else { /* This generates an interrupt on completion of this packet */ flag = 0xe0000000; sc->lmc_txfull = 1; netif_stop_queue(dev); }#else flag = LMC_TDES_INTERRUPT_ON_COMPLETION; if (sc->lmc_next_tx - sc->lmc_taint_tx >= LMC_TXDESCS - 1) { /* ring full, go busy */ sc->lmc_txfull = 1; netif_stop_queue(dev); sc->stats.tx_tbusy1++ ; LMC_EVENT_LOG(LMC_EVENT_TBUSY1, entry, 0); }#endif if (entry == LMC_TXDESCS - 1) /* last descriptor in ring */ flag |= LMC_TDES_END_OF_RING; /* flag as such for Tulip */ /* don't pad small packets either */ flag = sc->lmc_txring[entry].length = (skb->len) | flag | sc->TxDescriptControlInit; /* set the transmit timeout flag to be checked in * the watchdog timer handler. -baz */ sc->stats.tx_NoCompleteCnt++; sc->lmc_next_tx++; /* give ownership to the chip */ LMC_EVENT_LOG(LMC_EVENT_XMT, flag, entry); sc->lmc_txring[entry].status = 0x80000000; /* send now! */ LMC_CSR_WRITE (sc, csr_txpoll, 0); dev->trans_start = jiffies; spin_unlock_irqrestore(&sc->lmc_lock, flags); lmc_trace(dev, "lmc_start_xmit_out"); return ret;}static int lmc_rx (struct net_device *dev) /*fold00*/{ lmc_softc_t *sc; int i; int rx_work_limit = LMC_RXDESCS; unsigned int next_rx; int rxIntLoopCnt; /* debug -baz */ int localLengthErrCnt = 0; long stat; struct sk_buff *skb, *nsb; u16 len; lmc_trace(dev, "lmc_rx in"); sc = dev->priv; lmc_led_on(sc, LMC_DS3_LED3); rxIntLoopCnt = 0; /* debug -baz */ i = sc->lmc_next_rx % LMC_RXDESCS; next_rx = sc->lmc_next_rx; while (((stat = sc->lmc_rxring[i].status) & LMC_RDES_OWN_BIT) != DESC_OWNED_BY_DC21X4) { rxIntLoopCnt++; /* debug -baz */ len = ((stat & LMC_RDES_FRAME_LENGTH) >> RDES_FRAME_LENGTH_BIT_NUMBER); if ((stat & 0x0300) != 0x0300) { /* Check first segment and last segment */ if ((stat & 0x0000ffff) != 0x7fff) { /* Oversized frame */ sc->stats.rx_length_errors++; goto skip_packet; } } if(stat & 0x00000008){ /* Catch a dribbling bit error */ sc->stats.rx_errors++; sc->stats.rx_frame_errors++; goto skip_packet; } if(stat & 0x00000004){ /* Catch a CRC error by the Xilinx */ sc->stats.rx_errors++; sc->stats.rx_crc_errors++; goto skip_packet; } if (len > LMC_PKT_BUF_SZ){ sc->stats.rx_length_errors++; localLengthErrCnt++; goto skip_packet; } if (len < sc->lmc_crcSize + 2) { sc->stats.rx_length_errors++; sc->stats.rx_SmallPktCnt++; localLengthErrCnt++; goto skip_packet; } if(stat & 0x00004000){ printk(KERN_WARNING "%s: Receiver descriptor error, receiver out of sync?\n", dev->name); } len -= sc->lmc_crcSize; skb = sc->lmc_rxq[i]; /* * We ran out of memory at some point * just allocate an skb buff and continue. */ if(skb == 0x0){ nsb = dev_alloc_skb (LMC_PKT_BUF_SZ + 2); if (nsb) { sc->lmc_rxq[i] = nsb; nsb->dev = dev; sc->lmc_rxring[i].buffer1 = virt_to_bus (nsb->tail); } sc->failed_recv_alloc = 1; goto skip_packet; } dev->last_rx = jiffies; sc->stats.rx_packets++; sc->stats.rx_bytes += len; LMC_CONSOLE_LOG("recv", skb->data, len); /* * I'm not sure of the sanity of this * Packets could be arriving at a constant * 44.210mbits/sec and we're going to copy * them into a new buffer?? */ if(len > (LMC_MTU - (LMC_MTU>>2))){ /* len > LMC_MTU * 0.75 */ /* * If it's a large packet don't copy it just hand it up */ give_it_anyways: sc->lmc_rxq[i] = NULL; sc->lmc_rxring[i].buffer1 = 0x0; skb_put (skb, len); skb->protocol = lmc_proto_type(sc, skb); skb->protocol = htons(ETH_P_WAN_PPP); skb->mac.raw = skb->data;// skb->nh.raw = skb->data; skb->dev = dev; lmc_proto_netif(sc, skb); /* * This skb will be destroyed by the upper layers, make a new one */ nsb = dev_alloc_skb (LMC_PKT_BUF_SZ + 2); if (nsb) { sc->lmc_rxq[i] = nsb; nsb->dev = dev; sc->lmc_rxring[i].buffer1 = virt_to_bus (nsb->tail); /* Transferred to 21140 below */ } else { /* * We've run out of memory, stop trying to allocate * memory and exit the interrupt handler * * The chip may run out of receivers and stop * in which care we'll try to allocate the buffer * again. (once a second) */ sc->stats.rx_BuffAllocErr++; LMC_EVENT_LOG(LMC_EVENT_RCVINT, stat, len); sc->failed_recv_alloc = 1; goto skip_out_of_mem; } } else { nsb = dev_alloc_skb(len); if(!nsb) { goto give_it_anyways; } memcpy(skb_put(nsb, len), skb->data, len); nsb->protocol = lmc_proto_type(sc, skb); nsb->mac.raw = nsb->data;// nsb->nh.raw = nsb->data; nsb->dev = dev; lmc_proto_netif(sc, nsb); } skip_packet: LMC_EVENT_LOG(LMC_EVENT_RCVINT, stat, len); sc->lmc_rxring[i].status = DESC_OWNED_BY_DC21X4; sc->lmc_next_rx++; i = sc->lmc_next_rx % LMC_RXDESCS; rx_work_limit--; if (rx_work_limit < 0) break; } /* detect condition for LMC1000 where DSU cable attaches and fills * descriptors with bogus packets * if (localLengthErrCnt > LMC_RXDESCS - 3) { sc->stats.rx_BadPktSurgeCnt++; LMC_EVENT_LOG(LMC_EVENT_BADPKTSURGE, localLengthErrCnt, sc->stats.rx_BadPktSurgeCnt); } */ /* save max count of receive descriptors serviced */ if (rxIntLoopCnt > sc->stats.rxIntLoopCnt) { sc->stats.rxIntLoopCnt = rxIntLoopCnt; /* debug -baz */ }#ifdef DEBUG if (rxIntLoopCnt == 0) { for (i = 0; i < LMC_RXDESCS; i++) { if ((sc->lmc_rxring[i].status & LMC_RDES_OWN_BIT) != DESC_OWNED_BY_DC21X4) { rxIntLoopCnt++; } } LMC_EVENT_LOG(LMC_EVENT_RCVEND, rxIntLoopCnt, 0); }#endif lmc_led_off(sc, LMC_DS3_LED3);skip_out_of_mem: lmc_trace(dev, "lmc_rx out");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -