This fixes two related issues:
* Pbufs in the RX list weren't cleared out appropriately and this could
  cause multiple frees along with premature pbuf/memp reuse in
  circumstances where the system was running out of pbufs and receive
  overruns were occurring.
* This patch adds locking around pbuf list manipulation to prevent race
  conditions where the list might be in an inconsistent state.
---
 .../ports/xilinx/netif/xemacpsif_dma.c        | 74 +++++++++++++++++++
 1 file changed, 74 insertions(+)

diff --git 
a/embeddedsw/ThirdParty/sw_services/lwip211/src/contrib/ports/xilinx/netif/xemacpsif_dma.c
 
b/embeddedsw/ThirdParty/sw_services/lwip211/src/contrib/ports/xilinx/netif/xemacpsif_dma.c
index 2da3566..1d2439a 100644
--- 
a/embeddedsw/ThirdParty/sw_services/lwip211/src/contrib/ports/xilinx/netif/xemacpsif_dma.c
+++ 
b/embeddedsw/ThirdParty/sw_services/lwip211/src/contrib/ports/xilinx/netif/xemacpsif_dma.c
@@ -264,6 +264,10 @@ void process_sent_bds(xemacpsif_s *xemacpsif, 
XEmacPs_BdRing *txring)
                                *temp = 0x80000000;
                        }
                        dsb();
+#ifdef __rtems__
+                       SYS_ARCH_DECL_PROTECT(lev);
+                       SYS_ARCH_PROTECT(lev);
+#endif
                        p = (struct pbuf *)tx_pbufs_storage[index + bdindex];
                        if (p != NULL) {
                                pbuf_free(p);
@@ -272,6 +276,9 @@ void process_sent_bds(xemacpsif_s *xemacpsif, 
XEmacPs_BdRing *txring)
                        notifyinfo[tx_task_notifier_index + bdindex] = 0;
 #endif
                        tx_pbufs_storage[index + bdindex] = 0;
+#ifdef __rtems__
+                       SYS_ARCH_UNPROTECT(lev);
+#endif
                        curbdpntr = XEmacPs_BdRingNext(txring, curbdpntr);
                        n_pbufs_freed--;
                        dsb();
@@ -346,8 +353,15 @@ XStatus emacps_sgsend(xemacpsif_s *xemacpsif, struct pbuf 
*p)
 
        for(q = p, txbd = txbdset; q != NULL; q = q->next) {
                bdindex = XEMACPS_BD_TO_INDEX(txring, txbd);
+#ifdef __rtems__
+               SYS_ARCH_DECL_PROTECT(lev);
+               SYS_ARCH_PROTECT(lev);
+#endif
                if (tx_pbufs_storage[index + bdindex] != 0) {
                        LWIP_DEBUGF(NETIF_DEBUG, ("PBUFS not available\r\n"));
+#ifdef __rtems__
+                       SYS_ARCH_UNPROTECT(lev);
+#endif
                        return XST_FAILURE;
                }
 
@@ -373,6 +387,9 @@ XStatus emacps_sgsend(xemacpsif_s *xemacpsif, struct pbuf 
*p)
                tx_pbufs_storage[index + bdindex] = (UINTPTR)q;
 
                pbuf_ref(q);
+#ifdef __rtems__
+               SYS_ARCH_UNPROTECT(lev);
+#endif
                last_txbd = txbd;
                XEmacPs_BdClearLast(txbd);
                txbd = XEmacPs_BdRingNext(txring, txbd);
@@ -488,7 +505,14 @@ void setup_rx_bds(xemacpsif_s *xemacpsif, XEmacPs_BdRing 
*rxring)
                        XEmacPs_BdWrite(rxbd, XEMACPS_BD_ADDR_OFFSET, 
(UINTPTR)p->payload);
                }
 
+#ifdef __rtems__
+               SYS_ARCH_DECL_PROTECT(lev);
+               SYS_ARCH_PROTECT(lev);
+#endif
                rx_pbufs_storage[index + bdindex] = (UINTPTR)p;
+#ifdef __rtems__
+               SYS_ARCH_UNPROTECT(lev);
+#endif
        }
 }
 
@@ -536,8 +560,26 @@ void emacps_recv_handler(void *arg)
                for (k = 0, curbdptr=rxbdset; k < bd_processed; k++) {
 
                        bdindex = XEMACPS_BD_TO_INDEX(rxring, curbdptr);
+#ifdef __rtems__
+                       SYS_ARCH_DECL_PROTECT(lev);
+                       SYS_ARCH_PROTECT(lev);
+#endif
                        p = (struct pbuf *)rx_pbufs_storage[index + bdindex];
 
+#ifdef __rtems__
+                       /* Clear this since ownership is being passed elsewhere 
*/
+                       rx_pbufs_storage[index + bdindex] = 0;
+                       SYS_ARCH_UNPROTECT(lev);
+
+                       /*
+                        * Nulled descriptors are left flagged so the hardware
+                        * doesn't try to use them. They will still show up 
here.
+                        */
+                       if (p == NULL) {
+                               continue;
+                       }
+#endif
+
                        /*
                         * Adjust the buffer size to the actual number of bytes 
received.
                         */
@@ -768,7 +810,14 @@ XStatus init_dma(struct xemac_s *xemac)
 #endif
                XEmacPs_BdSetAddressRx(rxbd, (UINTPTR)p->payload);
 
+#ifdef __rtems__
+               SYS_ARCH_DECL_PROTECT(lev);
+               SYS_ARCH_PROTECT(lev);
+#endif
                rx_pbufs_storage[index + bdindex] = (UINTPTR)p;
+#ifdef __rtems__
+               SYS_ARCH_UNPROTECT(lev);
+#endif
        }
        XEmacPs_SetQueuePtr(&(xemacpsif->emacps), 
xemacpsif->emacps.RxBdRing.BaseBdAddr, 0, XEMACPS_RECV);
        if (gigeversion > 2) {
@@ -865,16 +914,34 @@ void free_txrx_pbufs(xemacpsif_s *xemacpsif)
        index1 = get_base_index_txpbufsstorage (xemacpsif);
 
        for (index = index1; index < (index1 + XLWIP_CONFIG_N_TX_DESC); 
index++) {
+#ifdef __rtems__
+               SYS_ARCH_DECL_PROTECT(lev);
+               SYS_ARCH_PROTECT(lev);
+#endif
                if (tx_pbufs_storage[index] != 0) {
                        p = (struct pbuf *)tx_pbufs_storage[index];
                        pbuf_free(p);
                        tx_pbufs_storage[index] = 0;
                }
+#ifdef __rtems__
+               SYS_ARCH_UNPROTECT(lev);
+#endif
        }
 
        index1 = get_base_index_rxpbufsstorage(xemacpsif);
        for (index = index1; index < (index1 + XLWIP_CONFIG_N_RX_DESC); 
index++) {
+#ifdef __rtems__
+               SYS_ARCH_DECL_PROTECT(lev);
+               SYS_ARCH_PROTECT(lev);
+#endif
                p = (struct pbuf *)rx_pbufs_storage[index];
+#ifdef __rtems__
+               rx_pbufs_storage[index] = 0;
+               SYS_ARCH_UNPROTECT(lev);
+               if (p == NULL) {
+                       continue;
+               }
+#endif
                pbuf_free(p);
 
        }
@@ -888,11 +955,18 @@ void free_onlytx_pbufs(xemacpsif_s *xemacpsif)
 
        index1 = get_base_index_txpbufsstorage (xemacpsif);
        for (index = index1; index < (index1 + XLWIP_CONFIG_N_TX_DESC); 
index++) {
+#ifdef __rtems__
+               SYS_ARCH_DECL_PROTECT(lev);
+               SYS_ARCH_PROTECT(lev);
+#endif
                if (tx_pbufs_storage[index] != 0) {
                        p = (struct pbuf *)tx_pbufs_storage[index];
                        pbuf_free(p);
                        tx_pbufs_storage[index] = 0;
                }
+#ifdef __rtems__
+               SYS_ARCH_UNPROTECT(lev);
+#endif
        }
 }
 
-- 
2.39.2

_______________________________________________
devel mailing list
devel@rtems.org
http://lists.rtems.org/mailman/listinfo/devel

Reply via email to