@@ -29,7 +29,7 @@ namespace roc
2929{
3030
3131CruDmaChannel::CruDmaChannel (const Parameters& parameters)
32- : DmaChannelPdaBase(parameters, allowedChannels()), //
32+ : DmaChannelPdaBase(parameters, allowedChannels()),
3333 mInitialResetLevel (ResetLevel::Internal), // It's good to reset at least the card channel in general
3434 mDataSource(parameters.getDataSource().get_value_or(DataSource::Internal)), // DG loopback mode by default
3535 mDmaPageSize(parameters.getDmaPageSize().get_value_or(Cru::DMA_PAGE_SIZE))
@@ -81,7 +81,10 @@ CruDmaChannel::CruDmaChannel(const Parameters& parameters)
8181 << ErrorInfo::LinkId (id));
8282 }
8383 stream << id << " " ;
84- mLinks .push_back ({ static_cast <LinkId>(id) });
84+ // Implicit constructors are deleted for the folly Queue. Workaround to keep the Link struct with a queue * field.
85+ std::shared_ptr<SuperpageQueue> linkQueue = std::make_shared<SuperpageQueue>(LINK_QUEUE_CAPACITY);
86+ Link newLink = { static_cast <LinkId>(id), 0 , linkQueue };
87+ mLinks .push_back (newLink);
8588 }
8689 log (stream.str ());
8790 }
@@ -96,8 +99,8 @@ auto CruDmaChannel::allowedChannels() -> AllowedChannels
9699CruDmaChannel::~CruDmaChannel ()
97100{
98101 setBufferNonReady ();
99- if (mReadyQueue .size () > 0 ) {
100- log ((format (" Remaining superpages in the ready queue: %1%" ) % mReadyQueue .size ()).str ());
102+ if (mReadyQueue .sizeGuess () > 0 ) {
103+ log ((format (" Remaining superpages in the ready queue: %1%" ) % mReadyQueue .sizeGuess ()).str ());
101104 }
102105
103106 if (mDataSource == DataSource::Internal) {
@@ -128,10 +131,15 @@ void CruDmaChannel::deviceStartDma()
128131
129132 // Initialize link queues
130133 for (auto & link : mLinks ) {
131- link.queue .clear ();
134+ // link.queue->clear();
135+ while (!link.queue ->isEmpty ()) {
136+ link.queue ->popFront ();
137+ }
132138 link.superpageCounter = 0 ;
133139 }
134- mReadyQueue .clear ();
140+ while (!mReadyQueue .isEmpty ()) {
141+ mReadyQueue .popFront ();
142+ }
135143 mLinkQueuesTotalAvailable = LINK_QUEUE_CAPACITY * mLinks .size ();
136144
137145 // Start DMA
@@ -167,16 +175,17 @@ void CruDmaChannel::deviceStopDma()
167175 fillSuperpages ();
168176
169177 // Return any superpages that have been pushed up in the meantime but won't get filled
178+ reclaimSuperpages ();
179+ }
180+
181+ void CruDmaChannel::reclaimSuperpages ()
182+ {
170183 for (auto & link : mLinks ) {
171- while (!link.queue .empty ()) {
172- link.queue .front ().setReceived (0 );
173- link.queue .front ().setReady (false );
174- mReadyQueue .push_back (link.queue .front ());
175- link.queue .pop_front ();
176- mLinkQueuesTotalAvailable ++;
184+ while (!link.queue ->isEmpty ()) {
185+ transferSuperpageFromLinkToReady (link, true ); // Reclaim pages, do *not* set as ready
177186 }
178187
179- if (!link.queue . empty ()) {
188+ if (!link.queue -> isEmpty ()) {
180189 log ((format (" Superpage queue of link %1% not empty after DMA stop. Superpages unclaimed." ) % link.id ).str (),
181190 InfoLogger::InfoLogger::Error);
182191 }
@@ -211,7 +220,7 @@ auto CruDmaChannel::getNextLinkIndex() -> LinkIndex
211220 auto smallestQueueSize = std::numeric_limits<size_t >::max ();
212221
213222 for (size_t i = 0 ; i < mLinks .size (); ++i) {
214- auto queueSize = mLinks [i].queue . size ();
223+ auto queueSize = mLinks [i].queue -> sizeGuess ();
215224 if (queueSize < smallestQueueSize) {
216225 smallestQueueIndex = i;
217226 smallestQueueSize = queueSize;
@@ -238,7 +247,7 @@ bool CruDmaChannel::pushSuperpage(Superpage superpage)
238247 // Get the next link to push
239248 auto & link = mLinks [getNextLinkIndex ()];
240249
241- if (link.queue . size () >= LINK_QUEUE_CAPACITY) {
250+ if (link.queue -> sizeGuess () >= LINK_QUEUE_CAPACITY) {
242251 // Is the link's FIFO out of space?
243252 // This should never happen
244253 BOOST_THROW_EXCEPTION (Exception () << ErrorInfo::Message (" Could not push superpage, link queue was full" ));
@@ -255,59 +264,69 @@ bool CruDmaChannel::pushSuperpage(Superpage superpage)
255264
256265auto CruDmaChannel::getSuperpage () -> Superpage
257266{
258- if (mReadyQueue .empty ()) {
267+ if (mReadyQueue .isEmpty ()) {
259268 BOOST_THROW_EXCEPTION (Exception () << ErrorInfo::Message (" Could not get superpage, ready queue was empty" ));
260269 }
261- return mReadyQueue .front ();
270+ return * mReadyQueue .frontPtr ();
262271}
263272
264273auto CruDmaChannel::popSuperpage () -> Superpage
265274{
266- if (mReadyQueue .empty ()) {
275+ if (mReadyQueue .isEmpty ()) {
267276 BOOST_THROW_EXCEPTION (Exception () << ErrorInfo::Message (" Could not pop superpage, ready queue was empty" ));
268277 }
269- auto superpage = mReadyQueue .front ();
270- mReadyQueue .pop_front ();
278+ auto superpage = *mReadyQueue .frontPtr ();
279+ mReadyQueue .popFront ();
280+
271281 return superpage;
272282}
273283
274284void CruDmaChannel::pushSuperpageToLink (Link& link, const Superpage& superpage)
275285{
276286 mLinkQueuesTotalAvailable --;
277- link.queue . push_back (superpage);
287+ link.queue -> write (superpage);
278288}
279289
280- void CruDmaChannel::transferSuperpageFromLinkToReady (Link& link)
290+ void CruDmaChannel::transferSuperpageFromLinkToReady (Link& link, bool reclaim )
281291{
282- if (link.queue . empty ()) {
292+ if (link.queue -> isEmpty ()) {
283293 BOOST_THROW_EXCEPTION (Exception () << ErrorInfo::Message (" Could not transfer Superpage from link to ready queue, link queue is empty" ));
284294 }
285295
286- link.queue .front ().setReady (true );
287-
288- uint32_t superpageSize = getBar ()->getSuperpageSize (link.id );
289- if (superpageSize == 0 ) {
290- link.queue .front ().setReceived (link.queue .front ().getSize ()); // force the full superpage size for backwards compatibility
296+ if (!reclaim) {
297+ link.queue ->frontPtr ()->setReady (true );
298+ uint32_t superpageSize = getBar ()->getSuperpageSize (link.id );
299+ if (superpageSize == 0 ) {
300+ link.queue ->frontPtr ()->setReceived (link.queue ->frontPtr ()->getSize ()); // force the full superpage size for backwards compatibility
301+ } else {
302+ link.queue ->frontPtr ()->setReceived (superpageSize);
303+ }
291304 } else {
292- link.queue .front ().setReceived (superpageSize);
305+ link.queue ->frontPtr ()->setReady (false );
306+ link.queue ->frontPtr ()->setReceived (0 );
293307 }
294308
295- mReadyQueue .push_back ( link.queue . front ());
296- link.queue . pop_front ();
309+ mReadyQueue .write (* link.queue -> frontPtr ());
310+ link.queue -> popFront ();
297311 link.superpageCounter ++;
298312 mLinkQueuesTotalAvailable ++;
299313}
300314
301315void CruDmaChannel::fillSuperpages ()
302316{
317+
318+ /* if (mDmaState != DmaState::STARTED) { //Would block fillSuperpages from deviceStopDma()
319+ //return;
320+ }*/
321+
303322 // Check for arrivals & handle them
304323 for (auto & link : mLinks ) {
305324 int32_t superpageCount = getBar ()->getSuperpageCount (link.id );
306325 uint32_t amountAvailable = superpageCount - link.superpageCounter ;
307- if (amountAvailable > link.queue . size ()) {
326+ if (amountAvailable > link.queue -> sizeGuess ()) {
308327
309328 std::stringstream stream;
310- stream << " FATAL: Firmware reported more superpages available (" << amountAvailable << " ) than should be present in FIFO (" << link.queue . size () << " ); "
329+ stream << " FATAL: Firmware reported more superpages available (" << amountAvailable << " ) than should be present in FIFO (" << link.queue -> sizeGuess () << " ); "
311330 << link.superpageCounter << " superpages received from link " << int (link.id ) << " according to driver, "
312331 << superpageCount << " pushed according to firmware" ;
313332 log (stream.str (), InfoLogger::InfoLogger::Error);
@@ -316,7 +335,7 @@ void CruDmaChannel::fillSuperpages()
316335 }
317336
318337 while (amountAvailable) {
319- if (mReadyQueue .size () >= READY_QUEUE_CAPACITY) {
338+ if (mReadyQueue .sizeGuess () >= READY_QUEUE_CAPACITY) {
320339 break ;
321340 }
322341
@@ -340,14 +359,14 @@ bool CruDmaChannel::isTransferQueueEmpty()
340359
341360int CruDmaChannel::getReadyQueueSize ()
342361{
343- return mReadyQueue .size ();
362+ return mReadyQueue .sizeGuess ();
344363}
345364
346365// Return a boolean that denotes whether the ready queue is full
347366// The ready queue is full when the CRU has filled it up
348367bool CruDmaChannel::isReadyQueueFull ()
349368{
350- return mReadyQueue .size () == READY_QUEUE_CAPACITY ;
369+ return mReadyQueue .isFull () ;
351370}
352371
353372int32_t CruDmaChannel::getDroppedPackets ()
0 commit comments