[PATCH 4/4] net: e1000: make use of multiple rx packets
Christian Gmeiner
christian.gmeiner at gmail.com
Fri Mar 3 21:48:44 CET 2023
When facing a very busy network, the single rx packet
buffer was oftentimes overwritten before a desired
response packet (e.g. a Ping reply) could have been
processed. This change improves resistance to this
by utilising multiple buffers.
Signed-off-by: Christian Gmeiner <christian.gmeiner at gmail.com>
---
drivers/net/e1000.c | 30 ++++++++++++++++++++++--------
drivers/net/e1000.h | 2 +-
2 files changed, 23 insertions(+), 9 deletions(-)
diff --git a/drivers/net/e1000.c b/drivers/net/e1000.c
index ea9ca76917..86300898af 100644
--- a/drivers/net/e1000.c
+++ b/drivers/net/e1000.c
@@ -5086,7 +5086,7 @@ e1000_sw_init(struct e1000_hw *hw)
void
fill_rx(struct e1000_hw *hw)
{
- unsigned char *packet = hw->rx_packet;
+ unsigned char *packet = hw->rx_packet[hw->rx_tail];
struct e1000_rx_desc *rd;
unsigned long flush_start, flush_end;
@@ -5284,6 +5284,9 @@ e1000_configure_rx(struct e1000_hw *hw)
mdelay(20);
}
+ for (int i = 0; i < NUM_RX_DESC; i++)
+ memset(&hw->rx_base[i], 0, 16);
+
E1000_WRITE_REG(hw, RCTL, rctl);
fill_rx(hw);
@@ -5295,9 +5298,9 @@ POLL - Wait for a frame
static int
_e1000_poll(struct e1000_hw *hw)
{
- unsigned char *packet = hw->rx_packet;
struct e1000_rx_desc *rd;
unsigned long inval_start, inval_end;
+ unsigned char *packet;
uint32_t len;
/* return true if there's an ethernet packet ready to read */
@@ -5310,6 +5313,9 @@ _e1000_poll(struct e1000_hw *hw)
if (!(rd->status & E1000_RXD_STAT_DD))
return 0;
+
+ packet = (unsigned char *)rd->buffer_addr;
+
/* DEBUGOUT("recv: packet len=%d\n", rd->length); */
/* Packet received, make sure the data are re-loaded from RAM. */
len = le16_to_cpu(rd->length);
@@ -5403,8 +5409,8 @@ _e1000_init(struct e1000_hw *hw, unsigned char enetaddr[6])
return ret_val;
}
e1000_configure_tx(hw);
- e1000_setup_rctl(hw);
e1000_configure_rx(hw);
+ e1000_setup_rctl(hw);
return 0;
}
@@ -5474,12 +5480,14 @@ static int e1000_init_one(struct e1000_hw *hw, int cardnum,
}
hw->rx_base = e1000_alloc(NUM_RX_DESC * sizeof(struct e1000_rx_desc));
- hw->rx_packet = e1000_alloc(4096);
- if (!hw->rx_base || !hw->rx_packet) {
- free(hw->rx_base);
- free(hw->rx_packet);
+ if (!hw->rx_base)
return -ENOMEM;
+
+ for (int i = 0; i < NUM_RX_DESC; i++) {
+ hw->rx_packet[i] = e1000_alloc(4096);
+ if (!hw->rx_packet[i])
+ goto out_alloc_fail;
}
/* Are these variables needed? */
@@ -5529,6 +5537,12 @@ static int e1000_init_one(struct e1000_hw *hw, int cardnum,
#endif
return 0;
+
+out_alloc_fail:
+ for (int i = 0; i < NUM_RX_DESC; i++)
+ free(hw->rx_packet[i]);
+
+ return -ENOMEM;
}
/* Put the name of a device in a string */
@@ -5676,7 +5690,7 @@ static int e1000_eth_recv(struct udevice *dev, int flags, uchar **packetp)
len = _e1000_poll(hw);
if (len)
- *packetp = hw->rx_packet;
+ *packetp = hw->rx_packet[hw->rx_last];
return len ? len : -EAGAIN;
}
diff --git a/drivers/net/e1000.h b/drivers/net/e1000.h
index f83e3a0b33..be3fce4bb6 100644
--- a/drivers/net/e1000.h
+++ b/drivers/net/e1000.h
@@ -1136,7 +1136,7 @@ struct e1000_hw {
e1000_dsp_config dsp_config_state;
struct e1000_rx_desc *rx_base;
- unsigned char *rx_packet;
+ unsigned char *rx_packet[NUM_RX_DESC];
int rx_tail;
int rx_last;
};
--
2.39.2
More information about the U-Boot
mailing list