
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 marex@denx.de Cc: Eugen Hristev eugen.hristev@microchip.com Cc: Joe Hershberger joe.hershberger@ni.com --- drivers/net/ks8851_mll.c | 65 ++++++++++++++++++++++------------------ 1 file changed, 36 insertions(+), 29 deletions(-)
diff --git a/drivers/net/ks8851_mll.c b/drivers/net/ks8851_mll.c index d70f0a4dc2..5a566d1c66 100644 --- a/drivers/net/ks8851_mll.c +++ b/drivers/net/ks8851_mll.c @@ -30,6 +30,7 @@ struct ks_net { phys_addr_t iobase; int bus_width; u16 sharedbus; + u16 rxfc; u8 extra_byte; };
@@ -223,33 +224,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; }
/* @@ -405,6 +404,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);
@@ -464,16 +465,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); @@ -482,7 +484,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]) @@ -522,8 +524,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)