[PATCH 14/30] net: eepro100: Add cache management
Ramon Fried
rfried.dev at gmail.com
Sat May 23 19:18:05 CEST 2020
On Sat, May 23, 2020 at 7:43 PM Marek Vasut <marek.vasut at gmail.com> wrote:
>
> Add cache invalidation and flushes wherever the DMA descriptors are
> written or read, otherwise this driver cannot work reliably on any
> systems where caches are enabled.
>
> Signed-off-by: Marek Vasut <marek.vasut+renesas at gmail.com>
> ---
> drivers/net/eepro100.c | 65 +++++++++++++++++++++++++++++-------------
> 1 file changed, 45 insertions(+), 20 deletions(-)
>
> diff --git a/drivers/net/eepro100.c b/drivers/net/eepro100.c
> index 03ba9a41a5..89bfcfba0a 100644
> --- a/drivers/net/eepro100.c
> +++ b/drivers/net/eepro100.c
> @@ -5,6 +5,7 @@
> */
>
> #include <common.h>
> +#include <cpu_func.h>
> #include <malloc.h>
> #include <net.h>
> #include <netdev.h>
> @@ -459,6 +460,9 @@ static int eepro100_txcmd_send(struct eth_device *dev,
> u16 rstat;
> int i = 0;
>
> + flush_dcache_range((unsigned long)desc,
> + (unsigned long)desc + sizeof(*desc));
> +
> if (!wait_for_eepro100(dev))
> return -ETIMEDOUT;
>
> @@ -466,6 +470,8 @@ static int eepro100_txcmd_send(struct eth_device *dev,
> OUTW(dev, SCB_M | CU_START, SCB_CMD);
>
> while (true) {
> + invalidate_dcache_range((unsigned long)desc,
> + (unsigned long)desc + sizeof(*desc));
> rstat = le16_to_cpu(desc->status);
> if (rstat & CONFIG_SYS_STATUS_C)
> break;
> @@ -476,6 +482,8 @@ static int eepro100_txcmd_send(struct eth_device *dev,
> }
> }
>
> + invalidate_dcache_range((unsigned long)desc,
> + (unsigned long)desc + sizeof(*desc));
> rstat = le16_to_cpu(desc->status);
>
> if (!(rstat & CONFIG_SYS_STATUS_OK)) {
> @@ -523,6 +531,7 @@ static int eepro100_init(struct eth_device *dev, bd_t *bis)
> goto done;
> }
>
> + /* RX ring cache was already flushed in init_rx_ring() */
> OUTL(dev, phys_to_bus((u32)&rx_ring[rx_next]), SCB_POINTER);
> OUTW(dev, SCB_M | RUC_START, SCB_CMD);
>
> @@ -573,6 +582,7 @@ done:
>
> static int eepro100_send(struct eth_device *dev, void *packet, int length)
> {
> + struct eepro100_txfd *desc;
> int ret, status = -1;
> int tx_cur;
>
> @@ -584,17 +594,15 @@ static int eepro100_send(struct eth_device *dev, void *packet, int length)
> tx_cur = tx_next;
> tx_next = (tx_next + 1) % NUM_TX_DESC;
>
> - tx_ring[tx_cur].command = cpu_to_le16(TXCB_CMD_TRANSMIT | TXCB_CMD_SF |
> - TXCB_CMD_S | TXCB_CMD_EL);
> - tx_ring[tx_cur].status = 0;
> - tx_ring[tx_cur].count = cpu_to_le32 (tx_threshold);
> - tx_ring[tx_cur].link =
> - cpu_to_le32 (phys_to_bus((u32)&tx_ring[tx_next]));
> - tx_ring[tx_cur].tx_desc_addr =
> - cpu_to_le32 (phys_to_bus((u32)&tx_ring[tx_cur].tx_buf_addr0));
> - tx_ring[tx_cur].tx_buf_addr0 =
> - cpu_to_le32 (phys_to_bus((u_long)packet));
> - tx_ring[tx_cur].tx_buf_size0 = cpu_to_le32 (length);
> + desc = &tx_ring[tx_cur];
> + desc->command = cpu_to_le16(TXCB_CMD_TRANSMIT | TXCB_CMD_SF |
> + TXCB_CMD_S | TXCB_CMD_EL);
> + desc->status = 0;
> + desc->count = cpu_to_le32(tx_threshold);
> + desc->link = cpu_to_le32(phys_to_bus((u32)&tx_ring[tx_next]));
> + desc->tx_desc_addr = cpu_to_le32(phys_to_bus((u32)&desc->tx_buf_addr0));
> + desc->tx_buf_addr0 = cpu_to_le32(phys_to_bus((u_long)packet));
> + desc->tx_buf_size0 = cpu_to_le32(length);
>
> ret = eepro100_txcmd_send(dev, &tx_ring[tx_cur]);
> if (ret) {
> @@ -612,14 +620,18 @@ done:
>
> static int eepro100_recv(struct eth_device *dev)
> {
> - u16 status, stat;
> + struct eepro100_rxfd *desc;
> int rx_prev, length = 0;
> + u16 status, stat;
>
> stat = INW(dev, SCB_STATUS);
> OUTW(dev, stat & SCB_STATUS_RNR, SCB_STATUS);
>
> for (;;) {
> - status = le16_to_cpu(rx_ring[rx_next].status);
> + desc = &rx_ring[rx_next];
> + invalidate_dcache_range((unsigned long)desc,
> + (unsigned long)desc + sizeof(*desc));
> + status = le16_to_cpu(desc->status);
>
> if (!(status & RFD_STATUS_C))
> break;
> @@ -627,22 +639,26 @@ static int eepro100_recv(struct eth_device *dev)
> /* Valid frame status. */
> if ((status & RFD_STATUS_OK)) {
> /* A valid frame received. */
> - length = le32_to_cpu(rx_ring[rx_next].count) & 0x3fff;
> + length = le32_to_cpu(desc->count) & 0x3fff;
>
> /* Pass the packet up to the protocol layers. */
> - net_process_received_packet((u8 *)rx_ring[rx_next].data,
> - length);
> + net_process_received_packet((u8 *)desc->data, length);
> } else {
> /* There was an error. */
> printf("RX error status = 0x%08X\n", status);
> }
>
> - rx_ring[rx_next].control = cpu_to_le16 (RFD_CONTROL_S);
> - rx_ring[rx_next].status = 0;
> - rx_ring[rx_next].count = cpu_to_le32 (PKTSIZE_ALIGN << 16);
> + desc->control = cpu_to_le16(RFD_CONTROL_S);
> + desc->status = 0;
> + desc->count = cpu_to_le32(PKTSIZE_ALIGN << 16);
> + flush_dcache_range((unsigned long)desc,
> + (unsigned long)desc + sizeof(*desc));
>
> rx_prev = (rx_next + NUM_RX_DESC - 1) % NUM_RX_DESC;
> - rx_ring[rx_prev].control = 0;
> + desc = &rx_ring[rx_prev];
> + desc->control = 0;
> + flush_dcache_range((unsigned long)desc,
> + (unsigned long)desc + sizeof(*desc));
>
> /* Update entry information. */
> rx_next = (rx_next + 1) % NUM_RX_DESC;
> @@ -659,6 +675,7 @@ static int eepro100_recv(struct eth_device *dev)
> goto done;
> }
>
> + /* RX ring cache was already flushed in init_rx_ring() */
> OUTL(dev, phys_to_bus((u32)&rx_ring[rx_next]), SCB_POINTER);
> OUTW(dev, SCB_M | RUC_START, SCB_CMD);
> }
> @@ -744,6 +761,10 @@ static void init_rx_ring(struct eth_device *dev)
> rx_ring[i].count = cpu_to_le32(PKTSIZE_ALIGN << 16);
> }
>
> + flush_dcache_range((unsigned long)rx_ring,
> + (unsigned long)rx_ring +
> + (sizeof(*rx_ring) * NUM_RX_DESC));
> +
> rx_next = 0;
> }
>
> @@ -752,6 +773,10 @@ static void purge_tx_ring(struct eth_device *dev)
> tx_next = 0;
> tx_threshold = 0x01208000;
> memset(tx_ring, 0, sizeof(*tx_ring) * NUM_TX_DESC);
> +
> + flush_dcache_range((unsigned long)tx_ring,
> + (unsigned long)tx_ring +
> + (sizeof(*tx_ring) * NUM_TX_DESC));
> }
>
> static void read_hw_addr(struct eth_device *dev, bd_t *bis)
> --
> 2.25.1
>
Reviewed-By: Ramon Fried <rfried.dev at gmail.com>
More information about the U-Boot
mailing list