@@ -159,26 +159,51 @@ void CruDmaChannel::setBufferNonReady()
159159
160160void CruDmaChannel::deviceStopDma ()
161161{
162+ // Block further pushes; transfer queue has no available place anymore
163+ mLinkQueuesTotalAvailable = 0 ;
164+
165+ // Disable data taking
162166 setBufferNonReady ();
163167 getBar2 ()->disableDataTaking ();
168+
169+ // Transfer remaining (filled) superpages to ReadyQueue
164170 int moved = 0 ;
165171 for (auto & link : mLinks ) {
166172 int32_t superpageCount = getBar ()->getSuperpageCount (link.id );
167173 uint32_t amountAvailable = superpageCount - link.superpageCounter ;
168174 // log((format("superpageCount %1% amountAvailable %2%") % superpageCount % amountAvailable).str());
169- for ( uint32_t i = 0 ; i < amountAvailable; ++i ) {
175+ while ( amountAvailable) {
170176 if (mReadyQueue .size () >= READY_QUEUE_CAPACITY) {
171177 break ;
172178 }
173179
174- if (!link.queue .empty ()) { // care for the extra filled superpage
175- transferSuperpageFromLinkToReady (link);
180+ if (!link.queue .empty ()) {
181+ transferSuperpageFromLinkToReady (link, true );
176182 moved++;
177183 }
184+ amountAvailable--;
178185 }
179- assert (link.queue .empty ());
180186 }
181- assert (mLinkQueuesTotalAvailable == LINK_QUEUE_CAPACITY * mLinks .size ());
187+
188+ // Return any superpages that have been pushed up in the meantime but won't get filled
189+ for (auto & link : mLinks ) {
190+ while (!link.queue .empty ()) {
191+ link.queue .front ().setReceived (0 );
192+ link.queue .front ().setReady (true );
193+ mReadyQueue .push_back (link.queue .front ());
194+ link.queue .pop_front ();
195+ }
196+
197+ if (!link.queue .empty ()) {
198+ log ((format (" Superpage queue of link %1% not empty after DMA stop. Superpages unclaimed." ) % link.id ).str (),
199+ InfoLogger::InfoLogger::Error);
200+ }
201+ }
202+
203+ if (getTransferQueueAvailable ()) {
204+ BOOST_THROW_EXCEPTION (Exception () << ErrorInfo::Message (" Transfer queue not full when it should be" ));
205+ }
206+
182207 log ((format (" Moved %1% remaining superpage(s) to ready queue" ) % moved).str ());
183208}
184209
@@ -270,7 +295,7 @@ void CruDmaChannel::pushSuperpageToLink(Link& link, const Superpage& superpage)
270295 link.queue .push_back (superpage);
271296}
272297
273- void CruDmaChannel::transferSuperpageFromLinkToReady (Link& link)
298+ void CruDmaChannel::transferSuperpageFromLinkToReady (Link& link, bool stopping )
274299{
275300 if (link.queue .empty ()) {
276301 BOOST_THROW_EXCEPTION (Exception () << ErrorInfo::Message (" Could not transfer Superpage from link to ready queue, link queue is empty" ));
@@ -288,7 +313,9 @@ void CruDmaChannel::transferSuperpageFromLinkToReady(Link& link)
288313 mReadyQueue .push_back (link.queue .front ());
289314 link.queue .pop_front ();
290315 link.superpageCounter ++;
291- mLinkQueuesTotalAvailable ++;
316+ if (!stopping) {
317+ mLinkQueuesTotalAvailable ++;
318+ }
292319}
293320
294321void CruDmaChannel::fillSuperpages ()
0 commit comments