@@ -85,7 +85,7 @@ struct ftgmac100 {
8585 bool use_ncsi ;
8686
8787 /* Misc */
88- int int_mask_all ;
88+ bool need_mac_restart ;
8989};
9090
9191static int ftgmac100_alloc_rx_page (struct ftgmac100 * priv ,
@@ -1048,79 +1048,101 @@ static irqreturn_t ftgmac100_interrupt(int irq, void *dev_id)
10481048{
10491049 struct net_device * netdev = dev_id ;
10501050 struct ftgmac100 * priv = netdev_priv (netdev );
1051+ unsigned int status , new_mask = FTGMAC100_INT_BAD ;
10511052
1052- /* Disable interrupts for polling */
1053- iowrite32 (0 , priv -> base + FTGMAC100_OFFSET_IER );
1054- napi_schedule (& priv -> napi );
1053+ /* Fetch and clear interrupt bits, process abnormal ones */
1054+ status = ioread32 (priv -> base + FTGMAC100_OFFSET_ISR );
1055+ iowrite32 (status , priv -> base + FTGMAC100_OFFSET_ISR );
1056+ if (unlikely (status & FTGMAC100_INT_BAD )) {
1057+
1058+ /* RX buffer unavailable */
1059+ if (status & FTGMAC100_INT_NO_RXBUF )
1060+ netdev -> stats .rx_over_errors ++ ;
1061+
1062+ /* received packet lost due to RX FIFO full */
1063+ if (status & FTGMAC100_INT_RPKT_LOST )
1064+ netdev -> stats .rx_fifo_errors ++ ;
1065+
1066+ /* sent packet lost due to excessive TX collision */
1067+ if (status & FTGMAC100_INT_XPKT_LOST )
1068+ netdev -> stats .tx_fifo_errors ++ ;
1069+
1070+ /* AHB error -> Reset the chip */
1071+ if (status & FTGMAC100_INT_AHB_ERR ) {
1072+ if (net_ratelimit ())
1073+ netdev_warn (netdev ,
1074+ "AHB bus error ! Resetting chip.\n" );
1075+ iowrite32 (0 , priv -> base + FTGMAC100_OFFSET_IER );
1076+ schedule_work (& priv -> reset_task );
1077+ return IRQ_HANDLED ;
1078+ }
1079+
1080+ /* We may need to restart the MAC after such errors, delay
1081+ * this until after we have freed some Rx buffers though
1082+ */
1083+ priv -> need_mac_restart = true;
1084+
1085+ /* Disable those errors until we restart */
1086+ new_mask &= ~status ;
1087+ }
1088+
1089+ /* Only enable "bad" interrupts while NAPI is on */
1090+ iowrite32 (new_mask , priv -> base + FTGMAC100_OFFSET_IER );
1091+
1092+ /* Schedule NAPI bh */
1093+ napi_schedule_irqoff (& priv -> napi );
10551094
10561095 return IRQ_HANDLED ;
10571096}
10581097
10591098static int ftgmac100_poll (struct napi_struct * napi , int budget )
10601099{
10611100 struct ftgmac100 * priv = container_of (napi , struct ftgmac100 , napi );
1062- struct net_device * netdev = priv -> netdev ;
1063- unsigned int status ;
1064- bool completed = true;
1101+ bool more , completed = true;
10651102 int rx = 0 ;
10661103
1067- status = ioread32 (priv -> base + FTGMAC100_OFFSET_ISR );
1068- iowrite32 (status , priv -> base + FTGMAC100_OFFSET_ISR );
1069-
1070- if (status & (FTGMAC100_INT_RPKT_BUF | FTGMAC100_INT_NO_RXBUF )) {
1071- /*
1072- * FTGMAC100_INT_RPKT_BUF:
1073- * RX DMA has received packets into RX buffer successfully
1074- *
1075- * FTGMAC100_INT_NO_RXBUF:
1076- * RX buffer unavailable
1077- */
1078- bool retry ;
1104+ ftgmac100_tx_complete (priv );
10791105
1080- do {
1081- retry = ftgmac100_rx_packet (priv , & rx );
1082- } while (retry && rx < budget );
1106+ do {
1107+ more = ftgmac100_rx_packet (priv , & rx );
1108+ } while (more && rx < budget );
10831109
1084- if (retry && rx == budget )
1085- completed = false;
1086- }
1110+ if (more && rx == budget )
1111+ completed = false;
10871112
1088- if (status & (FTGMAC100_INT_XPKT_ETH | FTGMAC100_INT_XPKT_LOST )) {
1089- /*
1090- * FTGMAC100_INT_XPKT_ETH:
1091- * packet transmitted to ethernet successfully
1092- *
1093- * FTGMAC100_INT_XPKT_LOST:
1094- * packet transmitted to ethernet lost due to late
1095- * collision or excessive collision
1096- */
1097- ftgmac100_tx_complete (priv );
1098- }
1099-
1100- if (status & priv -> int_mask_all & (FTGMAC100_INT_NO_RXBUF |
1101- FTGMAC100_INT_RPKT_LOST | FTGMAC100_INT_AHB_ERR )) {
1102- if (net_ratelimit ())
1103- netdev_info (netdev , "[ISR] = 0x%x: %s%s%s\n" , status ,
1104- status & FTGMAC100_INT_NO_RXBUF ? "NO_RXBUF " : "" ,
1105- status & FTGMAC100_INT_RPKT_LOST ? "RPKT_LOST " : "" ,
1106- status & FTGMAC100_INT_AHB_ERR ? "AHB_ERR " : "" );
11071113
1108- if (status & FTGMAC100_INT_NO_RXBUF ) {
1109- /* RX buffer unavailable */
1110- netdev -> stats .rx_over_errors ++ ;
1111- }
1114+ /* The interrupt is telling us to kick the MAC back to life
1115+ * after an RX overflow
1116+ */
1117+ if (unlikely (priv -> need_mac_restart )) {
1118+ ftgmac100_start_hw (priv );
11121119
1113- if (status & FTGMAC100_INT_RPKT_LOST ) {
1114- /* received packet lost due to RX FIFO full */
1115- netdev -> stats .rx_fifo_errors ++ ;
1116- }
1120+ /* Re-enable "bad" interrupts */
1121+ iowrite32 (FTGMAC100_INT_BAD ,
1122+ priv -> base + FTGMAC100_OFFSET_IER );
11171123 }
11181124
1125+ /* Keep NAPI going if we have still packets to reclaim */
1126+ if (priv -> tx_pending )
1127+ return budget ;
1128+
11191129 if (completed ) {
1130+ /* We are about to re-enable all interrupts. However
1131+ * the HW has been latching RX/TX packet interrupts while
1132+ * they were masked. So we clear them first, then we need
1133+ * to re-check if there's something to process
1134+ */
1135+ iowrite32 (FTGMAC100_INT_RXTX ,
1136+ priv -> base + FTGMAC100_OFFSET_ISR );
1137+ if (ftgmac100_rxdes_packet_ready
1138+ (ftgmac100_current_rxdes (priv )) || priv -> tx_pending )
1139+ return budget ;
1140+
1141+ /* deschedule NAPI */
11201142 napi_complete (napi );
11211143
11221144 /* enable all interrupts */
1123- iowrite32 (priv -> int_mask_all ,
1145+ iowrite32 (FTGMAC100_INT_ALL ,
11241146 priv -> base + FTGMAC100_OFFSET_IER );
11251147 }
11261148
@@ -1148,7 +1170,7 @@ static int ftgmac100_init_all(struct ftgmac100 *priv, bool ignore_alloc_err)
11481170 netif_start_queue (priv -> netdev );
11491171
11501172 /* Enable all interrupts */
1151- iowrite32 (priv -> int_mask_all , priv -> base + FTGMAC100_OFFSET_IER );
1173+ iowrite32 (FTGMAC100_INT_ALL , priv -> base + FTGMAC100_OFFSET_IER );
11521174
11531175 return err ;
11541176}
@@ -1491,13 +1513,6 @@ static int ftgmac100_probe(struct platform_device *pdev)
14911513 /* MAC address from chip or random one */
14921514 ftgmac100_setup_mac (priv );
14931515
1494- priv -> int_mask_all = (FTGMAC100_INT_RPKT_LOST |
1495- FTGMAC100_INT_XPKT_ETH |
1496- FTGMAC100_INT_XPKT_LOST |
1497- FTGMAC100_INT_AHB_ERR |
1498- FTGMAC100_INT_RPKT_BUF |
1499- FTGMAC100_INT_NO_RXBUF );
1500-
15011516 if (of_machine_is_compatible ("aspeed,ast2400" ) ||
15021517 of_machine_is_compatible ("aspeed,ast2500" )) {
15031518 priv -> rxdes0_edorr_mask = BIT (30 );
0 commit comments