stm32cube: stm32h7: eth: avoid descriptor leak with enabled timestamping

Ethernet HAL configures interrupts to be received upon filling every
RX descriptor. When timestamping is enabled, application needs to
process both normal and context descriptors, but there is a race
condition in HAL_ETH_IsRxDataAvailable() that might miss context
descriptor, effectively leaking it.

This change introduces spinlock to wait for context descriptor if
normal context indicates it will be available.

(cherry picked from commit 5ca535df5874d1f9ab931265a2b1f691b76df9ce)

Signed-off-by: Alex Sergeev <asergeev@carbonrobotics.com>
GitOrigin-RevId: 5ca535df5874d1f9ab931265a2b1f691b76df9ce
Change-Id: Ifa8efcb855119503ab497a331d96a5775cf454cf
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/third_party/zephyr/hal_stm32/+/3321810
Tested-by: CopyBot Service Account <copybot.service@gmail.com>
Reviewed-by: Keith Short <keithshort@chromium.org>
Commit-Queue: Keith Short <keithshort@chromium.org>
diff --git a/stm32cube/stm32h7xx/README b/stm32cube/stm32h7xx/README
index 509eea5..178d922 100644
--- a/stm32cube/stm32h7xx/README
+++ b/stm32cube/stm32h7xx/README
@@ -44,4 +44,8 @@
     -Added stm32cube/stm32h7xx/drivers/include/stm32_assert.h
     -Removed unused stm32cube/stm32h7xx/drivers/include/stm32_assert_template.h
 
+   *Fix context descriptor leak 
+    - Impacted file: stm32h7xx_hal_eth.c
+    - Internal reference: Not available. Will be fixed as part of a new eth hal implementation
+
    See release_note.html from STM32Cube
diff --git a/stm32cube/stm32h7xx/drivers/src/stm32h7xx_hal_eth.c b/stm32cube/stm32h7xx/drivers/src/stm32h7xx_hal_eth.c
index decff79..2178217 100644
--- a/stm32cube/stm32h7xx/drivers/src/stm32h7xx_hal_eth.c
+++ b/stm32cube/stm32h7xx/drivers/src/stm32h7xx_hal_eth.c
@@ -1074,6 +1074,7 @@
   ETH_DMADescTypeDef *dmarxdesc = (ETH_DMADescTypeDef *)dmarxdesclist->RxDesc[descidx];
   uint32_t descscancnt = 0;
   uint32_t appdesccnt = 0, firstappdescidx = 0;
+  uint8_t expectctx = 0;
 
   if(dmarxdesclist->AppDescNbr != 0U)
   {
@@ -1097,6 +1098,12 @@
         WRITE_REG(firstappdescidx, descidx);
       }
 
+      /* Check whether we should expect context descriptor based on TSA bit */
+      if(READ_BIT(dmarxdesc->DESC1, ETH_DMARXNDESCWBF_TSA) != (uint32_t)RESET)
+      {
+        expectctx = 1U;
+      }
+
       /* Increment current rx descriptor index */
       INCR_RX_DESC_INDEX(descidx, 1U);
 
@@ -1104,6 +1111,20 @@
       /* Get current descriptor address */
       dmarxdesc = (ETH_DMADescTypeDef *)dmarxdesclist->RxDesc[descidx];
 
+      /*
+       * If we expect context descriptor, we might need to wait for it due to
+       * interrupts triggered by normal descriptors. Failure to wait here
+       * results in leaked descriptors.
+       */
+      if(expectctx)
+      {
+        while(READ_BIT(dmarxdesc->DESC3, ETH_DMARXNDESCWBF_OWN) != (uint32_t)RESET ||
+              READ_BIT(dmarxdesc->DESC3, ETH_DMARXNDESCWBF_CTXT) == (uint32_t)RESET)
+        {
+          /* Spin */
+        }
+      }
+
       if(READ_BIT(dmarxdesc->DESC3,  ETH_DMARXNDESCWBF_OWN)  == (uint32_t)RESET)
       {
         if(READ_BIT(dmarxdesc->DESC3,  ETH_DMARXNDESCWBF_CTXT)  != (uint32_t)RESET)