mirror of
git://nv-tegra.nvidia.com/linux-nv-oot.git
synced 2025-12-22 17:25:35 +03:00
drm/tegra: Implement buffer object cache
This cache is used to avoid mapping and unmapping buffer objects unnecessarily. Mappings are cached per client and stay hot until the buffer object is destroyed. Bug 200768479 Signed-off-by: Thierry Reding <treding@nvidia.com> Change-Id: Ia2efe2b77b5043b665bae403d9eba4698e6a5228 Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvidia/+/2596399 (cherry picked from commit d23156d94fa9499256e8082250e3bc02559f9c8d) Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvidia/+/2620152 Tested-by: Jonathan Hunter <jonathanh@nvidia.com> Tested-by: mobile promotions <svcmobile_promotions@nvidia.com> Reviewed-by: Jonathan Hunter <jonathanh@nvidia.com> Reviewed-by: svc_kernel_abi <svc_kernel_abi@nvidia.com> Reviewed-by: Mikko Perttunen <mperttunen@nvidia.com> Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com> GVS: Gerrit_Virtual_Submit
This commit is contained in:
committed by
Laxman Dewangan
parent
d802ae96a7
commit
2a938c39ec
@@ -742,6 +742,7 @@ EXPORT_SYMBOL(host1x_driver_unregister);
|
|||||||
*/
|
*/
|
||||||
void __host1x_client_init(struct host1x_client *client, struct lock_class_key *key)
|
void __host1x_client_init(struct host1x_client *client, struct lock_class_key *key)
|
||||||
{
|
{
|
||||||
|
host1x_bo_cache_init(&client->cache);
|
||||||
INIT_LIST_HEAD(&client->list);
|
INIT_LIST_HEAD(&client->list);
|
||||||
__mutex_init(&client->lock, "host1x client lock", key);
|
__mutex_init(&client->lock, "host1x client lock", key);
|
||||||
client->usecount = 0;
|
client->usecount = 0;
|
||||||
@@ -830,6 +831,8 @@ int host1x_client_unregister(struct host1x_client *client)
|
|||||||
|
|
||||||
mutex_unlock(&clients_lock);
|
mutex_unlock(&clients_lock);
|
||||||
|
|
||||||
|
host1x_bo_cache_destroy(&client->cache);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(host1x_client_unregister);
|
EXPORT_SYMBOL(host1x_client_unregister);
|
||||||
@@ -904,3 +907,78 @@ unlock:
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(host1x_client_resume);
|
EXPORT_SYMBOL(host1x_client_resume);
|
||||||
|
|
||||||
|
struct host1x_bo_mapping *host1x_bo_pin(struct device *dev, struct host1x_bo *bo,
|
||||||
|
enum dma_data_direction dir,
|
||||||
|
struct host1x_bo_cache *cache)
|
||||||
|
{
|
||||||
|
struct host1x_bo_mapping *mapping;
|
||||||
|
|
||||||
|
if (cache) {
|
||||||
|
mutex_lock(&cache->lock);
|
||||||
|
|
||||||
|
list_for_each_entry(mapping, &cache->mappings, entry) {
|
||||||
|
if (mapping->bo == bo && mapping->direction == dir) {
|
||||||
|
kref_get(&mapping->ref);
|
||||||
|
goto unlock;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mapping = bo->ops->pin(dev, bo, dir);
|
||||||
|
if (IS_ERR(mapping))
|
||||||
|
goto unlock;
|
||||||
|
|
||||||
|
spin_lock(&mapping->bo->lock);
|
||||||
|
list_add_tail(&mapping->list, &bo->mappings);
|
||||||
|
spin_unlock(&mapping->bo->lock);
|
||||||
|
|
||||||
|
if (cache) {
|
||||||
|
INIT_LIST_HEAD(&mapping->entry);
|
||||||
|
mapping->cache = cache;
|
||||||
|
|
||||||
|
list_add_tail(&mapping->entry, &cache->mappings);
|
||||||
|
|
||||||
|
/* bump reference count to track the copy in the cache */
|
||||||
|
kref_get(&mapping->ref);
|
||||||
|
}
|
||||||
|
|
||||||
|
unlock:
|
||||||
|
if (cache)
|
||||||
|
mutex_unlock(&cache->lock);
|
||||||
|
|
||||||
|
return mapping;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(host1x_bo_pin);
|
||||||
|
|
||||||
|
static void __host1x_bo_unpin(struct kref *ref)
|
||||||
|
{
|
||||||
|
struct host1x_bo_mapping *mapping = to_host1x_bo_mapping(ref);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* When the last reference of the mapping goes away, make sure to remove the mapping from
|
||||||
|
* the cache.
|
||||||
|
*/
|
||||||
|
if (mapping->cache)
|
||||||
|
list_del(&mapping->entry);
|
||||||
|
|
||||||
|
spin_lock(&mapping->bo->lock);
|
||||||
|
list_del(&mapping->list);
|
||||||
|
spin_unlock(&mapping->bo->lock);
|
||||||
|
|
||||||
|
mapping->bo->ops->unpin(mapping);
|
||||||
|
}
|
||||||
|
|
||||||
|
void host1x_bo_unpin(struct host1x_bo_mapping *mapping)
|
||||||
|
{
|
||||||
|
struct host1x_bo_cache *cache = mapping->cache;
|
||||||
|
|
||||||
|
if (cache)
|
||||||
|
mutex_lock(&cache->lock);
|
||||||
|
|
||||||
|
kref_put(&mapping->ref, __host1x_bo_unpin);
|
||||||
|
|
||||||
|
if (cache)
|
||||||
|
mutex_unlock(&cache->lock);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(host1x_bo_unpin);
|
||||||
|
|||||||
@@ -404,6 +404,7 @@ static int host1x_probe(struct platform_device *pdev)
|
|||||||
if (syncpt_irq < 0)
|
if (syncpt_irq < 0)
|
||||||
return syncpt_irq;
|
return syncpt_irq;
|
||||||
|
|
||||||
|
host1x_bo_cache_init(&host->cache);
|
||||||
mutex_init(&host->devices_lock);
|
mutex_init(&host->devices_lock);
|
||||||
INIT_LIST_HEAD(&host->devices);
|
INIT_LIST_HEAD(&host->devices);
|
||||||
INIT_LIST_HEAD(&host->list);
|
INIT_LIST_HEAD(&host->list);
|
||||||
@@ -539,6 +540,7 @@ static int host1x_remove(struct platform_device *pdev)
|
|||||||
reset_control_assert(host->rst);
|
reset_control_assert(host->rst);
|
||||||
clk_disable_unprepare(host->clk);
|
clk_disable_unprepare(host->clk);
|
||||||
host1x_iommu_exit(host);
|
host1x_iommu_exit(host);
|
||||||
|
host1x_bo_cache_destroy(&host->cache);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -151,6 +151,7 @@ struct host1x {
|
|||||||
|
|
||||||
struct device_dma_parameters dma_parms;
|
struct device_dma_parameters dma_parms;
|
||||||
|
|
||||||
|
struct host1x_bo_cache cache;
|
||||||
struct host1x_uapi uapi;
|
struct host1x_uapi uapi;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
#include <linux/device.h>
|
#include <linux/device.h>
|
||||||
#include <linux/dma-direction.h>
|
#include <linux/dma-direction.h>
|
||||||
|
#include <linux/spinlock.h>
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
|
|
||||||
enum host1x_class {
|
enum host1x_class {
|
||||||
@@ -26,6 +27,28 @@ struct iommu_group;
|
|||||||
|
|
||||||
u64 host1x_get_dma_mask(struct host1x *host1x);
|
u64 host1x_get_dma_mask(struct host1x *host1x);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct host1x_bo_cache - host1x buffer object cache
|
||||||
|
* @mappings: list of mappings
|
||||||
|
* @lock: synchronizes accesses to the list of mappings
|
||||||
|
*/
|
||||||
|
struct host1x_bo_cache {
|
||||||
|
struct list_head mappings;
|
||||||
|
struct mutex lock;
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline void host1x_bo_cache_init(struct host1x_bo_cache *cache)
|
||||||
|
{
|
||||||
|
INIT_LIST_HEAD(&cache->mappings);
|
||||||
|
mutex_init(&cache->lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void host1x_bo_cache_destroy(struct host1x_bo_cache *cache)
|
||||||
|
{
|
||||||
|
/* XXX warn if not empty? */
|
||||||
|
mutex_destroy(&cache->lock);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct host1x_client_ops - host1x client operations
|
* struct host1x_client_ops - host1x client operations
|
||||||
* @early_init: host1x client early initialization code
|
* @early_init: host1x client early initialization code
|
||||||
@@ -76,6 +99,8 @@ struct host1x_client {
|
|||||||
struct host1x_client *parent;
|
struct host1x_client *parent;
|
||||||
unsigned int usecount;
|
unsigned int usecount;
|
||||||
struct mutex lock;
|
struct mutex lock;
|
||||||
|
|
||||||
|
struct host1x_bo_cache cache;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -86,6 +111,7 @@ struct host1x_bo;
|
|||||||
struct sg_table;
|
struct sg_table;
|
||||||
|
|
||||||
struct host1x_bo_mapping {
|
struct host1x_bo_mapping {
|
||||||
|
struct kref ref;
|
||||||
struct dma_buf_attachment *attach;
|
struct dma_buf_attachment *attach;
|
||||||
enum dma_data_direction direction;
|
enum dma_data_direction direction;
|
||||||
struct list_head list;
|
struct list_head list;
|
||||||
@@ -95,8 +121,16 @@ struct host1x_bo_mapping {
|
|||||||
struct device *dev;
|
struct device *dev;
|
||||||
dma_addr_t phys;
|
dma_addr_t phys;
|
||||||
size_t size;
|
size_t size;
|
||||||
|
|
||||||
|
struct host1x_bo_cache *cache;
|
||||||
|
struct list_head entry;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static inline struct host1x_bo_mapping *to_host1x_bo_mapping(struct kref *ref)
|
||||||
|
{
|
||||||
|
return container_of(ref, struct host1x_bo_mapping, ref);
|
||||||
|
}
|
||||||
|
|
||||||
struct host1x_bo_ops {
|
struct host1x_bo_ops {
|
||||||
struct host1x_bo *(*get)(struct host1x_bo *bo);
|
struct host1x_bo *(*get)(struct host1x_bo *bo);
|
||||||
void (*put)(struct host1x_bo *bo);
|
void (*put)(struct host1x_bo *bo);
|
||||||
@@ -109,11 +143,15 @@ struct host1x_bo_ops {
|
|||||||
|
|
||||||
struct host1x_bo {
|
struct host1x_bo {
|
||||||
const struct host1x_bo_ops *ops;
|
const struct host1x_bo_ops *ops;
|
||||||
|
struct list_head mappings;
|
||||||
|
spinlock_t lock;
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline void host1x_bo_init(struct host1x_bo *bo,
|
static inline void host1x_bo_init(struct host1x_bo *bo,
|
||||||
const struct host1x_bo_ops *ops)
|
const struct host1x_bo_ops *ops)
|
||||||
{
|
{
|
||||||
|
INIT_LIST_HEAD(&bo->mappings);
|
||||||
|
spin_lock_init(&bo->lock);
|
||||||
bo->ops = ops;
|
bo->ops = ops;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -127,16 +165,10 @@ static inline void host1x_bo_put(struct host1x_bo *bo)
|
|||||||
bo->ops->put(bo);
|
bo->ops->put(bo);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline struct host1x_bo_mapping *host1x_bo_pin(struct device *dev, struct host1x_bo *bo,
|
struct host1x_bo_mapping *host1x_bo_pin(struct device *dev, struct host1x_bo *bo,
|
||||||
enum dma_data_direction dir)
|
enum dma_data_direction dir,
|
||||||
{
|
struct host1x_bo_cache *cache);
|
||||||
return bo->ops->pin(dev, bo, dir);
|
void host1x_bo_unpin(struct host1x_bo_mapping *map);
|
||||||
}
|
|
||||||
|
|
||||||
static inline void host1x_bo_unpin(struct host1x_bo_mapping *map)
|
|
||||||
{
|
|
||||||
map->bo->ops->unpin(map);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void *host1x_bo_mmap(struct host1x_bo *bo)
|
static inline void *host1x_bo_mmap(struct host1x_bo *bo)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -168,7 +168,7 @@ static unsigned int pin_job(struct host1x *host, struct host1x_job *job)
|
|||||||
goto unpin;
|
goto unpin;
|
||||||
}
|
}
|
||||||
|
|
||||||
map = host1x_bo_pin(dev, bo, direction);
|
map = host1x_bo_pin(dev, bo, direction, &client->cache);
|
||||||
if (IS_ERR(map)) {
|
if (IS_ERR(map)) {
|
||||||
err = PTR_ERR(map);
|
err = PTR_ERR(map);
|
||||||
goto unpin;
|
goto unpin;
|
||||||
@@ -215,7 +215,7 @@ static unsigned int pin_job(struct host1x *host, struct host1x_job *job)
|
|||||||
goto unpin;
|
goto unpin;
|
||||||
}
|
}
|
||||||
|
|
||||||
map = host1x_bo_pin(host->dev, g->bo, DMA_TO_DEVICE);
|
map = host1x_bo_pin(host->dev, g->bo, DMA_TO_DEVICE, &host->cache);
|
||||||
if (IS_ERR(map)) {
|
if (IS_ERR(map)) {
|
||||||
err = PTR_ERR(map);
|
err = PTR_ERR(map);
|
||||||
goto unpin;
|
goto unpin;
|
||||||
|
|||||||
Reference in New Issue
Block a user