mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-11-26 14:40:41 +00:00
net: dm9000: 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. Reviewed-by: Ramon Fried <rfried.dev@gmail.com> Signed-off-by: Marek Vasut <marex@denx.de> Cc: Joe Hershberger <joe.hershberger@ni.com> Cc: Ramon Fried <rfried.dev@gmail.com>
This commit is contained in:
parent
85a7260186
commit
84bf20f6ce
1 changed files with 50 additions and 52 deletions
|
@ -481,10 +481,9 @@ static void dm9000_halt_common(struct dm9000_priv *db)
|
|||
/*
|
||||
* Received a packet and pass to upper layer
|
||||
*/
|
||||
static int dm9000_recv_common(struct dm9000_priv *db)
|
||||
static int dm9000_recv_common(struct dm9000_priv *db, uchar *rdptr)
|
||||
{
|
||||
u8 rxbyte;
|
||||
u8 *rdptr = (u8 *)net_rx_packets[0];
|
||||
u16 rxstatus, rxlen = 0;
|
||||
|
||||
/*
|
||||
|
@ -497,58 +496,52 @@ static int dm9000_recv_common(struct dm9000_priv *db)
|
|||
dm9000_iow(db, DM9000_ISR, 0x01); /* clear PR status latched in bit 0 */
|
||||
|
||||
/* There is _at least_ 1 package in the fifo, read them all */
|
||||
for (;;) {
|
||||
dm9000_ior(db, DM9000_MRCMDX); /* Dummy read */
|
||||
dm9000_ior(db, DM9000_MRCMDX); /* Dummy read */
|
||||
|
||||
/*
|
||||
* Get most updated data,
|
||||
* only look at bits 0:1, See application notes DM9000
|
||||
*/
|
||||
rxbyte = dm9000_inb(db->base_data) & 0x03;
|
||||
/*
|
||||
* Get most updated data,
|
||||
* only look at bits 0:1, See application notes DM9000
|
||||
*/
|
||||
rxbyte = dm9000_inb(db->base_data) & 0x03;
|
||||
|
||||
/* Status check: this byte must be 0 or 1 */
|
||||
if (rxbyte > DM9000_PKT_RDY) {
|
||||
dm9000_iow(db, DM9000_RCR, 0x00); /* Stop Device */
|
||||
dm9000_iow(db, DM9000_ISR, 0x80); /* Stop INT request */
|
||||
printf("DM9000 error: status check fail: 0x%x\n",
|
||||
rxbyte);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (rxbyte != DM9000_PKT_RDY)
|
||||
return 0; /* No packet received, ignore */
|
||||
|
||||
debug("receiving packet\n");
|
||||
|
||||
/* A packet ready now & Get status/length */
|
||||
db->rx_status(db, &rxstatus, &rxlen);
|
||||
|
||||
debug("rx status: 0x%04x rx len: %d\n", rxstatus, rxlen);
|
||||
|
||||
/* Move data from DM9000 */
|
||||
/* Read received packet from RX SRAM */
|
||||
db->inblk(db, rdptr, rxlen);
|
||||
|
||||
if (rxstatus & 0xbf00 || rxlen < 0x40 ||
|
||||
rxlen > DM9000_PKT_MAX) {
|
||||
if (rxstatus & 0x100)
|
||||
printf("rx fifo error\n");
|
||||
if (rxstatus & 0x200)
|
||||
printf("rx crc error\n");
|
||||
if (rxstatus & 0x8000)
|
||||
printf("rx length error\n");
|
||||
if (rxlen > DM9000_PKT_MAX) {
|
||||
printf("rx length too big\n");
|
||||
dm9000_reset(db);
|
||||
}
|
||||
} else {
|
||||
dm9000_dump_packet(__func__, rdptr, rxlen);
|
||||
|
||||
debug("passing packet to upper layer\n");
|
||||
net_process_received_packet(net_rx_packets[0], rxlen);
|
||||
}
|
||||
/* Status check: this byte must be 0 or 1 */
|
||||
if (rxbyte > DM9000_PKT_RDY) {
|
||||
dm9000_iow(db, DM9000_RCR, 0x00); /* Stop Device */
|
||||
dm9000_iow(db, DM9000_ISR, 0x80); /* Stop INT request */
|
||||
printf("DM9000 error: status check fail: 0x%x\n",
|
||||
rxbyte);
|
||||
return -EINVAL;
|
||||
}
|
||||
return 0;
|
||||
|
||||
if (rxbyte != DM9000_PKT_RDY)
|
||||
return 0; /* No packet received, ignore */
|
||||
|
||||
debug("receiving packet\n");
|
||||
|
||||
/* A packet ready now & Get status/length */
|
||||
db->rx_status(db, &rxstatus, &rxlen);
|
||||
|
||||
debug("rx status: 0x%04x rx len: %d\n", rxstatus, rxlen);
|
||||
|
||||
/* Move data from DM9000 */
|
||||
/* Read received packet from RX SRAM */
|
||||
db->inblk(db, rdptr, rxlen);
|
||||
|
||||
if (rxstatus & 0xbf00 || rxlen < 0x40 || rxlen > DM9000_PKT_MAX) {
|
||||
if (rxstatus & 0x100)
|
||||
printf("rx fifo error\n");
|
||||
if (rxstatus & 0x200)
|
||||
printf("rx crc error\n");
|
||||
if (rxstatus & 0x8000)
|
||||
printf("rx length error\n");
|
||||
if (rxlen > DM9000_PKT_MAX) {
|
||||
printf("rx length too big\n");
|
||||
dm9000_reset(db);
|
||||
}
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return rxlen;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -600,8 +593,13 @@ static int dm9000_send(struct eth_device *dev, void *packet, int length)
|
|||
static int dm9000_recv(struct eth_device *dev)
|
||||
{
|
||||
struct dm9000_priv *db = container_of(dev, struct dm9000_priv, dev);
|
||||
int ret;
|
||||
|
||||
return dm9000_recv_common(db);
|
||||
ret = dm9000_recv_common(db, net_rx_packets[0]);
|
||||
if (ret > 0)
|
||||
net_process_received_packet(net_rx_packets[0], ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int dm9000_initialize(struct bd_info *bis)
|
||||
|
|
Loading…
Reference in a new issue