Skip to content

Commit 10cbd64

Browse files
ozbenhdavem330
authored andcommitted
ftgmac100: Rework NAPI & interrupts handling
First, don't look at the interrupt status in the poll loop to decide what to poll. It's wrong. If we have run out of budget, we may still have RX packets to unqueue but no more RX interrupt pending. So instead move the code looking at the interrupt status into the interrupt handler where it belongs. That avoids a slow MMIO read in the NAPI fast path. We keep the abnormal interrupts enabled while NAPI is scheduled. While at it, actually do something useful in the "error" cases: On AHB bus error, trigger the new reset task, that's about all we can do. On RX packet fifo or descriptor overflows, we need to restart the MAC after having freed things up. So set a flag that NAPI will see and use to perform that restart after harvesting the RX ring. Finally, we shouldn't complete NAPI if there are still outgoing packets that will need harvesting. Waiting for more interrupts is less efficient than letting NAPI run a while longer while the queue drains. Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 9b86785 commit 10cbd64

File tree

2 files changed

+90
-61
lines changed

2 files changed

+90
-61
lines changed

drivers/net/ethernet/faraday/ftgmac100.c

Lines changed: 76 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -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

9191
static 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

10591098
static 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);

drivers/net/ethernet/faraday/ftgmac100.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,20 @@
8686
#define FTGMAC100_INT_PHYSTS_CHG (1 << 9)
8787
#define FTGMAC100_INT_NO_HPTXBUF (1 << 10)
8888

89+
/* Interrupts we care about in NAPI mode */
90+
#define FTGMAC100_INT_BAD (FTGMAC100_INT_RPKT_LOST | \
91+
FTGMAC100_INT_XPKT_LOST | \
92+
FTGMAC100_INT_AHB_ERR | \
93+
FTGMAC100_INT_NO_RXBUF)
94+
95+
/* Normal RX/TX interrupts, enabled when NAPI off */
96+
#define FTGMAC100_INT_RXTX (FTGMAC100_INT_XPKT_ETH | \
97+
FTGMAC100_INT_RPKT_BUF)
98+
99+
/* All the interrupts we care about */
100+
#define FTGMAC100_INT_ALL (FTGMAC100_INT_RPKT_BUF | \
101+
FTGMAC100_INT_BAD)
102+
89103
/*
90104
* Interrupt timer control register
91105
*/

0 commit comments

Comments
 (0)