From 9c9f3fc162ecbe1295ddf249e288a5a4739f5e07 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Wed, 25 Mar 2020 18:47:10 +0100 Subject: net: ks8851: Receive one packet per recv call Instead of reading out the entire FIFO and possibly overwriting U-Boot memory, read out one packet per recv call, pass it to U-Boot network stack, and repeat. It is however necessary to cache RXFC value, because reading that one out clears it. Signed-off-by: Marek Vasut Cc: Eugen Hristev Cc: Joe Hershberger --- drivers/net/ks8851_mll.c | 65 +++++++++++++++++++++++++++--------------------- 1 file changed, 36 insertions(+), 29 deletions(-) (limited to 'drivers/net/ks8851_mll.c') diff --git a/drivers/net/ks8851_mll.c b/drivers/net/ks8851_mll.c index 2d41e5b9c7..2424e4297e 100644 --- a/drivers/net/ks8851_mll.c +++ b/drivers/net/ks8851_mll.c @@ -32,6 +32,7 @@ struct ks_net { phys_addr_t iobase; int bus_width; u16 sharedbus; + u16 rxfc; u8 extra_byte; }; @@ -225,33 +226,31 @@ static inline void ks_read_qmu(struct ks_net *ks, u16 *buf, u32 len) ks_wrreg16(ks, KS_RXQCR, RXQCR_CMD_CNTL); } -static void ks_rcv(struct ks_net *ks, uchar **pv_data) +static int ks_rcv(struct ks_net *ks, uchar *data) { - unsigned int frame_cnt; u16 sts, len; - int i; - - frame_cnt = ks_rdreg16(ks, KS_RXFCTR) >> 8; - - /* read all header information */ - for (i = 0; i < frame_cnt; i++) { - /* Checking Received packet status */ - sts = ks_rdreg16(ks, KS_RXFHSR); - /* Get packet len from hardware */ - len = ks_rdreg16(ks, KS_RXFHBCR); - - if ((sts & RXFSHR_RXFV) && len && (len < RX_BUF_SIZE)) { - /* read data block including CRC 4 bytes */ - ks_read_qmu(ks, (u16 *)(*pv_data), len); - - /* net_rx_packets buffer size is ok (*pv_data) */ - net_process_received_packet(*pv_data, len); - pv_data++; - } else { - ks_wrreg16(ks, KS_RXQCR, RXQCR_CMD_CNTL | RXQCR_RRXEF); - printf(DRIVERNAME ": bad packet\n"); - } + + if (!ks->rxfc) + ks->rxfc = ks_rdreg16(ks, KS_RXFCTR) >> 8; + + if (!ks->rxfc) + return 0; + + /* Checking Received packet status */ + sts = ks_rdreg16(ks, KS_RXFHSR); + /* Get packet len from hardware */ + len = ks_rdreg16(ks, KS_RXFHBCR); + + if ((sts & RXFSHR_RXFV) && len && (len < RX_BUF_SIZE)) { + /* read data block including CRC 4 bytes */ + ks_read_qmu(ks, (u16 *)data, len); + ks->rxfc--; + return len - 4; } + + ks_wrreg16(ks, KS_RXQCR, RXQCR_CMD_CNTL | RXQCR_RRXEF); + printf(DRIVERNAME ": bad packet\n"); + return 0; } /* @@ -407,6 +406,8 @@ static int ks8851_mll_init_common(struct ks_net *ks) /* Configure the PHY, initialize the link state */ ks8851_mll_phy_configure(ks); + ks->rxfc = 0; + /* Turn on Tx + Rx */ ks8851_mll_enable(ks); @@ -466,16 +467,17 @@ static void ks8851_mll_halt_common(struct ks_net *ks) * needs to be enough to prevent a packet being discarded while * we are processing the previous one. */ -static int ks8851_mll_recv_common(struct ks_net *ks, uchar **data) +static int ks8851_mll_recv_common(struct ks_net *ks, uchar *data) { u16 status; + int ret = 0; status = ks_rdreg16(ks, KS_ISR); ks_wrreg16(ks, KS_ISR, status); - if (status & IRQ_RXI) - ks_rcv(ks, data); + if (ks->rxfc || (status & IRQ_RXI)) + ret = ks_rcv(ks, data); if (status & IRQ_LDI) { u16 pmecr = ks_rdreg16(ks, KS_PMECR); @@ -484,7 +486,7 @@ static int ks8851_mll_recv_common(struct ks_net *ks, uchar **data) ks_wrreg16(ks, KS_PMECR, pmecr | PMECR_WKEVT_LINK); } - return 0; + return ret; } static void ks8851_mll_write_hwaddr_common(struct ks_net *ks, u8 enetaddr[6]) @@ -524,8 +526,13 @@ static int ks8851_mll_send(struct eth_device *dev, void *packet, int length) static int ks8851_mll_recv(struct eth_device *dev) { struct ks_net *ks = container_of(dev, struct ks_net, dev); + int ret; + + ret = ks8851_mll_recv_common(ks, net_rx_packets[0]); + if (ret) + net_process_received_packet(net_rx_packets[0], ret); - return ks8851_mll_recv_common(ks, (uchar **)net_rx_packets); + return ret; } static int ks8851_mll_write_hwaddr(struct eth_device *dev) -- cgit v1.2.1