linux/drivers/gpu/drm/xe/xe_memirq.c

// SPDX-License-Identifier: MIT
/*
 * Copyright © 2023 Intel Corporation
 */

#include <drm/drm_managed.h>

#include "regs/xe_gt_regs.h"
#include "regs/xe_guc_regs.h"
#include "regs/xe_regs.h"

#include "xe_assert.h"
#include "xe_bo.h"
#include "xe_device.h"
#include "xe_device_types.h"
#include "xe_gt.h"
#include "xe_gt_printk.h"
#include "xe_guc.h"
#include "xe_hw_engine.h"
#include "xe_map.h"
#include "xe_memirq.h"
#include "xe_sriov.h"
#include "xe_sriov_printk.h"

#define memirq_assert(m, condition)
#define memirq_debug(m, msg...)

static struct xe_tile *memirq_to_tile(struct xe_memirq *memirq)
{}

static struct xe_device *memirq_to_xe(struct xe_memirq *memirq)
{}

static const char *guc_name(struct xe_guc *guc)
{}

/**
 * DOC: Memory Based Interrupts
 *
 * MMIO register based interrupts infrastructure used for non-virtualized mode
 * or SRIOV-8 (which supports 8 Virtual Functions) does not scale efficiently
 * to allow delivering interrupts to a large number of Virtual machines or
 * containers. Memory based interrupt status reporting provides an efficient
 * and scalable infrastructure.
 *
 * For memory based interrupt status reporting hardware sequence is:
 *  * Engine writes the interrupt event to memory
 *    (Pointer to memory location is provided by SW. This memory surface must
 *    be mapped to system memory and must be marked as un-cacheable (UC) on
 *    Graphics IP Caches)
 *  * Engine triggers an interrupt to host.
 */

/**
 * DOC: Memory Based Interrupts Page Layout
 *
 * `Memory Based Interrupts`_ requires three different objects, which are
 * called "page" in the specs, even if they aren't page-sized or aligned.
 *
 * To simplify the code we allocate a single page size object and then use
 * offsets to embedded "pages". The address of those "pages" are then
 * programmed in the HW via LRI and LRM in the context image.
 *
 * - _`Interrupt Status Report Page`: this page contains the interrupt
 *   status vectors for each unit. Each bit in the interrupt vectors is
 *   converted to a byte, with the byte being set to 0xFF when an
 *   interrupt is triggered; interrupt vectors are 16b big so each unit
 *   gets 16B. One space is reserved for each bit in one of the
 *   GT_INTR_DWx registers, so this object needs a total of 1024B.
 *   This object needs to be 4KiB aligned.
 *
 * - _`Interrupt Source Report Page`: this is the equivalent of the
 *   GEN11_GT_INTR_DWx registers, with each bit in those registers being
 *   mapped to a byte here. The offsets are the same, just bytes instead
 *   of bits. This object needs to be cacheline aligned.
 *
 * - Interrupt Mask: the HW needs a location to fetch the interrupt
 *   mask vector to be used by the LRM in the context, so we just use
 *   the next available space in the interrupt page.
 *
 * ::
 *
 *   0x0000   +===========+  <== Interrupt Status Report Page
 *            |           |
 *            |           |     ____ +----+----------------+
 *            |           |    /     |  0 | USER INTERRUPT |
 *            +-----------+ __/      |  1 |                |
 *            |  HWE(n)   | __       |    | CTX SWITCH     |
 *            +-----------+   \      |    | WAIT SEMAPHORE |
 *            |           |    \____ | 15 |                |
 *            |           |          +----+----------------+
 *            |           |
 *   0x0400   +===========+  <== Interrupt Source Report Page
 *            |  HWE(0)   |
 *            |  HWE(1)   |
 *            |           |
 *            |  HWE(x)   |
 *   0x0440   +===========+  <== Interrupt Enable Mask
 *            |           |
 *            |           |
 *            +-----------+
 */

static void __release_xe_bo(struct drm_device *drm, void *arg)
{}

static int memirq_alloc_pages(struct xe_memirq *memirq)
{}

static void memirq_set_enable(struct xe_memirq *memirq, bool enable)
{}

/**
 * xe_memirq_init - Initialize data used by `Memory Based Interrupts`_.
 * @memirq: the &xe_memirq to initialize
 *
 * Allocate `Interrupt Source Report Page`_ and `Interrupt Status Report Page`_
 * used by `Memory Based Interrupts`_.
 *
 * These allocations are managed and will be implicitly released on unload.
 *
 * Note: This function shall be called only by the VF driver.
 *
 * If this function fails then VF driver won't be able to operate correctly.
 * If `Memory Based Interrupts`_ are not used this function will return 0.
 *
 * Return: 0 on success or a negative error code on failure.
 */
int xe_memirq_init(struct xe_memirq *memirq)
{}

/**
 * xe_memirq_source_ptr - Get GGTT's offset of the `Interrupt Source Report Page`_.
 * @memirq: the &xe_memirq to query
 *
 * Shall be called only on VF driver when `Memory Based Interrupts`_ are used
 * and xe_memirq_init() didn't fail.
 *
 * Return: GGTT's offset of the `Interrupt Source Report Page`_.
 */
u32 xe_memirq_source_ptr(struct xe_memirq *memirq)
{}

/**
 * xe_memirq_status_ptr - Get GGTT's offset of the `Interrupt Status Report Page`_.
 * @memirq: the &xe_memirq to query
 *
 * Shall be called only on VF driver when `Memory Based Interrupts`_ are used
 * and xe_memirq_init() didn't fail.
 *
 * Return: GGTT's offset of the `Interrupt Status Report Page`_.
 */
u32 xe_memirq_status_ptr(struct xe_memirq *memirq)
{}

/**
 * xe_memirq_enable_ptr - Get GGTT's offset of the Interrupt Enable Mask.
 * @memirq: the &xe_memirq to query
 *
 * Shall be called only on VF driver when `Memory Based Interrupts`_ are used
 * and xe_memirq_init() didn't fail.
 *
 * Return: GGTT's offset of the Interrupt Enable Mask.
 */
u32 xe_memirq_enable_ptr(struct xe_memirq *memirq)
{}

/**
 * xe_memirq_init_guc - Prepare GuC for `Memory Based Interrupts`_.
 * @memirq: the &xe_memirq
 * @guc: the &xe_guc to setup
 *
 * Register `Interrupt Source Report Page`_ and `Interrupt Status Report Page`_
 * to be used by the GuC when `Memory Based Interrupts`_ are required.
 *
 * Shall be called only on VF driver when `Memory Based Interrupts`_ are used
 * and xe_memirq_init() didn't fail.
 *
 * Return: 0 on success or a negative error code on failure.
 */
int xe_memirq_init_guc(struct xe_memirq *memirq, struct xe_guc *guc)
{}

/**
 * xe_memirq_reset - Disable processing of `Memory Based Interrupts`_.
 * @memirq: struct xe_memirq
 *
 * This is part of the driver IRQ setup flow.
 *
 * This function shall only be used by the VF driver on platforms that use
 * `Memory Based Interrupts`_.
 */
void xe_memirq_reset(struct xe_memirq *memirq)
{}

/**
 * xe_memirq_postinstall - Enable processing of `Memory Based Interrupts`_.
 * @memirq: the &xe_memirq
 *
 * This is part of the driver IRQ setup flow.
 *
 * This function shall only be used by the VF driver on platforms that use
 * `Memory Based Interrupts`_.
 */
void xe_memirq_postinstall(struct xe_memirq *memirq)
{}

static bool memirq_received(struct xe_memirq *memirq, struct iosys_map *vector,
			    u16 offset, const char *name)
{}

static void memirq_dispatch_engine(struct xe_memirq *memirq, struct iosys_map *status,
				   struct xe_hw_engine *hwe)
{}

static void memirq_dispatch_guc(struct xe_memirq *memirq, struct iosys_map *status,
				struct xe_guc *guc)
{}

/**
 * xe_memirq_handler - The `Memory Based Interrupts`_ Handler.
 * @memirq: the &xe_memirq
 *
 * This function reads and dispatches `Memory Based Interrupts`.
 */
void xe_memirq_handler(struct xe_memirq *memirq)
{}