mirror of
https://github.com/apache/nuttx.git
synced 2026-10-10 07:40:27 +00:00
arch/mips/pic32mz: fix the Ethernet D-Cache coherency.
VIRT_ADDR() converted the DMA buffer addresses to KSEG1, while the buffers come from g_buffers, which is linked in KSEG0 when the data memory is cached. Buffers then ended up in the free list under both aliases. Use the segment g_buffers is linked in instead. A buffer handed to an RX descriptor may still have dirty D-Cache lines, at least the free list link written into it. If such a line is evicted while the DMA writes the frame, it overwrites part of the frame. Discard the buffer from the D-Cache before giving it to the DMA. Assisted-by: Claude Code:claude-opus-5-5 Signed-off-by: Daniel P. Carvalho <danieloak@gmail.com>
This commit is contained in:
parent
74eafb0354
commit
8eae6d950d
1 changed files with 38 additions and 3 deletions
|
|
@ -334,7 +334,11 @@
|
|||
/* Misc Helper Macros *******************************************************/
|
||||
|
||||
#define PHYS_ADDR(va) ((uint32_t)(va) & 0x1fffffff)
|
||||
#define VIRT_ADDR(pa) (KSEG1_BASE | (uint32_t)(pa))
|
||||
/* Buffers are always accessed through the segment g_buffers is linked in
|
||||
* (KSEG0 or KSEG1), so that no buffer is ever reached through two aliases.
|
||||
*/
|
||||
|
||||
#define VIRT_ADDR(pa) (((uint32_t)g_buffers & 0xe0000000) | (uint32_t)(pa))
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
|
|
@ -445,6 +449,7 @@ static void pic32mz_dumprxdesc(struct pic32mz_rxdesc_s *rxdesc,
|
|||
|
||||
static inline void pic32mz_bufferinit(struct pic32mz_driver_s *priv);
|
||||
static uint8_t *pic32mz_allocbuffer(struct pic32mz_driver_s *priv);
|
||||
static uint8_t *pic32mz_rxbuffer(struct pic32mz_driver_s *priv);
|
||||
static void pic32mz_freebuffer(struct pic32mz_driver_s *priv,
|
||||
uint8_t *buffer);
|
||||
|
||||
|
|
@ -768,6 +773,36 @@ static uint8_t *pic32mz_allocbuffer(struct pic32mz_driver_s *priv)
|
|||
return (uint8_t *)sq_remfirst(&priv->pd_freebuffers);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Function: pic32mz_rxbuffer
|
||||
*
|
||||
* Description:
|
||||
* Allocate one buffer for an RX descriptor. The free list link and any
|
||||
* data left by the network stack may still sit in dirty D-Cache lines;
|
||||
* they are discarded so that a later eviction cannot overwrite the frame
|
||||
* written by the DMA.
|
||||
*
|
||||
* Input Parameters:
|
||||
* priv - Pointer to EMAC device driver structure
|
||||
*
|
||||
* Returned Value:
|
||||
* Pointer to the allocated buffer (or NULL on failure)
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static uint8_t *pic32mz_rxbuffer(struct pic32mz_driver_s *priv)
|
||||
{
|
||||
uint8_t *buffer = pic32mz_allocbuffer(priv);
|
||||
|
||||
if (buffer != NULL)
|
||||
{
|
||||
up_invalidate_dcache((uintptr_t)buffer,
|
||||
(uintptr_t)buffer + PIC32MZ_ALIGNED_BUFSIZE);
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Function: pic32mz_freebuffer
|
||||
*
|
||||
|
|
@ -905,7 +940,7 @@ static inline void pic32mz_rxdescinit(struct pic32mz_driver_s *priv)
|
|||
|
||||
rxdesc->rsv1 = 0;
|
||||
rxdesc->rsv2 = 0;
|
||||
rxdesc->address = PHYS_ADDR(pic32mz_allocbuffer(priv));
|
||||
rxdesc->address = PHYS_ADDR(pic32mz_rxbuffer(priv));
|
||||
rxdesc->status = RXDESC_STATUS_EOWN | RXDESC_STATUS_NPV;
|
||||
|
||||
/* Set the NEXTED pointer. If this is the last descriptor in the
|
||||
|
|
@ -1514,7 +1549,7 @@ static void pic32mz_rxdone(struct pic32mz_driver_s *priv)
|
|||
* descriptor back to the hardware with its current buffer.
|
||||
*/
|
||||
|
||||
rxbuffer = pic32mz_allocbuffer(priv);
|
||||
rxbuffer = pic32mz_rxbuffer(priv);
|
||||
if (rxbuffer == NULL)
|
||||
{
|
||||
nwarn("WARNING: No free buffer, packet dropped\n");
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue