aboutsummaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorMarek Vasut2020-03-25 18:47:10 +0100
committerMarek Vasut2020-05-22 19:46:45 +0200
commit9c9f3fc162ecbe1295ddf249e288a5a4739f5e07 (patch)
tree8f6838c4cf90aa5ac9be2dfc0395bb5eed0c767e /drivers
parentf725912624878faf7c552dd686425e0e14e75a8b (diff)
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 <marex@denx.de> Cc: Eugen Hristev <eugen.hristev@microchip.com> Cc: Joe Hershberger <joe.hershberger@ni.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/ks8851_mll.c65
1 files changed, 36 insertions, 29 deletions
diff --git a/drivers/net/ks8851_mll.c b/drivers/net/ks8851_mll.c
index 2d41e5b9c7c..2424e4297e4 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)