@@ -191,7 +191,7 @@ namespace mbed {
191191 needToCopy = true ;
192192 }
193193
194- if (!needToCopy && (neededDescs < txDescsOwnedByApplication || txDescsOwnedByApplication > 0 )) {
194+ if (!needToCopy && (neededDescs > txDescsOwnedByApplication && txDescsOwnedByApplication > 0 )) {
195195 // Packet uses more buffers than we have descriptors, but we can send it immediately if we copy
196196 // it into a single buffer.
197197 needToCopy = true ;
@@ -228,7 +228,6 @@ namespace mbed {
228228 if (newBuf == nullptr )
229229 {
230230 // No free memory, drop packet
231- memory_manager->free (newBuf);
232231 return CompositeEMAC::ErrCode::OUT_OF_MEMORY;
233232 }
234233
@@ -478,10 +477,31 @@ namespace mbed {
478477 return false ;
479478 }
480479
480+ private:
481+
482+ // / Helper function: Discard received Rx descriptors from a given start index (inclusive) to stop index (exclusive)
483+ void discardRxDescs (size_t startIdx, size_t stopIdx)
484+ {
485+ for (size_t descToCleanIdx = startIdx; descToCleanIdx != stopIdx; descToCleanIdx = (descToCleanIdx + 1 ) % RX_NUM_DESCS) {
486+ // Free Rx buffer attached to this desc
487+ memory_manager->free (rxDescStackBufs[descToCleanIdx]);
488+ rxDescStackBufs[descToCleanIdx] = nullptr ;
489+
490+ // Allow desc to be rebuilt
491+ ++rxDescsOwnedByApplication;
492+ ++rxNextIndex;
493+ }
494+ }
495+
496+ public:
497+
481498 net_stack_mem_buf_t * dequeuePacket () override {
482499 // Indices of the first and last descriptors for the packet will be saved here
483500 std::optional<size_t > firstDescIdx, lastDescIdx;
484501
502+ // Packet length is stored here once we check it
503+ size_t pktLen;
504+
485505 // Prevent looping around into descriptors waiting for rebuild by limiting how many
486506 // we can process.
487507 const size_t maxDescsToProcess = RX_NUM_DESCS - rxDescsOwnedByApplication;
@@ -508,39 +528,33 @@ namespace mbed {
508528 // Error or non-first-descriptor before a first descriptor
509529 // (could be caused by incomplete packets/junk in the DMA buffer).
510530 // Ignore, free associated memory, and schedule for rebuild.
511- memory_manager->free (rxDescStackBufs[descIdx]);
512- rxDescStackBufs[descIdx] = nullptr ;
513- ++rxDescsOwnedByApplication;
514- ++rxNextIndex;
515-
531+ discardRxDescs (descIdx, (descIdx + 1 ) % RX_NUM_DESCS);
516532 continue ;
517533 }
518- else if (firstDescIdx.has_value () && ( isError || isFirst) )
534+ else if (firstDescIdx.has_value () && isError)
519535 {
520- // Already seen a first descriptor, but we have an error descriptor or another first descriptor.
521- // So, delete the in-progress packet up to this point.
522-
523- // Clean up the old first descriptor and any descriptors between there and here
524- const size_t endIdx = isFirst ? descIdx : (descIdx + 1 ) % RX_NUM_DESCS;
525-
526- for (size_t descToCleanIdx = *firstDescIdx; descToCleanIdx != endIdx; descToCleanIdx = (descToCleanIdx + 1 ) % RX_NUM_DESCS) {
527- memory_manager->free (rxDescStackBufs[descToCleanIdx]);
528- rxDescStackBufs[descToCleanIdx] = nullptr ;
529- ++rxDescsOwnedByApplication;
530- ++rxNextIndex;
531- }
532-
533- if (!isError)
534- {
535- firstDescIdx = descIdx;
536- }
536+ // Already seen a first descriptor, but we have an error descriptor.
537+ // So, delete the in-progress packet up to this point.
538+ discardRxDescs (*firstDescIdx, (descIdx + 1 ) % RX_NUM_DESCS);
539+ firstDescIdx.reset ();
540+ continue ;
541+ }
542+ else if (firstDescIdx.has_value () && isFirst)
543+ {
544+ // Already seen a first descriptor, but we have another first descriptor.
545+ // Some MACs do this if they run out of Rx descs when halfway through a packet.
546+ // Delete the in-progress packet up to this point and start over from descIdx.
547+ discardRxDescs (*firstDescIdx, descIdx);
548+ firstDescIdx = descIdx;
537549 }
538550 else if (isFirst)
539551 {
552+ // Normal first descriptor.
540553 firstDescIdx = descIdx;
541554 }
542555
543- if (isLast) {
556+ if (isLast) {
557+ pktLen = getTotalLen (*firstDescIdx, descIdx);
544558 lastDescIdx = descIdx;
545559 }
546560 }
@@ -559,9 +573,9 @@ namespace mbed {
559573
560574 // Set length of first buffer
561575 net_stack_mem_buf_t *const headBuffer = rxDescStackBufs[*firstDescIdx];
562- size_t lenRemaining = getTotalLen (*firstDescIdx, *lastDescIdx);
563- memory_manager->set_len (headBuffer, std::min (lenRemaining , rxPoolPayloadSize));
564- lenRemaining -= std::min (lenRemaining , rxPoolPayloadSize);
576+
577+ memory_manager->set_len (headBuffer, std::min (pktLen , rxPoolPayloadSize));
578+ size_t lenRemaining = pktLen - std::min (pktLen , rxPoolPayloadSize);
565579
566580 // Iterate through the subsequent descriptors in this packet and link the buffers
567581 // Note that this also transfers ownership of subsequent buffers to the first buffer,
0 commit comments