We should use spinlock to protect page pool's critical section as 1. The critical section is short, using spinlock is more efficient. 2. Spinlock could protect priority inversion. Ex. Low priority thread (dmabuf-deferred) hold the page lock but get scheduled out under heavy loading. Then the other high priority threads need to wait for dmabuf-deferred to release the lock. It causes long allocation latency and possible UI jank. Also, we could move NR_KERNEL_MISC_RECLAIMABLE stat out of the critical section to make it shorter as mod_node_page_state can handle concurrent access cases. Conflicts: drivers/dma-buf/heaps/page_pool.h drivers/dma-buf/heaps/page_pool.c 1. The android13-5.15 KMI is frozen, and the modification to struct dmabuf_page_pool in the original patch would break the KMI. Instead we wrap dmabuf_page_pool allocations in a struct dmabuf_page_pool_with_spinlock which also contains a spinlock replacement for dmabuf_page_pool's mutex. No callers should attempt to acquire dmabuf_page_pool's mutex on this branch, so it is locked immediately after initialization and never unlocked. (cherry picked from commit 060e38dce1d69b81fe633f31751a610e3dd8e983) Bug: 245454030 Change-Id: I15f349f9e893621f71ca79f1de037de184c33edf Signed-off-by: T.J. Mercier <tjmercier@google.com>
56 lines
1.5 KiB
C
56 lines
1.5 KiB
C
/* SPDX-License-Identifier: GPL-2.0 */
|
|
/*
|
|
* DMA BUF PagePool implementation
|
|
* Based on earlier ION code by Google
|
|
*
|
|
* Copyright (C) 2011 Google, Inc.
|
|
* Copyright (C) 2020 Linaro Ltd.
|
|
*/
|
|
|
|
#ifndef _DMABUF_PAGE_POOL_H
|
|
#define _DMABUF_PAGE_POOL_H
|
|
|
|
#include <linux/device.h>
|
|
#include <linux/kref.h>
|
|
#include <linux/mm_types.h>
|
|
#include <linux/mutex.h>
|
|
#include <linux/shrinker.h>
|
|
#include <linux/types.h>
|
|
|
|
/* page types we track in the pool */
|
|
enum {
|
|
POOL_LOWPAGE, /* Clean lowmem pages */
|
|
POOL_HIGHPAGE, /* Clean highmem pages */
|
|
|
|
POOL_TYPE_SIZE,
|
|
};
|
|
|
|
/**
|
|
* struct dmabuf_page_pool - pagepool struct
|
|
* @count[]: array of number of pages of that type in the pool
|
|
* @items[]: array of list of pages of the specific type
|
|
* @mutex: lock protecting this struct and especially the count
|
|
* item list
|
|
* @gfp_mask: gfp_mask to use from alloc
|
|
* @order: order of pages in the pool
|
|
* @list: list node for list of pools
|
|
*
|
|
* Allows you to keep a pool of pre allocated pages to use
|
|
*/
|
|
struct dmabuf_page_pool {
|
|
int count[POOL_TYPE_SIZE];
|
|
struct list_head items[POOL_TYPE_SIZE];
|
|
struct mutex mutex; /* No longer used! */
|
|
gfp_t gfp_mask;
|
|
unsigned int order;
|
|
struct list_head list;
|
|
};
|
|
|
|
struct dmabuf_page_pool *dmabuf_page_pool_create(gfp_t gfp_mask,
|
|
unsigned int order);
|
|
void dmabuf_page_pool_destroy(struct dmabuf_page_pool *pool);
|
|
struct page *dmabuf_page_pool_alloc(struct dmabuf_page_pool *pool);
|
|
void dmabuf_page_pool_free(struct dmabuf_page_pool *pool, struct page *page);
|
|
|
|
#endif /* _DMABUF_PAGE_POOL_H */
|