📄 spider_net.c
字号:
* * spider_net_handle_error_irq treats or ignores all error conditions * found when an interrupt is presented */static voidspider_net_handle_error_irq(struct spider_net_card *card, u32 status_reg){ u32 error_reg1, error_reg2; u32 i; int show_error = 1; error_reg1 = spider_net_read_reg(card, SPIDER_NET_GHIINT1STS); error_reg2 = spider_net_read_reg(card, SPIDER_NET_GHIINT2STS); error_reg1 &= SPIDER_NET_INT1_MASK_VALUE; error_reg2 &= SPIDER_NET_INT2_MASK_VALUE; /* check GHIINT0STS ************************************/ if (status_reg) for (i = 0; i < 32; i++) if (status_reg & (1<<i)) switch (i) { /* let error_reg1 and error_reg2 evaluation decide, what to do case SPIDER_NET_PHYINT: case SPIDER_NET_GMAC2INT: case SPIDER_NET_GMAC1INT: case SPIDER_NET_GFIFOINT: case SPIDER_NET_DMACINT: case SPIDER_NET_GSYSINT: break; */ case SPIDER_NET_GIPSINT: show_error = 0; break; case SPIDER_NET_GPWOPCMPINT: /* PHY write operation completed */ show_error = 0; break; case SPIDER_NET_GPROPCMPINT: /* PHY read operation completed */ /* we don't use semaphores, as we poll for the completion * of the read operation in spider_net_read_phy. Should take * about 50 us */ show_error = 0; break; case SPIDER_NET_GPWFFINT: /* PHY command queue full */ if (netif_msg_intr(card)) dev_err(&card->netdev->dev, "PHY write queue full\n"); show_error = 0; break; /* case SPIDER_NET_GRMDADRINT: not used. print a message */ /* case SPIDER_NET_GRMARPINT: not used. print a message */ /* case SPIDER_NET_GRMMPINT: not used. print a message */ case SPIDER_NET_GDTDEN0INT: /* someone has set TX_DMA_EN to 0 */ show_error = 0; break; case SPIDER_NET_GDDDEN0INT: /* fallthrough */ case SPIDER_NET_GDCDEN0INT: /* fallthrough */ case SPIDER_NET_GDBDEN0INT: /* fallthrough */ case SPIDER_NET_GDADEN0INT: /* someone has set RX_DMA_EN to 0 */ show_error = 0; break; /* RX interrupts */ case SPIDER_NET_GDDFDCINT: case SPIDER_NET_GDCFDCINT: case SPIDER_NET_GDBFDCINT: case SPIDER_NET_GDAFDCINT: /* case SPIDER_NET_GDNMINT: not used. print a message */ /* case SPIDER_NET_GCNMINT: not used. print a message */ /* case SPIDER_NET_GBNMINT: not used. print a message */ /* case SPIDER_NET_GANMINT: not used. print a message */ /* case SPIDER_NET_GRFNMINT: not used. print a message */ show_error = 0; break; /* TX interrupts */ case SPIDER_NET_GDTFDCINT: show_error = 0; break; case SPIDER_NET_GTTEDINT: show_error = 0; break; case SPIDER_NET_GDTDCEINT: /* chain end. If a descriptor should be sent, kick off * tx dma if (card->tx_chain.tail != card->tx_chain.head) spider_net_kick_tx_dma(card); */ show_error = 0; break; /* case SPIDER_NET_G1TMCNTINT: not used. print a message */ /* case SPIDER_NET_GFREECNTINT: not used. print a message */ } /* check GHIINT1STS ************************************/ if (error_reg1) for (i = 0; i < 32; i++) if (error_reg1 & (1<<i)) switch (i) { case SPIDER_NET_GTMFLLINT: /* TX RAM full may happen on a usual case. * Logging is not needed. */ show_error = 0; break; case SPIDER_NET_GRFDFLLINT: /* fallthrough */ case SPIDER_NET_GRFCFLLINT: /* fallthrough */ case SPIDER_NET_GRFBFLLINT: /* fallthrough */ case SPIDER_NET_GRFAFLLINT: /* fallthrough */ case SPIDER_NET_GRMFLLINT: /* Could happen when rx chain is full */ if (card->ignore_rx_ramfull == 0) { card->ignore_rx_ramfull = 1; spider_net_resync_head_ptr(card); spider_net_refill_rx_chain(card); spider_net_enable_rxdmac(card); card->num_rx_ints ++; netif_rx_schedule(card->netdev, &card->napi); } show_error = 0; break; /* case SPIDER_NET_GTMSHTINT: problem, print a message */ case SPIDER_NET_GDTINVDINT: /* allrighty. tx from previous descr ok */ show_error = 0; break; /* chain end */ case SPIDER_NET_GDDDCEINT: /* fallthrough */ case SPIDER_NET_GDCDCEINT: /* fallthrough */ case SPIDER_NET_GDBDCEINT: /* fallthrough */ case SPIDER_NET_GDADCEINT: spider_net_resync_head_ptr(card); spider_net_refill_rx_chain(card); spider_net_enable_rxdmac(card); card->num_rx_ints ++; netif_rx_schedule(card->netdev, &card->napi); show_error = 0; break; /* invalid descriptor */ case SPIDER_NET_GDDINVDINT: /* fallthrough */ case SPIDER_NET_GDCINVDINT: /* fallthrough */ case SPIDER_NET_GDBINVDINT: /* fallthrough */ case SPIDER_NET_GDAINVDINT: /* Could happen when rx chain is full */ spider_net_resync_head_ptr(card); spider_net_refill_rx_chain(card); spider_net_enable_rxdmac(card); card->num_rx_ints ++; netif_rx_schedule(card->netdev, &card->napi); show_error = 0; break; /* case SPIDER_NET_GDTRSERINT: problem, print a message */ /* case SPIDER_NET_GDDRSERINT: problem, print a message */ /* case SPIDER_NET_GDCRSERINT: problem, print a message */ /* case SPIDER_NET_GDBRSERINT: problem, print a message */ /* case SPIDER_NET_GDARSERINT: problem, print a message */ /* case SPIDER_NET_GDSERINT: problem, print a message */ /* case SPIDER_NET_GDTPTERINT: problem, print a message */ /* case SPIDER_NET_GDDPTERINT: problem, print a message */ /* case SPIDER_NET_GDCPTERINT: problem, print a message */ /* case SPIDER_NET_GDBPTERINT: problem, print a message */ /* case SPIDER_NET_GDAPTERINT: problem, print a message */ default: show_error = 1; break; } /* check GHIINT2STS ************************************/ if (error_reg2) for (i = 0; i < 32; i++) if (error_reg2 & (1<<i)) switch (i) { /* there is nothing we can (want to) do at this time. Log a * message, we can switch on and off the specific values later on case SPIDER_NET_GPROPERINT: case SPIDER_NET_GMCTCRSNGINT: case SPIDER_NET_GMCTLCOLINT: case SPIDER_NET_GMCTTMOTINT: case SPIDER_NET_GMCRCAERINT: case SPIDER_NET_GMCRCALERINT: case SPIDER_NET_GMCRALNERINT: case SPIDER_NET_GMCROVRINT: case SPIDER_NET_GMCRRNTINT: case SPIDER_NET_GMCRRXERINT: case SPIDER_NET_GTITCSERINT: case SPIDER_NET_GTIFMTERINT: case SPIDER_NET_GTIPKTRVKINT: case SPIDER_NET_GTISPINGINT: case SPIDER_NET_GTISADNGINT: case SPIDER_NET_GTISPDNGINT: case SPIDER_NET_GRIFMTERINT: case SPIDER_NET_GRIPKTRVKINT: case SPIDER_NET_GRISPINGINT: case SPIDER_NET_GRISADNGINT: case SPIDER_NET_GRISPDNGINT: break; */ default: break; } if ((show_error) && (netif_msg_intr(card)) && net_ratelimit()) dev_err(&card->netdev->dev, "Error interrupt, GHIINT0STS = 0x%08x, " "GHIINT1STS = 0x%08x, GHIINT2STS = 0x%08x\n", status_reg, error_reg1, error_reg2); /* clear interrupt sources */ spider_net_write_reg(card, SPIDER_NET_GHIINT1STS, error_reg1); spider_net_write_reg(card, SPIDER_NET_GHIINT2STS, error_reg2);}/** * spider_net_interrupt - interrupt handler for spider_net * @irq: interrupt number * @ptr: pointer to net_device * @regs: PU registers * * returns IRQ_HANDLED, if interrupt was for driver, or IRQ_NONE, if no * interrupt found raised by card. * * This is the interrupt handler, that turns off * interrupts for this device and makes the stack poll the driver */static irqreturn_tspider_net_interrupt(int irq, void *ptr){ struct net_device *netdev = ptr; struct spider_net_card *card = netdev_priv(netdev); u32 status_reg; status_reg = spider_net_read_reg(card, SPIDER_NET_GHIINT0STS); status_reg &= SPIDER_NET_INT0_MASK_VALUE; if (!status_reg) return IRQ_NONE; if (status_reg & SPIDER_NET_RXINT ) { spider_net_rx_irq_off(card); netif_rx_schedule(netdev, &card->napi); card->num_rx_ints ++; } if (status_reg & SPIDER_NET_TXINT) netif_rx_schedule(netdev, &card->napi); if (status_reg & SPIDER_NET_LINKINT) spider_net_link_reset(netdev); if (status_reg & SPIDER_NET_ERRINT ) spider_net_handle_error_irq(card, status_reg); /* clear interrupt sources */ spider_net_write_reg(card, SPIDER_NET_GHIINT0STS, status_reg); return IRQ_HANDLED;}#ifdef CONFIG_NET_POLL_CONTROLLER/** * spider_net_poll_controller - artificial interrupt for netconsole etc. * @netdev: interface device structure * * see Documentation/networking/netconsole.txt */static voidspider_net_poll_controller(struct net_device *netdev){ disable_irq(netdev->irq); spider_net_interrupt(netdev->irq, netdev); enable_irq(netdev->irq);}#endif /* CONFIG_NET_POLL_CONTROLLER *//** * spider_net_enable_interrupts - enable interrupts * @card: card structure * * spider_net_enable_interrupt enables several interrupts */static void spider_net_enable_interrupts(struct spider_net_card *card){ spider_net_write_reg(card, SPIDER_NET_GHIINT0MSK, SPIDER_NET_INT0_MASK_VALUE); spider_net_write_reg(card, SPIDER_NET_GHIINT1MSK, SPIDER_NET_INT1_MASK_VALUE); spider_net_write_reg(card, SPIDER_NET_GHIINT2MSK, SPIDER_NET_INT2_MASK_VALUE);}/** * spider_net_disable_interrupts - disable interrupts * @card: card structure * * spider_net_disable_interrupts disables all the interrupts */static void spider_net_disable_interrupts(struct spider_net_card *card){ spider_net_write_reg(card, SPIDER_NET_GHIINT0MSK, 0); spider_net_write_reg(card, SPIDER_NET_GHIINT1MSK, 0); spider_net_write_reg(card, SPIDER_NET_GHIINT2MSK, 0); spider_net_write_reg(card, SPIDER_NET_GMACINTEN, 0);}/** * spider_net_init_card - initializes the card * @card: card structure * * spider_net_init_card initializes the card so that other registers can * be used */static voidspider_net_init_card(struct spider_net_card *card){ spider_net_write_reg(card, SPIDER_NET_CKRCTRL, SPIDER_NET_CKRCTRL_STOP_VALUE); spider_net_write_reg(card, SPIDER_NET_CKRCTRL, SPIDER_NET_CKRCTRL_RUN_VALUE); /* trigger ETOMOD signal */ spider_net_write_reg(card, SPIDER_NET_GMACOPEMD, spider_net_read_reg(card, SPIDER_NET_GMACOPEMD) | 0x4); spider_net_disable_interrupts(card);}/** * spider_net_enable_card - enables the card by setting all kinds of regs * @card: card structure * * spider_net_enable_card sets a lot of SMMIO registers to enable the device */static voidspider_net_enable_card(struct spider_net_card *card){ int i; /* the following array consists of (register),(value) pairs * that are set in this function. A register of 0 ends the list */ u32 regs[][2] = { { SPIDER_NET_GRESUMINTNUM, 0 }, { SPIDER_NET_GREINTNUM, 0 }, /* set interrupt frame number registers */ /* clear the single DMA engine registers first */ { SPIDER_NET_GFAFRMNUM, SPIDER_NET_GFXFRAMES_VALUE }, { SPIDER_NET_GFBFRMNUM, SPIDER_NET_GFXFRAMES_VALUE }, { SPIDER_NET_GFCFRMNUM, SPIDER_NET_GFXFRAMES_VALUE }, { SPIDER_NET_GFDFRMNUM, SPIDER_NET_GFXFRAMES_VALUE }, /* then set, what we really need */ { SPIDER_NET_GFFRMNUM, SPIDER_NET_FRAMENUM_VALUE }, /* timer counter registers and stuff */ { SPIDER_NET_GFREECNNUM, 0 }, { SPIDER_NET_GONETIMENUM, 0 }, { SPIDER_NET_GTOUTFRMNUM, 0 }, /* RX mode setting */ { SPIDER_NET_GRXMDSET, SPIDER_NET_RXMODE_VALUE }, /* TX mode setting */ { SPIDER_NET_GTXMDSET, SPIDER_NET_TXMODE_VALUE }, /* IPSEC mode setting */ { SPIDER_NET_GIPSECINIT, SPIDER_NET_IPSECINIT_VALUE }, { SPIDER_NET_GFTRESTRT, SPIDER_NET_RESTART_VALUE }, { SPIDER_NET_GMRWOLCTRL, 0 }, { SPIDER_NET_GTESTMD, 0x10000000 }, { SPIDER_NET_GTTQMSK, 0x00400040 }, { SPIDER_NET_GMACINTEN, 0 }, /* flow control stuff */ { SPIDER_NET_GMACAPAUSE, SPIDER_NET_MACAPAUSE_VALUE }, { SPIDER_NET_GMACTXPAUSE, SPIDER_NET_TXPAUSE_VALUE }, { SPIDER_NET_GMACBSTLMT, SPIDER_NET_BURSTLMT_VALUE }, { 0, 0} }; i = 0; while (regs[i][0]) { spider_net_write_reg(card, regs[i][0], regs[i][1]); i++; } /* clear unicast filter table entries 1 to 14 */ for (i = 1; i <= 14; i++) { spider_net_write_reg(card, SPIDER_NET_GMRUAFILnR + i * 8, 0x00080000); spider_net_write_reg(card, SPIDER_NET_GMRUAFILnR + i * 8 + 4, 0x00000000); } spider_net_write_reg(card, SPIDER_NET_GMRUA0FIL15R, 0x08080000); spider_net_write_reg(card, SPIDER_NET_ECMODE, SPIDER_NET_ECMODE_VALUE); /* set chain tail adress for RX chains and * enable DMA */ spider_net_enable_rxchtails(card); spider_net_enable_rxdmac(card); spider_net_write_reg(card, SPIDER_NET_GRXDMAEN, SPIDER_NET_WOL_VALUE); spider_net_write_reg(card, SPIDER_NET_GMACLENLMT, SPIDER_NET_LENLMT_VALUE); spider_net_write_reg(card, SPIDER_NET_GMACOPEMD, SPIDER_NET_OPMODE_VALUE); spider_net_write_reg(card, SPIDER_NET_GDTDMACCNTR, SPIDER_NET_GDTBSTA);}/** * spider_net_download_firmware - loads firmware into the adapter * @card: card structure * @firmware_ptr: pointer to firmware data * * spider_net_download_firmware loads the firmware data into the * adapter. It assumes the length etc. to be allright. */static intspider_net_download_firmware(struct spider_net_card *card, const void *firmware_ptr){ int sequencer, i; const u32 *fw_ptr = firmware_ptr; /* stop sequencers */ spider_net_write_reg(card, SPIDER_NET_GSINIT, SPIDER_NET_STOP_SEQ_VALUE); for (sequencer = 0; sequencer < SPIDER_NET_FIRMWARE_SEQS; sequencer++) { spider_net_write_reg(card, SPIDER_NET_GSnPRGADR + sequencer * 8, 0); for (i = 0; i < SPIDER_NET_FIRMWARE_SEQWORDS; i++) { spider_net_write_reg(card, SPIDER_NET_GSnPRGDAT + sequencer * 8, *fw_ptr); fw_ptr++; } } if (spider_net_read_reg(card, SPIDER_NET_GSINIT)) return -EIO; spider_net_write_reg(card, SPIDER_NET_GSINIT, SPIDER_NET_RUN_SEQ_VALUE);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -