On Thu, Jul 26, 2018 at 9:54 PM, Tony Battersby <tonyb@xxxxxxxxxxxxxxx> wrote: > dma_pool_alloc() scales poorly when allocating a large number of pages > because it does a linear scan of all previously-allocated pages before > allocating a new one. Improve its scalability by maintaining a separate > list of pages that have free blocks ready to (re)allocate. In big O > notation, this improves the algorithm from O(n^2) to O(n). > spin_lock_irqsave(&pool->lock, flags); > - list_for_each_entry(page, &pool->page_list, page_list) { > - if (page->offset < pool->allocation) > - goto ready; > + if (!list_empty(&pool->avail_page_list)) { > + page = list_first_entry(&pool->avail_page_list, > + struct dma_page, > + avail_page_link); > + goto ready; > } It looks like page = list_first_entry_or_null(); if (page) goto ready; Though I don't know which one produces better code in the result. >From reader prospective of view I would go with my variant. > + /* This test checks if the page is already in avail_page_list. */ > + if (list_empty(&page->avail_page_link)) > + list_add(&page->avail_page_link, &pool->avail_page_list); How can you be sure that the page you are testing for is the first one? It seems you are relying on the fact that in the list should be either 0 or 1 page. In that case what's the point to have a list? -- With Best Regards, Andy Shevchenko