static void vc4_bo_cache_time_work(struct work_struct *work) { struct vc4_dev *vc4 = container_of(work, struct vc4_dev, bo_cache.time_work); struct drm_device *dev = vc4->dev; mutex_lock(&vc4->bo_lock); vc4_bo_cache_free_old(dev); mutex_unlock(&vc4->bo_lock); }
/* Called on the last userspace/kernel unreference of the BO. Returns * it to the BO cache if possible, otherwise frees it. */ void vc4_free_object(struct drm_gem_object *gem_bo) { struct drm_device *dev = gem_bo->dev; struct vc4_dev *vc4 = to_vc4_dev(dev); struct vc4_bo *bo = to_vc4_bo(gem_bo); struct list_head *cache_list; mutex_lock(&vc4->bo_lock); /* If the object references someone else's memory, we can't cache it. */ if (gem_bo->import_attach) { vc4_bo_destroy(bo); goto out; } /* Don't cache if it was publicly named. */ if (gem_bo->name) { vc4_bo_destroy(bo); goto out; } /* If this object was partially constructed but CMA allocation * had failed, just free it. */ if (!bo->base.vaddr) { vc4_bo_destroy(bo); goto out; } cache_list = vc4_get_cache_list_for_size(dev, gem_bo->size); if (!cache_list) { vc4_bo_destroy(bo); goto out; } if (bo->validated_shader) { kfree(bo->validated_shader->texture_samples); kfree(bo->validated_shader); bo->validated_shader = NULL; } bo->free_time = jiffies; list_add(&bo->size_head, cache_list); list_add(&bo->unref_head, &vc4->bo_cache.time_list); vc4->bo_stats.num_cached++; vc4->bo_stats.size_cached += gem_bo->size; vc4_bo_cache_free_old(dev); out: mutex_unlock(&vc4->bo_lock); }