drivers/gpu/drm/imagination/pvr_cccb.c

Source file repositories/reference/linux-study-clean/drivers/gpu/drm/imagination/pvr_cccb.c

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/imagination/pvr_cccb.c
Extension
.c
Size
8240 bytes
Lines
268
Domain
Driver Families
Bucket
drivers/gpu
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

// SPDX-License-Identifier: GPL-2.0-only OR MIT
/* Copyright (c) 2023 Imagination Technologies Ltd. */

#include "pvr_ccb.h"
#include "pvr_cccb.h"
#include "pvr_device.h"
#include "pvr_gem.h"
#include "pvr_hwrt.h"

#include <linux/compiler.h>
#include <linux/delay.h>
#include <linux/jiffies.h>
#include <linux/mutex.h>
#include <linux/types.h>

static __always_inline u32
get_ccb_space(u32 w_off, u32 r_off, u32 ccb_size)
{
	return (((r_off) - (w_off)) + ((ccb_size) - 1)) & ((ccb_size) - 1);
}

static void
cccb_ctrl_init(void *cpu_ptr, void *priv)
{
	struct rogue_fwif_cccb_ctl *ctrl = cpu_ptr;
	struct pvr_cccb *pvr_cccb = priv;

	WRITE_ONCE(ctrl->write_offset, 0);
	WRITE_ONCE(ctrl->read_offset, 0);
	WRITE_ONCE(ctrl->dep_offset, 0);
	WRITE_ONCE(ctrl->wrap_mask, pvr_cccb->wrap_mask);
}

/**
 * pvr_cccb_init() - Initialise a Client CCB
 * @pvr_dev: Device pointer.
 * @pvr_cccb: Pointer to Client CCB structure to initialise.
 * @size_log2: Log2 size of Client CCB in bytes.
 * @name: Name of owner of Client CCB. Used for fence context.
 *
 * Return:
 *  * Zero on success, or
 *  * Any error code returned by pvr_fw_object_create_and_map().
 */
int
pvr_cccb_init(struct pvr_device *pvr_dev, struct pvr_cccb *pvr_cccb,
	      u32 size_log2, const char *name)
{
	size_t size = 1 << size_log2;
	int err;

	pvr_cccb->size = size;
	pvr_cccb->write_offset = 0;
	pvr_cccb->wrap_mask = size - 1;

	/*
	 * Map CCCB and control structure as uncached, so we don't have to flush
	 * CPU cache repeatedly when polling for space.
	 */
	pvr_cccb->ctrl = pvr_fw_object_create_and_map(pvr_dev, sizeof(*pvr_cccb->ctrl),
						      PVR_BO_FW_FLAGS_DEVICE_UNCACHED,
						      cccb_ctrl_init, pvr_cccb,
						      &pvr_cccb->ctrl_obj);
	if (IS_ERR(pvr_cccb->ctrl))
		return PTR_ERR(pvr_cccb->ctrl);

	pvr_cccb->cccb = pvr_fw_object_create_and_map(pvr_dev, size,
						      PVR_BO_FW_FLAGS_DEVICE_UNCACHED,
						      NULL, NULL, &pvr_cccb->cccb_obj);
	if (IS_ERR(pvr_cccb->cccb)) {
		err = PTR_ERR(pvr_cccb->cccb);
		goto err_free_ctrl;
	}

	pvr_fw_object_get_fw_addr(pvr_cccb->ctrl_obj, &pvr_cccb->ctrl_fw_addr);
	pvr_fw_object_get_fw_addr(pvr_cccb->cccb_obj, &pvr_cccb->cccb_fw_addr);

	return 0;

err_free_ctrl:
	pvr_fw_object_unmap_and_destroy(pvr_cccb->ctrl_obj);

	return err;
}

/**
 * pvr_cccb_fini() - Release Client CCB structure
 * @pvr_cccb: Client CCB to release.
 */
void

Annotation

Implementation Notes