On Wed, Nov 16, 2011 at 10:50:01AM -0500, Konrad Rzeszutek Wilk wrote:
> > +int ttm_dma_populate(struct ttm_tt *ttm, struct device *dev)
> > +{
> .. snip..
> 
> > +   for (i = 0; i < ttm->num_pages; ++i) {
> > +           ret = ttm_dma_pool_get_pages(pool, ttm, i);
> > +           if (ret != 0) {
> > +                   ttm_dma_unpopulate(ttm, dev);
> > +                   return -ENOMEM;
> > +           }
> > +
> > +           ret = ttm_mem_global_alloc_page(mem_glob, ttm->pages[i],
> > +                                           false, false);
> 
> Ok, so we increment it here..
> 
> .. snip..
> > +void ttm_dma_unpopulate(struct ttm_tt *ttm, struct device *dev)
> > +{
> > +   struct dma_pool *pool;
> > +   struct dma_page *d_page;
> > +   enum pool_type type;
> > +   bool is_cached = false;
> > +   unsigned count = 0, i;
> > +   unsigned long irq_flags;
> > +
> > +   type = ttm_to_type(ttm->page_flags, ttm->caching_state);
> > +   pool = ttm_dma_find_pool(dev, type);
> > +   if (!pool) {
> > +           WARN_ON(!pool);
> > +           return;
> > +   }
> > +   is_cached = (ttm_dma_find_pool(pool->dev,
> > +                ttm_to_type(ttm->page_flags, tt_cached)) == pool);
> > +
> > +   /* make sure pages array match list and count number of pages */
> > +   list_for_each_entry(d_page, &ttm->alloc_list, page_list) {
> > +           ttm->pages[count] = d_page->p;
> > +           count++;
> > +   }
> > +
> > +   spin_lock_irqsave(&pool->lock, irq_flags);
> > +   pool->npages_in_use -= count;
> > +   if (is_cached) {
> > +           pool->nfrees += count;
> > +   } else {
> > +           pool->npages_free += count;
> > +           list_splice(&ttm->alloc_list, &pool->free_list);
> > +           if (pool->npages_free > _manager->options.max_size) {
> > +                   count = pool->npages_free - _manager->options.max_size;
> > +           }
> > +   }
> > +   spin_unlock_irqrestore(&pool->lock, irq_flags);
> 
> But we don't do it here.  I think you need:
> 
>       for (i = 0; i < ttm->num_pages; i++) {
>               ttm_mem_global_free_page(mem_glob, ttm->pages[i]);
> 
> And it has to be done before ttm_dma_pages_put as at that point the
> pages are truly gone.
> 
> Could actually be done in the '/* make sure pages array match list .."

Actually to avoid the race you need to do it one page at a time. Will
respin with that.

> 
> > +
> > +   if (is_cached) {
> > +           ttm_dma_pages_put(pool, &ttm->alloc_list,
> > +                             ttm->pages, count);
> > +   }
> > +
> > +   INIT_LIST_HEAD(&ttm->alloc_list);
> > +   for (i = 0; i < ttm->num_pages; i++) {
> > +           ttm->pages[i] = NULL;
> > +           ttm->dma_address[i] = 0;
> > +   }

Reply via email to