On Wed, May 29, 2019 at 10:16:59AM +0200, Jesper Dangaard Brouer wrote:
On Thu, 23 May 2019 21:20:35 +0300
Ivan Khoronzhuk <ivan.khoronzhuk@xxxxxxxxxx> wrote:
+static struct page *cpsw_alloc_page(struct cpsw_common *cpsw)
+{
+ struct page_pool *pool = cpsw->rx_page_pool;
+ struct page *page, *prev_page = NULL;
+ int try = pool->p.pool_size << 2;
+ int start_free = 0, ret;
+
+ do {
+ page = page_pool_dev_alloc_pages(pool);
+ if (!page)
+ return NULL;
+
+ /* if netstack has page_pool recycling remove the rest */
+ if (page_ref_count(page) == 1)
+ break;
+
+ /* start free pages in use, shouldn't happen */
+ if (prev_page == page || start_free) {
+ /* dma unmap/puts page if rfcnt != 1 */
+ page_pool_recycle_direct(pool, page);
+ start_free = 1;
+ continue;
+ }
+
+ /* if refcnt > 1, page has been holding by netstack, it's pity,
+ * so put it to the ring to be consumed later when fast cash is
+ * empty. If ring is full then free page by recycling as above.
+ */
+ ret = ptr_ring_produce(&pool->ring, page);
This looks very wrong to me! First of all you are manipulation
directly with the internal pool->ring and not using the API, which
makes this code un-maintainable.
Yes I know, it's hack, it was with assumption to be dropped once page_pool
recycling is added.
Second this is wrong, as page_pool
assume the in-variance that pages on the ring have refcnt==1.
Yes, but this is w/o obvious reason, seems like it can work with refcnt > 1 if
remove restriction and use >= instead of ==.
As I answered on Ilias comment, I'm going to leave version from RFC and drop
this one.
+ if (ret) {
+ page_pool_recycle_direct(pool, page);
+ continue;
+ }
+
+ if (!prev_page)
+ prev_page = page;
+ } while (try--);
+
+ return page;
+}
--
Best regards,
Jesper Dangaard Brouer
MSc.CS, Principal Kernel Engineer at Red Hat
LinkedIn: http://www.linkedin.com/in/brouer
--
Regards,
Ivan Khoronzhuk