diff options
author | Kinsey Moore <kinsey.moore@oarcorp.com> | 2023-11-15 15:12:07 -0600 |
---|---|---|
committer | Joel Sherrill <joel@rtems.org> | 2023-12-19 12:20:49 -0600 |
commit | 2bc181a125fce5913473c5c456741f615c2cbbe0 (patch) | |
tree | 67d7d4dea6edfba51c4ef62d66309e99d7c465f9 /embeddedsw | |
parent | Alter ownership of components in uLan (diff) | |
download | rtems-lwip-2bc181a125fce5913473c5c456741f615c2cbbe0.tar.bz2 |
xemacps: Improve pbuf handling
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.
Diffstat (limited to 'embeddedsw')
-rw-r--r-- | embeddedsw/ThirdParty/sw_services/lwip211/src/contrib/ports/xilinx/netif/xemacpsif_dma.c | 74 |
1 files changed, 74 insertions, 0 deletions
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 } } |