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
|
* 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 rxbyte;
|
||||||
u8 *rdptr = (u8 *)net_rx_packets[0];
|
|
||||||
u16 rxstatus, rxlen = 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 */
|
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 */
|
/* 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,
|
* Get most updated data,
|
||||||
* only look at bits 0:1, See application notes DM9000
|
* only look at bits 0:1, See application notes DM9000
|
||||||
*/
|
*/
|
||||||
rxbyte = dm9000_inb(db->base_data) & 0x03;
|
rxbyte = dm9000_inb(db->base_data) & 0x03;
|
||||||
|
|
||||||
/* Status check: this byte must be 0 or 1 */
|
/* Status check: this byte must be 0 or 1 */
|
||||||
if (rxbyte > DM9000_PKT_RDY) {
|
if (rxbyte > DM9000_PKT_RDY) {
|
||||||
dm9000_iow(db, DM9000_RCR, 0x00); /* Stop Device */
|
dm9000_iow(db, DM9000_RCR, 0x00); /* Stop Device */
|
||||||
dm9000_iow(db, DM9000_ISR, 0x80); /* Stop INT request */
|
dm9000_iow(db, DM9000_ISR, 0x80); /* Stop INT request */
|
||||||
printf("DM9000 error: status check fail: 0x%x\n",
|
printf("DM9000 error: status check fail: 0x%x\n",
|
||||||
rxbyte);
|
rxbyte);
|
||||||
return 0;
|
return -EINVAL;
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
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)
|
static int dm9000_recv(struct eth_device *dev)
|
||||||
{
|
{
|
||||||
struct dm9000_priv *db = container_of(dev, struct dm9000_priv, 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)
|
int dm9000_initialize(struct bd_info *bis)
|
||||||
|
|
Loading…
Reference in a new issue