/** * pvr_get_free_list_min_pages() - Get minimum free list size for this device * @pvr_dev: Device pointer. * * Returns: * * Minimum free list size, in PM physical pages.
*/
u32
pvr_get_free_list_min_pages(struct pvr_device *pvr_dev)
{
u32 value;
if (PVR_HAS_FEATURE(pvr_dev, roguexe)) { if (PVR_HAS_QUIRK(pvr_dev, 66011))
value = FREE_LIST_MIN_PAGES_BRN66011; else
value = FREE_LIST_MIN_PAGES_ROGUEXE;
} else {
value = FREE_LIST_MIN_PAGES;
}
/** * calculate_free_list_ready_pages_locked() - Function to work out the number of free * list pages to reserve for growing within * the FW without having to wait for the * host to progress a grow request * @free_list: Pointer to free list. * @pages: Total pages currently in free list. * * If the threshold or grow size means less than the alignment size (4 pages on * Rogue), then the feature is not used. * * Caller must hold &free_list->lock. * * Return: number of pages to reserve.
*/ static u32
calculate_free_list_ready_pages_locked(struct pvr_free_list *free_list, u32 pages)
{
u32 ready_pages;
/* * Create and map the FW structure so we can initialise it. This is not * accessed on the CPU side post-initialisation so the mapping lifetime * is only for this function.
*/
free_list->fw_data = pvr_fw_object_create_and_map(pvr_dev, sizeof(*free_list->fw_data),
PVR_BO_FW_FLAGS_DEVICE_UNCACHED,
free_list_fw_init, free_list,
&free_list->fw_obj); if (IS_ERR(free_list->fw_data)) return PTR_ERR(free_list->fw_data);
/* * Reserve a number ready pages to allow the FW to process OOM quickly * and asynchronously request a grow.
*/
free_list->ready_pages =
calculate_free_list_ready_pages_locked(free_list,
free_list->current_pages);
free_list->current_pages -= free_list->ready_pages;
/* If we don't have a freelist registered for this ID, we can't do much. */ if (WARN_ON(!free_list)) return;
/* Since the FW made the request, it has already consumed the ready pages, * update the host struct.
*/
free_list->current_pages += free_list->ready_pages;
free_list->ready_pages = 0;
/* If the grow succeeds, update the grow_pages argument. */ if (!pvr_free_list_grow(free_list, free_list->grow_pages))
grow_pages = free_list->grow_pages;
/* Now prepare the response and send it back to the FW. */
pvr_fw_object_get_fw_addr(free_list->fw_obj, &resp->freelist_fw_addr);
resp->delta_pages = grow_pages;
resp->new_pages = free_list->current_pages + free_list->ready_pages;
resp->ready_pages = free_list->ready_pages;
pvr_free_list_put(free_list);
/** * pvr_free_list_create() - Create a new free list and return an object pointer * @pvr_file: Pointer to pvr_file structure. * @args: Creation arguments from userspace. * * Return: * * Pointer to new free_list, or * * ERR_PTR(-%ENOMEM) on out of memory.
*/ struct pvr_free_list *
pvr_free_list_create(struct pvr_file *pvr_file, struct drm_pvr_ioctl_create_free_list_args *args)
{ struct pvr_free_list *free_list; int err;
/* Create and fill out the kernel structure */
free_list = kzalloc(sizeof(*free_list), GFP_KERNEL);
/* Allocate global object ID for firmware. */
err = xa_alloc(&pvr_file->pvr_dev->free_list_ids,
&free_list->fw_id,
free_list,
xa_limit_32b,
GFP_KERNEL); if (err) goto err_destroy_kernel_structure;
err = pvr_fw_structure_cleanup(free_list->pvr_dev,
ROGUE_FWIF_CLEANUP_FREELIST,
free_list->fw_obj, 0); if (err == -EBUSY) { /* Flush the FWCCB to process any HWR or freelist reconstruction * request that might keep the freelist busy, and try again.
*/
pvr_fwccb_process(free_list->pvr_dev);
err = pvr_fw_structure_cleanup(free_list->pvr_dev,
ROGUE_FWIF_CLEANUP_FREELIST,
free_list->fw_obj, 0);
}
WARN_ON(err);
/* clang-format off */
list_for_each_safe(pos, n, &free_list->mem_block_list) { struct pvr_free_list_node *free_list_node =
container_of(pos, struct pvr_free_list_node, node);
list_del(pos);
pvr_free_list_free_node(free_list_node);
} /* clang-format on */
/** * pvr_destroy_free_lists_for_file: Destroy any free lists associated with the * given file. * @pvr_file: Pointer to pvr_file structure. * * Removes all free lists associated with @pvr_file from the device free_list * list and drops initial references. Free lists will then be destroyed once * all outstanding references are dropped.
*/ void pvr_destroy_free_lists_for_file(struct pvr_file *pvr_file)
{ struct pvr_free_list *free_list; unsignedlong handle;
/** * pvr_free_list_put() - Release reference on free list * @free_list: Pointer to list to release reference on
*/ void
pvr_free_list_put(struct pvr_free_list *free_list)
{ if (free_list)
kref_put(&free_list->ref_count, pvr_free_list_release);
}
/* * Remove the ready pages, which are reserved to allow the FW to process OOM quickly and * asynchronously request a grow.
*/
free_list->current_pages -= free_list->ready_pages;
/* Reset the state of any associated HWRTs. */
list_for_each_entry(hwrt_data, &free_list->hwrt_list, freelist_node) { struct rogue_fwif_hwrtdata *hwrt_fw_data = pvr_fw_object_vmap(hwrt_data->fw_obj);
if (!WARN_ON(IS_ERR(hwrt_fw_data))) {
hwrt_fw_data->state = ROGUE_FWIF_RTDATA_STATE_HWR;
hwrt_fw_data->hwrt_data_flags &= ~HWRTDATA_HAS_LAST_GEOM;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.