1
0
Fork 0

Merge branch 'mxc/next' into next

* mxc/next: (119 commits)
  mxc: hdmi-cec: Add imx6 hdmi cec driver
  driver: mfd: hdmi: Add hdmi core driver
  MLK-22399 mxc IPUv3: cpmem: Get 0 u/v_offset in __ipu_ch_offset_calc() for some pfmts
  mxc: IPU3: Fix not including uapi/linux/sched/types.h
  media: platform: mxc: output: Forward IPUv3 V4L2 output driver from imx_4.19.y
  ...
5.4-rM2-2.2.x-imx-squashed
Dong Aisheng 2019-12-02 18:02:35 +08:00
commit b3d472cf0c
204 changed files with 316734 additions and 0 deletions

View File

@ -0,0 +1,27 @@
*MediaLB (MLB) for i.MX
Required properties:
- compatible :
- "fsl,imx6sx-mlb50" for MLB compatible with the one integrated on i.MX6SX soc
- "fsl,imx6q-mlb150" for MLB compatible with the one integrated on i.MX6Q
- "fsl,imx8qxp-mlb150" for MLB compatible with the one integrated on i.MX8 soc
- reg : address and length for mlb registers
- interrupt-parent : core interrupt controller
- interrupts : MLB Break/Error interrupt and ahb interrupt
Two ahb interrupt for imx6, ahb_int[0] and ahb_int[1]
One ahb interrupt for imx8, ahb_int[0]
- clocks : mlb clock specifier
Examples:
mlb: mlb@5B060000 {
compatible = "fsl,imx6q-mlb150";
reg = <0x0 0x5B060000 0x0 0x10000>;
interrupt-parent = <&gic>;
interrupts = <0 265 IRQ_TYPE_LEVEL_HIGH>,
<0 266 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clk IMX8QM_MLB_CLK>,
<&clk IMX8QM_MLB_HCLK>,
<&clk IMX8QM_MLB_IPG_CLK>;
status = "disabled";
};

View File

@ -228,4 +228,5 @@ source "drivers/interconnect/Kconfig"
source "drivers/counter/Kconfig"
source "drivers/mxc/Kconfig"
endmenu

View File

@ -186,3 +186,4 @@ obj-$(CONFIG_SIOX) += siox/
obj-$(CONFIG_GNSS) += gnss/
obj-$(CONFIG_INTERCONNECT) += interconnect/
obj-$(CONFIG_COUNTER) += counter/
obj-y += mxc/

View File

@ -153,8 +153,16 @@ config VIDEO_MXC_CAPTURE
---help---
This is the video4linux2 capture driver based on i.MX video-in module.
config VIDEO_MXC_OUTPUT
tristate "MXC Video For Linux Video Output"
depends on VIDEO_DEV && ARCH_MXC && FB_MXC
select VIDEOBUF_DMA_CONTIG
---help---
This is the video4linux2 output driver based on MXC module.
source "drivers/media/platform/imx8/Kconfig"
source "drivers/media/platform/mxc/capture/Kconfig"
source "drivers/media/platform/mxc/output/Kconfig"
source "drivers/media/platform/exynos4-is/Kconfig"
source "drivers/media/platform/am437x/Kconfig"
source "drivers/media/platform/xilinx/Kconfig"

View File

@ -86,6 +86,7 @@ obj-$(CONFIG_VIDEO_STM32_DCMI) += stm32/
obj-$(CONFIG_VIDEO_MX8_CAPTURE) += imx8/
obj-$(CONFIG_VIDEO_MXC_CAPTURE) += mxc/capture/
obj-$(CONFIG_VIDEO_MXC_OUTPUT) += mxc/output/
obj-$(CONFIG_VIDEO_MEDIATEK_VPU) += mtk-vpu/

View File

@ -0,0 +1,5 @@
config VIDEO_MXC_IPU_OUTPUT
tristate "IPU v4l2 output support"
depends on VIDEO_MXC_OUTPUT && MXC_IPU
help
This is the video4linux2 driver for IPU post processing video output.

View File

@ -0,0 +1 @@
obj-$(CONFIG_VIDEO_MXC_IPU_OUTPUT) += mxc_vout.o

File diff suppressed because it is too large Load Diff

View File

@ -460,6 +460,13 @@ config MFD_MX25_TSADC
i.MX25 processors. They consist of a conversion queue for general
purpose ADC and a queue for Touchscreens.
config MFD_MXC_HDMI
tristate "Freescale HDMI Core"
select MFD_CORE
help
This is the core driver for the Freescale i.MX6 on-chip HDMI.
This MFD driver connects with the video and audio drivers for HDMI.
config MFD_HI6421_PMIC
tristate "HiSilicon Hi6421 PMU/Codec IC"
depends on OF

View File

@ -112,6 +112,7 @@ obj-$(CONFIG_MFD_TWL4030_AUDIO) += twl4030-audio.o
obj-$(CONFIG_TWL6040_CORE) += twl6040.o
obj-$(CONFIG_MFD_MX25_TSADC) += fsl-imx25-tsadc.o
obj-$(CONFIG_MFD_MXC_HDMI) += mxc-hdmi-core.o
obj-$(CONFIG_MFD_MC13XXX) += mc13xxx-core.o
obj-$(CONFIG_MFD_MC13XXX_SPI) += mc13xxx-spi.o

View File

@ -0,0 +1,819 @@
/*
* Copyright (C) 2011-2016 Freescale Semiconductor, Inc.
* The code contained herein is licensed under the GNU General Public
* License. You may obtain a copy of the GNU General Public License
* Version 2 or later at the following locations:
*
* http://www.opensource.org/licenses/gpl-license.html
* http://www.gnu.org/copyleft/gpl.html
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/device.h>
#include <linux/err.h>
#include <linux/io.h>
#include <linux/clk.h>
#include <linux/spinlock.h>
#include <linux/irq.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/regulator/machine.h>
//#include <asm/mach-types.h>
#include <video/mxc_hdmi.h>
#include <linux/ipu-v3.h>
#include <video/mxc_edid.h>
#include "../mxc/ipu3/ipu_prv.h"
#include <linux/mfd/mxc-hdmi-core.h>
#include <linux/of_device.h>
#include <linux/mod_devicetable.h>
#include <linux/mfd/mxc-hdmi-core.h>
struct mxc_hdmi_data {
struct platform_device *pdev;
unsigned long __iomem *reg_base;
unsigned long reg_phys_base;
struct device *dev;
};
static void __iomem *hdmi_base;
static struct clk *isfr_clk;
static struct clk *iahb_clk;
static struct clk *mipi_core_clk;
static spinlock_t irq_spinlock;
static spinlock_t edid_spinlock;
static unsigned int sample_rate;
static unsigned long pixel_clk_rate;
static struct clk *pixel_clk;
static int hdmi_ratio;
int mxc_hdmi_ipu_id;
int mxc_hdmi_disp_id;
static struct mxc_edid_cfg hdmi_core_edid_cfg;
static int hdmi_core_init;
static unsigned int hdmi_dma_running;
static struct snd_pcm_substream *hdmi_audio_stream_playback;
static unsigned int hdmi_cable_state;
static unsigned int hdmi_blank_state;
static unsigned int hdmi_abort_state;
static spinlock_t hdmi_audio_lock, hdmi_blank_state_lock, hdmi_cable_state_lock;
unsigned int hdmi_set_cable_state(unsigned int state)
{
unsigned long flags;
struct snd_pcm_substream *substream = hdmi_audio_stream_playback;
spin_lock_irqsave(&hdmi_cable_state_lock, flags);
hdmi_cable_state = state;
spin_unlock_irqrestore(&hdmi_cable_state_lock, flags);
#ifndef CONFIG_MFD_MXC_HDMI_ANDROID
if (check_hdmi_state() && substream && hdmi_abort_state) {
hdmi_abort_state = 0;
substream->ops->trigger(substream, SNDRV_PCM_TRIGGER_START);
}
#endif
return 0;
}
EXPORT_SYMBOL(hdmi_set_cable_state);
unsigned int hdmi_set_blank_state(unsigned int state)
{
unsigned long flags;
struct snd_pcm_substream *substream = hdmi_audio_stream_playback;
spin_lock_irqsave(&hdmi_blank_state_lock, flags);
hdmi_blank_state = state;
spin_unlock_irqrestore(&hdmi_blank_state_lock, flags);
#ifndef CONFIG_MFD_MXC_HDMI_ANDROID
if (check_hdmi_state() && substream && hdmi_abort_state) {
hdmi_abort_state = 0;
substream->ops->trigger(substream, SNDRV_PCM_TRIGGER_START);
}
#endif
return 0;
}
EXPORT_SYMBOL(hdmi_set_blank_state);
#ifdef CONFIG_SND_SOC_IMX_HDMI_DMA
static void hdmi_audio_abort_stream(struct snd_pcm_substream *substream)
{
unsigned long flags;
snd_pcm_stream_lock_irqsave(substream, flags);
#ifndef CONFIG_MFD_MXC_HDMI_ANDROID
if (snd_pcm_running(substream)) {
hdmi_abort_state = 1;
substream->ops->trigger(substream, SNDRV_PCM_TRIGGER_STOP);
}
#else
if (snd_pcm_running(substream))
snd_pcm_stop(substream, SNDRV_PCM_STATE_DISCONNECTED);
#endif
snd_pcm_stream_unlock_irqrestore(substream, flags);
}
int mxc_hdmi_abort_stream(void)
{
unsigned long flags;
spin_lock_irqsave(&hdmi_audio_lock, flags);
if (hdmi_audio_stream_playback)
hdmi_audio_abort_stream(hdmi_audio_stream_playback);
spin_unlock_irqrestore(&hdmi_audio_lock, flags);
return 0;
}
EXPORT_SYMBOL(mxc_hdmi_abort_stream);
#else
int mxc_hdmi_abort_stream(void)
{
return 0;
}
EXPORT_SYMBOL(mxc_hdmi_abort_stream);
#endif
int check_hdmi_state(void)
{
unsigned long flags1, flags2;
unsigned int ret;
spin_lock_irqsave(&hdmi_cable_state_lock, flags1);
spin_lock_irqsave(&hdmi_blank_state_lock, flags2);
ret = hdmi_cable_state && hdmi_blank_state;
spin_unlock_irqrestore(&hdmi_blank_state_lock, flags2);
spin_unlock_irqrestore(&hdmi_cable_state_lock, flags1);
return ret;
}
EXPORT_SYMBOL(check_hdmi_state);
#ifdef CONFIG_SND_SOC_IMX_HDMI_DMA
int mxc_hdmi_register_audio(struct snd_pcm_substream *substream)
{
unsigned long flags, flags1;
int ret = 0;
if (!substream)
return -EINVAL;
snd_pcm_stream_lock_irqsave(substream, flags);
if (check_hdmi_state()) {
spin_lock_irqsave(&hdmi_audio_lock, flags1);
if (hdmi_audio_stream_playback) {
pr_err("%s unconsist hdmi auido stream!\n", __func__);
ret = -EINVAL;
}
hdmi_audio_stream_playback = substream;
hdmi_abort_state = 0;
spin_unlock_irqrestore(&hdmi_audio_lock, flags1);
} else
ret = -EINVAL;
snd_pcm_stream_unlock_irqrestore(substream, flags);
return ret;
}
EXPORT_SYMBOL(mxc_hdmi_register_audio);
#endif
void mxc_hdmi_unregister_audio(struct snd_pcm_substream *substream)
{
unsigned long flags;
spin_lock_irqsave(&hdmi_audio_lock, flags);
hdmi_audio_stream_playback = NULL;
hdmi_abort_state = 0;
spin_unlock_irqrestore(&hdmi_audio_lock, flags);
}
EXPORT_SYMBOL(mxc_hdmi_unregister_audio);
u8 hdmi_readb(unsigned int reg)
{
u8 value;
value = __raw_readb(hdmi_base + reg);
return value;
}
EXPORT_SYMBOL(hdmi_readb);
#ifdef DEBUG
static bool overflow_lo;
static bool overflow_hi;
bool hdmi_check_overflow(void)
{
u8 val, lo, hi;
val = hdmi_readb(HDMI_IH_FC_STAT2);
lo = (val & HDMI_IH_FC_STAT2_LOW_PRIORITY_OVERFLOW) != 0;
hi = (val & HDMI_IH_FC_STAT2_HIGH_PRIORITY_OVERFLOW) != 0;
if ((lo != overflow_lo) || (hi != overflow_hi)) {
pr_debug("%s LowPriority=%d HighPriority=%d <=======================\n",
__func__, lo, hi);
overflow_lo = lo;
overflow_hi = hi;
return true;
}
return false;
}
#else
bool hdmi_check_overflow(void)
{
return false;
}
#endif
EXPORT_SYMBOL(hdmi_check_overflow);
void hdmi_writeb(u8 value, unsigned int reg)
{
hdmi_check_overflow();
__raw_writeb(value, hdmi_base + reg);
hdmi_check_overflow();
}
EXPORT_SYMBOL(hdmi_writeb);
void hdmi_mask_writeb(u8 data, unsigned int reg, u8 shift, u8 mask)
{
u8 value = hdmi_readb(reg) & ~mask;
value |= (data << shift) & mask;
hdmi_writeb(value, reg);
}
EXPORT_SYMBOL(hdmi_mask_writeb);
unsigned int hdmi_read4(unsigned int reg)
{
/* read a four byte address from registers */
return (hdmi_readb(reg + 3) << 24) |
(hdmi_readb(reg + 2) << 16) |
(hdmi_readb(reg + 1) << 8) |
hdmi_readb(reg);
}
EXPORT_SYMBOL(hdmi_read4);
void hdmi_write4(unsigned int value, unsigned int reg)
{
/* write a four byte address to hdmi regs */
hdmi_writeb(value & 0xff, reg);
hdmi_writeb((value >> 8) & 0xff, reg + 1);
hdmi_writeb((value >> 16) & 0xff, reg + 2);
hdmi_writeb((value >> 24) & 0xff, reg + 3);
}
EXPORT_SYMBOL(hdmi_write4);
static void initialize_hdmi_ih_mutes(void)
{
u8 ih_mute;
/*
* Boot up defaults are:
* HDMI_IH_MUTE = 0x03 (disabled)
* HDMI_IH_MUTE_* = 0x00 (enabled)
*/
/* Disable top level interrupt bits in HDMI block */
ih_mute = hdmi_readb(HDMI_IH_MUTE) |
HDMI_IH_MUTE_MUTE_WAKEUP_INTERRUPT |
HDMI_IH_MUTE_MUTE_ALL_INTERRUPT;
hdmi_writeb(ih_mute, HDMI_IH_MUTE);
/* by default mask all interrupts */
hdmi_writeb(0xff, HDMI_VP_MASK);
hdmi_writeb(0xff, HDMI_FC_MASK0);
hdmi_writeb(0xff, HDMI_FC_MASK1);
hdmi_writeb(0xff, HDMI_FC_MASK2);
hdmi_writeb(0xff, HDMI_PHY_MASK0);
hdmi_writeb(0xff, HDMI_PHY_I2CM_INT_ADDR);
hdmi_writeb(0xff, HDMI_PHY_I2CM_CTLINT_ADDR);
hdmi_writeb(0xff, HDMI_AUD_INT);
hdmi_writeb(0xff, HDMI_AUD_SPDIFINT);
hdmi_writeb(0xff, HDMI_AUD_HBR_MASK);
hdmi_writeb(0xff, HDMI_GP_MASK);
hdmi_writeb(0xff, HDMI_A_APIINTMSK);
hdmi_writeb(0xff, HDMI_CEC_MASK);
hdmi_writeb(0xff, HDMI_I2CM_INT);
hdmi_writeb(0xff, HDMI_I2CM_CTLINT);
/* Disable interrupts in the IH_MUTE_* registers */
hdmi_writeb(0xff, HDMI_IH_MUTE_FC_STAT0);
hdmi_writeb(0xff, HDMI_IH_MUTE_FC_STAT1);
hdmi_writeb(0xff, HDMI_IH_MUTE_FC_STAT2);
hdmi_writeb(0xff, HDMI_IH_MUTE_AS_STAT0);
hdmi_writeb(0xff, HDMI_IH_MUTE_PHY_STAT0);
hdmi_writeb(0xff, HDMI_IH_MUTE_I2CM_STAT0);
hdmi_writeb(0xff, HDMI_IH_MUTE_CEC_STAT0);
hdmi_writeb(0xff, HDMI_IH_MUTE_VP_STAT0);
hdmi_writeb(0xff, HDMI_IH_MUTE_I2CMPHY_STAT0);
hdmi_writeb(0xff, HDMI_IH_MUTE_AHBDMAAUD_STAT0);
/* Enable top level interrupt bits in HDMI block */
ih_mute &= ~(HDMI_IH_MUTE_MUTE_WAKEUP_INTERRUPT |
HDMI_IH_MUTE_MUTE_ALL_INTERRUPT);
hdmi_writeb(ih_mute, HDMI_IH_MUTE);
}
static void hdmi_set_clock_regenerator_n(unsigned int value)
{
u8 val;
if (!hdmi_dma_running) {
hdmi_writeb(value & 0xff, HDMI_AUD_N1);
hdmi_writeb(0, HDMI_AUD_N2);
hdmi_writeb(0, HDMI_AUD_N3);
}
hdmi_writeb(value & 0xff, HDMI_AUD_N1);
hdmi_writeb((value >> 8) & 0xff, HDMI_AUD_N2);
hdmi_writeb((value >> 16) & 0x0f, HDMI_AUD_N3);
/* nshift factor = 0 */
val = hdmi_readb(HDMI_AUD_CTS3);
val &= ~HDMI_AUD_CTS3_N_SHIFT_MASK;
hdmi_writeb(val, HDMI_AUD_CTS3);
}
static void hdmi_set_clock_regenerator_cts(unsigned int cts)
{
u8 val;
if (!hdmi_dma_running) {
hdmi_writeb(cts & 0xff, HDMI_AUD_CTS1);
hdmi_writeb(0, HDMI_AUD_CTS2);
hdmi_writeb(0, HDMI_AUD_CTS3);
}
/* Must be set/cleared first */
val = hdmi_readb(HDMI_AUD_CTS3);
val &= ~HDMI_AUD_CTS3_CTS_MANUAL;
hdmi_writeb(val, HDMI_AUD_CTS3);
hdmi_writeb(cts & 0xff, HDMI_AUD_CTS1);
hdmi_writeb((cts >> 8) & 0xff, HDMI_AUD_CTS2);
hdmi_writeb(((cts >> 16) & HDMI_AUD_CTS3_AUDCTS19_16_MASK) |
HDMI_AUD_CTS3_CTS_MANUAL, HDMI_AUD_CTS3);
}
static unsigned int hdmi_compute_n(unsigned int freq, unsigned long pixel_clk,
unsigned int ratio)
{
unsigned int n = (128 * freq) / 1000;
switch (freq) {
case 32000:
if (pixel_clk == 25174000)
n = (ratio == 150) ? 9152 : 4576;
else if (pixel_clk == 27020000)
n = (ratio == 150) ? 8192 : 4096;
else if (pixel_clk == 74170000 || pixel_clk == 148350000)
n = 11648;
else if (pixel_clk == 297000000)
n = (ratio == 150) ? 6144 : 3072;
else
n = 4096;
break;
case 44100:
if (pixel_clk == 25174000)
n = 7007;
else if (pixel_clk == 74170000)
n = 17836;
else if (pixel_clk == 148350000)
n = (ratio == 150) ? 17836 : 8918;
else if (pixel_clk == 297000000)
n = (ratio == 150) ? 9408 : 4704;
else
n = 6272;
break;
case 48000:
if (pixel_clk == 25174000)
n = (ratio == 150) ? 9152 : 6864;
else if (pixel_clk == 27020000)
n = (ratio == 150) ? 8192 : 6144;
else if (pixel_clk == 74170000)
n = 11648;
else if (pixel_clk == 148350000)
n = (ratio == 150) ? 11648 : 5824;
else if (pixel_clk == 297000000)
n = (ratio == 150) ? 10240 : 5120;
else
n = 6144;
break;
case 88200:
n = hdmi_compute_n(44100, pixel_clk, ratio) * 2;
break;
case 96000:
n = hdmi_compute_n(48000, pixel_clk, ratio) * 2;
break;
case 176400:
n = hdmi_compute_n(44100, pixel_clk, ratio) * 4;
break;
case 192000:
n = hdmi_compute_n(48000, pixel_clk, ratio) * 4;
break;
default:
break;
}
return n;
}
static unsigned int hdmi_compute_cts(unsigned int freq, unsigned long pixel_clk,
unsigned int ratio)
{
unsigned int cts = 0;
switch (freq) {
case 32000:
if (pixel_clk == 297000000)
cts = 222750;
else if (pixel_clk == 25174000)
cts = 28125;
break;
case 48000:
case 96000:
case 192000:
switch (pixel_clk) {
case 25200000:
case 27000000:
case 54000000:
case 74250000:
case 148500000:
cts = pixel_clk / 1000;
break;
case 297000000:
cts = 247500;
break;
case 25174000:
cts = 28125l;
break;
/*
* All other TMDS clocks are not supported by
* DWC_hdmi_tx. The TMDS clocks divided or
* multiplied by 1,001 coefficients are not
* supported.
*/
default:
break;
}
break;
case 44100:
case 88200:
case 176400:
switch (pixel_clk) {
case 25200000:
cts = 28000;
break;
case 25174000:
cts = 31250;
break;
case 27000000:
cts = 30000;
break;
case 54000000:
cts = 60000;
break;
case 74250000:
cts = 82500;
break;
case 148500000:
cts = 165000;
break;
case 297000000:
cts = 247500;
break;
default:
break;
}
break;
default:
break;
}
if (ratio == 100)
return cts;
else
return (cts * ratio) / 100;
}
static void hdmi_set_clk_regenerator(void)
{
unsigned int clk_n, clk_cts;
clk_n = hdmi_compute_n(sample_rate, pixel_clk_rate, hdmi_ratio);
clk_cts = hdmi_compute_cts(sample_rate, pixel_clk_rate, hdmi_ratio);
if (clk_cts == 0) {
pr_debug("%s: pixel clock not supported: %d\n",
__func__, (int)pixel_clk_rate);
return;
}
pr_debug("%s: samplerate=%d ratio=%d pixelclk=%d N=%d cts=%d\n",
__func__, sample_rate, hdmi_ratio, (int)pixel_clk_rate,
clk_n, clk_cts);
hdmi_set_clock_regenerator_cts(clk_cts);
hdmi_set_clock_regenerator_n(clk_n);
}
static int hdmi_core_get_of_property(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
int err;
int ipu_id, disp_id;
err = of_property_read_u32(np, "ipu_id", &ipu_id);
if (err) {
dev_dbg(&pdev->dev, "get of property ipu_id fail\n");
return err;
}
err = of_property_read_u32(np, "disp_id", &disp_id);
if (err) {
dev_dbg(&pdev->dev, "get of property disp_id fail\n");
return err;
}
mxc_hdmi_ipu_id = ipu_id;
mxc_hdmi_disp_id = disp_id;
return err;
}
/* Need to run this before phy is enabled the first time to prevent
* overflow condition in HDMI_IH_FC_STAT2 */
void hdmi_init_clk_regenerator(void)
{
if (pixel_clk_rate == 0) {
pixel_clk_rate = 74250000;
hdmi_set_clk_regenerator();
}
}
EXPORT_SYMBOL(hdmi_init_clk_regenerator);
void hdmi_clk_regenerator_update_pixel_clock(u32 pixclock)
{
if (!pixclock)
return;
/* Translate pixel clock in ps (pico seconds) to Hz */
pixel_clk_rate = PICOS2KHZ(pixclock) * 1000UL;
hdmi_set_clk_regenerator();
}
EXPORT_SYMBOL(hdmi_clk_regenerator_update_pixel_clock);
void hdmi_set_dma_mode(unsigned int dma_running)
{
hdmi_dma_running = dma_running;
hdmi_set_clk_regenerator();
}
EXPORT_SYMBOL(hdmi_set_dma_mode);
void hdmi_set_sample_rate(unsigned int rate)
{
sample_rate = rate;
}
EXPORT_SYMBOL(hdmi_set_sample_rate);
void hdmi_set_edid_cfg(struct mxc_edid_cfg *cfg)
{
unsigned long flags;
spin_lock_irqsave(&edid_spinlock, flags);
memcpy(&hdmi_core_edid_cfg, cfg, sizeof(struct mxc_edid_cfg));
spin_unlock_irqrestore(&edid_spinlock, flags);
}
EXPORT_SYMBOL(hdmi_set_edid_cfg);
void hdmi_get_edid_cfg(struct mxc_edid_cfg *cfg)
{
unsigned long flags;
spin_lock_irqsave(&edid_spinlock, flags);
memcpy(cfg, &hdmi_core_edid_cfg, sizeof(struct mxc_edid_cfg));
spin_unlock_irqrestore(&edid_spinlock, flags);
}
EXPORT_SYMBOL(hdmi_get_edid_cfg);
void hdmi_set_registered(int registered)
{
hdmi_core_init = registered;
}
EXPORT_SYMBOL(hdmi_set_registered);
int hdmi_get_registered(void)
{
return hdmi_core_init;
}
EXPORT_SYMBOL(hdmi_get_registered);
static int mxc_hdmi_core_probe(struct platform_device *pdev)
{
struct mxc_hdmi_data *hdmi_data;
struct resource *res;
unsigned long flags;
int ret = 0;
#ifdef DEBUG
overflow_lo = false;
overflow_hi = false;
#endif
hdmi_core_init = 0;
hdmi_dma_running = 0;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res)
return -ENOENT;
ret = hdmi_core_get_of_property(pdev);
if (ret < 0) {
dev_err(&pdev->dev, "get hdmi of property fail\n");
return -ENOENT;
}
hdmi_data = devm_kzalloc(&pdev->dev, sizeof(struct mxc_hdmi_data), GFP_KERNEL);
if (!hdmi_data) {
dev_err(&pdev->dev, "Couldn't allocate mxc hdmi mfd device\n");
return -ENOMEM;
}
hdmi_data->pdev = pdev;
pixel_clk = NULL;
sample_rate = 48000;
pixel_clk_rate = 0;
hdmi_ratio = 100;
spin_lock_init(&irq_spinlock);
spin_lock_init(&edid_spinlock);
spin_lock_init(&hdmi_cable_state_lock);
spin_lock_init(&hdmi_blank_state_lock);
spin_lock_init(&hdmi_audio_lock);
spin_lock_irqsave(&hdmi_cable_state_lock, flags);
hdmi_cable_state = 0;
spin_unlock_irqrestore(&hdmi_cable_state_lock, flags);
spin_lock_irqsave(&hdmi_blank_state_lock, flags);
hdmi_blank_state = 0;
spin_unlock_irqrestore(&hdmi_blank_state_lock, flags);
spin_lock_irqsave(&hdmi_audio_lock, flags);
hdmi_audio_stream_playback = NULL;
hdmi_abort_state = 0;
spin_unlock_irqrestore(&hdmi_audio_lock, flags);
mipi_core_clk = clk_get(&hdmi_data->pdev->dev, "mipi_core");
if (IS_ERR(mipi_core_clk)) {
ret = PTR_ERR(mipi_core_clk);
dev_err(&hdmi_data->pdev->dev,
"Unable to get mipi core clk: %d\n", ret);
goto eclkg;
}
ret = clk_prepare_enable(mipi_core_clk);
if (ret < 0) {
dev_err(&pdev->dev, "Cannot enable mipi core clock: %d\n", ret);
goto eclke;
}
isfr_clk = clk_get(&hdmi_data->pdev->dev, "hdmi_isfr");
if (IS_ERR(isfr_clk)) {
ret = PTR_ERR(isfr_clk);
dev_err(&hdmi_data->pdev->dev,
"Unable to get HDMI isfr clk: %d\n", ret);
goto eclkg1;
}
ret = clk_prepare_enable(isfr_clk);
if (ret < 0) {
dev_err(&pdev->dev, "Cannot enable HDMI clock: %d\n", ret);
goto eclke1;
}
pr_debug("%s isfr_clk:%d\n", __func__,
(int)clk_get_rate(isfr_clk));
iahb_clk = clk_get(&hdmi_data->pdev->dev, "hdmi_iahb");
if (IS_ERR(iahb_clk)) {
ret = PTR_ERR(iahb_clk);
dev_err(&hdmi_data->pdev->dev,
"Unable to get HDMI iahb clk: %d\n", ret);
goto eclkg2;
}
ret = clk_prepare_enable(iahb_clk);
if (ret < 0) {
dev_err(&pdev->dev, "Cannot enable HDMI clock: %d\n", ret);
goto eclke2;
}
hdmi_data->reg_phys_base = res->start;
if (!request_mem_region(res->start, resource_size(res),
dev_name(&pdev->dev))) {
dev_err(&pdev->dev, "request_mem_region failed\n");
ret = -EBUSY;
goto emem;
}
hdmi_data->reg_base = ioremap(res->start, resource_size(res));
if (!hdmi_data->reg_base) {
dev_err(&pdev->dev, "ioremap failed\n");
ret = -ENOMEM;
goto eirq;
}
hdmi_base = hdmi_data->reg_base;
pr_debug("\n%s hdmi hw base = 0x%08x\n\n", __func__, (int)res->start);
initialize_hdmi_ih_mutes();
/* Disable HDMI clocks until video/audio sub-drivers are initialized */
clk_disable_unprepare(isfr_clk);
clk_disable_unprepare(iahb_clk);
clk_disable_unprepare(mipi_core_clk);
/* Replace platform data coming in with a local struct */
platform_set_drvdata(pdev, hdmi_data);
return ret;
eirq:
release_mem_region(res->start, resource_size(res));
emem:
clk_disable_unprepare(iahb_clk);
eclke2:
clk_put(iahb_clk);
eclkg2:
clk_disable_unprepare(isfr_clk);
eclke1:
clk_put(isfr_clk);
eclkg1:
clk_disable_unprepare(mipi_core_clk);
eclke:
clk_put(mipi_core_clk);
eclkg:
return ret;
}
static int __exit mxc_hdmi_core_remove(struct platform_device *pdev)
{
struct mxc_hdmi_data *hdmi_data = platform_get_drvdata(pdev);
struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
iounmap(hdmi_data->reg_base);
release_mem_region(res->start, resource_size(res));
return 0;
}
static const struct of_device_id imx_hdmi_dt_ids[] = {
{ .compatible = "fsl,imx6q-hdmi-core", },
{ .compatible = "fsl,imx6dl-hdmi-core", },
{ /* sentinel */ }
};
static struct platform_driver mxc_hdmi_core_driver = {
.driver = {
.name = "mxc_hdmi_core",
.of_match_table = imx_hdmi_dt_ids,
.owner = THIS_MODULE,
},
.remove = __exit_p(mxc_hdmi_core_remove),
};
static int __init mxc_hdmi_core_init(void)
{
return platform_driver_probe(&mxc_hdmi_core_driver,
mxc_hdmi_core_probe);
}
static void __exit mxc_hdmi_core_exit(void)
{
platform_driver_unregister(&mxc_hdmi_core_driver);
}
subsys_initcall(mxc_hdmi_core_init);
module_exit(mxc_hdmi_core_exit);
MODULE_DESCRIPTION("Core driver for Freescale i.Mx on-chip HDMI");
MODULE_AUTHOR("Freescale Semiconductor, Inc.");
MODULE_LICENSE("GPL");

View File

@ -1 +1,40 @@
# drivers/mxc/Kconfig
if ARCH_MXC
menu "MXC support drivers"
config MXC_SIM
tristate "MXC SIM support"
default n
help
Say Y to get MXC SIM support.
config MXC_IPU
bool "Image Processing Unit Driver"
select MXC_IPU_V3
help
If you plan to use the Image Processing unit, say
Y here. IPU is needed by Framebuffer and V4L2 drivers.
# drivers common to MXC and MX8 go here:
if ARM64
source "drivers/mxc/hantro/Kconfig"
source "drivers/mxc/hantro_845/Kconfig"
source "drivers/mxc/hantro_845_h1/Kconfig"
source "drivers/mxc/vpu_malone/Kconfig"
source "drivers/mxc/vpu_windsor/Kconfig"
endif
source "drivers/mxc/gpu-viv/Kconfig"
source "drivers/mxc/vpu/Kconfig"
source "drivers/mxc/sim/Kconfig"
source "drivers/mxc/mlb/Kconfig"
source "drivers/mxc/ipu3/Kconfig"
source "drivers/mxc/hdmi-cec/Kconfig"
source "drivers/mxc/mipi/Kconfig"
endmenu
endif

View File

@ -1 +1,12 @@
obj-$(CONFIG_MXC_GPU_VIV) += gpu-viv/
obj-$(CONFIG_MXC_HANTRO) += hantro/
obj-$(CONFIG_MXC_HANTRO_845) += hantro_845/
obj-$(CONFIG_MXC_HANTRO_845_H1) += hantro_845_h1/
obj-$(CONFIG_MXC_VPU_MALONE) += vpu_malone/
obj-$(CONFIG_MXC_VPU_WINDSOR) += vpu_windsor/
obj-$(CONFIG_MXC_VPU) += vpu/
obj-$(CONFIG_MXC_SIM) += sim/
obj-$(CONFIG_MXC_MLB) += mlb/
obj-$(CONFIG_MXC_IPU_V3) += ipu3/
obj-$(CONFIG_MXC_HDMI_CEC) += hdmi-cec/
obj-$(CONFIG_MXC_MIPI_CSI2) += mipi/

View File

@ -0,0 +1,330 @@
##############################################################################
#
# The MIT License (MIT)
#
# Copyright (c) 2014 - 2019 Vivante Corporation
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the "Software"),
# to deal in the Software without restriction, including without limitation
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
# and/or sell copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
# DEALINGS IN THE SOFTWARE.
#
##############################################################################
#
# The GPL License (GPL)
#
# Copyright (C) 2014 - 2019 Vivante Corporation
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
##############################################################################
#
# Note: This software is released under dual MIT and GPL licenses. A
# recipient may use this file under the terms of either the MIT license or
# GPL License. If you wish to use only one license not the other, you can
# indicate your decision by deleting one of the above license notices in your
# version of this file.
#
##############################################################################
#
# Linux build file for kernel HAL driver.
#
AQROOT := $(srctree)/drivers/mxc/gpu-viv
include $(AQROOT)/config
soc_vendor := $(firstword $(subst -, ,$(SOC_PLATFORM)))
soc_board := $(lastword $(subst -, ,$(SOC_PLATFORM)))
KERNEL_DIR ?= $(TOOL_DIR)/kernel
OS_KERNEL_DIR := hal/os/linux/kernel
ARCH_KERNEL_DIR := hal/kernel/arch
ARCH_VG_KERNEL_DIR := hal/kernel/archvg
HAL_KERNEL_DIR := hal/kernel
TA_DIR := hal/security_v1
HOST := $(shell hostname)
MODULE_NAME ?= galcore
CUSTOMER_ALLOCATOR_OBJS ?=
ALLOCATOR_ARRAY_H_LOCATION ?= $(OS_KERNEL_DIR)/allocator/default/
SOC_PLATFORM_LOCATION ?= $(OS_KERNEL_DIR)/platform/$(soc_vendor)
# Set common platform driver source
SOC_PLATFORM_OBJS ?= $(SOC_PLATFORM_LOCATION)/gc_hal_kernel_platform_$(soc_board).o
# Include platform config if exists.
-include $(AQROOT)/$(SOC_PLATFORM_LOCATION)/gc_hal_kernel_platform_$(soc_board).config
ifeq ($(CONFIG_KASAN),)
EXTRA_CFLAGS += -Werror -Wno-implicit-fallthrough
endif
OBJS := $(OS_KERNEL_DIR)/gc_hal_kernel_device.o \
$(OS_KERNEL_DIR)/gc_hal_kernel_linux.o \
$(OS_KERNEL_DIR)/gc_hal_kernel_math.o \
$(OS_KERNEL_DIR)/gc_hal_kernel_os.o \
$(OS_KERNEL_DIR)/gc_hal_kernel_debugfs.o \
$(OS_KERNEL_DIR)/gc_hal_kernel_allocator.o \
$(OS_KERNEL_DIR)/allocator/default/gc_hal_kernel_allocator_user_memory.o \
$(OS_KERNEL_DIR)/allocator/default/gc_hal_kernel_allocator_dma.o \
$(OS_KERNEL_DIR)/allocator/default/gc_hal_kernel_allocator_gfp.o \
$(OS_KERNEL_DIR)/allocator/default/gc_hal_kernel_allocator_reserved_mem.o \
$(OS_KERNEL_DIR)/gc_hal_kernel_driver.o
# Source files for soc platform board
OBJS += $(SOC_PLATFORM_OBJS)
ifneq ($(CONFIG_DMA_SHARED_BUFFER),)
OBJS += $(OS_KERNEL_DIR)/allocator/default/gc_hal_kernel_allocator_dmabuf.o
endif
ifneq ($(CONFIG_IOMMU_SUPPORT),)
OBJS += $(OS_KERNEL_DIR)/gc_hal_kernel_iommu.o
endif
ifneq ($(CONFIG_DRM),)
OBJS += $(OS_KERNEL_DIR)/gc_hal_kernel_drm.o
endif
OBJS += $(HAL_KERNEL_DIR)/gc_hal_kernel.o \
$(HAL_KERNEL_DIR)/gc_hal_kernel_command.o \
$(HAL_KERNEL_DIR)/gc_hal_kernel_db.o \
$(HAL_KERNEL_DIR)/gc_hal_kernel_debug.o \
$(HAL_KERNEL_DIR)/gc_hal_kernel_event.o \
$(HAL_KERNEL_DIR)/gc_hal_kernel_heap.o \
$(HAL_KERNEL_DIR)/gc_hal_kernel_mmu.o \
$(HAL_KERNEL_DIR)/gc_hal_kernel_video_memory.o \
$(HAL_KERNEL_DIR)/gc_hal_kernel_power.o \
$(HAL_KERNEL_DIR)/gc_hal_kernel_security_v1.o
OBJS += $(ARCH_KERNEL_DIR)/gc_hal_kernel_context.o \
$(ARCH_KERNEL_DIR)/gc_hal_kernel_hardware.o \
$(ARCH_KERNEL_DIR)/gc_hal_kernel_hardware_async_fe.o \
$(ARCH_KERNEL_DIR)/gc_hal_kernel_hardware_mc_fe.o \
$(ARCH_KERNEL_DIR)/gc_hal_kernel_hardware_waitlink_fe.o
ifeq ($(VIVANTE_ENABLE_3D), 1)
OBJS += $(ARCH_KERNEL_DIR)/gc_hal_kernel_recorder.o
endif
ifneq ($(CONFIG_ARM64),)
ifeq ($(CONFIG_ANDROID),)
VIVANTE_ENABLE_VG=0
endif
endif
ifeq ($(VIVANTE_ENABLE_VG), 1)
OBJS +=\
$(HAL_KERNEL_DIR)/gc_hal_kernel_vg.o\
$(HAL_KERNEL_DIR)/gc_hal_kernel_command_vg.o\
$(HAL_KERNEL_DIR)/gc_hal_kernel_interrupt_vg.o\
$(HAL_KERNEL_DIR)/gc_hal_kernel_mmu_vg.o\
$(ARCH_VG_KERNEL_DIR)/gc_hal_kernel_hardware_command_vg.o\
$(ARCH_VG_KERNEL_DIR)/gc_hal_kernel_hardware_vg.o
endif
ifneq ($(CONFIG_SYNC),)
EXTRA_CFLAGS += -Idrivers/staging/android
EXTRA_CFLAGS += -DgcdLINUX_SYNC_FILE=1
OBJS += $(OS_KERNEL_DIR)/gc_hal_kernel_sync.o
else
ifneq ($(CONFIG_SYNC_FILE),)
EXTRA_CFLAGS += -DgcdLINUX_SYNC_FILE=1
OBJS += $(OS_KERNEL_DIR)/gc_hal_kernel_sync.o
endif
endif
ifeq ($(SECURITY), 1)
OBJS += $(OS_KERNEL_DIR)/gc_hal_kernel_security_channel.o \
$(HAL_KERNEL_DIR)/gc_hal_kernel_security.o
endif
ifneq ($(CUSTOMER_ALLOCATOR_OBJS),)
OBJS += $(CUSTOMER_ALLOCATOR_OBJS)
endif
OBJS += $(OS_KERNEL_DIR)/gc_hal_kernel_security_channel_emulator.o \
$(TA_DIR)/gc_hal_ta.o \
$(TA_DIR)/gc_hal_ta_hardware.o \
$(TA_DIR)/gc_hal_ta_mmu.o \
$(TA_DIR)/os/emulator/gc_hal_ta_emulator.o
ifeq ($(KERNELRELEASE), )
.PHONY: all clean install
# Define targets.
all:
@$(MAKE) V=$(V) ARCH=$(ARCH_TYPE) -C $(KERNEL_DIR) SUBDIRS=`pwd` modules
clean:
@rm -rf $(OBJS)
@rm -rf modules.order Module.symvers .tmp_versions
@find $(AQROOT) -name ".gc_*.cmd" | xargs rm -f
install: all
@mkdir -p $(SDK_DIR)/drivers
@cp $(MODULE_NAME).ko $(SDK_DIR)/drivers
else
EXTRA_CFLAGS += -DLINUX -DDRIVER
ifeq ($(FLAREON),1)
EXTRA_CFLAGS += -DFLAREON
endif
ifeq ($(DEBUG), 1)
EXTRA_CFLAGS += -DDBG=1 -DDEBUG -D_DEBUG
else
EXTRA_CFLAGS += -DDBG=0
endif
ifeq ($(NO_DMA_COHERENT), 1)
EXTRA_CFLAGS += -DNO_DMA_COHERENT
endif
ifeq ($(CONFIG_DOVE_GPU), 1)
EXTRA_CFLAGS += -DCONFIG_DOVE_GPU=1
endif
ifneq ($(USE_PLATFORM_DRIVER), 0)
EXTRA_CFLAGS += -DUSE_PLATFORM_DRIVER=1
else
EXTRA_CFLAGS += -DUSE_PLATFORM_DRIVER=0
endif
EXTRA_CFLAGS += -DVIVANTE_PROFILER=1
EXTRA_CFLAGS += -DVIVANTE_PROFILER_CONTEXT=1
ifeq ($(ENABLE_GPU_CLOCK_BY_DRIVER), 1)
EXTRA_CFLAGS += -DENABLE_GPU_CLOCK_BY_DRIVER=1
else
EXTRA_CFLAGS += -DENABLE_GPU_CLOCK_BY_DRIVER=0
endif
ifeq ($(USE_NEW_LINUX_SIGNAL), 1)
EXTRA_CFLAGS += -DUSE_NEW_LINUX_SIGNAL=1
else
EXTRA_CFLAGS += -DUSE_NEW_LINUX_SIGNAL=0
endif
ifeq ($(USE_LINUX_PCIE), 1)
EXTRA_CFLAGS += -DUSE_LINUX_PCIE=1
else
EXTRA_CFLAGS += -DUSE_LINUX_PCIE=0
endif
ifeq ($(CACHE_FUNCTION_UNIMPLEMENTED), 1)
EXTRA_CFLAGS += -DgcdCACHE_FUNCTION_UNIMPLEMENTED=1
else
EXTRA_CFLAGS += -DgcdCACHE_FUNCTION_UNIMPLEMENTED=0
endif
ifeq ($(VIVANTE_ENABLE_3D),0)
EXTRA_CFLAGS += -DgcdENABLE_3D=0
else
EXTRA_CFLAGS += -DgcdENABLE_3D=1
endif
ifeq ($(VIVANTE_ENABLE_2D),0)
EXTRA_CFLAGS += -DgcdENABLE_2D=0
else
EXTRA_CFLAGS += -DgcdENABLE_2D=1
endif
ifeq ($(VIVANTE_ENABLE_VG),0)
EXTRA_CFLAGS += -DgcdENABLE_VG=0
else
EXTRA_CFLAGS += -DgcdENABLE_VG=1
endif
ifeq ($(USE_BANK_ALIGNMENT), 1)
EXTRA_CFLAGS += -DgcdENABLE_BANK_ALIGNMENT=1
ifneq ($(BANK_BIT_START), 0)
ifneq ($(BANK_BIT_END), 0)
EXTRA_CFLAGS += -DgcdBANK_BIT_START=$(BANK_BIT_START)
EXTRA_CFLAGS += -DgcdBANK_BIT_END=$(BANK_BIT_END)
endif
endif
ifneq ($(BANK_CHANNEL_BIT), 0)
EXTRA_CFLAGS += -DgcdBANK_CHANNEL_BIT=$(BANK_CHANNEL_BIT)
endif
endif
ifeq ($(FPGA_BUILD), 1)
EXTRA_CFLAGS += -DgcdFPGA_BUILD=1
else
EXTRA_CFLAGS += -DgcdFPGA_BUILD=0
endif
ifeq ($(SECURITY), 1)
EXTRA_CFLAGS += -DgcdSECURITY=1
endif
ifneq ($(CONFIG_DRM), )
ifneq ($(CONFIG_ANDROID),)
EXTRA_CFLAGS += -DgcdENABLE_DRM=$(VIVANTE_ENABLE_DRM)
else
EXTRA_CFLAGS += -DgcdENABLE_DRM=0
endif
else
EXTRA_CFLAGS += -DgcdENABLE_DRM=0
endif
EXTRA_CFLAGS += -I$(AQROOT)/hal/kernel/inc
EXTRA_CFLAGS += -I$(AQROOT)/hal/kernel
EXTRA_CFLAGS += -I$(AQROOT)/hal/kernel/arch
EXTRA_CFLAGS += -I$(AQROOT)/hal/kernel/inc
EXTRA_CFLAGS += -I$(AQROOT)/hal/os/linux/kernel
EXTRA_CFLAGS += -I$(AQROOT)/$(ALLOCATOR_ARRAY_H_LOCATION)
EXTRA_CFLAGS += -I$(AQROOT)/hal/security_v1/
EXTRA_CFLAGS += -I$(AQROOT)/$(SOC_PLATFORM_LOCATION)
ifneq ($(CONFIG_ARM), )
EXTRA_CFLAGS += -Iarch/arm/mm
endif
ifeq ($(VIVANTE_ENABLE_VG), 1)
EXTRA_CFLAGS += -I$(AQROOT)/hal/kernel/archvg
endif
EXTRA_CFLAGS += -DHOST=\"$(HOST)\"
EXTRA_CFLAGS += -DgcdENABLE_TRUST_APPLICATION=1
obj-$(CONFIG_MXC_GPU_VIV) = $(MODULE_NAME).o
$(MODULE_NAME)-objs = $(OBJS)
endif

View File

@ -0,0 +1,10 @@
menu "MXC Vivante GPU support"
config MXC_GPU_VIV
tristate "MXC Vivante GPU support"
default y
---help---
Say Y to get the GPU driver support.
endmenu

View File

@ -0,0 +1,71 @@
##############################################################################
#
# The MIT License (MIT)
#
# Copyright (c) 2014 - 2019 Vivante Corporation
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the "Software"),
# to deal in the Software without restriction, including without limitation
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
# and/or sell copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
# DEALINGS IN THE SOFTWARE.
#
##############################################################################
#
# The GPL License (GPL)
#
# Copyright (C) 2014 - 2019 Vivante Corporation
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
##############################################################################
#
# Note: This software is released under dual MIT and GPL licenses. A
# recipient may use this file under the terms of either the MIT license or
# GPL License. If you wish to use only one license not the other, you can
# indicate your decision by deleting one of the above license notices in your
# version of this file.
#
##############################################################################
ARCH_TYPE ?= arm
SDK_DIR ?= $(AQROOT)/build/sdk
VIVANTE_ENABLE_3D ?= 1
VIVANTE_ENABLE_2D ?= 1
VIVANTE_ENABLE_VG ?= 1
VIVANTE_ENABLE_DRM ?= 1
NO_DMA_COHERENT ?= 0
USE_PLATFORM_DRIVER ?= 1
ENABLE_GPU_CLOCK_BY_DRIVER ?= 0
CACHE_FUNCTION_UNIMPLEMENTED ?= 0
USE_BANK_ALIGNMENT ?= 1
BANK_BIT_START ?= 13
BANK_BIT_END ?= 15
BANK_CHANNEL_BIT ?= 12
SECURITY ?= 0
SOC_PLATFORM ?= freescale-imx

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,183 @@
/****************************************************************************
*
* The MIT License (MIT)
*
* Copyright (c) 2014 - 2019 Vivante Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
*****************************************************************************
*
* The GPL License (GPL)
*
* Copyright (C) 2014 - 2019 Vivante Corporation
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*****************************************************************************
*
* Note: This software is released under dual MIT and GPL licenses. A
* recipient may use this file under the terms of either the MIT license or
* GPL License. If you wish to use only one license not the other, you can
* indicate your decision by deleting one of the above license notices in your
* version of this file.
*
*****************************************************************************/
#ifndef __gc_hal_kernel_context_h_
#define __gc_hal_kernel_context_h_
#include "gc_hal_kernel_buffer.h"
#ifdef __cplusplus
extern "C" {
#endif
/* Maps state locations within the context buffer. */
typedef struct _gcsSTATE_MAP * gcsSTATE_MAP_PTR;
typedef struct _gcsSTATE_MAP
{
/* Index of the state in the context buffer. */
gctUINT index;
/* State mask. */
gctUINT32 mask;
}
gcsSTATE_MAP;
/* Context buffer. */
typedef struct _gcsCONTEXT * gcsCONTEXT_PTR;
typedef struct _gcsCONTEXT
{
/* For debugging: the number of context buffer in the order of creation. */
gctUINT num;
/* Pointer to gckEVENT object. */
gckEVENT eventObj;
/* Context busy signal. */
gctSIGNAL signal;
/* Video memory of the context buffer. */
gckVIDMEM_NODE videoMem;
/* Logical address of the context buffer. */
gctUINT32_PTR logical;
/* Hardware address of the context buffer. */
gctUINT32 address;
/* Pointer to the LINK commands. */
gctPOINTER link2D;
gctPOINTER link3D;
/* Next context buffer. */
gcsCONTEXT_PTR next;
}
gcsCONTEXT;
typedef struct _gcsRECORD_ARRAY_MAP * gcsRECORD_ARRAY_MAP_PTR;
struct _gcsRECORD_ARRAY_MAP
{
/* User pointer key. */
gctUINT64 key;
/* Kernel memory buffer. */
gcsSTATE_DELTA_RECORD_PTR kData;
/* Next map. */
gcsRECORD_ARRAY_MAP_PTR next;
};
#define USE_SW_RESET 1
/* gckCONTEXT structure that hold the current context. */
struct _gckCONTEXT
{
/* Object. */
gcsOBJECT object;
/* Pointer to gckOS object. */
gckOS os;
/* Pointer to gckHARDWARE object. */
gckHARDWARE hardware;
/* Command buffer alignment. */
gctUINT32 alignment;
gctUINT32 reservedHead;
/* Context buffer metrics. */
gctSIZE_T maxState;
gctUINT32 numStates;
gctUINT32 totalSize;
gctUINT32 bufferSize;
gctUINT32 linkIndex2D;
gctUINT32 linkIndex3D;
gctUINT32 linkIndexXD;
gctUINT32 entryOffset3D;
gctUINT32 entryOffsetXDFrom2D;
gctUINT32 entryOffsetXDFrom3D;
/* State mapping. */
gcsSTATE_MAP_PTR map;
/* List of context buffers. */
gcsCONTEXT_PTR buffer;
/* Requested pipe select for context. */
gcePIPE_SELECT entryPipe;
gcePIPE_SELECT exitPipe;
/* Variables used for building state buffer. */
gctUINT32 lastAddress;
gctSIZE_T lastSize;
gctUINT32 lastIndex;
gctBOOL lastFixed;
gctUINT32 pipeSelectBytes;
gcsPROFILER_COUNTERS_PART1 latestProfiler_part1;
gcsPROFILER_COUNTERS_PART1 histroyProfiler_part1;
gcsPROFILER_COUNTERS_PART1 preProfiler_part1;
gcsPROFILER_COUNTERS_PART2 latestProfiler_part2;
gcsPROFILER_COUNTERS_PART2 histroyProfiler_part2;
gcsPROFILER_COUNTERS_PART2 preProfiler_part2;
};
#ifdef __cplusplus
}
#endif
#endif /* __gc_hal_kernel_context_h_ */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,345 @@
/****************************************************************************
*
* The MIT License (MIT)
*
* Copyright (c) 2014 - 2019 Vivante Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
*****************************************************************************
*
* The GPL License (GPL)
*
* Copyright (C) 2014 - 2019 Vivante Corporation
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*****************************************************************************
*
* Note: This software is released under dual MIT and GPL licenses. A
* recipient may use this file under the terms of either the MIT license or
* GPL License. If you wish to use only one license not the other, you can
* indicate your decision by deleting one of the above license notices in your
* version of this file.
*
*****************************************************************************/
#ifndef __gc_hal_kernel_hardware_h_
#define __gc_hal_kernel_hardware_h_
#if gcdENABLE_VG
#include "gc_hal_kernel_hardware_vg.h"
#endif
#ifdef __cplusplus
extern "C" {
#endif
#define EVENT_ID_INVALIDATE_PIPE 29
typedef enum {
gcvHARDWARE_FUNCTION_MMU,
gcvHARDWARE_FUNCTION_FLUSH,
gcvHARDWARE_FUNCTION_DUMMY_DRAW,
gcvHARDWARE_FUNCTION_NUM,
}
gceHARDWARE_FUNCTION;
typedef struct _gckASYNC_FE * gckASYNC_FE;
typedef struct _gckWLFE * gckWLFE;
typedef struct _gckMCFE * gckMCFE;
typedef struct _gcsHARWARE_FUNCTION
{
/* Entry of the function. */
gctUINT32 address;
/* CPU address of the function. */
gctUINT8_PTR logical;
/* Bytes of the function. */
gctUINT32 bytes;
/* Hardware address of END in this function. */
gctUINT32 endAddress;
/* Logical of END in this function. */
gctUINT8_PTR endLogical;
}
gcsHARDWARE_FUNCTION;
typedef struct _gcsSTATETIMER
{
gctUINT64 start;
gctUINT64 recent;
/* Elapse of each power state. */
gctUINT64 elapse[4];
}
gcsSTATETIMER;
typedef struct _gcsHARDWARE_SIGNATURE
{
/* Chip model. */
gceCHIPMODEL chipModel;
/* Revision value.*/
gctUINT32 chipRevision;
/* Supported feature fields. */
gctUINT32 chipFeatures;
/* Supported minor feature fields. */
gctUINT32 chipMinorFeatures;
/* Supported minor feature 1 fields. */
gctUINT32 chipMinorFeatures1;
/* Supported minor feature 2 fields. */
gctUINT32 chipMinorFeatures2;
}
gcsHARDWARE_SIGNATURE;
typedef struct _gcsMMU_TABLE_ARRAY_ENTRY
{
gctUINT32 low;
gctUINT32 high;
}
gcsMMU_TABLE_ARRAY_ENTRY;
typedef struct _gcsHARDWARE_PAGETABLE_ARRAY
{
/* Number of entries in page table array. */
gctUINT num;
/* Video memory node. */
gckVIDMEM_NODE videoMem;
/* Size in bytes of array. */
gctSIZE_T size;
/* Physical address of array. */
gctPHYS_ADDR_T address;
/* Logical address of array. */
gctPOINTER logical;
}
gcsHARDWARE_PAGETABLE_ARRAY;
/* gckHARDWARE object. */
struct _gckHARDWARE
{
/* Object. */
gcsOBJECT object;
/* Pointer to gctKERNEL object. */
gckKERNEL kernel;
/* Pointer to gctOS object. */
gckOS os;
/* Core */
gceCORE core;
/* Type */
gceHARDWARE_TYPE type;
/* Chip characteristics. */
gcsHAL_QUERY_CHIP_IDENTITY identity;
gcsHAL_QUERY_CHIP_OPTIONS options;
gctUINT32 powerBaseAddress;
gctBOOL extraEventStates;
/* Big endian */
gctBOOL bigEndian;
/* Base address. */
gctUINT32 baseAddress;
/* FE modules. */
gckWLFE wlFE;
gckASYNC_FE asyncFE;
gckMCFE mcFE;
/* Chip status */
gctPOINTER powerMutex;
gceCHIPPOWERSTATE chipPowerState;
gctBOOL clockState;
gctBOOL powerState;
gctPOINTER globalSemaphore;
gctBOOL isLastPowerGlobal;
/* Wait Link FE only. */
gctUINT32 lastWaitLink;
gctUINT32 lastEnd;
gctUINT32 mmuVersion;
gceCHIPPOWERSTATE nextPowerState;
gctPOINTER powerStateTimer;
#if gcdENABLE_FSCALE_VAL_ADJUST
gctUINT32 powerOnFscaleVal;
#endif
gctPOINTER pageTableDirty[gcvENGINE_GPU_ENGINE_COUNT];
#if gcdLINK_QUEUE_SIZE
struct _gckQUEUE linkQueue;
#endif
gctBOOL stallFEPrefetch;
gctUINT32 minFscaleValue;
gctUINT waitCount;
gctUINT32 mcClk;
gctUINT32 shClk;
gctPOINTER pendingEvent;
/* Function used by gckHARDWARE. */
gckVIDMEM_NODE mmuFuncVideoMem;
gctPOINTER mmuFuncLogical;
gctSIZE_T mmuFuncBytes;
gckVIDMEM_NODE auxFuncVideoMem;
gctPOINTER auxFuncLogical;
gctUINT32 auxFuncAddress;
gctSIZE_T auxFuncBytes;
gcsHARDWARE_FUNCTION functions[gcvHARDWARE_FUNCTION_NUM];
gcsSTATETIMER powerStateCounter;
gctUINT32 executeCount;
gctUINT32 lastExecuteAddress;
/* Head for hardware list in gckMMU. */
gcsLISTHEAD mmuHead;
/* Internal SRAMs info. */
gckVIDMEM sRAMVidMem[gcvSRAM_INTER_COUNT];
gctPHYS_ADDR sRAMPhysical[gcvSRAM_INTER_COUNT];
gctPOINTER featureDatabase;
gctBOOL hasL2Cache;
/* MCFE channel bindings, temporary. */
gceMCFE_CHANNEL_TYPE mcfeChannels[64];
gctUINT32 mcfeChannelCount;
gcsHARDWARE_SIGNATURE signature;
gctUINT32 maxOutstandingReads;
gcsHARDWARE_PAGETABLE_ARRAY pagetableArray;
gctUINT64 contextID;
};
gceSTATUS
gckHARDWARE_GetBaseAddress(
IN gckHARDWARE Hardware,
OUT gctUINT32_PTR BaseAddress
);
gceSTATUS
gckHARDWARE_NeedBaseAddress(
IN gckHARDWARE Hardware,
IN gctUINT32 State,
OUT gctBOOL_PTR NeedBase
);
gceSTATUS
gckHARDWARE_GetFrameInfo(
IN gckHARDWARE Hardware,
OUT gcsHAL_FRAME_INFO * FrameInfo
);
gceSTATUS
gckHARDWARE_DumpGpuProfile(
IN gckHARDWARE Hardware
);
gceSTATUS
gckHARDWARE_HandleFault(
IN gckHARDWARE Hardware
);
gceSTATUS
gckHARDWARE_ExecuteFunctions(
IN gckHARDWARE Hardware,
IN gceHARDWARE_FUNCTION Function
);
gceSTATUS
gckHARDWARE_DummyDraw(
IN gckHARDWARE Hardware,
IN gctPOINTER Logical,
IN gctUINT32 Address,
IN gceDUMMY_DRAW_TYPE DummyDrawType,
IN OUT gctUINT32 * Bytes
);
gceSTATUS
gckHARDWARE_EnterQueryClock(
IN gckHARDWARE Hardware,
OUT gctUINT64 *McStart,
OUT gctUINT64 *ShStart
);
gceSTATUS
gckHARDWARE_ExitQueryClock(
IN gckHARDWARE Hardware,
IN gctUINT64 McStart,
IN gctUINT64 ShStart,
OUT gctUINT32 *McClk,
OUT gctUINT32 *ShClk
);
gceSTATUS
gckHARDWARE_QueryFrequency(
IN gckHARDWARE Hardware
);
#define gcmkWRITE_MEMORY(logical, data) \
do { \
gcmkVERIFY_OK(gckOS_WriteMemory(os, logical, data)); \
logical++; \
}\
while (0) ; \
#ifdef __cplusplus
}
#endif
#endif /* __gc_hal_kernel_hardware_h_ */

View File

@ -0,0 +1,670 @@
/****************************************************************************
*
* The MIT License (MIT)
*
* Copyright (c) 2014 - 2019 Vivante Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
*****************************************************************************
*
* The GPL License (GPL)
*
* Copyright (C) 2014 - 2019 Vivante Corporation
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*****************************************************************************
*
* Note: This software is released under dual MIT and GPL licenses. A
* recipient may use this file under the terms of either the MIT license or
* GPL License. If you wish to use only one license not the other, you can
* indicate your decision by deleting one of the above license notices in your
* version of this file.
*
*****************************************************************************/
#include "gc_hal.h"
#include "gc_hal_kernel.h"
#include "gc_hal_kernel_context.h"
#define _GC_OBJ_ZONE gcvZONE_HARDWARE
struct _gckASYNC_FE
{
/* Number of free descriptors. */
gctPOINTER freeDscriptors;
};
gceSTATUS
gckASYNC_FE_Construct(
IN gckHARDWARE Hardware,
OUT gckASYNC_FE * FE
)
{
gceSTATUS status;
gctUINT32 data;
gckASYNC_FE fe;
gcmkHEADER();
gcmkONERROR(gckOS_Allocate(Hardware->os,
gcmSIZEOF(struct _gckASYNC_FE),
(gctPOINTER *)&fe));
gckOS_ZeroMemory(fe, gcmSIZEOF(struct _gckASYNC_FE));
gcmkVERIFY_OK(gckOS_ReadRegisterEx(
Hardware->os,
Hardware->core,
0x007E4,
&data
));
gcmkONERROR(gckOS_AtomConstruct(Hardware->os, &fe->freeDscriptors));
data = (((((gctUINT32) (data)) >> (0 ? 6:0)) & ((gctUINT32) ((((1 ? 6:0) - (0 ? 6:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 6:0) - (0 ? 6:0) + 1)))))) );
gcmkTRACE_ZONE(gcvLEVEL_INFO, _GC_OBJ_ZONE, "free descriptor=%d", data);
gcmkONERROR(gckOS_AtomSet(Hardware->os, fe->freeDscriptors, data));
/* Enable interrupts. */
gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x000D8, ~0U));
*FE = fe;
gcmkFOOTER_NO();
return gcvSTATUS_OK;
OnError:
if (fe)
{
if (fe->freeDscriptors)
{
gckOS_AtomDestroy(Hardware->os, fe->freeDscriptors);
}
gcmkOS_SAFE_FREE(Hardware->os, fe);
}
gcmkFOOTER();
return status;
}
void
gckASYNC_FE_Destroy(
IN gckHARDWARE Hardware,
IN gckASYNC_FE FE
)
{
if (FE->freeDscriptors)
{
gcmkOS_SAFE_FREE(Hardware->os, FE->freeDscriptors);
}
gcmkOS_SAFE_FREE(Hardware->os, FE);
}
gceSTATUS
gckASYNC_FE_Initialize(
IN gckHARDWARE Hardware,
IN gckASYNC_FE FE
)
{
return gcvSTATUS_OK;
}
gceSTATUS
gckASYNC_FE_Nop(
IN gckHARDWARE Hardware,
IN gctPOINTER Logical,
IN OUT gctSIZE_T * Bytes
)
{
gctUINT32_PTR logical = (gctUINT32_PTR) Logical;
gceSTATUS status;
gcmkHEADER_ARG("Hardware=0x%x Logical=0x%x *Bytes=%lu",
Hardware, Logical, gcmOPT_VALUE(Bytes));
/* Verify the arguments. */
gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
gcmkVERIFY_ARGUMENT((Logical == gcvNULL) || (Bytes != gcvNULL));
if (Logical != gcvNULL)
{
if (*Bytes < 8)
{
/* Command queue too small. */
gcmkONERROR(gcvSTATUS_BUFFER_TOO_SMALL);
}
/* Append NOP. */
logical[0] = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
31:27) - (0 ?
31:27) + 1) == 32) ?
~0U : (~(~0U << ((1 ?
31:27) - (0 ?
31:27) + 1))))))) << (0 ?
31:27))) | (((gctUINT32) (0x03 & ((gctUINT32) ((((1 ?
31:27) - (0 ?
31:27) + 1) == 32) ?
~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)));
gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE, "0x%x: NOP", Logical);
}
if (Bytes != gcvNULL)
{
/* Return number of bytes required by the NOP command. */
*Bytes = 8;
}
/* Success. */
gcmkFOOTER_ARG("*Bytes=%lu", gcmOPT_VALUE(Bytes));
return gcvSTATUS_OK;
OnError:
/* Return the status. */
gcmkFOOTER();
return status;
}
gceSTATUS
gckASYNC_FE_Event(
IN gckHARDWARE Hardware,
IN gctPOINTER Logical,
IN gctUINT8 Event,
IN gceKERNEL_WHERE FromWhere,
IN OUT gctUINT32 * Bytes
)
{
gctUINT size;
gctUINT32 destination = 0;
gctUINT32_PTR logical = (gctUINT32_PTR) Logical;
gceSTATUS status;
gctBOOL blt;
gctBOOL extraEventStates;
gctBOOL multiCluster;
gcmkHEADER_ARG("Hardware=0x%x Logical=0x%x Event=%u FromWhere=%d *Bytes=%lu",
Hardware, Logical, Event, FromWhere, gcmOPT_VALUE(Bytes));
/* Verify the arguments. */
gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
gcmkVERIFY_ARGUMENT((Logical == gcvNULL) || (Bytes != gcvNULL));
gcmkVERIFY_ARGUMENT(Event < 32);
if (gckHARDWARE_IsFeatureAvailable(Hardware, gcvFEATURE_BLT_ENGINE))
{
/* Send all event from blt. */
if (FromWhere == gcvKERNEL_PIXEL)
{
FromWhere = gcvKERNEL_BLT;
}
}
blt = FromWhere == gcvKERNEL_BLT ? gcvTRUE : gcvFALSE;
multiCluster = gckHARDWARE_IsFeatureAvailable(Hardware, gcvFEATURE_MULTI_CLUSTER);
/* Determine the size of the command. */
extraEventStates = Hardware->extraEventStates && (FromWhere == gcvKERNEL_PIXEL);
size = extraEventStates
? gcmALIGN(8 + (1 + 5) * 4, 8) /* EVENT + 5 STATES */
: 8;
if (blt)
{
size += 16;
if (multiCluster)
size += 8;
}
if (Logical != gcvNULL)
{
if (*Bytes < size)
{
/* Command queue too small. */
gcmkONERROR(gcvSTATUS_BUFFER_TOO_SMALL);
}
switch (FromWhere)
{
case gcvKERNEL_COMMAND:
/* From command processor. */
destination = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
5:5) - (0 ?
5:5) + 1) == 32) ?
~0U : (~(~0U << ((1 ?
5:5) - (0 ?
5:5) + 1))))))) << (0 ?
5:5))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ?
5:5) - (0 ?
5:5) + 1) == 32) ?
~0U : (~(~0U << ((1 ? 5:5) - (0 ? 5:5) + 1))))))) << (0 ? 5:5)));
break;
case gcvKERNEL_PIXEL:
/* From pixel engine. */
destination = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
6:6) - (0 ?
6:6) + 1) == 32) ?
~0U : (~(~0U << ((1 ?
6:6) - (0 ?
6:6) + 1))))))) << (0 ?
6:6))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ?
6:6) - (0 ?
6:6) + 1) == 32) ?
~0U : (~(~0U << ((1 ? 6:6) - (0 ? 6:6) + 1))))))) << (0 ? 6:6)));
break;
case gcvKERNEL_BLT:
destination = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
7:7) - (0 ?
7:7) + 1) == 32) ?
~0U : (~(~0U << ((1 ?
7:7) - (0 ?
7:7) + 1))))))) << (0 ?
7:7))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ?
7:7) - (0 ?
7:7) + 1) == 32) ?
~0U : (~(~0U << ((1 ? 7:7) - (0 ? 7:7) + 1))))))) << (0 ? 7:7)));
break;
default:
gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
}
if (blt)
{
*logical++
= ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
31:27) - (0 ?
31:27) + 1) == 32) ?
~0U : (~(~0U << ((1 ?
31:27) - (0 ?
31:27) + 1))))))) << (0 ?
31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ?
31:27) - (0 ?
31:27) + 1) == 32) ?
~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
| ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
25:16) - (0 ?
25:16) + 1) == 32) ?
~0U : (~(~0U << ((1 ?
25:16) - (0 ?
25:16) + 1))))))) << (0 ?
25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ?
25:16) - (0 ?
25:16) + 1) == 32) ?
~0U : (~(~0U << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)))
| ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
15:0) - (0 ?
15:0) + 1) == 32) ?
~0U : (~(~0U << ((1 ?
15:0) - (0 ?
15:0) + 1))))))) << (0 ?
15:0))) | (((gctUINT32) ((gctUINT32) (0x502E) & ((gctUINT32) ((((1 ?
15:0) - (0 ?
15:0) + 1) == 32) ?
~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)));
*logical++
= ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
0:0) - (0 ?
0:0) + 1) == 32) ?
~0U : (~(~0U << ((1 ?
0:0) - (0 ?
0:0) + 1))))))) << (0 ?
0:0))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ?
0:0) - (0 ?
0:0) + 1) == 32) ?
~0U : (~(~0U << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0)));
if (multiCluster)
{
*logical++
= ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
31:27) - (0 ?
31:27) + 1) == 32) ?
~0U : (~(~0U << ((1 ?
31:27) - (0 ?
31:27) + 1))))))) << (0 ?
31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ?
31:27) - (0 ?
31:27) + 1) == 32) ?
~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
| ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
25:16) - (0 ?
25:16) + 1) == 32) ?
~0U : (~(~0U << ((1 ?
25:16) - (0 ?
25:16) + 1))))))) << (0 ?
25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ?
25:16) - (0 ?
25:16) + 1) == 32) ?
~0U : (~(~0U << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)))
| ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
15:0) - (0 ?
15:0) + 1) == 32) ?
~0U : (~(~0U << ((1 ?
15:0) - (0 ?
15:0) + 1))))))) << (0 ?
15:0))) | (((gctUINT32) ((gctUINT32) (0x50CE) & ((gctUINT32) ((((1 ?
15:0) - (0 ?
15:0) + 1) == 32) ?
~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)));
*logical++
= ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
7:0) - (0 ?
7:0) + 1) == 32) ?
~0U : (~(~0U << ((1 ?
7:0) - (0 ?
7:0) + 1))))))) << (0 ?
7:0))) | (((gctUINT32) ((gctUINT32) (Hardware->identity.clusterAvailMask & Hardware->options.userClusterMask) & ((gctUINT32) ((((1 ?
7:0) - (0 ?
7:0) + 1) == 32) ?
~0U : (~(~0U << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0)));
}
}
/* Append EVENT(Event, destination). */
*logical++
= ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
31:27) - (0 ?
31:27) + 1) == 32) ?
~0U : (~(~0U << ((1 ?
31:27) - (0 ?
31:27) + 1))))))) << (0 ?
31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ?
31:27) - (0 ?
31:27) + 1) == 32) ?
~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
| ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
15:0) - (0 ?
15:0) + 1) == 32) ?
~0U : (~(~0U << ((1 ?
15:0) - (0 ?
15:0) + 1))))))) << (0 ?
15:0))) | (((gctUINT32) ((gctUINT32) (0x0E01) & ((gctUINT32) ((((1 ?
15:0) - (0 ?
15:0) + 1) == 32) ?
~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)))
| ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
25:16) - (0 ?
25:16) + 1) == 32) ?
~0U : (~(~0U << ((1 ?
25:16) - (0 ?
25:16) + 1))))))) << (0 ?
25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ?
25:16) - (0 ?
25:16) + 1) == 32) ?
~0U : (~(~0U << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)));
*logical++
= ((((gctUINT32) (destination)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
4:0) - (0 ?
4:0) + 1) == 32) ?
~0U : (~(~0U << ((1 ?
4:0) - (0 ?
4:0) + 1))))))) << (0 ?
4:0))) | (((gctUINT32) ((gctUINT32) (Event) & ((gctUINT32) ((((1 ?
4:0) - (0 ?
4:0) + 1) == 32) ?
~0U : (~(~0U << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0)));
if (blt)
{
*logical++
= ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
31:27) - (0 ?
31:27) + 1) == 32) ?
~0U : (~(~0U << ((1 ?
31:27) - (0 ?
31:27) + 1))))))) << (0 ?
31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ?
31:27) - (0 ?
31:27) + 1) == 32) ?
~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
| ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
25:16) - (0 ?
25:16) + 1) == 32) ?
~0U : (~(~0U << ((1 ?
25:16) - (0 ?
25:16) + 1))))))) << (0 ?
25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ?
25:16) - (0 ?
25:16) + 1) == 32) ?
~0U : (~(~0U << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)))
| ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
15:0) - (0 ?
15:0) + 1) == 32) ?
~0U : (~(~0U << ((1 ?
15:0) - (0 ?
15:0) + 1))))))) << (0 ?
15:0))) | (((gctUINT32) ((gctUINT32) (0x502E) & ((gctUINT32) ((((1 ?
15:0) - (0 ?
15:0) + 1) == 32) ?
~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)));
*logical++
= ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
0:0) - (0 ?
0:0) + 1) == 32) ?
~0U : (~(~0U << ((1 ?
0:0) - (0 ?
0:0) + 1))))))) << (0 ?
0:0))) | (((gctUINT32) (0x0 & ((gctUINT32) ((((1 ?
0:0) - (0 ?
0:0) + 1) == 32) ?
~0U : (~(~0U << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0)));
}
/* Make sure the event ID gets written out before GPU can access it. */
gcmkONERROR(
gckOS_MemoryBarrier(Hardware->os, logical + 1));
#if gcmIS_DEBUG(gcdDEBUG_TRACE)
{
gctPHYS_ADDR_T phys;
gckOS_GetPhysicalAddress(Hardware->os, Logical, &phys);
gckOS_CPUPhysicalToGPUPhysical(Hardware->os, phys, &phys);
gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
"0x%08x: EVENT %d", phys, Event);
}
#endif
/* Append the extra states. These are needed for the chips that do not
** support back-to-back events due to the async interface. The extra
** states add the necessary delay to ensure that event IDs do not
** collide. */
if (extraEventStates)
{
*logical++ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
31:27) - (0 ?
31:27) + 1) == 32) ?
~0U : (~(~0U << ((1 ?
31:27) - (0 ?
31:27) + 1))))))) << (0 ?
31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ?
31:27) - (0 ?
31:27) + 1) == 32) ?
~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
| ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
15:0) - (0 ?
15:0) + 1) == 32) ?
~0U : (~(~0U << ((1 ?
15:0) - (0 ?
15:0) + 1))))))) << (0 ?
15:0))) | (((gctUINT32) ((gctUINT32) (0x0100) & ((gctUINT32) ((((1 ?
15:0) - (0 ?
15:0) + 1) == 32) ?
~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)))
| ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
25:16) - (0 ?
25:16) + 1) == 32) ?
~0U : (~(~0U << ((1 ?
25:16) - (0 ?
25:16) + 1))))))) << (0 ?
25:16))) | (((gctUINT32) ((gctUINT32) (5) & ((gctUINT32) ((((1 ?
25:16) - (0 ?
25:16) + 1) == 32) ?
~0U : (~(~0U << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)));
*logical++ = 0;
*logical++ = 0;
*logical++ = 0;
*logical++ = 0;
*logical++ = 0;
}
#if gcdINTERRUPT_STATISTIC
if (Event < gcmCOUNTOF(Hardware->kernel->eventObj->queues))
{
gckOS_AtomSetMask(Hardware->pendingEvent, 1 << Event);
}
#endif
}
if (Bytes != gcvNULL)
{
/* Return number of bytes required by the EVENT command. */
*Bytes = size;
}
/* Success. */
gcmkFOOTER_ARG("*Bytes=%lu", gcmOPT_VALUE(Bytes));
return gcvSTATUS_OK;
OnError:
/* Return the status. */
gcmkFOOTER();
return status;
}
void
gckASYNC_FE_UpdateAvaiable(
IN gckHARDWARE Hardware
)
{
gceSTATUS status;
gctUINT32 data;
gctINT32 oldValue;
gckASYNC_FE fe = Hardware->asyncFE;
status = gckOS_ReadRegisterEx(
Hardware->os,
Hardware->core,
0x007E4,
&data
);
if (gcmIS_SUCCESS(status))
{
data = (((((gctUINT32) (data)) >> (0 ? 6:0)) & ((gctUINT32) ((((1 ? 6:0) - (0 ? 6:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 6:0) - (0 ? 6:0) + 1)))))) );
while (data--)
{
gckOS_AtomIncrement(Hardware->os, fe->freeDscriptors, &oldValue);
}
}
}
gceSTATUS
gckASYNC_FE_ReserveSlot(
IN gckHARDWARE Hardware,
OUT gctBOOL * Available
)
{
gctINT32 oldValue;
gckASYNC_FE fe = Hardware->asyncFE;
gckOS_AtomDecrement(Hardware->os, fe->freeDscriptors, &oldValue);
if (oldValue > 0)
{
/* Get one slot. */
*Available = gcvTRUE;
}
else
{
/* No available slot, restore decreased one.*/
gckOS_AtomIncrement(Hardware->os, fe->freeDscriptors, &oldValue);
*Available = gcvFALSE;
}
return gcvSTATUS_OK;
}
gceSTATUS
gckASYNC_FE_Execute(
IN gckHARDWARE Hardware,
IN gctUINT32 Address,
IN gctUINT32 Bytes
)
{
gceSTATUS status;
status = gckOS_WriteRegisterEx(
Hardware->os,
Hardware->core,
0x007DC,
Address
);
if (gcmIS_ERROR(status))
{
return status;
}
gckOS_MemoryBarrier(
Hardware->os,
gcvNULL
);
status = gckOS_WriteRegisterEx(
Hardware->os,
Hardware->core,
0x007E0,
Address + Bytes
);
if (gcmIS_ERROR(status))
{
return status;
}
return gcvSTATUS_OK;
}

View File

@ -0,0 +1,290 @@
/****************************************************************************
*
* The MIT License (MIT)
*
* Copyright (c) 2014 - 2019 Vivante Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
*****************************************************************************
*
* The GPL License (GPL)
*
* Copyright (C) 2014 - 2019 Vivante Corporation
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*****************************************************************************
*
* Note: This software is released under dual MIT and GPL licenses. A
* recipient may use this file under the terms of either the MIT license or
* GPL License. If you wish to use only one license not the other, you can
* indicate your decision by deleting one of the above license notices in your
* version of this file.
*
*****************************************************************************/
#ifndef __gc_hal_kernel_hardware_fe_h_
#define __gc_hal_kernel_hardware_fe_h_
#include "gc_hal.h"
/******************************************************************************/
/* Wait-Link FE commands. */
/* Construct Wait-Link FE. */
gceSTATUS
gckWLFE_Construct(
IN gckHARDWARE Hardware,
OUT gckWLFE * FE
);
void
gckWLFE_Destroy(
IN gckHARDWARE Hardware,
IN gckWLFE FE
);
/* Initialize Wait-Link FE, when hardware reset. */
gceSTATUS
gckWLFE_Initialize(
IN gckHARDWARE Hardware,
IN gckWLFE FE
);
/* Add a WAIT/LINK pair in the command queue. */
gceSTATUS
gckWLFE_WaitLink(
IN gckHARDWARE Hardware,
IN gctPOINTER Logical,
IN gctUINT32 Address,
IN gctUINT32 Offset,
IN OUT gctUINT32 * Bytes,
OUT gctUINT32 * WaitOffset,
OUT gctUINT32 * WaitBytes
);
/* Add a LINK command in the command queue. */
gceSTATUS
gckWLFE_Link(
IN gckHARDWARE Hardware,
IN gctPOINTER Logical,
IN gctUINT32 FetchAddress,
IN gctUINT32 FetchSize,
IN OUT gctUINT32 * Bytes,
OUT gctUINT32 * Low,
OUT gctUINT32 * High
);
/* Add an END command in the command queue. */
gceSTATUS
gckWLFE_End(
IN gckHARDWARE Hardware,
IN gctPOINTER Logical,
IN gctUINT32 Address,
IN OUT gctUINT32 * Bytes
);
/* Add a NOP command in the command queue. */
gceSTATUS
gckWLFE_Nop(
IN gckHARDWARE Hardware,
IN gctPOINTER Logical,
IN OUT gctSIZE_T * Bytes
);
/* Add an EVENT command in the command queue. */
gceSTATUS
gckWLFE_Event(
IN gckHARDWARE Hardware,
IN gctPOINTER Logical,
IN gctUINT8 Event,
IN gceKERNEL_WHERE FromWhere,
IN OUT gctUINT32 * Bytes
);
gceSTATUS
gckWLFE_ChipEnable(
IN gckHARDWARE Hardware,
IN gctPOINTER Logical,
IN gceCORE_3D_MASK ChipEnable,
IN OUT gctSIZE_T * Bytes
);
/* Kickstart the command processor. */
gceSTATUS
gckWLFE_Execute(
IN gckHARDWARE Hardware,
IN gctUINT32 Address,
IN gctUINT32 Bytes
);
/* Atomic version or IRQ routine. */
gceSTATUS
gckWLFE_AtomicExecute(
IN gckHARDWARE Hardware,
IN gctUINT32 Address,
IN gctUINT32 Bytes
);
/******************************************************************************/
/* ASync FE commands. */
gceSTATUS
gckASYNC_FE_Construct(
IN gckHARDWARE Hardware,
OUT gckASYNC_FE * FE
);
void
gckASYNC_FE_Destroy(
IN gckHARDWARE Hardware,
IN gckASYNC_FE FE
);
/* Initialize Async FE, when hardware reset. */
gceSTATUS
gckASYNC_FE_Initialize(
IN gckHARDWARE Hardware,
IN gckASYNC_FE FE
);
/* Add a NOP command in the command queue. */
gceSTATUS
gckASYNC_FE_Nop(
IN gckHARDWARE Hardware,
IN gctPOINTER Logical,
IN OUT gctSIZE_T * Bytes
);
/* Add an EVENT command in the command queue. */
gceSTATUS
gckASYNC_FE_Event(
IN gckHARDWARE Hardware,
IN gctPOINTER Logical,
IN gctUINT8 Event,
IN gceKERNEL_WHERE FromWhere,
IN OUT gctUINT32 * Bytes
);
/* Kickstart the command processor. */
gceSTATUS
gckASYNC_FE_Execute(
IN gckHARDWARE Hardware,
IN gctUINT32 Address,
IN gctUINT32 Bytes
);
gceSTATUS
gckASYNC_FE_ReserveSlot(
IN gckHARDWARE Hardware,
OUT gctBOOL * Available
);
void
gckASYNC_FE_UpdateAvaiable(
IN gckHARDWARE Hardware
);
/******************************************************************************/
/* MC FE commands. */
/* One MCFE includes max 64 engine, each engine contains 2 channels. */
gceSTATUS
gckMCFE_Construct(
IN gckHARDWARE Hardware,
OUT gckMCFE * FE
);
void
gckMCFE_Destroy(
IN gckHARDWARE Hardware,
IN gckMCFE FE
);
/* Initialize MC FE, when hardware reset. */
gceSTATUS
gckMCFE_Initialize(
IN gckHARDWARE Hardware,
IN gctBOOL MMUEnabled,
IN gckMCFE FE
);
/* Add a NOP command in the command queue. */
gceSTATUS
gckMCFE_Nop(
IN gckHARDWARE Hardware,
IN gctPOINTER Logical,
IN OUT gctSIZE_T * Bytes
);
/* Add an EVENT command in the command queue. */
gceSTATUS
gckMCFE_Event(
IN gckHARDWARE Hardware,
IN gctPOINTER Logical,
IN gctUINT8 Event,
IN gceKERNEL_WHERE FromWhere,
IN OUT gctUINT32 * Bytes
);
/* Add a SendSemaphore command in the command queue. */
gceSTATUS
gckMCFE_SendSemaphore(
IN gckHARDWARE Hardware,
IN gctPOINTER Logical,
IN gctUINT32 SemaId,
IN OUT gctUINT32 * Bytes
);
/* Add a WaitSemaphore command in the command queue. */
gceSTATUS
gckMCFE_WaitSemaphore(
IN gckHARDWARE Hardware,
IN gctPOINTER Logical,
IN gctUINT32 SemaId,
IN OUT gctUINT32 * Bytes
);
/* Kickstart the command processor. */
gceSTATUS
gckMCFE_Execute(
IN gckHARDWARE Hardware,
IN gctBOOL Priority,
IN gctUINT32 ChannelId,
IN gctUINT32 Address,
IN gctUINT32 Bytes
);
#endif

View File

@ -0,0 +1,838 @@
/****************************************************************************
*
* The MIT License (MIT)
*
* Copyright (c) 2014 - 2019 Vivante Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
*****************************************************************************
*
* The GPL License (GPL)
*
* Copyright (C) 2014 - 2019 Vivante Corporation
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*****************************************************************************
*
* Note: This software is released under dual MIT and GPL licenses. A
* recipient may use this file under the terms of either the MIT license or
* GPL License. If you wish to use only one license not the other, you can
* indicate your decision by deleting one of the above license notices in your
* version of this file.
*
*****************************************************************************/
#include "gc_hal.h"
#include "gc_hal_kernel.h"
#include "gc_hal_kernel_context.h"
#define _GC_OBJ_ZONE gcvZONE_HARDWARE
typedef struct _gcsMCFE_DESCRIPTOR
{
gctUINT32 start;
gctUINT32 end;
}
gcsMCFE_DESCRIPTOR;
/* 2^DepthExp = Depth. */
#define MCFE_RINGBUF_DEPTH_EXP 9
/* Depth. */
#define MCFE_RINGBUF_DEPTH (1 << MCFE_RINGBUF_DEPTH_EXP)
/* MCFE descriptor size in bytes, fixed 8. */
#define MCFE_COMMAND_DESC_SIZE 8
/* FIFO size in bytes. */
#define MCFE_RINGBUF_SIZE (MCFE_RINGBUF_DEPTH * MCFE_COMMAND_DESC_SIZE)
typedef struct _gcsMCFE_RING_BUF
{
gckVIDMEM_NODE ringBufVideoMem;
gctUINT32 ringBufAddress;
gctUINT32 * ringBufLogical;
gctSIZE_T ringBufBytes;
gctUINT32 gpuAddress;
gctPHYS_ADDR_T physical;
/* Read ptr should be often out-of-date. */
gctUINT32 readPtr;
gctUINT32 writePtr;
}
gcsMCFE_RING_BUF;
typedef struct _gcsMCFE_CHANNEL
{
gceMCFE_CHANNEL_TYPE binding;
gcsMCFE_RING_BUF stdRingBuf;
gcsMCFE_RING_BUF priRingBuf;
}
gcsMCFE_CHANNEL;
struct _gckMCFE
{
gctUINT32 channelCount;
gctBOOL mmuEnabled;
/*
* Channels must be the last field.
* Will allocate struct size according to channel count.
*/
gcsMCFE_CHANNEL channels[1];
};
static gcmINLINE gctUINT32
_NextPtr(
gctUINT32 Ptr
)
{
return (Ptr + 1) & (MCFE_RINGBUF_DEPTH - 1);
}
static gceSTATUS
_AllocateDescRingBuf(
gckHARDWARE Hardware,
gcsMCFE_RING_BUF * Channel
)
{
gceSTATUS status;
gcePOOL pool = gcvPOOL_DEFAULT;
gckKERNEL kernel = Hardware->kernel;
gctUINT32 allocFlag = 0;
#if gcdENABLE_CACHEABLE_COMMAND_BUFFER
allocFlag |= gcvALLOC_FLAG_CACHEABLE;
#endif
Channel->ringBufBytes = MCFE_RINGBUF_SIZE;
/* Allocate video memory node for mcfe ring buffer. */
gcmkONERROR(gckKERNEL_AllocateVideoMemory(
kernel,
64,
gcvVIDMEM_TYPE_COMMAND,
allocFlag,
&Channel->ringBufBytes,
&pool,
&Channel->ringBufVideoMem
));
/* Lock for GPU access. */
gcmkONERROR(gckVIDMEM_NODE_Lock(
kernel,
Channel->ringBufVideoMem,
&Channel->gpuAddress
));
/* Lock for kernel side CPU access. */
gcmkONERROR(gckVIDMEM_NODE_LockCPU(
kernel,
Channel->ringBufVideoMem,
gcvFALSE,
gcvFALSE,
(gctPOINTER *)&Channel->ringBufLogical
));
/* Get CPU physical address. */
gcmkONERROR(gckVIDMEM_NODE_GetPhysical(
kernel,
Channel->ringBufVideoMem,
0,
&Channel->physical
));
gcmkVERIFY_OK(gckOS_CPUPhysicalToGPUPhysical(
Hardware->os, Channel->physical, &Channel->physical));
if (Channel->physical > 0xffffffffull)
{
gcmkPRINT("%s(%d): MCFE ring buffer physical over 4G: 0x%llx",
__FUNCTION__, __LINE__, (unsigned long long)Channel->physical);
}
/* Default to use physical. */
Channel->ringBufAddress = (gctUINT32)Channel->physical;
return gcvSTATUS_OK;
OnError:
return status;
}
static void
_DestroyDescRingBuf(
gckHARDWARE Hardware,
gcsMCFE_RING_BUF * Channel
)
{
gckKERNEL kernel = Hardware->kernel;
if (Channel->ringBufVideoMem)
{
gcmkVERIFY_OK(gckVIDMEM_NODE_UnlockCPU(
kernel,
Channel->ringBufVideoMem,
0,
gcvFALSE,
gcvFALSE
));
gcmkVERIFY_OK(gckVIDMEM_NODE_Dereference(
kernel,
Channel->ringBufVideoMem
));
Channel->ringBufVideoMem = gcvNULL;
Channel->ringBufLogical = gcvNULL;
}
}
static gcmINLINE void
_DestroyMCFE(
IN gckHARDWARE Hardware,
IN gckMCFE FE
)
{
if (FE)
{
gctUINT i;
for (i = 0; i < FE->channelCount; i++)
{
if (FE->channels[i].binding)
{
_DestroyDescRingBuf(Hardware, &FE->channels[i].stdRingBuf);
_DestroyDescRingBuf(Hardware, &FE->channels[i].priRingBuf);
}
}
gcmkOS_SAFE_FREE(Hardware->os, FE);
}
}
static gceSTATUS
_ConstructChannel(
IN gckHARDWARE Hardware,
IN gceMCFE_CHANNEL_TYPE ChannelType,
IN gcsMCFE_CHANNEL * Channel
)
{
Channel->binding = ChannelType;
return gcvSTATUS_OK;
}
gceSTATUS
gckMCFE_Construct(
IN gckHARDWARE Hardware,
OUT gckMCFE *FE
)
{
gceSTATUS status;
gckMCFE fe = gcvNULL;
gctUINT32 i;
gctSIZE_T size = sizeof(struct _gckMCFE);
if (Hardware->mcfeChannelCount > 1)
{
size += sizeof(gcsMCFE_CHANNEL) * (Hardware->mcfeChannelCount - 1);
}
gcmkONERROR(gckOS_Allocate(Hardware->os,
size,
(gctPOINTER *)&fe));
gckOS_ZeroMemory(fe, size);
fe->channelCount = Hardware->mcfeChannelCount;
for (i = 0; i < fe->channelCount; i++)
{
gcmkONERROR(
_ConstructChannel(Hardware,
Hardware->mcfeChannels[i],
&fe->channels[i]));
}
/* Enable all events. */
gcmkONERROR(
gckOS_WriteRegisterEx(Hardware->os,
Hardware->core,
0x00014,
0xFFFFFFFF));
*FE = fe;
return gcvSTATUS_OK;
OnError:
_DestroyMCFE(Hardware, fe);
return status;
}
void
gckMCFE_Destroy(
IN gckHARDWARE Hardware,
IN gckMCFE FE
)
{
_DestroyMCFE(Hardware, FE);
}
static gceSTATUS
_ProgramDescRingBuf(
IN gckHARDWARE Hardware,
IN gctBOOL MMUEnabled,
IN gcsMCFE_RING_BUF * Channel,
IN gctUINT32 Index,
IN gctBOOL Priority
)
{
gctUINT32 ringBufStartReg;
gctUINT32 depthExpReg;
gctUINT32 readPtrReg;
gctUINT32 writePtrReg;
gctUINT32 data = 0;
if (Priority)
{
ringBufStartReg = 0x02800;
depthExpReg = 0x02900;
readPtrReg = 0x02B00;
writePtrReg = 0x02A00;
}
else
{
ringBufStartReg = 0x02400;
depthExpReg = 0x02500;
readPtrReg = 0x02700;
writePtrReg = 0x02600;
}
ringBufStartReg += Index << 2;
depthExpReg += Index << 2;
readPtrReg += Index << 2;
writePtrReg += Index << 2;
Channel->ringBufAddress = MMUEnabled ? Channel->gpuAddress
: (gctUINT32)Channel->physical;
/* Channel ringBuf start address. */
gcmkVERIFY_OK(gckOS_WriteRegisterEx(
Hardware->os, Hardware->core, ringBufStartReg, Channel->ringBufAddress));
/* Channel ringBuf depth (exponent of 2). */
gcmkVERIFY_OK(gckOS_WriteRegisterEx(
Hardware->os, Hardware->core, depthExpReg, MCFE_RINGBUF_DEPTH_EXP));
/* The RD ptr could keep unchanged, read and compute WR ptr. */
gcmkVERIFY_OK(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, readPtrReg, &data));
/* Priority ring buffer write ptr. */
/* gcmkVERIFY_OK(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, writePtrReg, data)); */
/* No valid descriptor initially. */
Channel->readPtr = Channel->writePtr = data;
return gcvSTATUS_OK;
}
static gceSTATUS
_InitializeChannel(
IN gckHARDWARE Hardware,
IN gctBOOL MMUEnabled,
IN gcsMCFE_CHANNEL * Channel,
IN gctUINT32 Index
)
{
gceSTATUS status;
/* Allocate ring buffer descriptor memory. */
if (!Channel->stdRingBuf.ringBufVideoMem)
{
gcmkONERROR(_AllocateDescRingBuf(Hardware, &Channel->stdRingBuf));
}
/* No priority channel in system engine. */
if (!Channel->priRingBuf.ringBufVideoMem && Index != 0)
{
gcmkONERROR(_AllocateDescRingBuf(Hardware, &Channel->priRingBuf));
}
gcmkONERROR(_ProgramDescRingBuf(Hardware, MMUEnabled, &Channel->stdRingBuf, Index, gcvFALSE));
/* No priority channel in system engine. */
if (Channel->binding != gcvMCFE_CHANNEL_SYSTEM)
{
gcmkONERROR(_ProgramDescRingBuf(Hardware, MMUEnabled, &Channel->priRingBuf, Index, gcvTRUE));
}
return gcvSTATUS_OK;
OnError:
/* It's OK to leave ringBuf memory not free'd here. */
return status;
}
gceSTATUS
gckMCFE_Initialize(
IN gckHARDWARE Hardware,
IN gctBOOL MMUEnabled,
IN gckMCFE FE
)
{
gctUINT32 i;
gceSTATUS status;
for (i = 0; i < FE->channelCount; i++)
{
if (FE->channels[i].binding)
{
gcmkONERROR(_InitializeChannel(Hardware, MMUEnabled, &FE->channels[i], i));
}
}
FE->mmuEnabled = MMUEnabled;
return gcvSTATUS_OK;
OnError:
return status;
}
gceSTATUS
gckMCFE_Nop(
IN gckHARDWARE Hardware,
IN gctPOINTER Logical,
IN OUT gctSIZE_T * Bytes
)
{
gctUINT32_PTR logical = (gctUINT32_PTR) Logical;
gceSTATUS status;
gcmkHEADER_ARG("Hardware=0x%x Logical=0x%x *Bytes=%lu",
Hardware, Logical, gcmOPT_VALUE(Bytes));
/* Verify the arguments. */
gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
gcmkVERIFY_ARGUMENT((Logical == gcvNULL) || (Bytes != gcvNULL));
if (Logical != gcvNULL)
{
if (*Bytes < 8)
{
/* Command queue too small. */
gcmkONERROR(gcvSTATUS_BUFFER_TOO_SMALL);
}
/* Append NOP. */
logical[0] = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
31:27) - (0 ?
31:27) + 1) == 32) ?
~0U : (~(~0U << ((1 ?
31:27) - (0 ?
31:27) + 1))))))) << (0 ?
31:27))) | (((gctUINT32) (0x03 & ((gctUINT32) ((((1 ?
31:27) - (0 ?
31:27) + 1) == 32) ?
~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)));
logical[1] = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
31:27) - (0 ?
31:27) + 1) == 32) ?
~0U : (~(~0U << ((1 ?
31:27) - (0 ?
31:27) + 1))))))) << (0 ?
31:27))) | (((gctUINT32) (0x03 & ((gctUINT32) ((((1 ?
31:27) - (0 ?
31:27) + 1) == 32) ?
~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)));
gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE, "0x%x: NOP", Logical);
}
if (Bytes != gcvNULL)
{
/* Return number of bytes required by the NOP command. */
*Bytes = 8;
}
/* Success. */
gcmkFOOTER_ARG("*Bytes=%lu", gcmOPT_VALUE(Bytes));
return gcvSTATUS_OK;
OnError:
/* Return the status. */
gcmkFOOTER();
return status;
}
gceSTATUS
gckMCFE_Event(
IN gckHARDWARE Hardware,
IN gctPOINTER Logical,
IN gctUINT8 Event,
IN gceKERNEL_WHERE FromWhere,
IN OUT gctUINT32 * Bytes
)
{
gctUINT size;
gctUINT32_PTR logical = (gctUINT32_PTR) Logical;
gceSTATUS status;
gcmkHEADER_ARG("Hardware=0x%x Logical=0x%x Event=%u FromWhere=%d *Bytes=%lu",
Hardware, Logical, Event, FromWhere, gcmOPT_VALUE(Bytes));
/* Verify the arguments. */
gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
gcmkVERIFY_ARGUMENT((Logical == gcvNULL) || (Bytes != gcvNULL));
gcmkVERIFY_ARGUMENT(Event < 32);
/* Ignored. */
(void)FromWhere;
size = 8;
if (Logical != gcvNULL)
{
if (*Bytes < size)
{
/* Command queue too small. */
gcmkONERROR(gcvSTATUS_BUFFER_TOO_SMALL);
}
/* Append EVENT(Event). */
logical[0] = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
31:27) - (0 ?
31:27) + 1) == 32) ?
~0U : (~(~0U << ((1 ?
31:27) - (0 ?
31:27) + 1))))))) << (0 ?
31:27))) | (((gctUINT32) (0x16 & ((gctUINT32) ((((1 ?
31:27) - (0 ?
31:27) + 1) == 32) ?
~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
| ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
25:16) - (0 ?
25:16) + 1) == 32) ?
~0U : (~(~0U << ((1 ?
25:16) - (0 ?
25:16) + 1))))))) << (0 ?
25:16))) | (((gctUINT32) (0x006 & ((gctUINT32) ((((1 ?
25:16) - (0 ?
25:16) + 1) == 32) ?
~0U : (~(~0U << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)))
| Event;
logical[1] = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
31:27) - (0 ?
31:27) + 1) == 32) ?
~0U : (~(~0U << ((1 ?
31:27) - (0 ?
31:27) + 1))))))) << (0 ?
31:27))) | (((gctUINT32) (0x03 & ((gctUINT32) ((((1 ?
31:27) - (0 ?
31:27) + 1) == 32) ?
~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)));
#if gcmIS_DEBUG(gcdDEBUG_TRACE)
{
gctPHYS_ADDR_T phys;
gckOS_GetPhysicalAddress(Hardware->os, Logical, &phys);
gckOS_CPUPhysicalToGPUPhysical(Hardware->os, phys, &phys);
gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
"0x%08x: EVENT %d", phys, Event);
}
#endif
#if gcdINTERRUPT_STATISTIC
if (Event < gcmCOUNTOF(Hardware->kernel->eventObj->queues))
{
gckOS_AtomSetMask(Hardware->pendingEvent, 1 << Event);
}
#endif
}
if (Bytes != gcvNULL)
{
/* Return number of bytes required by the EVENT command. */
*Bytes = size;
}
/* Success. */
gcmkFOOTER_ARG("*Bytes=%lu", gcmOPT_VALUE(Bytes));
return gcvSTATUS_OK;
OnError:
/* Return the status. */
gcmkFOOTER();
return status;
}
gceSTATUS
gckMCFE_SendSemaphore(
IN gckHARDWARE Hardware,
IN gctPOINTER Logical,
IN gctUINT32 SemaId,
IN OUT gctUINT32 * Bytes
)
{
gctUINT32_PTR logical = (gctUINT32_PTR) Logical;
gceSTATUS status;
gcmkHEADER_ARG("Hardware=0x%x Logical=0x%x SemaId=%u *Bytes=%lu",
Hardware, Logical, SemaId, gcmOPT_VALUE(Bytes));
/* Verify the arguments. */
gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
gcmkVERIFY_ARGUMENT((Logical == gcvNULL) || (Bytes != gcvNULL));
gcmkVERIFY_ARGUMENT(SemaId < 0xFFFF);
if (Logical != gcvNULL)
{
if (*Bytes < 8)
{
/* Command queue too small. */
gcmkONERROR(gcvSTATUS_BUFFER_TOO_SMALL);
}
/* Append SEND_SEMAPHORE(SemaId). */
logical[0] = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
31:27) - (0 ?
31:27) + 1) == 32) ?
~0U : (~(~0U << ((1 ?
31:27) - (0 ?
31:27) + 1))))))) << (0 ?
31:27))) | (((gctUINT32) (0x16 & ((gctUINT32) ((((1 ?
31:27) - (0 ?
31:27) + 1) == 32) ?
~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
| ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
25:16) - (0 ?
25:16) + 1) == 32) ?
~0U : (~(~0U << ((1 ?
25:16) - (0 ?
25:16) + 1))))))) << (0 ?
25:16))) | (((gctUINT32) (0x002 & ((gctUINT32) ((((1 ?
25:16) - (0 ?
25:16) + 1) == 32) ?
~0U : (~(~0U << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)))
| SemaId;
logical[1] = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
31:27) - (0 ?
31:27) + 1) == 32) ?
~0U : (~(~0U << ((1 ?
31:27) - (0 ?
31:27) + 1))))))) << (0 ?
31:27))) | (((gctUINT32) (0x03 & ((gctUINT32) ((((1 ?
31:27) - (0 ?
31:27) + 1) == 32) ?
~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)));
}
if (Bytes != gcvNULL)
{
*Bytes = 8;
}
/* Success. */
gcmkFOOTER_ARG("*Bytes=%lu", gcmOPT_VALUE(Bytes));
return gcvSTATUS_OK;
OnError:
/* Return the status. */
gcmkFOOTER();
return status;
}
gceSTATUS
gckMCFE_WaitSemaphore(
IN gckHARDWARE Hardware,
IN gctPOINTER Logical,
IN gctUINT32 SemaId,
IN OUT gctUINT32 * Bytes
)
{
gctUINT32_PTR logical = (gctUINT32_PTR) Logical;
gceSTATUS status;
gcmkHEADER_ARG("Hardware=0x%x Logical=0x%x SemaId=%u *Bytes=%lu",
Hardware, Logical, SemaId, gcmOPT_VALUE(Bytes));
/* Verify the arguments. */
gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
gcmkVERIFY_ARGUMENT((Logical == gcvNULL) || (Bytes != gcvNULL));
gcmkVERIFY_ARGUMENT(SemaId < 0xFFFF);
if (Logical != gcvNULL)
{
if (*Bytes < 8)
{
/* Command queue too small. */
gcmkONERROR(gcvSTATUS_BUFFER_TOO_SMALL);
}
/* Append WAIT_SEMAPHORE(SemaId). */
logical[0] = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
31:27) - (0 ?
31:27) + 1) == 32) ?
~0U : (~(~0U << ((1 ?
31:27) - (0 ?
31:27) + 1))))))) << (0 ?
31:27))) | (((gctUINT32) (0x16 & ((gctUINT32) ((((1 ?
31:27) - (0 ?
31:27) + 1) == 32) ?
~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
| ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
25:16) - (0 ?
25:16) + 1) == 32) ?
~0U : (~(~0U << ((1 ?
25:16) - (0 ?
25:16) + 1))))))) << (0 ?
25:16))) | (((gctUINT32) (0x003 & ((gctUINT32) ((((1 ?
25:16) - (0 ?
25:16) + 1) == 32) ?
~0U : (~(~0U << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)))
| SemaId;
logical[1] = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
31:27) - (0 ?
31:27) + 1) == 32) ?
~0U : (~(~0U << ((1 ?
31:27) - (0 ?
31:27) + 1))))))) << (0 ?
31:27))) | (((gctUINT32) (0x03 & ((gctUINT32) ((((1 ?
31:27) - (0 ?
31:27) + 1) == 32) ?
~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)));
}
if (Bytes != gcvNULL)
{
*Bytes = 8;
}
/* Success. */
gcmkFOOTER_ARG("*Bytes=%lu", gcmOPT_VALUE(Bytes));
return gcvSTATUS_OK;
OnError:
/* Return the status. */
gcmkFOOTER();
return status;
}
gceSTATUS
gckMCFE_Execute(
IN gckHARDWARE Hardware,
IN gctBOOL Priority,
IN gctUINT32 ChannelId,
IN gctUINT32 Address,
IN gctUINT32 Bytes
)
{
gctUINT32 regBase;
gcsMCFE_DESCRIPTOR *desc;
gcsMCFE_CHANNEL * channel = &Hardware->mcFE->channels[ChannelId];
gcsMCFE_RING_BUF * ringBuf = Priority ? &channel->priRingBuf
: &channel->stdRingBuf;
/* No priority channel in system channel by design. */
gcmkASSERT(!(channel->binding == gcvMCFE_CHANNEL_SYSTEM && Priority == 1));
while (_NextPtr(ringBuf->writePtr) == ringBuf->readPtr)
{
gctUINT32 data;
regBase = Priority ? 0x02B00
: 0x02700;
gcmkVERIFY_OK(gckOS_ReadRegisterEx(Hardware->os,
Hardware->core,
regBase + ChannelId * 4,
&data));
ringBuf->readPtr = data;
if (_NextPtr(ringBuf->writePtr) == ringBuf->readPtr)
{
gcmkPRINT("%s: MCFE channel %s-%d ringBuf is full!",
__FUNCTION__,
Priority ? "Pri" : "Std",
ChannelId);
gckOS_Delay(Hardware->os, 100);
}
}
regBase = Priority ? 0x02A00
: 0x02600;
/* ringBufLogical is in uint32, 2 uint32 contributes 1 descriptr. */
desc = (gcsMCFE_DESCRIPTOR *)&ringBuf->ringBufLogical[ringBuf->writePtr * 2];
desc->start = Address;
desc->end = Address + Bytes;
gcmkDUMP(Hardware->os,
"#[descriptor %d: channel %s-%d]",
ringBuf->writePtr,
Priority ? "Pri" : "Std",
ChannelId);
gcmkDUMP_BUFFER(Hardware->os,
gcvDUMP_BUFFER_KERNEL_COMMAND,
desc,
ringBuf->ringBufAddress + ringBuf->writePtr * 8,
8);
gcmkVERIFY_OK(gckVIDMEM_NODE_CleanCache(Hardware->kernel,
ringBuf->ringBufVideoMem,
0,
desc,
8));
ringBuf->writePtr = _NextPtr(ringBuf->writePtr);
gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
"0x%08X - 0x%08X: %06d bytes, Channel=%s-%d",
desc->start, desc->end, Bytes,
Priority ? "Pri" : "Std", ChannelId);
gcmkVERIFY_OK(gckOS_WriteRegisterEx(Hardware->os,
Hardware->core,
regBase + ChannelId * 4,
ringBuf->writePtr));
return gcvSTATUS_OK;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,721 @@
/****************************************************************************
*
* The MIT License (MIT)
*
* Copyright (c) 2014 - 2019 Vivante Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
*****************************************************************************
*
* The GPL License (GPL)
*
* Copyright (C) 2014 - 2019 Vivante Corporation
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*****************************************************************************
*
* Note: This software is released under dual MIT and GPL licenses. A
* recipient may use this file under the terms of either the MIT license or
* GPL License. If you wish to use only one license not the other, you can
* indicate your decision by deleting one of the above license notices in your
* version of this file.
*
*****************************************************************************/
#include "gc_hal.h"
#include "gc_hal_kernel.h"
#include "gc_hal_kernel_context.h"
/*
* -----------------------
* HARDWARE STATE RECORDER
* -----------------------
*
* State mirror buffer is used to 'mirror' hardware states since hardware
* states can't be dumpped. It is a context buffer which stores 'global'
* context.
*
* For each commit, state recorder
* 1) Records context buffer (if there is) and command buffers in this commit.
* 2) Parse those buffers to estimate the state changed.
* 3) Stores result to a mirror buffer.
*
* == Commit 0 ====================================================================
*
* Context Buffer 0
*
* Command Buffer 0
*
* Mirror Buffer 0 <- Context Buffer 0 + Command Buffer 0
*
* == Commit 1 ====================================================================
*
* Command Buffer 1
*
* Mirror Buffer 1 <- Command buffer 1 + Mirror Buffer 0
*
* == Commit 2 ====================================================================
*
* Context Buffer 2 (optional)
*
* Command Buffer 2
*
* Mirror Buffer 2 <- Command buffer 2 + Context Buffer 2 + Mirror Buffer 1
*
* == Commit N ====================================================================
*
* For Commit N, these buffers are needed to reproduce hardware's behavior in
* this commit.
*
* Mirror Buffer [N - 1] : State Mirror accumlated by past commits,
* which is used to restore hardware state.
* Context Buffer [N] :
* Command Buffer [N] : Command buffer executed by hardware in this commit.
*
* If sequence of states programming matters, hardware's behavior can't be reproduced,
* but the state values stored in mirror buffer are assuring.
*/
/* Queue size. */
#define gcdNUM_RECORDS 6
typedef struct _gcsPARSER_HANDLER * gckPARSER_HANDLER;
typedef void
(*HandlerFunction)(
IN gckPARSER_HANDLER Handler,
IN gctUINT32 Addr,
IN gctUINT32 Data
);
typedef struct _gcsPARSER_HANDLER
{
gctUINT32 type;
gctUINT32 cmd;
gctPOINTER private;
HandlerFunction function;
}
gcsPARSER_HANDLER;
typedef struct _gcsPARSER * gckPARSER;
typedef struct _gcsPARSER
{
gctUINT8_PTR currentCmdBufferAddr;
/* Current command. */
gctUINT32 lo;
gctUINT32 hi;
gctUINT8 cmdOpcode;
gctUINT16 cmdAddr;
gctUINT32 cmdSize;
gctUINT32 cmdRectCount;
gctUINT8 skip;
gctUINT32 skipCount;
gctBOOL allow;
gctBOOL stop;
/* Callback used by parser to handle a command. */
gckPARSER_HANDLER commandHandler;
}
gcsPARSER;
typedef struct _gcsMIRROR
{
gctUINT32_PTR logical[gcdNUM_RECORDS];
gctUINT32 bytes;
gcsSTATE_MAP_PTR map;
gctSIZE_T maxState;
}
gcsMIRROR;
typedef struct _gcsDELTA
{
gctUINT64 commitStamp;
gctUINT32_PTR command;
gctUINT32 commandBytes;
gctUINT32_PTR context;
gctUINT32 contextBytes;
}
gcsDELTA;
typedef struct _gcsRECORDER
{
gckOS os;
gcsMIRROR mirror;
gcsDELTA deltas[gcdNUM_RECORDS];
/* Index of current record. */
gctUINT index;
/* Number of records. */
gctUINT num;
/* Plugin used by gckPARSER. */
gcsPARSER_HANDLER recorderHandler;
gckPARSER parser;
}
gcsRECORDER;
/******************************************************************************\
***************************** Command Buffer Parser ****************************
\******************************************************************************/
/*
** Command buffer parser checks command buffer in FE's view to make sure there
** is no format error.
**
** Parser provide a callback mechnisam, so plug-in can be added to implement
** other functions.
*/
static void
_HandleLoadState(
IN OUT gckPARSER Parser
)
{
gctUINT i;
gctUINT32_PTR data = (gctUINT32_PTR)Parser->currentCmdBufferAddr;
gctUINT32 cmdAddr = Parser->cmdAddr;
if (Parser->commandHandler == gcvNULL
|| Parser->commandHandler->cmd != 0x01
)
{
/* No handler for this command. */
return;
}
for (i = 0; i < Parser->cmdSize; i++)
{
Parser->commandHandler->function(Parser->commandHandler, cmdAddr, *data);
/* Advance to next state. */
cmdAddr++;
data++;
}
}
static void
_GetCommand(
IN OUT gckPARSER Parser
)
{
gctUINT32 * buffer = (gctUINT32 *)Parser->currentCmdBufferAddr;
gctUINT16 cmdRectCount;
gctUINT16 cmdDataCount;
Parser->hi = buffer[0];
Parser->lo = buffer[1];
Parser->cmdOpcode = (((((gctUINT32) (Parser->hi)) >> (0 ? 31:27)) & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ? 31:27) + 1)))))) );
Parser->cmdRectCount = 1;
switch (Parser->cmdOpcode)
{
case 0x01:
/* Extract count. */
Parser->cmdSize = (((((gctUINT32) (Parser->hi)) >> (0 ? 25:16)) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ? 25:16) + 1)))))) );
if (Parser->cmdSize == 0)
{
/* 0 means 1024. */
Parser->cmdSize = 1024;
}
Parser->skip = (Parser->cmdSize & 0x1) ? 0 : 1;
/* Extract address. */
Parser->cmdAddr = (((((gctUINT32) (Parser->hi)) >> (0 ? 15:0)) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1)))))) );
Parser->currentCmdBufferAddr = Parser->currentCmdBufferAddr + 4;
Parser->skipCount = Parser->cmdSize + Parser->skip;
break;
case 0x05:
Parser->cmdSize = 4;
Parser->skipCount = gcmALIGN(Parser->cmdSize, 2);
break;
case 0x06:
Parser->cmdSize = 5;
Parser->skipCount = gcmALIGN(Parser->cmdSize, 2);
break;
case 0x0C:
Parser->cmdSize = 3;
Parser->skipCount = gcmALIGN(Parser->cmdSize, 2);
break;
case 0x09:
Parser->cmdSize = 2;
Parser->cmdAddr = 0x0F16;
Parser->skipCount = gcmALIGN(Parser->cmdSize, 2);
break;
case 0x04:
Parser->cmdSize = 1;
Parser->cmdAddr = 0x0F06;
cmdRectCount = (((((gctUINT32) (Parser->hi)) >> (0 ? 15:8)) & ((gctUINT32) ((((1 ? 15:8) - (0 ? 15:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:8) - (0 ? 15:8) + 1)))))) );
cmdDataCount = (((((gctUINT32) (Parser->hi)) >> (0 ? 26:16)) & ((gctUINT32) ((((1 ? 26:16) - (0 ? 26:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 26:16) - (0 ? 26:16) + 1)))))) );
Parser->skipCount = gcmALIGN(Parser->cmdSize, 2)
+ cmdRectCount * 2
+ gcmALIGN(cmdDataCount, 2);
Parser->cmdRectCount = cmdRectCount;
break;
case 0x03:
Parser->currentCmdBufferAddr = Parser->currentCmdBufferAddr + 8;
Parser->skipCount = 0;
break;
case 0x02:
Parser->currentCmdBufferAddr = Parser->currentCmdBufferAddr + 8;
Parser->skipCount = 0;
break;
case 0x07:
Parser->currentCmdBufferAddr = Parser->currentCmdBufferAddr + 8;
Parser->skipCount = 0;
break;
case 0x08:
/* Commands after LINK isn't executed, skip them. */
Parser->stop = gcvTRUE;
break;
default:
/* Unknown command is a risk. */
Parser->allow = gcvFALSE;
break;
}
}
static void
_ParseCommand(
IN OUT gckPARSER Parser
)
{
switch(Parser->cmdOpcode)
{
case 0x01:
_HandleLoadState(Parser);
break;
case 0x05:
case 0x06:
case 0x0C:
break;
case 0x04:
break;
default:
break;
}
/* Advance to next command. */
Parser->currentCmdBufferAddr = Parser->currentCmdBufferAddr
+ (Parser->skipCount << 2);
}
gceSTATUS
gckPARSER_Parse(
IN gckPARSER Parser,
IN gctUINT8_PTR Buffer,
IN gctUINT32 Bytes
)
{
gckPARSER parser = Parser;
gctUINT8_PTR end = (gctUINT8_PTR)Buffer + Bytes;
/* Initialize parser. */
parser->currentCmdBufferAddr = (gctUINT8_PTR)Buffer;
parser->skip = 0;
parser->allow = gcvTRUE;
parser->stop = gcvFALSE;
/* Go through command buffer until reaching the end
** or meeting an error. */
do
{
_GetCommand(parser);
_ParseCommand(parser);
}
while ((parser->currentCmdBufferAddr < end)
&& (parser->allow == gcvTRUE)
&& (parser->stop == gcvFALSE)
);
if (parser->allow == gcvFALSE)
{
/* Error detected. */
return gcvSTATUS_NOT_SUPPORTED;
}
return gcvSTATUS_OK;
}
/*******************************************************************************
**
** gckPARSER_RegisterCommandHandler
**
** Register a command handler which will be called when parser get a command.
**
*/
gceSTATUS
gckPARSER_RegisterCommandHandler(
IN gckPARSER Parser,
IN gckPARSER_HANDLER Handler
)
{
Parser->commandHandler = Handler;
return gcvSTATUS_OK;
}
gceSTATUS
gckPARSER_Construct(
IN gckOS Os,
IN gckPARSER_HANDLER Handler,
OUT gckPARSER * Parser
)
{
gceSTATUS status;
gckPARSER pointer;
gcmkONERROR(gckOS_Allocate(Os, gcmSIZEOF(gcsPARSER), (gctPOINTER *)&pointer));
/* Put it here temp, should have a more general plug-in mechnisam. */
pointer->commandHandler = Handler;
*Parser = pointer;
return gcvSTATUS_OK;
OnError:
return status;
}
void
gckPARSER_Destroy(
IN gckOS Os,
IN gckPARSER Parser
)
{
gcmkOS_SAFE_FREE(Os, Parser);
}
/******************************************************************************\
**************************** Hardware States Recorder **************************
\******************************************************************************/
static void
_RecodeState(
IN gckPARSER_HANDLER Handler,
IN gctUINT32 Addr,
IN gctUINT32 Data
)
{
gcmkVERIFY_OK(gckRECORDER_UpdateMirror(Handler->private, Addr, Data));
}
static gctUINT
_Previous(
IN gctUINT Index
)
{
if (Index == 0)
{
return gcdNUM_RECORDS - 1;
}
return Index - 1;
}
static gctUINT
_Next(
IN gctUINT Index
)
{
return (Index + 1) % gcdNUM_RECORDS;
}
gceSTATUS
gckRECORDER_Construct(
IN gckOS Os,
IN gckHARDWARE Hardware,
OUT gckRECORDER * Recorder
)
{
gceSTATUS status;
gckCONTEXT context = gcvNULL;
gckRECORDER recorder = gcvNULL;
gctSIZE_T mapSize;
gctUINT i;
gcmkONERROR(gckCONTEXT_Construct(Os, Hardware, 0, &context));
gcmkONERROR(gckOS_Allocate(Os, gcmSIZEOF(gcsRECORDER), (gctPOINTER *)&recorder));
gckOS_ZeroMemory(recorder, gcmSIZEOF(gcsRECORDER));
/* Copy state map. */
recorder->mirror.maxState = context->maxState;
mapSize = context->maxState * gcmSIZEOF(gcsSTATE_MAP);
gcmkONERROR(gckOS_Allocate(Os, mapSize, (gctPOINTER *)&recorder->mirror.map));
gckOS_MemCopy(recorder->mirror.map, context->map, mapSize);
/* Copy context buffer. */
recorder->mirror.bytes = context->totalSize;
for (i = 0; i < gcdNUM_RECORDS; i++)
{
gcmkONERROR(gckOS_Allocate(Os, context->totalSize, (gctPOINTER *)&recorder->mirror.logical[i]));
gckOS_MemCopy(recorder->mirror.logical[i], context->buffer->logical, context->totalSize);
}
for (i = 0; i < gcdNUM_RECORDS; i++)
{
gcmkONERROR(gckOS_Allocate(Os, gcdCMD_BUFFER_SIZE, (gctPOINTER *)&recorder->deltas[i].command));
gcmkONERROR(gckOS_Allocate(Os, context->totalSize, (gctPOINTER *)&recorder->deltas[i].context));
}
recorder->index = 0;
recorder->num = 0;
/* Initialize Parser plugin. */
recorder->recorderHandler.cmd = 0x01;
recorder->recorderHandler.private = recorder;
recorder->recorderHandler.function = _RecodeState;
gcmkONERROR(gckPARSER_Construct(Os, &recorder->recorderHandler, &recorder->parser));
recorder->os = Os;
*Recorder = recorder;
gckCONTEXT_Destroy(context);
return gcvSTATUS_OK;
OnError:
if (context)
{
gckCONTEXT_Destroy(context);
}
if (recorder)
{
gckRECORDER_Destory(Os, recorder);
}
return status;
}
gceSTATUS
gckRECORDER_Destory(
IN gckOS Os,
IN gckRECORDER Recorder
)
{
gctUINT i;
if (Recorder->mirror.map)
{
gcmkOS_SAFE_FREE(Os, Recorder->mirror.map);
}
for (i = 0; i < gcdNUM_RECORDS; i++)
{
if (Recorder->mirror.logical[i])
{
gcmkOS_SAFE_FREE(Os, Recorder->mirror.logical[i]);
}
}
for (i = 0; i < gcdNUM_RECORDS; i++)
{
if (Recorder->deltas[i].command)
{
gcmkOS_SAFE_FREE(Os, Recorder->deltas[i].command);
}
if (Recorder->deltas[i].context)
{
gcmkOS_SAFE_FREE(Os, Recorder->deltas[i].context);
}
}
if (Recorder->parser)
{
gckPARSER_Destroy(Os, Recorder->parser);
}
gcmkOS_SAFE_FREE(Os, Recorder);
return gcvSTATUS_OK;
}
gceSTATUS
gckRECORDER_UpdateMirror(
IN gckRECORDER Recorder,
IN gctUINT32 State,
IN gctUINT32 Data
)
{
gctUINT32 index;
gcsSTATE_MAP_PTR map = Recorder->mirror.map;
gctUINT32_PTR buffer = Recorder->mirror.logical[Recorder->index];
if (State >= Recorder->mirror.maxState)
{
/* Ignore them just like HW does. */
return gcvSTATUS_OK;
}
index = map[State].index;
if (index)
{
buffer[index] = Data;
}
return gcvSTATUS_OK;
}
void
gckRECORDER_AdvanceIndex(
IN gckRECORDER Recorder,
IN gctUINT64 CommitStamp
)
{
/* Get next record. */
gctUINT next = (Recorder->index + 1) % gcdNUM_RECORDS;
/* Record stamp of this commit. */
Recorder->deltas[Recorder->index].commitStamp = CommitStamp;
/* Mirror of next record is mirror of this record and delta in next record. */
gckOS_MemCopy(Recorder->mirror.logical[next],
Recorder->mirror.logical[Recorder->index], Recorder->mirror.bytes);
/* Advance to next record. */
Recorder->index = next;
Recorder->num = gcmMIN(Recorder->num + 1, gcdNUM_RECORDS - 1);
/* Reset delta. */
Recorder->deltas[Recorder->index].commandBytes = 0;
Recorder->deltas[Recorder->index].contextBytes = 0;
}
void
gckRECORDER_Record(
IN gckRECORDER Recorder,
IN gctUINT8_PTR CommandBuffer,
IN gctUINT32 CommandBytes,
IN gctUINT8_PTR ContextBuffer,
IN gctUINT32 ContextBytes
)
{
gcsDELTA * delta = &Recorder->deltas[Recorder->index];
if (CommandBytes != 0xFFFFFFFF)
{
gckPARSER_Parse(Recorder->parser, CommandBuffer, CommandBytes);
gckOS_MemCopy(delta->command, CommandBuffer, CommandBytes);
delta->commandBytes = CommandBytes;
}
if (ContextBytes != 0xFFFFFFFF)
{
gckPARSER_Parse(Recorder->parser, ContextBuffer, ContextBytes);
gckOS_MemCopy(delta->context, ContextBuffer, ContextBytes);
delta->contextBytes = ContextBytes;
}
}
void
gckRECORDER_Dump(
IN gckRECORDER Recorder
)
{
gctUINT last = Recorder->index;
gctUINT previous;
gctUINT i;
gcsMIRROR *mirror = &Recorder->mirror;
gcsDELTA *delta;
gckOS os = Recorder->os;
for (i = 0; i < Recorder->num; i++)
{
last = _Previous(last);
}
for (i = 0; i < Recorder->num; i++)
{
delta = &Recorder->deltas[last];
/* Dump record */
gcmkPRINT("#[commit %llu]", delta->commitStamp);
if (delta->commitStamp)
{
previous = _Previous(last);
gcmkPRINT("#[mirror]");
gckOS_DumpBuffer(os, gcvDUMP_BUFFER_KERNEL_CONTEXT, mirror->logical[previous], ~0U, mirror->bytes);
gcmkPRINT("#[kernel.execute]");
}
if (delta->contextBytes)
{
gckOS_DumpBuffer(os, gcvDUMP_BUFFER_KERNEL_CONTEXT, delta->context, ~0U, delta->contextBytes);
gcmkPRINT("#[kernel.execute]");
}
gckOS_DumpBuffer(os, gcvDUMP_BUFFER_KERNEL_COMMAND, delta->command, ~0U, delta->commandBytes);
gcmkPRINT("#[kernel.execute]");
last = _Next(last);
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,353 @@
/****************************************************************************
*
* The MIT License (MIT)
*
* Copyright (c) 2014 - 2019 Vivante Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
*****************************************************************************
*
* The GPL License (GPL)
*
* Copyright (C) 2014 - 2019 Vivante Corporation
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*****************************************************************************
*
* Note: This software is released under dual MIT and GPL licenses. A
* recipient may use this file under the terms of either the MIT license or
* GPL License. If you wish to use only one license not the other, you can
* indicate your decision by deleting one of the above license notices in your
* version of this file.
*
*****************************************************************************/
#ifndef __gc_hal_kernel_hardware_command_vg_h_
#define __gc_hal_kernel_hardware_command_vg_h_
/******************************************************************************\
******************* Task and Interrupt Management Structures. ******************
\******************************************************************************/
/* Task storage header. */
typedef struct _gcsTASK_STORAGE * gcsTASK_STORAGE_PTR;
typedef struct _gcsTASK_STORAGE
{
/* Next allocated storage buffer. */
gcsTASK_STORAGE_PTR next;
}
gcsTASK_STORAGE;
/* Task container header. */
typedef struct _gcsTASK_CONTAINER * gcsTASK_CONTAINER_PTR;
typedef struct _gcsTASK_CONTAINER
{
/* The number of tasks left to be processed in the container. */
gctINT referenceCount;
/* Size of the buffer. */
gctUINT size;
/* Link to the previous and the next allocated containers. */
gcsTASK_CONTAINER_PTR allocPrev;
gcsTASK_CONTAINER_PTR allocNext;
/* Link to the previous and the next containers in the free list. */
gcsTASK_CONTAINER_PTR freePrev;
gcsTASK_CONTAINER_PTR freeNext;
}
gcsTASK_CONTAINER;
/* Kernel space task master table entry. */
typedef struct _gcsBLOCK_TASK_ENTRY * gcsBLOCK_TASK_ENTRY_PTR;
typedef struct _gcsBLOCK_TASK_ENTRY
{
/* Pointer to the current task container for the block. */
gcsTASK_CONTAINER_PTR container;
/* Pointer to the current task data within the container. */
gcsTASK_HEADER_PTR task;
/* Pointer to the last link task within the container. */
gcsTASK_LINK_PTR link;
/* Number of interrupts allocated for this block. */
gctUINT interruptCount;
/* The index of the current interrupt. */
gctUINT interruptIndex;
/* Interrupt semaphore. */
gctSEMAPHORE interruptSemaphore;
/* Interrupt value array. */
gctINT32 interruptArray[32];
}
gcsBLOCK_TASK_ENTRY;
/******************************************************************************\
********************* Command Queue Management Structures. *********************
\******************************************************************************/
/* Command queue kernel element pointer. */
typedef struct _gcsKERNEL_CMDQUEUE * gcsKERNEL_CMDQUEUE_PTR;
/* Command queue object handler function type. */
typedef gceSTATUS (* gctOBJECT_HANDLER) (
gckVGKERNEL Kernel,
gcsKERNEL_CMDQUEUE_PTR Entry
);
/* Command queue kernel element. */
typedef struct _gcsKERNEL_CMDQUEUE
{
/* The number of buffers in the queue. */
gcsCMDBUFFER_PTR commandBuffer;
/* Pointer to the object handler function. */
gctOBJECT_HANDLER handler;
}
gcsKERNEL_CMDQUEUE;
/* Command queue header. */
typedef struct _gcsKERNEL_QUEUE_HEADER * gcsKERNEL_QUEUE_HEADER_PTR;
typedef struct _gcsKERNEL_QUEUE_HEADER
{
/* The size of the buffer in bytes. */
gctUINT size;
/* The number of pending entries to be processed. */
volatile gctUINT pending;
/* The current command queue entry. */
gcsKERNEL_CMDQUEUE_PTR currentEntry;
/* Next buffer. */
gcsKERNEL_QUEUE_HEADER_PTR next;
}
gcsKERNEL_QUEUE_HEADER;
/******************************************************************************\
******************************* gckVGCOMMAND Object *******************************
\******************************************************************************/
/* gckVGCOMMAND object. */
struct _gckVGCOMMAND
{
/***************************************************************************
** Object data and pointers.
*/
gcsOBJECT object;
gckVGKERNEL kernel;
gckOS os;
gckVGHARDWARE hardware;
/* Features. */
gctBOOL fe20;
gctBOOL vg20;
gctBOOL vg21;
/***************************************************************************
** Enable command queue dumping.
*/
gctBOOL enableDumping;
/***************************************************************************
** Bus Error interrupt.
*/
gctINT32 busErrorInt;
/***************************************************************************
** Command buffer information.
*/
gcsCOMMAND_BUFFER_INFO info;
/***************************************************************************
** Synchronization objects.
*/
gctPOINTER queueMutex;
gctPOINTER taskMutex;
gctPOINTER commitMutex;
/***************************************************************************
** Task management.
*/
/* The head of the storage buffer linked list. */
gcsTASK_STORAGE_PTR taskStorage;
/* Allocation size. */
gctUINT taskStorageGranularity;
gctUINT taskStorageUsable;
/* The free container list. */
gcsTASK_CONTAINER_PTR taskFreeHead;
gcsTASK_CONTAINER_PTR taskFreeTail;
/* Task table */
gcsBLOCK_TASK_ENTRY taskTable[gcvBLOCK_COUNT];
/***************************************************************************
** Command queue.
*/
/* Pointer to the allocated queue memory. */
gcsKERNEL_QUEUE_HEADER_PTR queue;
/* Pointer to the current available queue from which new queue entries
will be allocated. */
gcsKERNEL_QUEUE_HEADER_PTR queueHead;
/* If different from queueHead, points to the command queue which is
currently being executed by the hardware. */
gcsKERNEL_QUEUE_HEADER_PTR queueTail;
/* Points to the queue to merge the tail with when the tail is processed. */
gcsKERNEL_QUEUE_HEADER_PTR mergeQueue;
/* Queue overflow counter. */
gctUINT queueOverflow;
/***************************************************************************
** Context.
*/
/* Context counter used for unique ID. */
gctUINT64 contextCounter;
/* Current context ID. */
gctUINT64 currentContext;
/* Command queue power semaphore. */
gctPOINTER powerSemaphore;
gctINT32 powerStallInt;
gcsCMDBUFFER_PTR powerStallBuffer;
gctSIGNAL powerStallSignal;
};
/******************************************************************************\
************************ gckVGCOMMAND Object Internal API. ***********************
\******************************************************************************/
/* Initialize architecture dependent command buffer information. */
gceSTATUS
gckVGCOMMAND_InitializeInfo(
IN gckVGCOMMAND Command
);
/* Form a STATE command at the specified location in the command buffer. */
gceSTATUS
gckVGCOMMAND_StateCommand(
IN gckVGCOMMAND Command,
IN gctUINT32 Pipe,
IN gctPOINTER Logical,
IN gctUINT32 Address,
IN gctUINT32 Count,
IN OUT gctUINT32 * Bytes
);
/* Form a RESTART command at the specified location in the command buffer. */
gceSTATUS
gckVGCOMMAND_RestartCommand(
IN gckVGCOMMAND Command,
IN gctPOINTER Logical,
IN gctUINT32 FetchAddress,
IN gctUINT FetchCount,
IN OUT gctUINT32 * Bytes
);
/* Form a FETCH command at the specified location in the command buffer. */
gceSTATUS
gckVGCOMMAND_FetchCommand(
IN gckVGCOMMAND Command,
IN gctPOINTER Logical,
IN gctUINT32 FetchAddress,
IN gctUINT FetchCount,
IN OUT gctUINT32 * Bytes
);
/* Form a CALL command at the specified location in the command buffer. */
gceSTATUS
gckVGCOMMAND_CallCommand(
IN gckVGCOMMAND Command,
IN gctPOINTER Logical,
IN gctUINT32 FetchAddress,
IN gctUINT FetchCount,
IN OUT gctUINT32 * Bytes
);
/* Form a RETURN command at the specified location in the command buffer. */
gceSTATUS
gckVGCOMMAND_ReturnCommand(
IN gckVGCOMMAND Command,
IN gctPOINTER Logical,
IN OUT gctUINT32 * Bytes
);
/* Form an EVENT command at the specified location in the command buffer. */
gceSTATUS
gckVGCOMMAND_EventCommand(
IN gckVGCOMMAND Command,
IN gctPOINTER Logical,
IN gceBLOCK Block,
IN gctINT32 InterruptId,
IN OUT gctUINT32 * Bytes
);
/* Form an END command at the specified location in the command buffer. */
gceSTATUS
gckVGCOMMAND_EndCommand(
IN gckVGCOMMAND Command,
IN gctPOINTER Logical,
IN gctINT32 InterruptId,
IN OUT gctUINT32 * Bytes
);
#endif /* __gc_hal_kernel_hardware_command_h_ */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,110 @@
/****************************************************************************
*
* The MIT License (MIT)
*
* Copyright (c) 2014 - 2019 Vivante Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
*****************************************************************************
*
* The GPL License (GPL)
*
* Copyright (C) 2014 - 2019 Vivante Corporation
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*****************************************************************************
*
* Note: This software is released under dual MIT and GPL licenses. A
* recipient may use this file under the terms of either the MIT license or
* GPL License. If you wish to use only one license not the other, you can
* indicate your decision by deleting one of the above license notices in your
* version of this file.
*
*****************************************************************************/
#ifndef __gc_hal_kernel_hardware_vg_h_
#define __gc_hal_kernel_hardware_vg_h_
/* gckHARDWARE object. */
struct _gckVGHARDWARE
{
/* Object. */
gcsOBJECT object;
/* Pointer to gckKERNEL object. */
gckVGKERNEL kernel;
/* Pointer to gckOS object. */
gckOS os;
/* Chip characteristics. */
gceCHIPMODEL chipModel;
gctUINT32 chipRevision;
gctUINT32 productID;
gctUINT32 ecoID;
gctUINT32 customerID;
gctUINT32 chipFeatures;
gctUINT32 chipMinorFeatures;
gctUINT32 chipMinorFeatures2;
/* Features. */
gctBOOL fe20;
gctBOOL vg20;
gctBOOL vg21;
gctBOOL fc;
/* Event mask. */
gctUINT32 eventMask;
gctBOOL clockState;
gctBOOL powerState;
gctPOINTER powerMutex;
gctUINT32 powerProcess;
gctUINT32 powerThread;
gceCHIPPOWERSTATE chipPowerState;
gceCHIPPOWERSTATE chipPowerStateGlobal;
gctPOINTER pageTableDirty;
#if gcdPOWEROFF_TIMEOUT
gctUINT32 powerOffTime;
gctUINT32 powerOffTimeout;
gctPOINTER powerOffTimer;
#endif
gcsHAL_QUERY_CHIP_OPTIONS options;
gctPOINTER featureDatabase;
};
#endif /* __gc_hal_kernel_hardware_h_ */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,888 @@
/****************************************************************************
*
* The MIT License (MIT)
*
* Copyright (c) 2014 - 2019 Vivante Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
*****************************************************************************
*
* The GPL License (GPL)
*
* Copyright (C) 2014 - 2019 Vivante Corporation
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*****************************************************************************
*
* Note: This software is released under dual MIT and GPL licenses. A
* recipient may use this file under the terms of either the MIT license or
* GPL License. If you wish to use only one license not the other, you can
* indicate your decision by deleting one of the above license notices in your
* version of this file.
*
*****************************************************************************/
/**
** @file
** gckHEAP object for kernel HAL layer. The heap implemented here is an arena-
** based memory allocation. An arena-based memory heap allocates data quickly
** from specified arenas and reduces memory fragmentation.
**
*/
#include "gc_hal_kernel_precomp.h"
#define _GC_OBJ_ZONE gcvZONE_HEAP
/*******************************************************************************
***** Structures ***************************************************************
*******************************************************************************/
#define gcdIN_USE ((gcskNODE_PTR)gcvMAXUINTPTR_T)
typedef struct _gcskNODE * gcskNODE_PTR;
typedef struct _gcskNODE
{
/* Number of byets in node. */
gctSIZE_T bytes;
/* Pointer to next free node, or gcvNULL to mark the node as freed, or
** gcdIN_USE to mark the node as used. */
gcskNODE_PTR next;
#if gcmIS_DEBUG(gcdDEBUG_CODE)
/* Time stamp of allocation. */
gctUINT64 timeStamp;
#endif
}
gcskNODE;
typedef struct _gcskHEAP * gcskHEAP_PTR;
typedef struct _gcskHEAP
{
/* Linked list. */
gcskHEAP_PTR next;
gcskHEAP_PTR prev;
/* Heap size. */
gctSIZE_T size;
/* Free list. */
gcskNODE_PTR freeList;
}
gcskHEAP;
struct _gckHEAP
{
/* Object. */
gcsOBJECT object;
/* Pointer to a gckOS object. */
gckOS os;
/* Locking mutex. */
gctPOINTER mutex;
/* Allocation parameters. */
gctSIZE_T allocationSize;
/* Heap list. */
gcskHEAP_PTR heap;
#if gcmIS_DEBUG(gcdDEBUG_CODE)
gctUINT64 timeStamp;
#endif
#if VIVANTE_PROFILER_SYSTEM_MEMORY || gcmIS_DEBUG(gcdDEBUG_CODE)
/* Profile information. */
gctUINT32 allocCount;
gctUINT64 allocBytes;
gctUINT64 allocBytesMax;
gctUINT64 allocBytesTotal;
gctUINT32 heapCount;
gctUINT32 heapCountMax;
gctUINT64 heapMemory;
gctUINT64 heapMemoryMax;
#endif
};
/*******************************************************************************
***** Static Support Functions *************************************************
*******************************************************************************/
#if gcmIS_DEBUG(gcdDEBUG_CODE)
static gctSIZE_T
_DumpHeap(
IN gcskHEAP_PTR Heap
)
{
gctPOINTER p;
gctSIZE_T leaked = 0;
/* Start at first node. */
for (p = Heap + 1;;)
{
/* Convert the pointer. */
gcskNODE_PTR node = (gcskNODE_PTR) p;
/* Check if this is a used node. */
if (node->next == gcdIN_USE)
{
/* Print the leaking node. */
gcmkTRACE_ZONE(gcvLEVEL_WARNING, gcvZONE_HEAP,
"Detected leaking: node=0x%x bytes=%lu timeStamp=%llu "
"(%08X %c%c%c%c)",
node, node->bytes, node->timeStamp,
((gctUINT32_PTR) (node + 1))[0],
gcmPRINTABLE(((gctUINT8_PTR) (node + 1))[0]),
gcmPRINTABLE(((gctUINT8_PTR) (node + 1))[1]),
gcmPRINTABLE(((gctUINT8_PTR) (node + 1))[2]),
gcmPRINTABLE(((gctUINT8_PTR) (node + 1))[3]));
/* Add leaking byte count. */
leaked += node->bytes;
}
/* Test for end of heap. */
if (node->bytes == 0)
{
break;
}
else
{
/* Move to next node. */
p = (gctUINT8_PTR) node + node->bytes;
}
}
/* Return the number of leaked bytes. */
return leaked;
}
#endif
static gceSTATUS
_CompactKernelHeap(
IN gckHEAP Heap
)
{
gcskHEAP_PTR heap, next;
gctPOINTER p;
gcskHEAP_PTR freeList = gcvNULL;
gcmkHEADER_ARG("Heap=0x%x", Heap);
/* Walk all the heaps. */
for (heap = Heap->heap; heap != gcvNULL; heap = next)
{
gcskNODE_PTR lastFree = gcvNULL;
/* Zero out the free list. */
heap->freeList = gcvNULL;
/* Start at the first node. */
for (p = (gctUINT8_PTR) (heap + 1);;)
{
/* Convert the pointer. */
gcskNODE_PTR node = (gcskNODE_PTR) p;
gcmkASSERT(p <= (gctPOINTER) ((gctUINT8_PTR) (heap + 1) + heap->size));
/* Test if this node not used. */
if (node->next != gcdIN_USE)
{
/* Test if this is the end of the heap. */
if (node->bytes == 0)
{
break;
}
/* Test of this is the first free node. */
else if (lastFree == gcvNULL)
{
/* Initialzie the free list. */
heap->freeList = node;
lastFree = node;
}
else
{
/* Test if this free node is contiguous with the previous
** free node. */
if ((gctUINT8_PTR) lastFree + lastFree->bytes == p)
{
/* Just increase the size of the previous free node. */
lastFree->bytes += node->bytes;
}
else
{
/* Add to linked list. */
lastFree->next = node;
lastFree = node;
}
}
}
/* Move to next node. */
p = (gctUINT8_PTR) node + node->bytes;
}
/* Mark the end of the chain. */
if (lastFree != gcvNULL)
{
lastFree->next = gcvNULL;
}
/* Get next heap. */
next = heap->next;
/* Check if the entire heap is free. */
if ((heap->freeList != gcvNULL)
&& (heap->freeList->bytes == heap->size - gcmSIZEOF(gcskNODE))
)
{
/* Remove the heap from the linked list. */
if (heap->prev == gcvNULL)
{
Heap->heap = next;
}
else
{
heap->prev->next = next;
}
if (heap->next != gcvNULL)
{
heap->next->prev = heap->prev;
}
#if VIVANTE_PROFILER_SYSTEM_MEMORY || gcmIS_DEBUG(gcdDEBUG_CODE)
/* Update profiling. */
Heap->heapCount -= 1;
Heap->heapMemory -= heap->size + gcmSIZEOF(gcskHEAP);
#endif
/* Add this heap to the list of heaps that need to be freed. */
heap->next = freeList;
freeList = heap;
}
}
if (freeList != gcvNULL)
{
/* Release the mutex, remove any chance for a dead lock. */
gcmkVERIFY_OK(
gckOS_ReleaseMutex(Heap->os, Heap->mutex));
/* Free all heaps in the free list. */
for (heap = freeList; heap != gcvNULL; heap = next)
{
/* Get pointer to the next heap. */
next = heap->next;
/* Free the heap. */
gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HEAP,
"Freeing heap 0x%x (%lu bytes)",
heap, heap->size + gcmSIZEOF(gcskHEAP));
gcmkVERIFY_OK(gckOS_FreeMemory(Heap->os, heap));
}
/* Acquire the mutex again. */
gcmkVERIFY_OK(
gckOS_AcquireMutex(Heap->os, Heap->mutex, gcvINFINITE));
}
/* Success. */
gcmkFOOTER_NO();
return gcvSTATUS_OK;
}
/*******************************************************************************
***** gckHEAP API Code *********************************************************
*******************************************************************************/
/*******************************************************************************
**
** gckHEAP_Construct
**
** Construct a new gckHEAP object.
**
** INPUT:
**
** gckOS Os
** Pointer to a gckOS object.
**
** gctSIZE_T AllocationSize
** Minimum size per arena.
**
** OUTPUT:
**
** gckHEAP * Heap
** Pointer to a variable that will hold the pointer to the gckHEAP
** object.
*/
gceSTATUS
gckHEAP_Construct(
IN gckOS Os,
IN gctSIZE_T AllocationSize,
OUT gckHEAP * Heap
)
{
gceSTATUS status;
gckHEAP heap = gcvNULL;
gctPOINTER pointer = gcvNULL;
gcmkHEADER_ARG("Os=0x%x AllocationSize=%lu", Os, AllocationSize);
/* Verify the arguments. */
gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
gcmkVERIFY_ARGUMENT(Heap != gcvNULL);
/* Allocate the gckHEAP object. */
gcmkONERROR(gckOS_AllocateMemory(Os,
gcmSIZEOF(struct _gckHEAP),
&pointer));
heap = pointer;
/* Initialize the gckHEAP object. */
heap->object.type = gcvOBJ_HEAP;
heap->os = Os;
heap->allocationSize = AllocationSize;
heap->heap = gcvNULL;
#if gcmIS_DEBUG(gcdDEBUG_CODE)
heap->timeStamp = 0;
#endif
#if VIVANTE_PROFILER_SYSTEM_MEMORY || gcmIS_DEBUG(gcdDEBUG_CODE)
/* Zero the counters. */
heap->allocCount = 0;
heap->allocBytes = 0;
heap->allocBytesMax = 0;
heap->allocBytesTotal = 0;
heap->heapCount = 0;
heap->heapCountMax = 0;
heap->heapMemory = 0;
heap->heapMemoryMax = 0;
#endif
/* Create the mutex. */
gcmkONERROR(gckOS_CreateMutex(Os, &heap->mutex));
/* Return the pointer to the gckHEAP object. */
*Heap = heap;
/* Success. */
gcmkFOOTER_ARG("*Heap=0x%x", *Heap);
return gcvSTATUS_OK;
OnError:
/* Roll back. */
if (heap != gcvNULL)
{
/* Free the heap structure. */
gcmkVERIFY_OK(gckOS_FreeMemory(Os, heap));
}
/* Return the status. */
gcmkFOOTER();
return status;
}
/*******************************************************************************
**
** gckHEAP_Destroy
**
** Destroy a gckHEAP object.
**
** INPUT:
**
** gckHEAP Heap
** Pointer to a gckHEAP object to destroy.
**
** OUTPUT:
**
** Nothing.
*/
gceSTATUS
gckHEAP_Destroy(
IN gckHEAP Heap
)
{
gcskHEAP_PTR heap;
#if gcmIS_DEBUG(gcdDEBUG_CODE)
gctSIZE_T leaked = 0;
#endif
gcmkHEADER_ARG("Heap=0x%x", Heap);
for (heap = Heap->heap; heap != gcvNULL; heap = Heap->heap)
{
/* Unlink heap from linked list. */
Heap->heap = heap->next;
#if gcmIS_DEBUG(gcdDEBUG_CODE)
/* Check for leaked memory. */
leaked += _DumpHeap(heap);
#endif
/* Free the heap. */
gcmkVERIFY_OK(gckOS_FreeMemory(Heap->os, heap));
}
/* Free the mutex. */
gcmkVERIFY_OK(gckOS_DeleteMutex(Heap->os, Heap->mutex));
/* Free the heap structure. */
gcmkVERIFY_OK(gckOS_FreeMemory(Heap->os, Heap));
/* Success. */
#if gcmIS_DEBUG(gcdDEBUG_CODE)
gcmkFOOTER_ARG("leaked=%lu", leaked);
#else
gcmkFOOTER_NO();
#endif
return gcvSTATUS_OK;
}
/*******************************************************************************
**
** gckHEAP_Allocate
**
** Allocate data from the heap.
**
** INPUT:
**
** gckHEAP Heap
** Pointer to a gckHEAP object.
**
** IN gctSIZE_T Bytes
** Number of byte to allocate.
**
** OUTPUT:
**
** gctPOINTER * Memory
** Pointer to a variable that will hold the address of the allocated
** memory.
*/
gceSTATUS
gckHEAP_Allocate(
IN gckHEAP Heap,
IN gctSIZE_T Bytes,
OUT gctPOINTER * Memory
)
{
gctBOOL acquired = gcvFALSE;
gcskHEAP_PTR heap;
gceSTATUS status;
gctSIZE_T bytes;
gcskNODE_PTR node, used, prevFree = gcvNULL;
gctPOINTER memory = gcvNULL;
gcmkHEADER_ARG("Heap=0x%x Bytes=%lu", Heap, Bytes);
/* Verify the arguments. */
gcmkVERIFY_OBJECT(Heap, gcvOBJ_HEAP);
gcmkVERIFY_ARGUMENT(Bytes > 0);
gcmkVERIFY_ARGUMENT(Memory != gcvNULL);
/* Determine number of bytes required for a node. */
bytes = gcmALIGN(Bytes + gcmSIZEOF(gcskNODE), 8);
/* Acquire the mutex. */
gcmkONERROR(
gckOS_AcquireMutex(Heap->os, Heap->mutex, gcvINFINITE));
acquired = gcvTRUE;
/* Check if this allocation is bigger than the default allocation size. */
if (bytes > Heap->allocationSize - gcmSIZEOF(gcskHEAP) - gcmSIZEOF(gcskNODE))
{
/* Adjust allocation size. */
Heap->allocationSize = bytes * 2;
}
else if (Heap->heap != gcvNULL)
{
gctINT i;
/* 2 retries, since we might need to compact. */
for (i = 0; i < 2; ++i)
{
/* Walk all the heaps. */
for (heap = Heap->heap; heap != gcvNULL; heap = heap->next)
{
/* Check if this heap has enough bytes to hold the request. */
if (bytes <= heap->size - gcmSIZEOF(gcskNODE))
{
prevFree = gcvNULL;
/* Walk the chain of free nodes. */
for (node = heap->freeList;
node != gcvNULL;
node = node->next
)
{
gcmkASSERT(node->next != gcdIN_USE);
/* Check if this free node has enough bytes. */
if (node->bytes >= bytes)
{
/* Use the node. */
goto UseNode;
}
/* Save current free node for linked list management. */
prevFree = node;
}
}
}
if (i == 0)
{
/* Compact the heap. */
gcmkVERIFY_OK(_CompactKernelHeap(Heap));
#if gcmIS_DEBUG(gcdDEBUG_CODE)
gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_HEAP,
"===== KERNEL HEAP =====");
gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_HEAP,
"Number of allocations : %12u",
Heap->allocCount);
gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_HEAP,
"Number of bytes allocated : %12llu",
Heap->allocBytes);
gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_HEAP,
"Maximum allocation size : %12llu",
Heap->allocBytesMax);
gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_HEAP,
"Total number of bytes allocated : %12llu",
Heap->allocBytesTotal);
gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_HEAP,
"Number of heaps : %12u",
Heap->heapCount);
gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_HEAP,
"Heap memory in bytes : %12llu",
Heap->heapMemory);
gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_HEAP,
"Maximum number of heaps : %12u",
Heap->heapCountMax);
gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_HEAP,
"Maximum heap memory in bytes : %12llu",
Heap->heapMemoryMax);
#endif
}
}
}
/* Release the mutex. */
gcmkONERROR(
gckOS_ReleaseMutex(Heap->os, Heap->mutex));
acquired = gcvFALSE;
/* Allocate a new heap. */
gcmkONERROR(
gckOS_AllocateMemory(Heap->os,
Heap->allocationSize,
&memory));
gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HEAP,
"Allocated heap 0x%x (%lu bytes)",
memory, Heap->allocationSize);
/* Acquire the mutex. */
gcmkONERROR(
gckOS_AcquireMutex(Heap->os, Heap->mutex, gcvINFINITE));
acquired = gcvTRUE;
/* Use the allocated memory as the heap. */
heap = (gcskHEAP_PTR) memory;
/* Insert this heap to the head of the chain. */
heap->next = Heap->heap;
heap->prev = gcvNULL;
heap->size = Heap->allocationSize - gcmSIZEOF(gcskHEAP);
if (heap->next != gcvNULL)
{
heap->next->prev = heap;
}
Heap->heap = heap;
/* Mark the end of the heap. */
node = (gcskNODE_PTR) ( (gctUINT8_PTR) heap
+ Heap->allocationSize
- gcmSIZEOF(gcskNODE)
);
node->bytes = 0;
node->next = gcvNULL;
/* Create a free list. */
node = (gcskNODE_PTR) (heap + 1);
heap->freeList = node;
/* Initialize the free list. */
node->bytes = heap->size - gcmSIZEOF(gcskNODE);
node->next = gcvNULL;
/* No previous free. */
prevFree = gcvNULL;
#if VIVANTE_PROFILER_SYSTEM_MEMORY || gcmIS_DEBUG(gcdDEBUG_CODE)
/* Update profiling. */
Heap->heapCount += 1;
Heap->heapMemory += Heap->allocationSize;
if (Heap->heapCount > Heap->heapCountMax)
{
Heap->heapCountMax = Heap->heapCount;
}
if (Heap->heapMemory > Heap->heapMemoryMax)
{
Heap->heapMemoryMax = Heap->heapMemory;
}
#endif
UseNode:
/* Verify some stuff. */
gcmkASSERT(heap != gcvNULL);
gcmkASSERT(node != gcvNULL);
gcmkASSERT(node->bytes >= bytes);
if (heap->prev != gcvNULL)
{
/* Unlink the heap from the linked list. */
heap->prev->next = heap->next;
if (heap->next != gcvNULL)
{
heap->next->prev = heap->prev;
}
/* Move the heap to the front of the list. */
heap->next = Heap->heap;
heap->prev = gcvNULL;
Heap->heap = heap;
heap->next->prev = heap;
}
/* Check if there is enough free space left after usage for another free
** node. */
if (node->bytes - bytes >= gcmSIZEOF(gcskNODE))
{
/* Allocated used space from the back of the free list. */
used = (gcskNODE_PTR) ((gctUINT8_PTR) node + node->bytes - bytes);
/* Adjust the number of free bytes. */
node->bytes -= bytes;
gcmkASSERT(node->bytes >= gcmSIZEOF(gcskNODE));
}
else
{
/* Remove this free list from the chain. */
if (prevFree == gcvNULL)
{
heap->freeList = node->next;
}
else
{
prevFree->next = node->next;
}
/* Consume the entire free node. */
used = (gcskNODE_PTR) node;
bytes = node->bytes;
}
/* Mark node as used. */
used->bytes = bytes;
used->next = gcdIN_USE;
#if gcmIS_DEBUG(gcdDEBUG_CODE)
used->timeStamp = ++Heap->timeStamp;
#endif
#if VIVANTE_PROFILER_SYSTEM_MEMORY || gcmIS_DEBUG(gcdDEBUG_CODE)
/* Update profile counters. */
Heap->allocCount += 1;
Heap->allocBytes += bytes;
Heap->allocBytesMax = gcmMAX(Heap->allocBytes, Heap->allocBytesMax);
Heap->allocBytesTotal += bytes;
#endif
/* Release the mutex. */
gcmkVERIFY_OK(
gckOS_ReleaseMutex(Heap->os, Heap->mutex));
/* Return pointer to memory. */
*Memory = used + 1;
/* Success. */
gcmkFOOTER_ARG("*Memory=0x%x", *Memory);
return gcvSTATUS_OK;
OnError:
if (acquired)
{
/* Release the mutex. */
gcmkVERIFY_OK(
gckOS_ReleaseMutex(Heap->os, Heap->mutex));
}
if (memory != gcvNULL)
{
/* Free the heap memory. */
gckOS_FreeMemory(Heap->os, memory);
}
/* Return the status. */
gcmkFOOTER();
return status;
}
/*******************************************************************************
**
** gckHEAP_Free
**
** Free allocated memory from the heap.
**
** INPUT:
**
** gckHEAP Heap
** Pointer to a gckHEAP object.
**
** IN gctPOINTER Memory
** Pointer to memory to free.
**
** OUTPUT:
**
** NOTHING.
*/
gceSTATUS
gckHEAP_Free(
IN gckHEAP Heap,
IN gctPOINTER Memory
)
{
gcskNODE_PTR node;
gceSTATUS status;
gcmkHEADER_ARG("Heap=0x%x Memory=0x%x", Heap, Memory);
/* Verify the arguments. */
gcmkVERIFY_OBJECT(Heap, gcvOBJ_HEAP);
gcmkVERIFY_ARGUMENT(Memory != gcvNULL);
/* Acquire the mutex. */
gcmkONERROR(
gckOS_AcquireMutex(Heap->os, Heap->mutex, gcvINFINITE));
/* Pointer to structure. */
node = (gcskNODE_PTR) Memory - 1;
/* Mark the node as freed. */
node->next = gcvNULL;
#if VIVANTE_PROFILER_SYSTEM_MEMORY || gcmIS_DEBUG(gcdDEBUG_CODE)
/* Update profile counters. */
Heap->allocBytes -= node->bytes;
#endif
/* Release the mutex. */
gcmkVERIFY_OK(
gckOS_ReleaseMutex(Heap->os, Heap->mutex));
/* Success. */
gcmkFOOTER_NO();
return gcvSTATUS_OK;
OnError:
/* Return the status. */
gcmkFOOTER();
return status;
}
#if VIVANTE_PROFILER_SYSTEM_MEMORY
gceSTATUS
gckHEAP_ProfileStart(
IN gckHEAP Heap
)
{
gcmkHEADER_ARG("Heap=0x%x", Heap);
/* Verify the arguments. */
gcmkVERIFY_OBJECT(Heap, gcvOBJ_HEAP);
/* Zero the counters. */
Heap->allocCount = 0;
Heap->allocBytes = 0;
Heap->allocBytesMax = 0;
Heap->allocBytesTotal = 0;
Heap->heapCount = 0;
Heap->heapCountMax = 0;
Heap->heapMemory = 0;
Heap->heapMemoryMax = 0;
/* Success. */
gcmkFOOTER_NO();
return gcvSTATUS_OK;
}
gceSTATUS
gckHEAP_ProfileEnd(
IN gckHEAP Heap,
IN gctCONST_STRING Title
)
{
gcmkHEADER_ARG("Heap=0x%x Title=0x%x", Heap, Title);
/* Verify the arguments. */
gcmkVERIFY_OBJECT(Heap, gcvOBJ_HEAP);
gcmkVERIFY_ARGUMENT(Title != gcvNULL);
gcmkPRINT("\n");
gcmkPRINT("=====[ HEAP - %s ]=====", Title);
gcmkPRINT("Number of allocations : %12u", Heap->allocCount);
gcmkPRINT("Number of bytes allocated : %12llu", Heap->allocBytes);
gcmkPRINT("Maximum allocation size : %12llu", Heap->allocBytesMax);
gcmkPRINT("Total number of bytes allocated : %12llu", Heap->allocBytesTotal);
gcmkPRINT("Number of heaps : %12u", Heap->heapCount);
gcmkPRINT("Heap memory in bytes : %12llu", Heap->heapMemory);
gcmkPRINT("Maximum number of heaps : %12u", Heap->heapCountMax);
gcmkPRINT("Maximum heap memory in bytes : %12llu", Heap->heapMemoryMax);
gcmkPRINT("==============================================");
/* Success. */
gcmkFOOTER_NO();
return gcvSTATUS_OK;
}
#endif /* VIVANTE_PROFILER_SYSTEM_MEMORY */

View File

@ -0,0 +1,911 @@
/****************************************************************************
*
* The MIT License (MIT)
*
* Copyright (c) 2014 - 2019 Vivante Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
*****************************************************************************
*
* The GPL License (GPL)
*
* Copyright (C) 2014 - 2019 Vivante Corporation
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*****************************************************************************
*
* Note: This software is released under dual MIT and GPL licenses. A
* recipient may use this file under the terms of either the MIT license or
* GPL License. If you wish to use only one license not the other, you can
* indicate your decision by deleting one of the above license notices in your
* version of this file.
*
*****************************************************************************/
#include "gc_hal_kernel_precomp.h"
#if gcdENABLE_VG
/******************************************************************************\
*********************** Support Functions and Definitions **********************
\******************************************************************************/
/* Interruot statistics will be accumulated if not zero. */
#define gcmENABLE_INTERRUPT_STATISTICS 0
#define _GC_OBJ_ZONE gcvZONE_INTERRUPT
/* Object structure. */
struct _gckVGINTERRUPT
{
/* Object. */
gcsOBJECT object;
/* gckVGKERNEL pointer. */
gckVGKERNEL kernel;
/* gckOS pointer. */
gckOS os;
/* Interrupt handlers. */
gctINTERRUPT_HANDLER handlers[32];
/* Main interrupt handler thread. */
gctTHREAD handler;
gctBOOL terminate;
/* Interrupt FIFO. */
gctSEMAPHORE fifoValid;
gctUINT32 fifo[256];
gctUINT fifoItems;
gctUINT8 head;
gctUINT8 tail;
/* Interrupt statistics. */
#if gcmENABLE_INTERRUPT_STATISTICS
gctUINT maxFifoItems;
gctUINT fifoOverflow;
gctUINT maxSimultaneous;
gctUINT multipleCount;
#endif
};
/*******************************************************************************
**
** _ProcessInterrupt
**
** The interrupt processor.
**
** INPUT:
**
** ThreadParameter
** Pointer to the gckVGINTERRUPT object.
**
** OUTPUT:
**
** Nothing.
*/
#if gcmENABLE_INTERRUPT_STATISTICS
static void
_ProcessInterrupt(
gckVGINTERRUPT Interrupt,
gctUINT_PTR TriggeredCount
)
#else
static void
_ProcessInterrupt(
gckVGINTERRUPT Interrupt
)
#endif
{
gceSTATUS status;
gctUINT32 triggered;
gctUINT i;
/* Advance to the next entry. */
Interrupt->tail += 1;
Interrupt->fifoItems -= 1;
/* Get the interrupt value. */
triggered = Interrupt->fifo[Interrupt->tail];
gcmkASSERT(triggered != 0);
gcmkTRACE_ZONE(
gcvLEVEL_VERBOSE, gcvZONE_COMMAND,
"%s: triggered=0x%08X\n",
__FUNCTION__,
triggered
);
/* Walk through all possible interrupts. */
for (i = 0; i < gcmSIZEOF(Interrupt->handlers); i += 1)
{
/* Test if interrupt happened. */
if ((triggered & 1) == 1)
{
#if gcmENABLE_INTERRUPT_STATISTICS
if (TriggeredCount != gcvNULL)
{
(* TriggeredCount) += 1;
}
#endif
/* Make sure we have valid handler. */
if (Interrupt->handlers[i] == gcvNULL)
{
gcmkTRACE(
gcvLEVEL_ERROR,
"%s: Interrupt %d isn't registered.\n",
__FUNCTION__, i
);
}
else
{
gcmkTRACE_ZONE(
gcvLEVEL_VERBOSE, gcvZONE_COMMAND,
"%s: interrupt=%d\n",
__FUNCTION__,
i
);
/* Call the handler. */
status = Interrupt->handlers[i] (Interrupt->kernel);
if (gcmkIS_ERROR(status))
{
/* Failed to signal the semaphore. */
gcmkTRACE(
gcvLEVEL_ERROR,
"%s: Error %d incrementing the semaphore #%d.\n",
__FUNCTION__, status, i
);
}
}
}
/* Next interrupt. */
triggered >>= 1;
/* No more interrupts to handle? */
if (triggered == 0)
{
break;
}
}
}
/*******************************************************************************
**
** _MainInterruptHandler
**
** The main interrupt thread serves the interrupt FIFO and calls registered
** handlers for the interrupts that occured. The handlers are called in the
** sequence interrupts occured with the exception when multiple interrupts
** occured at the same time. In that case the handler calls are "sorted" by
** the interrupt number therefore giving the interrupts with lower numbers
** higher priority.
**
** INPUT:
**
** ThreadParameter
** Pointer to the gckVGINTERRUPT object.
**
** OUTPUT:
**
** Nothing.
*/
static gctTHREADFUNCRESULT gctTHREADFUNCTYPE
_MainInterruptHandler(
gctTHREADFUNCPARAMETER ThreadParameter
)
{
gceSTATUS status;
gckVGINTERRUPT interrupt;
#if gcmENABLE_INTERRUPT_STATISTICS
gctUINT count;
#endif
/* Cast the object. */
interrupt = (gckVGINTERRUPT) ThreadParameter;
/* Enter the loop. */
while (gcvTRUE)
{
/* Wait for an interrupt. */
status = gckOS_DecrementSemaphore(interrupt->os, interrupt->fifoValid);
/* Error? */
if (gcmkIS_ERROR(status))
{
break;
}
/* System termination request? */
if (status == gcvSTATUS_TERMINATE)
{
break;
}
/* Driver is shutting down? */
if (interrupt->terminate)
{
break;
}
#if gcmENABLE_INTERRUPT_STATISTICS
/* Reset triggered count. */
count = 0;
/* Process the interrupt. */
_ProcessInterrupt(interrupt, &count);
/* Update conters. */
if (count > interrupt->maxSimultaneous)
{
interrupt->maxSimultaneous = count;
}
if (count > 1)
{
interrupt->multipleCount += 1;
}
#else
/* Process the interrupt. */
_ProcessInterrupt(interrupt);
#endif
}
return 0;
}
/*******************************************************************************
**
** _StartInterruptHandler / _StopInterruptHandler
**
** Main interrupt handler routine control.
**
** INPUT:
**
** ThreadParameter
** Pointer to the gckVGINTERRUPT object.
**
** OUTPUT:
**
** Nothing.
*/
static gceSTATUS
_StartInterruptHandler(
gckVGINTERRUPT Interrupt
)
{
gceSTATUS status, last;
do
{
/* Objects must not be already created. */
gcmkASSERT(Interrupt->fifoValid == gcvNULL);
gcmkASSERT(Interrupt->handler == gcvNULL);
/* Reset the termination request. */
Interrupt->terminate = gcvFALSE;
#if !gcdENABLE_INFINITE_SPEED_HW
/* Construct the fifo semaphore. */
gcmkERR_BREAK(gckOS_CreateSemaphoreVG(
Interrupt->os, &Interrupt->fifoValid
));
/* Start the interrupt handler thread. */
gcmkERR_BREAK(gckOS_StartThread(
Interrupt->os,
_MainInterruptHandler,
Interrupt,
&Interrupt->handler
));
#endif
/* Success. */
return gcvSTATUS_OK;
}
while (gcvFALSE);
/* Roll back. */
if (Interrupt->fifoValid != gcvNULL)
{
gcmkCHECK_STATUS(gckOS_DestroySemaphore(
Interrupt->os, Interrupt->fifoValid
));
Interrupt->fifoValid = gcvNULL;
}
/* Return the status. */
return status;
}
static gceSTATUS
_StopInterruptHandler(
gckVGINTERRUPT Interrupt
)
{
gceSTATUS status;
do
{
/* Does the thread exist? */
if (Interrupt->handler == gcvNULL)
{
/* The semaphore must be NULL as well. */
gcmkASSERT(Interrupt->fifoValid == gcvNULL);
/* Success. */
status = gcvSTATUS_OK;
break;
}
/* The semaphore must exist as well. */
gcmkASSERT(Interrupt->fifoValid != gcvNULL);
/* Set the termination request. */
Interrupt->terminate = gcvTRUE;
/* Unlock the thread. */
gcmkERR_BREAK(gckOS_IncrementSemaphore(
Interrupt->os, Interrupt->fifoValid
));
/* Wait until the thread quits. */
gcmkERR_BREAK(gckOS_StopThread(
Interrupt->os,
Interrupt->handler
));
/* Destroy the semaphore. */
gcmkERR_BREAK(gckOS_DestroySemaphore(
Interrupt->os, Interrupt->fifoValid
));
/* Reset handles. */
Interrupt->handler = gcvNULL;
Interrupt->fifoValid = gcvNULL;
}
while (gcvFALSE);
/* Return the status. */
return status;
}
/******************************************************************************\
***************************** Interrupt Object API *****************************
\******************************************************************************/
/*******************************************************************************
**
** gckVGINTERRUPT_Construct
**
** Construct an interrupt object.
**
** INPUT:
**
** Kernel
** Pointer to the gckVGKERNEL object.
**
** OUTPUT:
**
** Interrupt
** Pointer to the new gckVGINTERRUPT object.
*/
gceSTATUS
gckVGINTERRUPT_Construct(
IN gckVGKERNEL Kernel,
OUT gckVGINTERRUPT * Interrupt
)
{
gceSTATUS status;
gckVGINTERRUPT interrupt = gcvNULL;
gcmkHEADER_ARG("Kernel=0x%x Interrupt=0x%x", Kernel, Interrupt);
/* Verify argeuments. */
gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
gcmkVERIFY_ARGUMENT(Interrupt != gcvNULL);
do
{
/* Allocate the gckVGINTERRUPT structure. */
gcmkERR_BREAK(gckOS_Allocate(
Kernel->os,
gcmSIZEOF(struct _gckVGINTERRUPT),
(gctPOINTER *) &interrupt
));
/* Reset the object data. */
gcmkVERIFY_OK(gckOS_ZeroMemory(
interrupt, gcmSIZEOF(struct _gckVGINTERRUPT)
));
/* Initialize the object. */
interrupt->object.type = gcvOBJ_INTERRUPT;
/* Initialize the object pointers. */
interrupt->kernel = Kernel;
interrupt->os = Kernel->os;
/* Initialize the current FIFO position. */
interrupt->head = (gctUINT8)~0;
interrupt->tail = (gctUINT8)~0;
/* Start the thread. */
gcmkERR_BREAK(_StartInterruptHandler(interrupt));
/* Return interrupt object. */
*Interrupt = interrupt;
gcmkFOOTER_ARG("*Interrup=0x%x", *Interrupt);
/* Success. */
return gcvSTATUS_OK;
}
while (gcvFALSE);
/* Roll back. */
if (interrupt != gcvNULL)
{
/* Free the gckVGINTERRUPT structure. */
gcmkVERIFY_OK(gckOS_Free(interrupt->os, interrupt));
}
gcmkFOOTER();
/* Return the status. */
return status;
}
/*******************************************************************************
**
** gckVGINTERRUPT_Destroy
**
** Destroy an interrupt object.
**
** INPUT:
**
** Interrupt
** Pointer to the gckVGINTERRUPT object to destroy.
**
** OUTPUT:
**
** Nothing.
*/
gceSTATUS
gckVGINTERRUPT_Destroy(
IN gckVGINTERRUPT Interrupt
)
{
gceSTATUS status;
gcmkHEADER_ARG("Interrupt=0x%x", Interrupt);
/* Verify the arguments. */
gcmkVERIFY_OBJECT(Interrupt, gcvOBJ_INTERRUPT);
do
{
/* Stop the interrupt thread. */
gcmkERR_BREAK(_StopInterruptHandler(Interrupt));
/* Mark the object as unknown. */
Interrupt->object.type = gcvOBJ_UNKNOWN;
/* Free the gckVGINTERRUPT structure. */
gcmkERR_BREAK(gckOS_Free(Interrupt->os, Interrupt));
}
while (gcvFALSE);
gcmkFOOTER();
/* Return the status. */
return status;
}
/*******************************************************************************
**
** gckVGINTERRUPT_DumpState
**
** Print the current state of the interrupt manager.
**
** INPUT:
**
** Interrupt
** Pointer to a gckVGINTERRUPT object.
**
** OUTPUT:
**
** Nothing.
*/
#if gcvDEBUG
gceSTATUS
gckVGINTERRUPT_DumpState(
IN gckVGINTERRUPT Interrupt
)
{
gcmkHEADER_ARG("Interrupt=0x%x", Interrupt);
/* Verify the arguments. */
gcmkVERIFY_OBJECT(Interrupt, gcvOBJ_INTERRUPT);
/* Print the header. */
gcmkTRACE_ZONE(
gcvLEVEL_VERBOSE, gcvZONE_COMMAND,
"%s: INTERRUPT OBJECT STATUS\n",
__FUNCTION__
);
/* Print statistics. */
#if gcmENABLE_INTERRUPT_STATISTICS
gcmkTRACE_ZONE(
gcvLEVEL_VERBOSE, gcvZONE_COMMAND,
" Maximum number of FIFO items accumulated at a single time: %d\n",
Interrupt->maxFifoItems
);
gcmkTRACE_ZONE(
gcvLEVEL_VERBOSE, gcvZONE_COMMAND,
" Interrupt FIFO overflow happened times: %d\n",
Interrupt->fifoOverflow
);
gcmkTRACE_ZONE(
gcvLEVEL_VERBOSE, gcvZONE_COMMAND,
" Maximum number of interrupts simultaneously generated: %d\n",
Interrupt->maxSimultaneous
);
gcmkTRACE_ZONE(
gcvLEVEL_VERBOSE, gcvZONE_COMMAND,
" Number of times when there were multiple interrupts generated: %d\n",
Interrupt->multipleCount
);
#endif
gcmkTRACE_ZONE(
gcvLEVEL_VERBOSE, gcvZONE_COMMAND,
" The current number of entries in the FIFO: %d\n",
Interrupt->fifoItems
);
/* Print the FIFO contents. */
if (Interrupt->fifoItems != 0)
{
gctUINT8 index;
gctUINT8 last;
gcmkTRACE_ZONE(
gcvLEVEL_VERBOSE, gcvZONE_COMMAND,
" FIFO current contents:\n"
);
/* Get the current pointers. */
index = Interrupt->tail;
last = Interrupt->head;
while (index != last)
{
/* Advance to the next entry. */
index += 1;
gcmkTRACE_ZONE(
gcvLEVEL_VERBOSE, gcvZONE_COMMAND,
" %d: 0x%08X\n",
index, Interrupt->fifo[index]
);
}
}
gcmkFOOTER_NO();
/* Success. */
return gcvSTATUS_OK;
}
#endif
/*******************************************************************************
**
** gckVGINTERRUPT_Enable
**
** Enable the specified interrupt.
**
** INPUT:
**
** Interrupt
** Pointer to a gckVGINTERRUPT object.
**
** Id
** Pointer to the variable that holds the interrupt number to be
** registered in range 0..31.
** If the value is less then 0, gckVGINTERRUPT_Enable will attempt
** to find an unused interrupt. If such interrupt is found, the number
** will be assigned to the variable if the functuion call succeedes.
**
** Handler
** Pointer to the handler to register for the interrupt.
**
** OUTPUT:
**
** Nothing.
*/
gceSTATUS
gckVGINTERRUPT_Enable(
IN gckVGINTERRUPT Interrupt,
IN OUT gctINT32_PTR Id,
IN gctINTERRUPT_HANDLER Handler
)
{
gceSTATUS status;
gctINT32 i;
gcmkHEADER_ARG("Interrupt=0x%x Id=0x%x Handler=0x%x", Interrupt, Id, Handler);
/* Verify the arguments. */
gcmkVERIFY_OBJECT(Interrupt, gcvOBJ_INTERRUPT);
gcmkVERIFY_ARGUMENT(Id != gcvNULL);
gcmkVERIFY_ARGUMENT(Handler != gcvNULL);
do
{
/* See if we need to allocate an ID. */
if (*Id < 0)
{
/* Find the first unused interrupt handler. */
for (i = 0; i < gcmCOUNTOF(Interrupt->handlers); ++i)
{
if (Interrupt->handlers[i] == gcvNULL)
{
break;
}
}
/* No unused innterrupts? */
if (i == gcmCOUNTOF(Interrupt->handlers))
{
status = gcvSTATUS_OUT_OF_RESOURCES;
break;
}
/* Update the interrupt ID. */
*Id = i;
}
/* Make sure the ID is in range. */
else if (*Id >= gcmCOUNTOF(Interrupt->handlers))
{
status = gcvSTATUS_INVALID_ARGUMENT;
break;
}
/* Set interrupt handler. */
Interrupt->handlers[*Id] = Handler;
/* Success. */
status = gcvSTATUS_OK;
}
while (gcvFALSE);
gcmkFOOTER();
/* Return the status. */
return status;
}
/*******************************************************************************
**
** gckVGINTERRUPT_Disable
**
** Disable the specified interrupt.
**
** INPUT:
**
** Interrupt
** Pointer to a gckVGINTERRUPT object.
**
** Id
** Interrupt number to be disabled in range 0..31.
**
** OUTPUT:
**
** Nothing.
*/
gceSTATUS
gckVGINTERRUPT_Disable(
IN gckVGINTERRUPT Interrupt,
IN gctINT32 Id
)
{
gcmkHEADER_ARG("Interrupt=0x%x Id=0x%x", Interrupt, Id);
/* Verify the arguments. */
gcmkVERIFY_OBJECT(Interrupt, gcvOBJ_INTERRUPT);
gcmkVERIFY_ARGUMENT((Id >= 0) && (Id < gcmCOUNTOF(Interrupt->handlers)));
/* Reset interrupt handler. */
Interrupt->handlers[Id] = gcvNULL;
gcmkFOOTER_NO();
/* Success. */
return gcvSTATUS_OK;
}
/*******************************************************************************
**
** gckVGINTERRUPT_Enque
**
** Read the interrupt status register and put the value in the interrupt FIFO.
**
** INPUT:
**
** Interrupt
** Pointer to a gckVGINTERRUPT object.
**
** OUTPUT:
**
** Nothing.
*/
#ifndef __QNXNTO__
gceSTATUS
gckVGINTERRUPT_Enque(
IN gckVGINTERRUPT Interrupt
)
#else
gceSTATUS
gckVGINTERRUPT_Enque(
IN gckVGINTERRUPT Interrupt,
OUT gckOS *Os,
OUT gctSEMAPHORE *Semaphore
)
#endif
{
gceSTATUS status;
gctUINT32 triggered;
gcmkHEADER_ARG("Interrupt=0x%x", Interrupt);
/* Verify the arguments. */
gcmkVERIFY_OBJECT(Interrupt, gcvOBJ_INTERRUPT);
#ifdef __QNXNTO__
*Os = gcvNULL;
*Semaphore = gcvNULL;
#endif
do
{
/* Read interrupt status register. */
gcmkERR_BREAK(gckVGHARDWARE_ReadInterrupt(
Interrupt->kernel->hardware, &triggered
));
/* Mask out TS overflow interrupt */
triggered &= 0xfffffffe;
/* No interrupts to process? */
if (triggered == 0)
{
status = gcvSTATUS_NOT_OUR_INTERRUPT;
break;
}
/* FIFO overflow? */
if (Interrupt->fifoItems == gcmCOUNTOF(Interrupt->fifo))
{
#if gcmENABLE_INTERRUPT_STATISTICS
Interrupt->fifoOverflow += 1;
#endif
/* OR the interrupt with the last value in the FIFO. */
Interrupt->fifo[Interrupt->head] |= triggered;
/* Success (kind of). */
status = gcvSTATUS_OK;
}
else
{
/* Advance to the next entry. */
Interrupt->head += 1;
Interrupt->fifoItems += 1;
#if gcmENABLE_INTERRUPT_STATISTICS
if (Interrupt->fifoItems > Interrupt->maxFifoItems)
{
Interrupt->maxFifoItems = Interrupt->fifoItems;
}
#endif
/* Set the new value. */
Interrupt->fifo[Interrupt->head] = triggered;
#ifndef __QNXNTO__
/* Increment the FIFO semaphore. */
gcmkERR_BREAK(gckOS_IncrementSemaphore(
Interrupt->os, Interrupt->fifoValid
));
#else
*Os = Interrupt->os;
*Semaphore = Interrupt->fifoValid;
#endif
/* Windows kills our threads prematurely when the application
exists. Verify here that the thread is still alive. */
status = gckOS_VerifyThread(Interrupt->os, Interrupt->handler);
/* Has the thread been prematurely terminated? */
if (status != gcvSTATUS_OK)
{
/* Process all accumulated interrupts. */
while (Interrupt->head != Interrupt->tail)
{
#if gcmENABLE_INTERRUPT_STATISTICS
/* Process the interrupt. */
_ProcessInterrupt(Interrupt, gcvNULL);
#else
/* Process the interrupt. */
_ProcessInterrupt(Interrupt);
#endif
}
/* Set success. */
status = gcvSTATUS_OK;
}
}
}
while (gcvFALSE);
gcmkFOOTER();
/* Return status. */
return status;
}
#endif /* gcdENABLE_VG */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,557 @@
/****************************************************************************
*
* The MIT License (MIT)
*
* Copyright (c) 2014 - 2019 Vivante Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
*****************************************************************************
*
* The GPL License (GPL)
*
* Copyright (C) 2014 - 2019 Vivante Corporation
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*****************************************************************************
*
* Note: This software is released under dual MIT and GPL licenses. A
* recipient may use this file under the terms of either the MIT license or
* GPL License. If you wish to use only one license not the other, you can
* indicate your decision by deleting one of the above license notices in your
* version of this file.
*
*****************************************************************************/
#include "gc_hal_kernel_precomp.h"
#if gcdENABLE_VG
#define _GC_OBJ_ZONE gcvZONE_MMU
/*******************************************************************************
**
** gckVGMMU_Construct
**
** Construct a new gckVGMMU object.
**
** INPUT:
**
** gckVGKERNEL Kernel
** Pointer to an gckVGKERNEL object.
**
** gctSIZE_T MmuSize
** Number of bytes for the page table.
**
** OUTPUT:
**
** gckVGMMU * Mmu
** Pointer to a variable that receives the gckVGMMU object pointer.
*/
gceSTATUS gckVGMMU_Construct(
IN gckVGKERNEL Kernel,
IN gctUINT32 MmuSize,
OUT gckVGMMU * Mmu
)
{
gckOS os;
gckVGHARDWARE hardware;
gceSTATUS status;
gckVGMMU mmu;
gctUINT32 * pageTable;
gctUINT32 i;
gcmkHEADER_ARG("Kernel=0x%x MmuSize=0x%x Mmu=0x%x", Kernel, MmuSize, Mmu);
/* Verify the arguments. */
gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
gcmkVERIFY_ARGUMENT(MmuSize > 0);
gcmkVERIFY_ARGUMENT(Mmu != gcvNULL);
/* Extract the gckOS object pointer. */
os = Kernel->os;
gcmkVERIFY_OBJECT(os, gcvOBJ_OS);
/* Extract the gckVGHARDWARE object pointer. */
hardware = Kernel->hardware;
gcmkVERIFY_OBJECT(hardware, gcvOBJ_HARDWARE);
/* Allocate memory for the gckVGMMU object. */
status = gckOS_Allocate(os, sizeof(struct _gckVGMMU), (gctPOINTER *) &mmu);
if (status < 0)
{
/* Error. */
gcmkFATAL(
"%s(%d): could not allocate gckVGMMU object.",
__FUNCTION__, __LINE__
);
gcmkFOOTER();
return status;
}
/* Initialize the gckVGMMU object. */
mmu->object.type = gcvOBJ_MMU;
mmu->os = os;
mmu->hardware = hardware;
/* Create the mutex. */
status = gckOS_CreateMutex(os, &mmu->mutex);
if (status < 0)
{
/* Roll back. */
mmu->object.type = gcvOBJ_UNKNOWN;
gcmkVERIFY_OK(gckOS_Free(os, mmu));
gcmkFOOTER();
/* Error. */
return status;
}
/* Allocate the page table. */
mmu->pageTableSize = (gctUINT32)MmuSize;
status = gckOS_AllocateNonPagedMemory(os,
gcvFALSE,
gcvALLOC_FLAG_CONTIGUOUS,
&mmu->pageTableSize,
&mmu->pageTablePhysical,
&mmu->pageTableLogical);
if (status < 0)
{
/* Roll back. */
gcmkVERIFY_OK(gckOS_DeleteMutex(os, mmu->mutex));
mmu->object.type = gcvOBJ_UNKNOWN;
gcmkVERIFY_OK(gckOS_Free(os, mmu));
/* Error. */
gcmkFATAL(
"%s(%d): could not allocate page table.",
__FUNCTION__, __LINE__
);
gcmkFOOTER();
return status;
}
/* Compute number of entries in page table. */
mmu->entryCount = (gctUINT32)mmu->pageTableSize / sizeof(gctUINT32);
mmu->entry = 0;
/* Mark the entire page table as available. */
pageTable = (gctUINT32 *) mmu->pageTableLogical;
for (i = 0; i < mmu->entryCount; i++)
{
pageTable[i] = (gctUINT32)~0;
}
/* Set page table address. */
status = gckVGHARDWARE_SetMMU(hardware, mmu->pageTableLogical);
if (status < 0)
{
/* Free the page table. */
gcmkVERIFY_OK(gckOS_FreeNonPagedMemory(mmu->os,
mmu->pageTablePhysical,
mmu->pageTableLogical,
mmu->pageTableSize));
/* Roll back. */
gcmkVERIFY_OK(gckOS_DeleteMutex(os, mmu->mutex));
mmu->object.type = gcvOBJ_UNKNOWN;
gcmkVERIFY_OK(gckOS_Free(os, mmu));
/* Error. */
gcmkFATAL(
"%s(%d): could not program page table.",
__FUNCTION__, __LINE__
);
gcmkFOOTER();
return status;
}
/* Return the gckVGMMU object pointer. */
*Mmu = mmu;
gcmkTRACE_ZONE(
gcvLEVEL_INFO, gcvZONE_MMU,
"%s(%d): %u entries at %p.(0x%08X)\n",
__FUNCTION__, __LINE__,
mmu->entryCount,
mmu->pageTableLogical,
mmu->pageTablePhysical
);
gcmkFOOTER_NO();
/* Success. */
return gcvSTATUS_OK;
}
/*******************************************************************************
**
** gckVGMMU_Destroy
**
** Destroy a nAQMMU object.
**
** INPUT:
**
** gckVGMMU Mmu
** Pointer to an gckVGMMU object.
**
** OUTPUT:
**
** Nothing.
*/
gceSTATUS gckVGMMU_Destroy(
IN gckVGMMU Mmu
)
{
gcmkHEADER_ARG("Mmu=0x%x", Mmu);
/* Verify the arguments. */
gcmkVERIFY_OBJECT(Mmu, gcvOBJ_MMU);
/* Free the page table. */
gcmkVERIFY_OK(gckOS_FreeNonPagedMemory(Mmu->os,
Mmu->pageTablePhysical,
Mmu->pageTableLogical,
Mmu->pageTableSize));
/* Roll back. */
gcmkVERIFY_OK(gckOS_DeleteMutex(Mmu->os, Mmu->mutex));
/* Mark the gckVGMMU object as unknown. */
Mmu->object.type = gcvOBJ_UNKNOWN;
/* Free the gckVGMMU object. */
gcmkVERIFY_OK(gckOS_Free(Mmu->os, Mmu));
gcmkFOOTER_NO();
/* Success. */
return gcvSTATUS_OK;
}
/*******************************************************************************
**
** gckVGMMU_AllocatePages
**
** Allocate pages inside the page table.
**
** INPUT:
**
** gckVGMMU Mmu
** Pointer to an gckVGMMU object.
**
** gctSIZE_T PageCount
** Number of pages to allocate.
**
** OUTPUT:
**
** gctPOINTER * PageTable
** Pointer to a variable that receives the base address of the page
** table.
**
** gctUINT32 * Address
** Pointer to a variable that receives the hardware specific address.
*/
gceSTATUS gckVGMMU_AllocatePages(
IN gckVGMMU Mmu,
IN gctSIZE_T PageCount,
OUT gctPOINTER * PageTable,
OUT gctUINT32 * Address
)
{
gceSTATUS status;
gctUINT32 tail, index, i;
gctUINT32 * table;
gctBOOL allocated = gcvFALSE;
gcmkHEADER_ARG("Mmu=0x%x PageCount=0x%x PageTable=0x%x Address=0x%x",
Mmu, PageCount, PageTable, Address);
/* Verify the arguments. */
gcmkVERIFY_OBJECT(Mmu, gcvOBJ_MMU);
gcmkVERIFY_ARGUMENT(PageCount > 0);
gcmkVERIFY_ARGUMENT(PageTable != gcvNULL);
gcmkVERIFY_ARGUMENT(Address != gcvNULL);
gcmkTRACE_ZONE(
gcvLEVEL_INFO, gcvZONE_MMU,
"%s(%d): %u pages.\n",
__FUNCTION__, __LINE__,
PageCount
);
if (PageCount > Mmu->entryCount)
{
gcmkTRACE_ZONE(
gcvLEVEL_ERROR, gcvZONE_MMU,
"%s(%d): page table too small for %u pages.\n",
__FUNCTION__, __LINE__,
PageCount
);
gcmkFOOTER_NO();
/* Not enough pages avaiable. */
return gcvSTATUS_OUT_OF_RESOURCES;
}
/* Grab the mutex. */
status = gckOS_AcquireMutex(Mmu->os, Mmu->mutex, gcvINFINITE);
if (status < 0)
{
gcmkTRACE_ZONE(
gcvLEVEL_ERROR, gcvZONE_MMU,
"%s(%d): could not acquire mutex.\n"
,__FUNCTION__, __LINE__
);
gcmkFOOTER();
/* Error. */
return status;
}
/* Compute the tail for this allocation. */
tail = Mmu->entryCount - (gctUINT32)PageCount;
/* Walk all entries until we find enough slots. */
for (index = Mmu->entry; index <= tail;)
{
/* Access page table. */
table = (gctUINT32 *) Mmu->pageTableLogical + index;
/* See if all slots are available. */
for (i = 0; i < PageCount; i++, table++)
{
if (*table != ~0)
{
/* Start from next slot. */
index += i + 1;
break;
}
}
if (i == PageCount)
{
/* Bail out if we have enough page entries. */
allocated = gcvTRUE;
break;
}
}
if (!allocated)
{
if (status >= 0)
{
/* Walk all entries until we find enough slots. */
for (index = 0; index <= tail;)
{
/* Access page table. */
table = (gctUINT32 *) Mmu->pageTableLogical + index;
/* See if all slots are available. */
for (i = 0; i < PageCount; i++, table++)
{
if (*table != ~0)
{
/* Start from next slot. */
index += i + 1;
break;
}
}
if (i == PageCount)
{
/* Bail out if we have enough page entries. */
allocated = gcvTRUE;
break;
}
}
}
}
if (!allocated && (status >= 0))
{
gcmkTRACE_ZONE(
gcvLEVEL_ERROR, gcvZONE_MMU,
"%s(%d): not enough free pages for %u pages.\n",
__FUNCTION__, __LINE__,
PageCount
);
/* Not enough empty slots available. */
status = gcvSTATUS_OUT_OF_RESOURCES;
}
if (status >= 0)
{
/* Build virtual address. */
status = gckVGHARDWARE_BuildVirtualAddress(Mmu->hardware,
index,
0,
Address);
if (status >= 0)
{
/* Update current entry into page table. */
Mmu->entry = index + (gctUINT32)PageCount;
/* Return pointer to page table. */
*PageTable = (gctUINT32 *) Mmu->pageTableLogical + index;
gcmkTRACE_ZONE(
gcvLEVEL_INFO, gcvZONE_MMU,
"%s(%d): allocated %u pages at index %u (0x%08X) @ %p.\n",
__FUNCTION__, __LINE__,
PageCount,
index,
*Address,
*PageTable
);
}
}
/* Release the mutex. */
gcmkVERIFY_OK(gckOS_ReleaseMutex(Mmu->os, Mmu->mutex));
gcmkFOOTER();
/* Return status. */
return status;
}
/*******************************************************************************
**
** gckVGMMU_FreePages
**
** Free pages inside the page table.
**
** INPUT:
**
** gckVGMMU Mmu
** Pointer to an gckVGMMU object.
**
** gctPOINTER PageTable
** Base address of the page table to free.
**
** gctSIZE_T PageCount
** Number of pages to free.
**
** OUTPUT:
**
** Nothing.
*/
gceSTATUS gckVGMMU_FreePages(
IN gckVGMMU Mmu,
IN gctPOINTER PageTable,
IN gctSIZE_T PageCount
)
{
gctUINT32 * table;
gcmkHEADER_ARG("Mmu=0x%x PageTable=0x%x PageCount=0x%x",
Mmu, PageTable, PageCount);
/* Verify the arguments. */
gcmkVERIFY_OBJECT(Mmu, gcvOBJ_MMU);
gcmkVERIFY_ARGUMENT(PageTable != gcvNULL);
gcmkVERIFY_ARGUMENT(PageCount > 0);
gcmkTRACE_ZONE(
gcvLEVEL_INFO, gcvZONE_MMU,
"%s(%d): freeing %u pages at index %u @ %p.\n",
__FUNCTION__, __LINE__,
PageCount,
((gctUINT32 *) PageTable - (gctUINT32 *) Mmu->pageTableLogical),
PageTable
);
/* Convert pointer. */
table = (gctUINT32 *) PageTable;
/* Mark the page table entries as available. */
while (PageCount-- > 0)
{
*table++ = (gctUINT32)~0;
}
gcmkFOOTER_NO();
/* Success. */
return gcvSTATUS_OK;
}
gceSTATUS
gckVGMMU_SetPage(
IN gckVGMMU Mmu,
IN gctUINT32 PageAddress,
IN gctUINT32 *PageEntry
)
{
gcmkHEADER_ARG("Mmu=0x%x", Mmu);
/* Verify the arguments. */
gcmkVERIFY_OBJECT(Mmu, gcvOBJ_MMU);
gcmkVERIFY_ARGUMENT(PageEntry != gcvNULL);
gcmkVERIFY_ARGUMENT(!(PageAddress & 0xFFF));
*PageEntry = PageAddress;
/* Success. */
gcmkFOOTER_NO();
return gcvSTATUS_OK;
}
gceSTATUS
gckVGMMU_Flush(
IN gckVGMMU Mmu
)
{
gckVGHARDWARE hardware;
gcmkHEADER_ARG("Mmu=0x%x", Mmu);
hardware = Mmu->hardware;
gcmkVERIFY_OK(
gckOS_AtomSet(hardware->os, hardware->pageTableDirty, 1));
/* Success. */
gcmkFOOTER_NO();
return gcvSTATUS_OK;
}
#endif /* gcdENABLE_VG */

View File

@ -0,0 +1,381 @@
/****************************************************************************
*
* The MIT License (MIT)
*
* Copyright (c) 2014 - 2019 Vivante Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
*****************************************************************************
*
* The GPL License (GPL)
*
* Copyright (C) 2014 - 2019 Vivante Corporation
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*****************************************************************************
*
* Note: This software is released under dual MIT and GPL licenses. A
* recipient may use this file under the terms of either the MIT license or
* GPL License. If you wish to use only one license not the other, you can
* indicate your decision by deleting one of the above license notices in your
* version of this file.
*
*****************************************************************************/
#include "gc_hal_kernel_precomp.h"
#define _GC_OBJ_ZONE gcvZONE_POWER
/******************************************************************************\
************************ Dynamic Voltage Frequency Setting *********************
\******************************************************************************/
#if gcdDVFS
static gctUINT32
_GetLoadHistory(
IN gckDVFS Dvfs,
IN gctUINT32 Select,
IN gctUINT32 Index
)
{
return Dvfs->loads[Index];
}
static void
_IncreaseScale(
IN gckDVFS Dvfs,
IN gctUINT32 Load,
OUT gctUINT8 *Scale
)
{
if (Dvfs->currentScale < 32)
{
*Scale = Dvfs->currentScale + 8;
}
else
{
*Scale = Dvfs->currentScale + 8;
*Scale = gcmMIN(64, *Scale);
}
}
static void
_RecordFrequencyHistory(
gckDVFS Dvfs,
gctUINT32 Frequency
)
{
gctUINT32 i = 0;
struct _FrequencyHistory *history = Dvfs->frequencyHistory;
for (i = 0; i < 16; i++)
{
if (history->frequency == Frequency)
{
break;
}
if (history->frequency == 0)
{
history->frequency = Frequency;
break;
}
history++;
}
if (i < 16)
{
history->count++;
}
}
static gctUINT32
_GetFrequencyHistory(
gckDVFS Dvfs,
gctUINT32 Frequency
)
{
gctUINT32 i = 0;
struct _FrequencyHistory * history = Dvfs->frequencyHistory;
for (i = 0; i < 16; i++)
{
if (history->frequency == Frequency)
{
break;
}
history++;
}
if (i < 16)
{
return history->count;
}
return 0;
}
static void
_Policy(
IN gckDVFS Dvfs,
IN gctUINT32 Load,
OUT gctUINT8 *Scale
)
{
gctUINT8 load[4], nextLoad;
gctUINT8 scale;
/* Last 4 history. */
load[0] = (Load & 0xFF);
load[1] = (Load & 0xFF00) >> 8;
load[2] = (Load & 0xFF0000) >> 16;
load[3] = (Load & 0xFF000000) >> 24;
/* Determine target scale. */
if (load[0] > 54)
{
_IncreaseScale(Dvfs, Load, &scale);
}
else
{
nextLoad = (load[0] + load[1] + load[2] + load[3])/4;
scale = Dvfs->currentScale * (nextLoad) / 54;
scale = gcmMAX(1, scale);
scale = gcmMIN(64, scale);
}
Dvfs->totalConfig++;
Dvfs->loads[(load[0]-1)/8]++;
*Scale = scale;
if (Dvfs->totalConfig % 100 == 0)
{
gcmkPRINT("=======================================================");
gcmkPRINT("GPU Load: %-8d %-8d %-8d %-8d %-8d %-8d %-8d %-8d",
8, 16, 24, 32, 40, 48, 56, 64);
gcmkPRINT(" %-8d %-8d %-8d %-8d %-8d %-8d %-8d %-8d",
_GetLoadHistory(Dvfs,2, 0),
_GetLoadHistory(Dvfs,2, 1),
_GetLoadHistory(Dvfs,2, 2),
_GetLoadHistory(Dvfs,2, 3),
_GetLoadHistory(Dvfs,2, 4),
_GetLoadHistory(Dvfs,2, 5),
_GetLoadHistory(Dvfs,2, 6),
_GetLoadHistory(Dvfs,2, 7)
);
gcmkPRINT("Frequency(MHz) %-8d %-8d %-8d %-8d %-8d",
58, 120, 240, 360, 480);
gcmkPRINT(" %-8d %-8d %-8d %-8d %-8d",
_GetFrequencyHistory(Dvfs, 58),
_GetFrequencyHistory(Dvfs,120),
_GetFrequencyHistory(Dvfs,240),
_GetFrequencyHistory(Dvfs,360),
_GetFrequencyHistory(Dvfs,480)
);
}
}
static void
_TimerFunction(
gctPOINTER Data
)
{
gceSTATUS status;
gckDVFS dvfs = (gckDVFS) Data;
gckHARDWARE hardware = dvfs->hardware;
gctUINT32 value;
gctUINT32 frequency;
gctUINT8 scale;
gctUINT32 t1, t2, consumed;
gckOS_GetTicks(&t1);
gcmkONERROR(gckHARDWARE_QueryLoad(hardware, &value));
/* determine target sacle. */
_Policy(dvfs, value, &scale);
/* Set frequency and voltage. */
gcmkONERROR(gckOS_SetGPUFrequency(hardware->os, hardware->core, scale));
/* Query real frequency. */
gcmkONERROR(
gckOS_QueryGPUFrequency(hardware->os,
hardware->core,
&frequency,
&dvfs->currentScale));
_RecordFrequencyHistory(dvfs, frequency);
gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_POWER,
"Current frequency = %d",
frequency);
/* Set period. */
gcmkONERROR(gckHARDWARE_SetDVFSPeroid(hardware, frequency));
OnError:
/* Determine next querying time. */
gckOS_GetTicks(&t2);
consumed = gcmMIN(((long)t2 - (long)t1), 5);
if (dvfs->stop == gcvFALSE)
{
gcmkVERIFY_OK(gckOS_StartTimer(hardware->os,
dvfs->timer,
dvfs->pollingTime - consumed));
}
return;
}
gceSTATUS
gckDVFS_Construct(
IN gckHARDWARE Hardware,
OUT gckDVFS * Dvfs
)
{
gceSTATUS status;
gctPOINTER pointer;
gckDVFS dvfs = gcvNULL;
gckOS os = Hardware->os;
gcmkHEADER_ARG("Hardware=0x%X", Hardware);
gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
gcmkVERIFY_ARGUMENT(Dvfs != gcvNULL);
/* Allocate a gckDVFS manager. */
gcmkONERROR(gckOS_Allocate(os, gcmSIZEOF(struct _gckDVFS), &pointer));
gckOS_ZeroMemory(pointer, gcmSIZEOF(struct _gckDVFS));
dvfs = pointer;
/* Initialization. */
dvfs->hardware = Hardware;
dvfs->pollingTime = gcdDVFS_POLLING_TIME;
dvfs->os = Hardware->os;
dvfs->currentScale = 64;
/* Create a polling timer. */
gcmkONERROR(gckOS_CreateTimer(os, _TimerFunction, pointer, &dvfs->timer));
/* Initialize frequency and voltage adjustment helper. */
gcmkONERROR(gckOS_PrepareGPUFrequency(os, Hardware->core));
/* Return result. */
*Dvfs = dvfs;
gcmkFOOTER_NO();
return gcvSTATUS_OK;
OnError:
/* Roll back. */
if (dvfs)
{
if (dvfs->timer)
{
gcmkVERIFY_OK(gckOS_DestroyTimer(os, dvfs->timer));
}
gcmkOS_SAFE_FREE(os, dvfs);
}
gcmkFOOTER();
return status;
}
gceSTATUS
gckDVFS_Destroy(
IN gckDVFS Dvfs
)
{
gcmkHEADER_ARG("Dvfs=0x%X", Dvfs);
gcmkVERIFY_ARGUMENT(Dvfs != gcvNULL);
/* Deinitialize helper fuunction. */
gcmkVERIFY_OK(gckOS_FinishGPUFrequency(Dvfs->os, Dvfs->hardware->core));
/* DestroyTimer. */
gcmkVERIFY_OK(gckOS_DestroyTimer(Dvfs->os, Dvfs->timer));
gcmkOS_SAFE_FREE(Dvfs->os, Dvfs);
gcmkFOOTER_NO();
return gcvSTATUS_OK;
}
gceSTATUS
gckDVFS_Start(
IN gckDVFS Dvfs
)
{
gcmkHEADER_ARG("Dvfs=0x%X", Dvfs);
gcmkVERIFY_ARGUMENT(Dvfs != gcvNULL);
gckHARDWARE_InitDVFS(Dvfs->hardware);
Dvfs->stop = gcvFALSE;
gckOS_StartTimer(Dvfs->os, Dvfs->timer, Dvfs->pollingTime);
gcmkFOOTER_NO();
return gcvSTATUS_OK;
}
gceSTATUS
gckDVFS_Stop(
IN gckDVFS Dvfs
)
{
gcmkHEADER_ARG("Dvfs=0x%X", Dvfs);
gcmkVERIFY_ARGUMENT(Dvfs != gcvNULL);
Dvfs->stop = gcvTRUE;
gcmkFOOTER_NO();
return gcvSTATUS_OK;
}
#endif

View File

@ -0,0 +1,63 @@
/****************************************************************************
*
* The MIT License (MIT)
*
* Copyright (c) 2014 - 2019 Vivante Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
*****************************************************************************
*
* The GPL License (GPL)
*
* Copyright (C) 2014 - 2019 Vivante Corporation
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*****************************************************************************
*
* Note: This software is released under dual MIT and GPL licenses. A
* recipient may use this file under the terms of either the MIT license or
* GPL License. If you wish to use only one license not the other, you can
* indicate your decision by deleting one of the above license notices in your
* version of this file.
*
*****************************************************************************/
#ifndef __gc_hal_kernel_precomp_h_
#define __gc_hal_kernel_precomp_h_
#include "gc_hal.h"
#include "gc_hal_driver.h"
#include "gc_hal_kernel.h"
#endif /* __gc_hal_kernel_precomp_h_ */

View File

@ -0,0 +1,286 @@
/****************************************************************************
*
* The MIT License (MIT)
*
* Copyright (c) 2014 - 2019 Vivante Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
*****************************************************************************
*
* The GPL License (GPL)
*
* Copyright (C) 2014 - 2019 Vivante Corporation
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*****************************************************************************
*
* Note: This software is released under dual MIT and GPL licenses. A
* recipient may use this file under the terms of either the MIT license or
* GPL License. If you wish to use only one license not the other, you can
* indicate your decision by deleting one of the above license notices in your
* version of this file.
*
*****************************************************************************/
#include "gc_hal_kernel_precomp.h"
#define _GC_OBJ_ZONE gcvZONE_KERNEL
#if gcdSECURITY
/*
** Open a security service channel.
*/
gceSTATUS
gckKERNEL_SecurityOpen(
IN gckKERNEL Kernel,
IN gctUINT32 GPU,
OUT gctUINT32 *Channel
)
{
gceSTATUS status;
gcmkONERROR(gckOS_OpenSecurityChannel(Kernel->os, Kernel->core, Channel));
gcmkONERROR(gckOS_InitSecurityChannel(*Channel));
return gcvSTATUS_OK;
OnError:
return status;
}
/*
** Close a security service channel
*/
gceSTATUS
gckKERNEL_SecurityClose(
IN gctUINT32 Channel
)
{
return gcvSTATUS_OK;
}
/*
** Security service interface.
*/
gceSTATUS
gckKERNEL_SecurityCallService(
IN gctUINT32 Channel,
IN OUT gcsTA_INTERFACE * Interface
)
{
gceSTATUS status;
gcmkHEADER();
gcmkVERIFY_ARGUMENT(Interface != gcvNULL);
gckOS_CallSecurityService(Channel, Interface);
status = Interface->result;
gcmkONERROR(status);
gcmkFOOTER_NO();
return gcvSTATUS_OK;
OnError:
gcmkFOOTER();
return status;
}
gceSTATUS
gckKERNEL_SecurityStartCommand(
IN gckKERNEL Kernel
)
{
gceSTATUS status;
gcsTA_INTERFACE iface;
gcmkHEADER();
iface.command = KERNEL_START_COMMAND;
iface.u.StartCommand.gpu = Kernel->core;
gcmkONERROR(gckKERNEL_SecurityCallService(Kernel->securityChannel, &iface));
gcmkFOOTER_NO();
return gcvSTATUS_OK;
OnError:
gcmkFOOTER();
return status;
}
gceSTATUS
gckKERNEL_SecurityAllocateSecurityMemory(
IN gckKERNEL Kernel,
IN gctUINT32 Bytes,
OUT gctUINT32 * Handle
)
{
gceSTATUS status;
gcsTA_INTERFACE iface;
gcmkHEADER();
iface.command = KERNEL_ALLOCATE_SECRUE_MEMORY;
iface.u.AllocateSecurityMemory.bytes = Bytes;
gcmkONERROR(gckKERNEL_SecurityCallService(Kernel->securityChannel, &iface));
*Handle = iface.u.AllocateSecurityMemory.memory_handle;
gcmkFOOTER_NO();
return gcvSTATUS_OK;
OnError:
gcmkFOOTER();
return status;
}
gceSTATUS
gckKERNEL_SecurityExecute(
IN gckKERNEL Kernel,
IN gctPOINTER Buffer,
IN gctUINT32 Bytes
)
{
gceSTATUS status;
#if defined(LINUX)
gctPHYS_ADDR_T physical;
gctUINT32 address;
#endif
gcsTA_INTERFACE iface;
gcmkHEADER();
iface.command = KERNEL_EXECUTE;
iface.u.Execute.command_buffer = (gctUINT32 *)Buffer;
iface.u.Execute.gpu = Kernel->core;
iface.u.Execute.command_buffer_length = Bytes;
#if defined(LINUX)
gcmkONERROR(gckOS_GetPhysicalAddress(Kernel->os, Buffer, &physical));
gcmkVERIFY_OK(gckOS_CPUPhysicalToGPUPhysical(Kernel->os, physical, &physical));
gcmkSAFECASTPHYSADDRT(address, physical);
iface.u.Execute.command_buffer = (gctUINT32 *)address;
#endif
gcmkONERROR(gckKERNEL_SecurityCallService(Kernel->securityChannel, &iface));
/* Update queue tail pointer. */
gcmkONERROR(gckHARDWARE_UpdateQueueTail(
Kernel->hardware, 0, 0
));
gcmkFOOTER_NO();
return gcvSTATUS_OK;
OnError:
gcmkFOOTER();
return status;
}
gceSTATUS
gckKERNEL_SecurityMapMemory(
IN gckKERNEL Kernel,
IN gctUINT32 *PhysicalArray,
IN gctUINT32 PageCount,
OUT gctUINT32 * GPUAddress
)
{
gceSTATUS status;
gcsTA_INTERFACE iface;
#if defined(LINUX)
gctPHYS_ADDR_T physical;
gctUINT32 address;
#endif
gcmkHEADER();
iface.command = KERNEL_MAP_MEMORY;
#if defined(LINUX)
gcmkONERROR(gckOS_GetPhysicalAddress(Kernel->os, PhysicalArray, &physical));
gcmkVERIFY_OK(gckOS_CPUPhysicalToGPUPhysical(Kernel->os, physical, &physical));
gcmkSAFECASTPHYSADDRT(address, physical);
iface.u.MapMemory.physicals = (gctUINT32 *)address;
#endif
iface.u.MapMemory.pageCount = PageCount;
gcmkONERROR(gckKERNEL_SecurityCallService(Kernel->securityChannel, &iface));
*GPUAddress = iface.u.MapMemory.gpuAddress;
gcmkFOOTER_NO();
return gcvSTATUS_OK;
OnError:
gcmkFOOTER();
return status;
}
gceSTATUS
gckKERNEL_SecurityUnmapMemory(
IN gckKERNEL Kernel,
IN gctUINT32 GPUAddress,
IN gctUINT32 PageCount
)
{
gceSTATUS status;
gcsTA_INTERFACE iface;
gcmkHEADER();
iface.command = KERNEL_UNMAP_MEMORY;
iface.u.UnmapMemory.gpuAddress = GPUAddress;
iface.u.UnmapMemory.pageCount = PageCount;
gcmkONERROR(gckKERNEL_SecurityCallService(Kernel->securityChannel, &iface));
gcmkFOOTER_NO();
return gcvSTATUS_OK;
OnError:
gcmkFOOTER();
return status;
}
#endif

View File

@ -0,0 +1,320 @@
/****************************************************************************
*
* The MIT License (MIT)
*
* Copyright (c) 2014 - 2019 Vivante Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
*****************************************************************************
*
* The GPL License (GPL)
*
* Copyright (C) 2014 - 2019 Vivante Corporation
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*****************************************************************************
*
* Note: This software is released under dual MIT and GPL licenses. A
* recipient may use this file under the terms of either the MIT license or
* GPL License. If you wish to use only one license not the other, you can
* indicate your decision by deleting one of the above license notices in your
* version of this file.
*
*****************************************************************************/
#include "gc_hal_kernel_precomp.h"
#define _GC_OBJ_ZONE gcvZONE_KERNEL
#if gcdENABLE_TRUST_APPLICATION
/*
** Open a security service channel.
*/
gceSTATUS
gckKERNEL_SecurityOpen(
IN gckKERNEL Kernel,
IN gctUINT32 GPU,
OUT gctUINT32 *Channel
)
{
gceSTATUS status;
gcmkONERROR(gckOS_OpenSecurityChannel(Kernel->os, Kernel->core, Channel));
gcmkONERROR(gckOS_InitSecurityChannel(*Channel));
return gcvSTATUS_OK;
OnError:
return status;
}
/*
** Close a security service channel
*/
gceSTATUS
gckKERNEL_SecurityClose(
IN gctUINT32 Channel
)
{
return gcvSTATUS_OK;
}
/*
** Security service interface.
*/
gceSTATUS
gckKERNEL_SecurityCallService(
IN gctUINT32 Channel,
IN OUT gcsTA_INTERFACE * Interface
)
{
gceSTATUS status;
gcmkHEADER();
gcmkVERIFY_ARGUMENT(Interface != gcvNULL);
gckOS_CallSecurityService(Channel, Interface);
status = Interface->result;
gcmkONERROR(status);
gcmkFOOTER_NO();
return gcvSTATUS_OK;
OnError:
gcmkFOOTER();
return status;
}
gceSTATUS
gckKERNEL_SecurityStartCommand(
IN gckKERNEL Kernel,
IN gctUINT32 Address,
IN gctUINT32 Bytes
)
{
gceSTATUS status;
gcsTA_INTERFACE iface;
gcmkHEADER();
iface.command = KERNEL_START_COMMAND;
iface.u.StartCommand.gpu = Kernel->core;
iface.u.StartCommand.address = Address;
iface.u.StartCommand.bytes = Bytes;
gcmkONERROR(gckKERNEL_SecurityCallService(Kernel->securityChannel, &iface));
gcmkFOOTER_NO();
return gcvSTATUS_OK;
OnError:
gcmkFOOTER();
return status;
}
gceSTATUS
gckKERNEL_SecurityAllocateSecurityMemory(
IN gckKERNEL Kernel,
IN gctUINT32 Bytes,
OUT gctUINT32 * Handle
)
{
gceSTATUS status;
gcsTA_INTERFACE iface;
gcmkHEADER();
iface.command = KERNEL_ALLOCATE_SECRUE_MEMORY;
iface.u.AllocateSecurityMemory.bytes = Bytes;
gcmkONERROR(gckKERNEL_SecurityCallService(Kernel->securityChannel, &iface));
*Handle = iface.u.AllocateSecurityMemory.memory_handle;
gcmkFOOTER_NO();
return gcvSTATUS_OK;
OnError:
gcmkFOOTER();
return status;
}
gceSTATUS
gckKERNEL_SecurityMapMemory(
IN gckKERNEL Kernel,
IN gctUINT32 *PhysicalArray,
IN gctPHYS_ADDR_T Physical,
IN gctUINT32 PageCount,
OUT gctUINT32 * GPUAddress
)
{
gceSTATUS status;
gcsTA_INTERFACE iface;
gcmkHEADER();
iface.command = KERNEL_MAP_MEMORY;
iface.u.MapMemory.physicals = PhysicalArray;
iface.u.MapMemory.physical = Physical;
iface.u.MapMemory.pageCount = PageCount;
iface.u.MapMemory.gpuAddress = *GPUAddress;
gcmkONERROR(gckKERNEL_SecurityCallService(Kernel->securityChannel, &iface));
gcmkFOOTER_NO();
return gcvSTATUS_OK;
OnError:
gcmkFOOTER();
return status;
}
gceSTATUS
gckKERNEL_SecurityDumpMMUException(
IN gckKERNEL Kernel
)
{
gceSTATUS status;
gcsTA_INTERFACE iface;
gcmkHEADER();
iface.command = KERNEL_DUMP_MMU_EXCEPTION;
gcmkONERROR(gckKERNEL_SecurityCallService(Kernel->securityChannel, &iface));
gcmkFOOTER_NO();
return gcvSTATUS_OK;
OnError:
gcmkFOOTER();
return status;
}
gceSTATUS
gckKERNEL_SecurityUnmapMemory(
IN gckKERNEL Kernel,
IN gctUINT32 GPUAddress,
IN gctUINT32 PageCount
)
{
gceSTATUS status;
gcsTA_INTERFACE iface;
gcmkHEADER();
iface.command = KERNEL_UNMAP_MEMORY;
iface.u.UnmapMemory.gpuAddress = GPUAddress;
iface.u.UnmapMemory.pageCount = PageCount;
gcmkONERROR(gckKERNEL_SecurityCallService(Kernel->securityChannel, &iface));
gcmkFOOTER_NO();
return gcvSTATUS_OK;
OnError:
gcmkFOOTER();
return status;
}
gceSTATUS
gckKERNEL_ReadMMUException(
IN gckKERNEL Kernel,
IN gctUINT32_PTR MMUStatus,
IN gctUINT32_PTR MMUException
)
{
gceSTATUS status;
gcsTA_INTERFACE iface;
gcmkHEADER();
iface.command = KERNEL_READ_MMU_EXCEPTION;
gcmkONERROR(gckKERNEL_SecurityCallService(Kernel->securityChannel, &iface));
*MMUStatus = iface.u.ReadMMUException.mmuStatus;
*MMUException = iface.u.ReadMMUException.mmuException;
gcmkFOOTER_NO();
return gcvSTATUS_OK;
OnError:
gcmkFOOTER();
return status;
}
gceSTATUS
gckKERNEL_HandleMMUException(
IN gckKERNEL Kernel,
IN gctUINT32 MMUStatus,
IN gctPHYS_ADDR_T Physical,
IN gctUINT32 GPUAddress
)
{
gceSTATUS status;
gcsTA_INTERFACE iface;
gcmkHEADER();
iface.command = KERNEL_HANDLE_MMU_EXCEPTION;
iface.u.HandleMMUException.mmuStatus = MMUStatus;
iface.u.HandleMMUException.physical = Physical;
iface.u.HandleMMUException.gpuAddress = GPUAddress;
gcmkONERROR(gckKERNEL_SecurityCallService(Kernel->securityChannel, &iface));
gcmkFOOTER_NO();
return gcvSTATUS_OK;
OnError:
gcmkFOOTER();
return status;
}
#endif

View File

@ -0,0 +1,514 @@
/****************************************************************************
*
* The MIT License (MIT)
*
* Copyright (c) 2014 - 2019 Vivante Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
*****************************************************************************
*
* The GPL License (GPL)
*
* Copyright (C) 2014 - 2019 Vivante Corporation
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*****************************************************************************
*
* Note: This software is released under dual MIT and GPL licenses. A
* recipient may use this file under the terms of either the MIT license or
* GPL License. If you wish to use only one license not the other, you can
* indicate your decision by deleting one of the above license notices in your
* version of this file.
*
*****************************************************************************/
#include "gc_hal_kernel_precomp.h"
#if gcdENABLE_VG
#define _GC_OBJ_ZONE gcdZONE_VG
/******************************************************************************\
******************************* gckKERNEL API Code ******************************
\******************************************************************************/
/*******************************************************************************
**
** gckKERNEL_Construct
**
** Construct a new gckKERNEL object.
**
** INPUT:
**
** gckOS Os
** Pointer to an gckOS object.
**
** IN gctPOINTER Context
** Pointer to a driver defined context.
**
** OUTPUT:
**
** gckKERNEL * Kernel
** Pointer to a variable that will hold the pointer to the gckKERNEL
** object.
*/
gceSTATUS gckVGKERNEL_Construct(
IN gckOS Os,
IN gctPOINTER Context,
IN gckKERNEL inKernel,
OUT gckVGKERNEL * Kernel
)
{
gceSTATUS status;
gckVGKERNEL kernel = gcvNULL;
gcmkHEADER_ARG("Os=0x%x Context=0x%x", Os, Context);
/* Verify the arguments. */
gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
gcmkVERIFY_ARGUMENT(Kernel != gcvNULL);
do
{
/* Allocate the gckKERNEL object. */
gcmkERR_BREAK(gckOS_Allocate(
Os,
sizeof(struct _gckVGKERNEL),
(gctPOINTER *) &kernel
));
/* Initialize the gckKERNEL object. */
kernel->object.type = gcvOBJ_KERNEL;
kernel->os = Os;
kernel->context = Context;
kernel->hardware = gcvNULL;
kernel->interrupt = gcvNULL;
kernel->command = gcvNULL;
kernel->mmu = gcvNULL;
kernel->kernel = inKernel;
/* Construct the gckVGHARDWARE object. */
gcmkERR_BREAK(gckVGHARDWARE_Construct(
Os, &kernel->hardware
));
/* Set pointer to gckKERNEL object in gckVGHARDWARE object. */
kernel->hardware->kernel = kernel;
/* Construct the gckVGINTERRUPT object. */
gcmkERR_BREAK(gckVGINTERRUPT_Construct(
kernel, &kernel->interrupt
));
/* Construct the gckVGCOMMAND object. */
gcmkERR_BREAK(gckVGCOMMAND_Construct(
kernel, gcmKB2BYTES(8), gcmKB2BYTES(2), &kernel->command
));
/* Construct the gckVGMMU object. */
gcmkERR_BREAK(gckVGMMU_Construct(
kernel, gcmKB2BYTES(gcdGC355_VGMMU_MEMORY_SIZE_KB), &kernel->mmu
));
/* Return pointer to the gckKERNEL object. */
*Kernel = kernel;
gcmkFOOTER_ARG("*Kernel=0x%x", *Kernel);
/* Success. */
return gcvSTATUS_OK;
}
while (gcvFALSE);
/* Roll back. */
if (kernel != gcvNULL)
{
if (kernel->mmu != gcvNULL)
{
gcmkVERIFY_OK(gckVGMMU_Destroy(kernel->mmu));
}
if (kernel->command != gcvNULL)
{
gcmkVERIFY_OK(gckVGCOMMAND_Destroy(kernel->command));
}
if (kernel->interrupt != gcvNULL)
{
gcmkVERIFY_OK(gckVGINTERRUPT_Destroy(kernel->interrupt));
}
if (kernel->hardware != gcvNULL)
{
gcmkVERIFY_OK(gckVGHARDWARE_Destroy(kernel->hardware));
}
gcmkVERIFY_OK(gckOS_Free(Os, kernel));
}
gcmkFOOTER();
/* Return status. */
return status;
}
/*******************************************************************************
**
** gckKERNEL_Destroy
**
** Destroy an gckKERNEL object.
**
** INPUT:
**
** gckKERNEL Kernel
** Pointer to an gckKERNEL object to destroy.
**
** OUTPUT:
**
** Nothing.
*/
gceSTATUS gckVGKERNEL_Destroy(
IN gckVGKERNEL Kernel
)
{
gceSTATUS status;
gcmkHEADER_ARG("Kernel=0x%x", Kernel);
/* Verify the arguments. */
gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
do
{
/* Destroy the gckVGMMU object. */
if (Kernel->mmu != gcvNULL)
{
gcmkERR_BREAK(gckVGMMU_Destroy(Kernel->mmu));
Kernel->mmu = gcvNULL;
}
/* Destroy the gckVGCOMMAND object. */
if (Kernel->command != gcvNULL)
{
gcmkERR_BREAK(gckVGCOMMAND_Destroy(Kernel->command));
Kernel->command = gcvNULL;
}
/* Destroy the gckVGINTERRUPT object. */
if (Kernel->interrupt != gcvNULL)
{
gcmkERR_BREAK(gckVGINTERRUPT_Destroy(Kernel->interrupt));
Kernel->interrupt = gcvNULL;
}
/* Destroy the gckVGHARDWARE object. */
if (Kernel->hardware != gcvNULL)
{
gcmkERR_BREAK(gckVGHARDWARE_Destroy(Kernel->hardware));
Kernel->hardware = gcvNULL;
}
/* Mark the gckKERNEL object as unknown. */
Kernel->object.type = gcvOBJ_UNKNOWN;
/* Free the gckKERNEL object. */
gcmkERR_BREAK(gckOS_Free(Kernel->os, Kernel));
}
while (gcvFALSE);
gcmkFOOTER();
/* Return status. */
return status;
}
/*******************************************************************************
**
** gckVGKERNEL_Dispatch
**
** Dispatch a command received from the user HAL layer.
**
** INPUT:
**
** gckKERNEL Kernel
** Pointer to an gckKERNEL object.
**
** gcsHAL_INTERFACE * Interface
** Pointer to a gcsHAL_INTERFACE structure that defines the command to
** be dispatched.
**
** OUTPUT:
**
** gcsHAL_INTERFACE * Interface
** Pointer to a gcsHAL_INTERFACE structure that receives any data to be
** returned.
*/
gceSTATUS gckVGKERNEL_Dispatch(
IN gckKERNEL Kernel,
IN OUT gcsHAL_INTERFACE * Interface
)
{
gceSTATUS status;
gcsHAL_INTERFACE * kernelInterface = Interface;
gctUINT32 processID;
gctBOOL powerMutexAcquired = gcvFALSE;
gcmkHEADER_ARG("Kernel=0x%x Interface=0x%x ", Kernel, Interface);
/* Verify the arguments. */
gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
gcmkVERIFY_ARGUMENT(Interface != gcvNULL);
gcmkONERROR(gckOS_GetProcessID(&processID));
/* Dispatch on command. */
switch (Interface->command)
{
case gcvHAL_QUERY_CHIP_IDENTITY:
/* Query chip identity. */
gcmkERR_BREAK(gckVGHARDWARE_QueryChipIdentity(
Kernel->vg->hardware,
&kernelInterface->u.QueryChipIdentity.chipModel,
&kernelInterface->u.QueryChipIdentity.chipRevision,
&kernelInterface->u.QueryChipIdentity.productID,
&kernelInterface->u.QueryChipIdentity.ecoID,
&kernelInterface->u.QueryChipIdentity.customerID,
&kernelInterface->u.QueryChipIdentity.chipFeatures,
&kernelInterface->u.QueryChipIdentity.chipMinorFeatures,
&kernelInterface->u.QueryChipIdentity.chipMinorFeatures2
));
break;
case gcvHAL_QUERY_COMMAND_BUFFER:
/* Query command buffer information. */
gcmkERR_BREAK(gckKERNEL_QueryCommandBuffer(
Kernel,
&kernelInterface->u.QueryCommandBuffer.information
));
break;
case gcvHAL_USER_SIGNAL:
#if !USE_NEW_LINUX_SIGNAL
/* Dispatch depends on the user signal subcommands. */
switch(Interface->u.UserSignal.command)
{
case gcvUSER_SIGNAL_CREATE:
/* Create a signal used in the user space. */
gcmkERR_BREAK(
gckOS_CreateUserSignal(Kernel->os,
Interface->u.UserSignal.manualReset,
&Interface->u.UserSignal.id));
gcmkVERIFY_OK(
gckKERNEL_AddProcessDB(Kernel,
processID, gcvDB_SIGNAL,
gcmINT2PTR(Interface->u.UserSignal.id),
gcvNULL,
0));
break;
case gcvUSER_SIGNAL_DESTROY:
gcmkVERIFY_OK(gckKERNEL_RemoveProcessDB(
Kernel,
processID, gcvDB_SIGNAL,
gcmINT2PTR(Interface->u.UserSignal.id)));
/* Destroy the signal. */
gcmkERR_BREAK(
gckOS_DestroyUserSignal(Kernel->os,
Interface->u.UserSignal.id));
break;
case gcvUSER_SIGNAL_SIGNAL:
/* Signal the signal. */
gcmkERR_BREAK(
gckOS_SignalUserSignal(Kernel->os,
Interface->u.UserSignal.id,
Interface->u.UserSignal.state));
break;
case gcvUSER_SIGNAL_WAIT:
/* Wait on the signal. */
status = gckOS_WaitUserSignal(Kernel->os,
Interface->u.UserSignal.id,
Interface->u.UserSignal.wait);
break;
default:
/* Invalid user signal command. */
gcmkERR_BREAK(gcvSTATUS_INVALID_ARGUMENT);
}
#endif
break;
case gcvHAL_READ_REGISTER:
#if gcdREGISTER_READ_FROM_USER
{
gceCHIPPOWERSTATE power;
gcmkONERROR(gckOS_AcquireMutex(Kernel->os, Kernel->vg->hardware->powerMutex, gcvINFINITE));
powerMutexAcquired = gcvTRUE;
gcmkONERROR(gckVGHARDWARE_QueryPowerManagementState(Kernel->vg->hardware,
&power));
if (power == gcvPOWER_ON)
{
/* Read a register. */
gcmkONERROR(gckOS_ReadRegisterEx(
Kernel->os,
Kernel->core,
Interface->u.ReadRegisterData.address,
&Interface->u.ReadRegisterData.data));
}
else
{
/* Chip is in power-state. */
Interface->u.ReadRegisterData.data = 0;
status = gcvSTATUS_CHIP_NOT_READY;
}
gcmkONERROR(gckOS_ReleaseMutex(Kernel->os, Kernel->vg->hardware->powerMutex));
powerMutexAcquired = gcvFALSE;
}
#else
/* No access from user land to read registers. */
Interface->u.ReadRegisterData.data = 0;
status = gcvSTATUS_NOT_SUPPORTED;
#endif
break;
case gcvHAL_WRITE_REGISTER:
#if gcdREGISTER_WRITE_FROM_USER
{
gceCHIPPOWERSTATE power;
gcmkONERROR(gckOS_AcquireMutex(Kernel->os, Kernel->vg->hardware->powerMutex, gcvINFINITE));
powerMutexAcquired = gcvTRUE;
gcmkONERROR(gckVGHARDWARE_QueryPowerManagementState(Kernel->vg->hardware,
&power));
if (power == gcvPOWER_ON)
{
/* Write a register. */
gcmkONERROR(
gckOS_WriteRegisterEx(Kernel->os,
Kernel->core,
Interface->u.WriteRegisterData.address,
Interface->u.WriteRegisterData.data));
}
else
{
/* Chip is in power-state. */
Interface->u.WriteRegisterData.data = 0;
status = gcvSTATUS_CHIP_NOT_READY;
}
gcmkONERROR(gckOS_ReleaseMutex(Kernel->os, Kernel->vg->hardware->powerMutex));
powerMutexAcquired = gcvFALSE;
}
#else
/* No access from user land to write registers. */
status = gcvSTATUS_NOT_SUPPORTED;
#endif
break;
case gcvHAL_COMMIT:
/* Commit a command and context buffer. */
gcmkERR_BREAK(gckVGCOMMAND_Commit(
Kernel->vg->command,
gcmUINT64_TO_PTR(kernelInterface->u.VGCommit.context),
gcmUINT64_TO_PTR(kernelInterface->u.VGCommit.queue),
kernelInterface->u.VGCommit.entryCount,
gcmUINT64_TO_PTR(kernelInterface->u.VGCommit.taskTable)
));
break;
case gcvHAL_GET_BASE_ADDRESS:
/* Get base address. */
gcmkONERROR(
gckOS_GetBaseAddress(Kernel->os,
&Interface->u.GetBaseAddress.baseAddress));
break;
case gcvHAL_EVENT_COMMIT:
gcmkERR_BREAK(gcvSTATUS_NOT_SUPPORTED);
break;
default:
/* Invalid command, try gckKERNEL_Dispatch */
status = gckKERNEL_Dispatch(Kernel, gcvNULL, Interface);
}
OnError:
/* Save status. */
kernelInterface->status = status;
if (powerMutexAcquired == gcvTRUE)
{
gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel->os, Kernel->vg->hardware->powerMutex));
}
gcmkFOOTER();
/* Return the status. */
return status;
}
/*******************************************************************************
**
** gckKERNEL_QueryCommandBuffer
**
** Query command buffer attributes.
**
** INPUT:
**
** gckKERNEL Kernel
** Pointer to an gckVGHARDWARE object.
**
** OUTPUT:
**
** gcsCOMMAND_BUFFER_INFO_PTR Information
** Pointer to the information structure to receive buffer attributes.
*/
gceSTATUS
gckKERNEL_QueryCommandBuffer(
IN gckKERNEL Kernel,
OUT gcsCOMMAND_BUFFER_INFO_PTR Information
)
{
gceSTATUS status;
gcmkHEADER_ARG("Kernel=0x%x *Pool=0x%x",
Kernel, Information);
/* Verify the arguments. */
gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
/* Get the information. */
status = gckVGCOMMAND_QueryCommandBuffer(Kernel->vg->command, Information);
gcmkFOOTER();
/* Return status. */
return status;
}
#endif /* gcdENABLE_VG */

View File

@ -0,0 +1,119 @@
/****************************************************************************
*
* The MIT License (MIT)
*
* Copyright (c) 2014 - 2019 Vivante Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
*****************************************************************************
*
* The GPL License (GPL)
*
* Copyright (C) 2014 - 2019 Vivante Corporation
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*****************************************************************************
*
* Note: This software is released under dual MIT and GPL licenses. A
* recipient may use this file under the terms of either the MIT license or
* GPL License. If you wish to use only one license not the other, you can
* indicate your decision by deleting one of the above license notices in your
* version of this file.
*
*****************************************************************************/
#ifndef __gc_hal_kernel_vg_h_
#define __gc_hal_kernel_vg_h_
#include "gc_hal.h"
#include "gc_hal_driver.h"
#include "gc_hal_kernel_hardware.h"
/******************************************************************************\
********************************** Structures **********************************
\******************************************************************************/
/* gckKERNEL object. */
struct _gckVGKERNEL
{
/* Object. */
gcsOBJECT object;
/* Pointer to gckOS object. */
gckOS os;
/* Pointer to gckHARDWARE object. */
gckVGHARDWARE hardware;
/* Pointer to gckINTERRUPT object. */
gckVGINTERRUPT interrupt;
/* Pointer to gckCOMMAND object. */
gckVGCOMMAND command;
/* Pointer to context. */
gctPOINTER context;
/* Pointer to gckMMU object. */
gckVGMMU mmu;
gckKERNEL kernel;
};
/* gckMMU object. */
struct _gckVGMMU
{
/* The object. */
gcsOBJECT object;
/* Pointer to gckOS object. */
gckOS os;
/* Pointer to gckHARDWARE object. */
gckVGHARDWARE hardware;
/* The page table mutex. */
gctPOINTER mutex;
/* Page table information. */
gctSIZE_T pageTableSize;
gctPHYS_ADDR pageTablePhysical;
gctPOINTER pageTableLogical;
/* Allocation index. */
gctUINT32 entryCount;
gctUINT32 entry;
};
#endif /* __gc_hal_kernel_h_ */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,329 @@
/****************************************************************************
*
* The MIT License (MIT)
*
* Copyright (c) 2014 - 2019 Vivante Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
*****************************************************************************
*
* The GPL License (GPL)
*
* Copyright (C) 2014 - 2019 Vivante Corporation
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*****************************************************************************
*
* Note: This software is released under dual MIT and GPL licenses. A
* recipient may use this file under the terms of either the MIT license or
* GPL License. If you wish to use only one license not the other, you can
* indicate your decision by deleting one of the above license notices in your
* version of this file.
*
*****************************************************************************/
#ifndef __gc_hal_debug_zones_h_
#define __gc_hal_debug_zones_h_
#ifdef __cplusplus
extern "C" {
#endif
/******************************************************************************\
************************ Debug Zone Pattern Summary ***************************
* A debug zone is an unsigned integer of 32 bit (Bit 31- Bit 0). *
* Bit 31 to 28 defines API, which is 0 for HAL API and has value of 1 - 14 *
* for Khronos API. Value 15 (0xF) is reserved for gcdZONE_NONE. *
* Bit 27 to 0 defines subzones of each API. Value 0xFFFFFFF is resevered for *
* gcdZONE_ALL. *
* *
\******************************************************************************/
/* Retrieve API bits 31 to 28 */
#define gcmZONE_GET_API(zone) ((zone) >> 28)
/* Retrieve Subzone bits 27 to 0 */
#define gcmZONE_GET_SUBZONES(zone) ((zone) << 4)
/******************************************************************************\
******************************** HAL Zone **************************************
\******************************************************************************/
#define gcdZONE_API_HAL ((gctUINT32) 0 << 28)
/******************************************************************************\
******************************** HAL Subzones **********************************
\******************************************************************************/
/* Subzones Kernel and User have in common */
#define gcvZONE_OS (1 << 0)
#define gcvZONE_HARDWARE (1 << 1)
#define gcvZONE_HEAP (1 << 2)
#define gcvZONE_SIGNAL (1 << 3)
/* Subzones of HAL Kernel */
#define gcvZONE_KERNEL (1 << 4)
#define gcvZONE_VIDMEM (1 << 5)
#define gcvZONE_COMMAND (1 << 6)
#define gcvZONE_DRIVER (1 << 7)
#define gcvZONE_CMODEL (1 << 8)
#define gcvZONE_MMU (1 << 9)
#define gcvZONE_EVENT (1 << 10)
#define gcvZONE_DEVICE (1 << 11)
#define gcvZONE_DATABASE (1 << 12)
#define gcvZONE_INTERRUPT (1 << 13)
#define gcvZONE_POWER (1 << 14)
#define gcvZONE_ASYNC_COMMAND (1 << 15)
#define gcvZONE_ALLOCATOR (1 << 16)
/* Subzones of HAL User */
#define gcdZONE_HAL_API (1 << 4)
#define gcdZONE_BUFFER (1 << 5)
#define gcdZONE_VGBUFFER (1 << 6)
#define gcdZONE_SURFACE (1 << 7)
#define gcdZONE_INDEX (1 << 8)
#define gcdZONE_STREAM (1 << 9)
#define gcdZONE_TEXTURE (1 << 10)
#define gcdZONE_2D (1 << 11)
#define gcdZONE_3D (1 << 12)
#define gcdZONE_COMPILER (1 << 13)
#define gcdZONE_MEM (1 << 14)
#define gcdZONE_VERTEXARRAY (1 << 15)
#define gcdZONE_CL (1 << 16)
#define gcdZONE_VG (1 << 17)
#define gcdZONE_VX (1 << 18)
#define gcdZONE_UTILITY (1 << 19)
#define gcdZONE_RECT (1 << 20)
#define gcdZONE_BUFOBJ (1 << 21)
#define gcdZONE_PROFILER (1 << 22)
#define gcdZONE_SHADER (1 << 23)
/******************************************************************************\
******************************** Khronos API Zones *****************************
\******************************************************************************/
#define gcdZONE_API_EGL ((gctUINT32) 1 << 28)
#define gcdZONE_API_ES11 ((gctUINT32) 2 << 28)
#define gcdZONE_API_ES30 ((gctUINT32) 3 << 28)
#define gcdZONE_API_GL40 ((gctUINT32) 4 << 28)
#define gcdZONE_API_VG3D ((gctUINT32) 5 << 28)
#define gcdZONE_API_CL ((gctUINT32) 6 << 28)
#define gcdZONE_API_VX ((gctUINT32) 7 << 28)
#define gcdZONE_API_VG ((gctUINT32) 8 << 28)
/******************************************************************************\
************************* Subzones of Khronos API Zones ************************
\******************************************************************************/
/* Subzones of EGL API */
#define gcdZONE_EGL_API (gcdZONE_API_EGL | (1 << 0))
#define gcdZONE_EGL_SURFACE (gcdZONE_API_EGL | (1 << 1))
#define gcdZONE_EGL_CONTEXT (gcdZONE_API_EGL | (1 << 2))
#define gcdZONE_EGL_CONFIG (gcdZONE_API_EGL | (1 << 3))
#define gcdZONE_EGL_OS (gcdZONE_API_EGL | (1 << 4)) /* unused */
#define gcdZONE_EGL_IMAGE (gcdZONE_API_EGL | (1 << 5))
#define gcdZONE_EGL_SWAP (gcdZONE_API_EGL | (1 << 6))
#define gcdZONE_EGL_INIT (gcdZONE_API_EGL | (1 << 7))
#define gcdZONE_EGL_SYNC (gcdZONE_API_EGL | (1 << 8))
#define gcdZONE_EGL_COMPOSE (gcdZONE_API_EGL | (1 << 9)) /* unused */
#define gcdZONE_EGL_RENDER_THREAD (gcdZONE_API_EGL | (1 << 10)) /* unused */
/* Subzones of ES11 API */
#define gcdZONE_ES11_BUFFER (gcdZONE_API_ES11 | (1 << 0))
#define gcdZONE_ES11_CLEAR (gcdZONE_API_ES11 | (1 << 1))
#define gcdZONE_ES11_CLIP (gcdZONE_API_ES11 | (1 << 2))
#define gcdZONE_ES11_CONTEXT (gcdZONE_API_ES11 | (1 << 3))
#define gcdZONE_ES11_DRAW (gcdZONE_API_ES11 | (1 << 4))
#define gcdZONE_ES11_ENABLE (gcdZONE_API_ES11 | (1 << 5))
#define gcdZONE_ES11_EXTENTION (gcdZONE_API_ES11 | (1 << 6))
#define gcdZONE_ES11_FOG (gcdZONE_API_ES11 | (1 << 7))
#define gcdZONE_ES11_FRAGMENT (gcdZONE_API_ES11 | (1 << 8))
#define gcdZONE_ES11_LIGHT (gcdZONE_API_ES11 | (1 << 9))
#define gcdZONE_ES11_MATRIX (gcdZONE_API_ES11 | (1 << 10))
#define gcdZONE_ES11_PIXEL (gcdZONE_API_ES11 | (1 << 11))
#define gcdZONE_ES11_POLIGON (gcdZONE_API_ES11 | (1 << 12))
#define gcdZONE_ES11_LINE (gcdZONE_API_ES11 | (1 << 13)) /* unused */
#define gcdZONE_ES11_QUERY (gcdZONE_API_ES11 | (1 << 14))
#define gcdZONE_ES11_TEXTURE (gcdZONE_API_ES11 | (1 << 15))
#define gcdZONE_ES11_STATES (gcdZONE_API_ES11 | (1 << 16))
#define gcdZONE_ES11_STREAM (gcdZONE_API_ES11 | (1 << 17))
#define gcdZONE_ES11_VIEWPORT (gcdZONE_API_ES11 | (1 << 18))
#define gcdZONE_ES11_SHADER (gcdZONE_API_ES11 | (1 << 19))
#define gcdZONE_ES11_HASH (gcdZONE_API_ES11 | (1 << 20))
#define gcdZONE_ES11_TRACE (gcdZONE_API_ES11 | (1 << 21))
/* Subzones of ES30 API */
#define gcdZONE_ES30_TRACE (gcdZONE_API_ES30 | (1 << 0))
#define gcdZONE_ES30_BUFFER (gcdZONE_API_ES30 | (1 << 1))
#define gcdZONE_ES30_CLEAR (gcdZONE_API_ES30 | (1 << 2))
#define gcdZONE_ES30_CODEC (gcdZONE_API_ES30 | (1 << 3))
#define gcdZONE_ES30_CONTEXT (gcdZONE_API_ES30 | (1 << 4))
#define gcdZONE_ES30_DEPTH (gcdZONE_API_ES30 | (1 << 5))
#define gcdZONE_ES30_DEVICE (gcdZONE_API_ES30 | (1 << 6))
#define gcdZONE_ES30_DRAW (gcdZONE_API_ES30 | (1 << 7))
#define gcdZONE_ES30_FBO (gcdZONE_API_ES30 | (1 << 8))
#define gcdZONE_ES30_PIXEL (gcdZONE_API_ES30 | (1 << 9))
#define gcdZONE_ES30_SHADER (gcdZONE_API_ES30 | (1 << 10))
#define gcdZONE_ES30_STATE (gcdZONE_API_ES30 | (1 << 11))
#define gcdZONE_ES30_TEXTURE (gcdZONE_API_ES30 | (1 << 12))
#define gcdZONE_ES30_UTILS (gcdZONE_API_ES30 | (1 << 13))
#define gcdZONE_ES30_PROFILER (gcdZONE_API_ES30 | (1 << 14))
#define gcdZONE_ES30_CORE (gcdZONE_API_ES30 | (1 << 15))
/* Subzones of GL40 API */
#define gcdZONE_GL40_TRACE (gcdZONE_API_GL40 | (1 << 0))
#define gcdZONE_GL40_BUFFER (gcdZONE_API_GL40 | (1 << 1))
#define gcdZONE_GL40_CLEAR (gcdZONE_API_GL40 | (1 << 2)) /* unused */
#define gcdZONE_GL40_CODEC (gcdZONE_API_GL40 | (1 << 3))
#define gcdZONE_GL40_CONTEXT (gcdZONE_API_GL40 | (1 << 4))
#define gcdZONE_GL40_DEPTH (gcdZONE_API_GL40 | (1 << 5))
#define gcdZONE_GL40_DEVICE (gcdZONE_API_GL40 | (1 << 6))
#define gcdZONE_GL40_DRAW (gcdZONE_API_GL40 | (1 << 7))
#define gcdZONE_GL40_FBO (gcdZONE_API_GL40 | (1 << 8))
#define gcdZONE_GL40_PIXEL (gcdZONE_API_GL40 | (1 << 9))
#define gcdZONE_GL40_SHADER (gcdZONE_API_GL40 | (1 << 10))
#define gcdZONE_GL40_STATE (gcdZONE_API_GL40 | (1 << 11))
#define gcdZONE_GL40_TEXTURE (gcdZONE_API_GL40 | (1 << 12))
#define gcdZONE_GL40_UTILS (gcdZONE_API_GL40 | (1 << 13))
#define gcdZONE_GL40_PROFILER (gcdZONE_API_GL40 | (1 << 14))
#define gcdZONE_GL40_CORE (gcdZONE_API_GL40 | (1 << 15))
#define gcdZONE_GL40_FIXVERTEX (gcdZONE_API_GL40 | (1 << 16))
#define gcdZONE_GL40_FIXFRAG (gcdZONE_API_GL40 | (1 << 17))
#define gcdZONE_GL40_HASH (gcdZONE_API_GL40 | (1 << 18))
/* Subzones of VG3D API */
#define gcdZONE_VG3D_CONTEXT (gcdZONE_API_VG3D | (1 << 0))
#define gcdZONE_VG3D_DUMP (gcdZONE_API_VG3D | (1 << 1))
#define gcdZONE_VG3D_EGL (gcdZONE_API_VG3D | (1 << 2))
#define gcdZONE_VG3D_FONT (gcdZONE_API_VG3D | (1 << 3))
#define gcdZONE_VG3D_HARDWARE (gcdZONE_API_VG3D | (1 << 4))
#define gcdZONE_VG3D_IMAGE (gcdZONE_API_VG3D | (1 << 5))
#define gcdZONE_VG3D_MASK (gcdZONE_API_VG3D | (1 << 6))
#define gcdZONE_VG3D_MATRIX (gcdZONE_API_VG3D | (1 << 7))
#define gcdZONE_VG3D_OBJECT (gcdZONE_API_VG3D | (1 << 8))
#define gcdZONE_VG3D_PAINT (gcdZONE_API_VG3D | (1 << 9))
#define gcdZONE_VG3D_PATH (gcdZONE_API_VG3D | (1 << 10))
#define gcdZONE_VG3D_PROFILER (gcdZONE_API_VG3D | (1 << 11))
#define gcdZONE_VG3D_SCANLINE (gcdZONE_API_VG3D | (1 << 12))
#define gcdZONE_VG3D_SHADER (gcdZONE_API_VG3D | (1 << 13))
#define gcdZONE_VG3D_TESSELLATOR (gcdZONE_API_VG3D | (1 << 14))
#define gcdZONE_VG3D_VGU (gcdZONE_API_VG3D | (1 << 15))
/* Subzones of VG11 API */
#define gcdZONE_VG_ARC (gcdZONE_API_VG | (1 << 0))
#define gcdZONE_VG_CONTEXT (gcdZONE_API_VG | (1 << 1))
#define gcdZONE_VG_DEBUG (gcdZONE_API_VG | (1 << 2))
#define gcdZONE_VG_FILTER (gcdZONE_API_VG | (1 << 3))
#define gcdZONE_VG_FORMAT (gcdZONE_API_VG | (1 << 4))
#define gcdZONE_VG_IMAGE (gcdZONE_API_VG | (1 << 5))
#define gcdZONE_VG_MAIN (gcdZONE_API_VG | (1 << 6))
#define gcdZONE_VG_MASK (gcdZONE_API_VG | (1 << 7))
#define gcdZONE_VG_MATRIX (gcdZONE_API_VG | (1 << 8))
#define gcdZONE_VG_MEMORYMGR (gcdZONE_API_VG | (1 << 9))
#define gcdZONE_VG_OBJECT (gcdZONE_API_VG | (1 << 10))
#define gcdZONE_VG_PAINT (gcdZONE_API_VG | (1 << 11))
#define gcdZONE_VG_PATH (gcdZONE_API_VG | (1 << 12))
#define gcdZONE_VG_STATE (gcdZONE_API_VG | (1 << 13))
#define gcdZONE_VG_STROKE (gcdZONE_API_VG | (1 << 14))
#define gcdZONE_VG_TEXT (gcdZONE_API_VG | (1 << 15))
#define gcdZONE_VG_VGU (gcdZONE_API_VG | (1 << 16))
/* Subzones of CL API */
#define gcdZONE_CL_COMMAND (gcdZONE_API_CL | (1 << 0))
#define gcdZONE_CL_CONTEXT (gcdZONE_API_CL | (1 << 1))
#define gcdZONE_CL_DEVICE (gcdZONE_API_CL | (1 << 2))
#define gcdZONE_CL_ENQUEUE (gcdZONE_API_CL | (1 << 3))
#define gcdZONE_CL_EVENT (gcdZONE_API_CL | (1 << 4))
#define gcdZONE_CL_EXT (gcdZONE_API_CL | (1 << 5))
#define gcdZONE_CL_GL (gcdZONE_API_CL | (1 << 6))
#define gcdZONE_CL_KERNEL (gcdZONE_API_CL | (1 << 7))
#define gcdZONE_CL_MEM (gcdZONE_API_CL | (1 << 8))
#define gcdZONE_CL_PLATFORM (gcdZONE_API_CL | (1 << 9))
#define gcdZONE_CL_PROFILER (gcdZONE_API_CL | (1 << 10))
#define gcdZONE_CL_PROGRAM (gcdZONE_API_CL | (1 << 11))
#define gcdZONE_CL_SAMPLER (gcdZONE_API_CL | (1 << 12))
/* Subzones of VX API */
#define gcdZONE_VX_ARRAY (gcdZONE_API_VX | (1 << 0))
#define gcdZONE_VX_BINARY (gcdZONE_API_VX | (1 << 1))
#define gcdZONE_VX_CONTEXT (gcdZONE_API_VX | (1 << 2))
#define gcdZONE_VX_CONV (gcdZONE_API_VX | (1 << 3))
#define gcdZONE_VX_DELAY (gcdZONE_API_VX | (1 << 4))
#define gcdZONE_VX_DIST (gcdZONE_API_VX | (1 << 5))
#define gcdZONE_VX_GPULAYER (gcdZONE_API_VX | (1 << 6))
#define gcdZONE_VX_GRAPH (gcdZONE_API_VX | (1 << 7))
#define gcdZONE_VX_IMAGE (gcdZONE_API_VX | (1 << 8))
#define gcdZONE_VX_INTERFACE (gcdZONE_API_VX | (1 << 9))
#define gcdZONE_VX_KERNEL (gcdZONE_API_VX | (1 << 10))
#define gcdZONE_VX_LAYER (gcdZONE_API_VX | (1 << 11))
#define gcdZONE_VX_LUT (gcdZONE_API_VX | (1 << 12))
#define gcdZONE_VX_MATRIX (gcdZONE_API_VX | (1 << 13))
#define gcdZONE_VX_MEMORY (gcdZONE_API_VX | (1 << 14))
#define gcdZONE_VX_METAFMT (gcdZONE_API_VX | (1 << 15))
#define gcdZONE_VX_NODE (gcdZONE_API_VX | (1 << 16))
#define gcdZONE_VX_OBJARRAY (gcdZONE_API_VX | (1 << 17))
#define gcdZONE_VX_PARAM (gcdZONE_API_VX | (1 << 18))
#define gcdZONE_VX_PROGRAM (gcdZONE_API_VX | (1 << 19))
#define gcdZONE_VX_PYRAMID (gcdZONE_API_VX | (1 << 20))
#define gcdZONE_VX_REF (gcdZONE_API_VX | (1 << 21))
#define gcdZONE_VX_REMAP (gcdZONE_API_VX | (1 << 22))
#define gcdZONE_VX_SCALAR (gcdZONE_API_VX | (1 << 23))
#define gcdZONE_VX_TARGET (gcdZONE_API_VX | (1 << 24))
#define gcdZONE_VX_TENSOR (gcdZONE_API_VX | (1 << 25))
#define gcdZONE_VX_THRESHOLD (gcdZONE_API_VX | (1 << 26))
#define gcdZONE_VX_OTHERS (gcdZONE_API_VX | (1 << 27))
/******************************************************************************\
******************************** Utility Zones *********************************
\******************************************************************************/
/* Value for Disabling All Subzones */
#define gcdZONE_NONE 0xF0000000
/* Value for Enabling All Subzones */
#define gcdZONE_ALL 0x0FFFFFFF
/******************************************************************************\
*********************************** END ****************************************
\******************************************************************************/
#ifdef __cplusplus
}
#endif
#endif /* __gc_hal_debug_zones_h_ */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,280 @@
/****************************************************************************
*
* The MIT License (MIT)
*
* Copyright (c) 2014 - 2019 Vivante Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
*****************************************************************************
*
* The GPL License (GPL)
*
* Copyright (C) 2014 - 2019 Vivante Corporation
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*****************************************************************************
*
* Note: This software is released under dual MIT and GPL licenses. A
* recipient may use this file under the terms of either the MIT license or
* GPL License. If you wish to use only one license not the other, you can
* indicate your decision by deleting one of the above license notices in your
* version of this file.
*
*****************************************************************************/
#ifndef __gc_hal_driver_vg_h_
#define __gc_hal_driver_vg_h_
#include "gc_hal_types.h"
#ifdef __cplusplus
extern "C" {
#endif
/******************************************************************************\
******************************* I/O Control Codes ******************************
\******************************************************************************/
#define gcvHAL_CLASS "galcore"
#define IOCTL_GCHAL_INTERFACE 30000
/******************************************************************************\
********************* Command buffer information structure. ********************
\******************************************************************************/
typedef struct _gcsCOMMAND_BUFFER_INFO * gcsCOMMAND_BUFFER_INFO_PTR;
typedef struct _gcsCOMMAND_BUFFER_INFO
{
/* FE command buffer interrupt ID. */
gctINT32 feBufferInt;
/* TS overflow interrupt ID. */
gctINT32 tsOverflowInt;
/* Alignment and mask for the buffer address. */
gctUINT addressMask;
gctUINT32 addressAlignment;
/* Alignment for each command. */
gctUINT32 commandAlignment;
/* Number of bytes required by the STATE command. */
gctUINT32 stateCommandSize;
/* Number of bytes required by the RESTART command. */
gctUINT32 restartCommandSize;
/* Number of bytes required by the FETCH command. */
gctUINT32 fetchCommandSize;
/* Number of bytes required by the CALL command. */
gctUINT32 callCommandSize;
/* Number of bytes required by the RETURN command. */
gctUINT32 returnCommandSize;
/* Number of bytes required by the EVENT command. */
gctUINT32 eventCommandSize;
/* Number of bytes required by the END command. */
gctUINT32 endCommandSize;
/* Number of bytes reserved at the tail of a static command buffer. */
gctUINT32 staticTailSize;
/* Number of bytes reserved at the tail of a dynamic command buffer. */
gctUINT32 dynamicTailSize;
}
gcsCOMMAND_BUFFER_INFO;
/******************************************************************************\
******************************** Task Structures *******************************
\******************************************************************************/
typedef enum _gceTASK
{
gcvTASK_LINK,
gcvTASK_CLUSTER,
gcvTASK_INCREMENT,
gcvTASK_DECREMENT,
gcvTASK_SIGNAL,
gcvTASK_LOCKDOWN,
gcvTASK_UNLOCK_VIDEO_MEMORY,
gcvTASK_FREE_VIDEO_MEMORY,
gcvTASK_FREE_CONTIGUOUS_MEMORY,
}
gceTASK;
typedef struct _gcsTASK_HEADER * gcsTASK_HEADER_PTR;
typedef struct _gcsTASK_HEADER
{
/* Task ID. */
IN gceTASK id;
}
gcsTASK_HEADER;
typedef struct _gcsTASK_LINK * gcsTASK_LINK_PTR;
typedef struct _gcsTASK_LINK
{
/* Task ID (gcvTASK_LINK). */
IN gceTASK id;
/* Pointer to the next task container. */
IN gctPOINTER cotainer;
/* Pointer to the next task from the next task container. */
IN gcsTASK_HEADER_PTR task;
}
gcsTASK_LINK;
typedef struct _gcsTASK_CLUSTER * gcsTASK_CLUSTER_PTR;
typedef struct _gcsTASK_CLUSTER
{
/* Task ID (gcvTASK_CLUSTER). */
IN gceTASK id;
/* Number of tasks in the cluster. */
IN gctUINT taskCount;
}
gcsTASK_CLUSTER;
typedef struct _gcsTASK_INCREMENT * gcsTASK_INCREMENT_PTR;
typedef struct _gcsTASK_INCREMENT
{
/* Task ID (gcvTASK_INCREMENT). */
IN gceTASK id;
/* Address of the variable to increment. */
IN gctUINT32 address;
}
gcsTASK_INCREMENT;
typedef struct _gcsTASK_DECREMENT * gcsTASK_DECREMENT_PTR;
typedef struct _gcsTASK_DECREMENT
{
/* Task ID (gcvTASK_DECREMENT). */
IN gceTASK id;
/* Address of the variable to decrement. */
IN gctUINT32 address;
}
gcsTASK_DECREMENT;
typedef struct _gcsTASK_SIGNAL * gcsTASK_SIGNAL_PTR;
typedef struct _gcsTASK_SIGNAL
{
/* Task ID (gcvTASK_SIGNAL). */
IN gceTASK id;
/* Process owning the signal. */
IN gctHANDLE process;
/* Signal handle to signal. */
IN gctSIGNAL signal;
#if defined(__QNXNTO__)
IN gctINT32 coid;
IN gctINT32 rcvid;
#endif
}
gcsTASK_SIGNAL;
typedef struct _gcsTASK_LOCKDOWN * gcsTASK_LOCKDOWN_PTR;
typedef struct _gcsTASK_LOCKDOWN
{
/* Task ID (gcvTASK_LOCKDOWN). */
IN gceTASK id;
/* Address of the user space counter. */
IN gctUINT32 userCounter;
/* Address of the kernel space counter. */
IN gctUINT32 kernelCounter;
/* Process owning the signal. */
IN gctHANDLE process;
/* Signal handle to signal. */
IN gctSIGNAL signal;
}
gcsTASK_LOCKDOWN;
typedef struct _gcsTASK_UNLOCK_VIDEO_MEMORY * gcsTASK_UNLOCK_VIDEO_MEMORY_PTR;
typedef struct _gcsTASK_UNLOCK_VIDEO_MEMORY
{
/* Task ID (gcvTASK_UNLOCK_VIDEO_MEMORY). */
IN gceTASK id;
/* Allocated video memory. */
IN gctUINT64 node;
}
gcsTASK_UNLOCK_VIDEO_MEMORY;
typedef struct _gcsTASK_FREE_VIDEO_MEMORY * gcsTASK_FREE_VIDEO_MEMORY_PTR;
typedef struct _gcsTASK_FREE_VIDEO_MEMORY
{
/* Task ID (gcvTASK_FREE_VIDEO_MEMORY). */
IN gceTASK id;
/* Allocated video memory. */
IN gctUINT32 node;
}
gcsTASK_FREE_VIDEO_MEMORY;
typedef struct _gcsTASK_FREE_CONTIGUOUS_MEMORY * gcsTASK_FREE_CONTIGUOUS_MEMORY_PTR;
typedef struct _gcsTASK_FREE_CONTIGUOUS_MEMORY
{
/* Task ID (gcvTASK_FREE_CONTIGUOUS_MEMORY). */
IN gceTASK id;
/* Number of bytes allocated. */
IN gctSIZE_T bytes;
/* Physical address of allocation. */
IN gctPHYS_ADDR physical;
/* Logical address of allocation. */
IN gctPOINTER logical;
}
gcsTASK_FREE_CONTIGUOUS_MEMORY;
#ifdef __cplusplus
}
#endif
#endif /* __gc_hal_driver_h_ */

View File

@ -0,0 +1,195 @@
/****************************************************************************
*
* The MIT License (MIT)
*
* Copyright (c) 2014 - 2019 Vivante Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
*****************************************************************************
*
* The GPL License (GPL)
*
* Copyright (C) 2014 - 2019 Vivante Corporation
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*****************************************************************************
*
* Note: This software is released under dual MIT and GPL licenses. A
* recipient may use this file under the terms of either the MIT license or
* GPL License. If you wish to use only one license not the other, you can
* indicate your decision by deleting one of the above license notices in your
* version of this file.
*
*****************************************************************************/
#ifndef __VIVNATE_DRM_H__
#define __VIVNATE_DRM_H__
#if defined(__cplusplus)
extern "C" {
#endif
/* creation flag bits. */
#define DRM_VIV_GEM_CONTIGUOUS (1u << 0)
#define DRM_VIV_GEM_CACHED (1u << 1)
#define DRM_VIV_GEM_SECURE (1u << 2)
#define DRM_VIV_GEM_CMA_LIMIT (1u << 3)
struct drm_viv_gem_create {
__u64 size;
__u32 flags;
__u32 handle;
};
struct drm_viv_gem_lock {
__u32 handle;
__u32 cacheable;
__u64 logical;
};
struct drm_viv_gem_unlock {
__u32 handle;
};
#define DRM_VIV_GEM_CLEAN_CACHE 0x01
#define DRM_VIV_GEM_INVALIDATE_CACHE 0x02
#define DRM_VIV_GEM_FLUSH_CACHE 0x03
#define DRM_VIV_GEM_MEMORY_BARRIER 0x04
struct drm_viv_gem_cache {
__u32 handle;
__u32 op;
__u64 logical;
__u64 bytes;
};
#define DRM_VIV_GEM_PARAM_POOL 0x00
#define DRM_VIV_GEM_PARAM_SIZE 0x01
struct drm_viv_gem_query {
__u32 handle;
__u32 param;
__u64 value;
};
struct drm_viv_gem_timestamp {
__u32 handle;
/* inc count, 0 for query current. */
__u32 inc;
/* output inc'ed timestamp. */
__u64 timestamp;
};
/* basic tiling mode. */
#define DRM_VIV_GEM_TILING_LINEAR 0x01
#define DRM_VIV_GEM_TILING_TILED 0x02
#define DRM_VIV_GEM_TILING_SUPERTILED 0x04
#define DRM_VIV_GEM_TILING_MINORTILED 0x08
/* tiling mode modifiers. */
#define DRM_VIV_GEM_TILING_SPLIT 0x10
#define DRM_VIV_GEM_TILING_X_MAJOR 0x20
#define DRM_VIV_GEM_TILING_Y_MAJOR 0x40
#define DRM_VIV_GEM_TILING_SWAP 0x80
/* ts mode. */
#define DRM_VIV_GEM_TS_NONE 0x00
#define DRM_VIV_GEM_TS_DISABLED 0x01
#define DRM_VIV_GEM_TS_NORMAL 0x02
#define DRM_VIV_GEM_TS_COMPRESSED 0x03
struct drm_viv_gem_set_tiling {
__u32 handle;
__u32 tiling_mode;
__u32 ts_mode;
__u64 clear_value;
};
struct drm_viv_gem_get_tiling {
__u32 handle;
__u32 tiling_mode;
__u32 ts_mode;
__u64 clear_value;
};
struct drm_viv_gem_attach_aux {
__u32 handle;
__u32 ts_handle;
};
struct drm_viv_gem_ref_node {
__u32 handle;
/* output. */
__u32 node;
__u32 ts_node;
};
#define DRM_VIV_GEM_CREATE 0x00
#define DRM_VIV_GEM_LOCK 0x01
#define DRM_VIV_GEM_UNLOCK 0x02
#define DRM_VIV_GEM_CACHE 0x03
#define DRM_VIV_GEM_QUERY 0x04
#define DRM_VIV_GEM_TIMESTAMP 0x05
#define DRM_VIV_GEM_SET_TILING 0x06
#define DRM_VIV_GEM_GET_TILING 0x07
#define DRM_VIV_GEM_ATTACH_AUX 0x08
#define DRM_VIV_GEM_REF_NODE 0x09
#define DRM_VIV_NUM_IOCTLS 0x0A
#define DRM_IOCTL_VIV_GEM_CREATE DRM_IOWR(DRM_COMMAND_BASE + DRM_VIV_GEM_CREATE, struct drm_viv_gem_create)
#define DRM_IOCTL_VIV_GEM_LOCK DRM_IOWR(DRM_COMMAND_BASE + DRM_VIV_GEM_LOCK, struct drm_viv_gem_lock)
#define DRM_IOCTL_VIV_GEM_UNLOCK DRM_IOWR(DRM_COMMAND_BASE + DRM_VIV_GEM_UNLOCK, struct drm_viv_gem_unlock)
#define DRM_IOCTL_VIV_GEM_CACHE DRM_IOWR(DRM_COMMAND_BASE + DRM_VIV_GEM_CACHE, struct drm_viv_gem_cache)
#define DRM_IOCTL_VIV_GEM_QUERY DRM_IOWR(DRM_COMMAND_BASE + DRM_VIV_GEM_QUERY, struct drm_viv_gem_query)
#define DRM_IOCTL_VIV_GEM_TIMESTAMP DRM_IOWR(DRM_COMMAND_BASE + DRM_VIV_GEM_TIMESTAMP, struct drm_viv_gem_timestamp)
#define DRM_IOCTL_VIV_GEM_SET_TILING DRM_IOWR(DRM_COMMAND_BASE + DRM_VIV_GEM_SET_TILING, struct drm_viv_gem_set_tiling)
#define DRM_IOCTL_VIV_GEM_GET_TILING DRM_IOWR(DRM_COMMAND_BASE + DRM_VIV_GEM_GET_TILING, struct drm_viv_gem_get_tiling)
#define DRM_IOCTL_VIV_GEM_ATTACH_AUX DRM_IOWR(DRM_COMMAND_BASE + DRM_VIV_GEM_ATTACH_AUX, struct drm_viv_gem_attach_aux)
#define DRM_IOCTL_VIV_GEM_REF_NODE DRM_IOWR(DRM_COMMAND_BASE + DRM_VIV_GEM_REF_NODE, struct drm_viv_gem_ref_node)
#if defined(__cplusplus)
}
#endif
#endif /* __VIVNATE_DRM_H__ */

View File

@ -0,0 +1,146 @@
/****************************************************************************
*
* The MIT License (MIT)
*
* Copyright (c) 2014 - 2019 Vivante Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
*****************************************************************************
*
* The GPL License (GPL)
*
* Copyright (C) 2014 - 2019 Vivante Corporation
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*****************************************************************************
*
* Note: This software is released under dual MIT and GPL licenses. A
* recipient may use this file under the terms of either the MIT license or
* GPL License. If you wish to use only one license not the other, you can
* indicate your decision by deleting one of the above license notices in your
* version of this file.
*
*****************************************************************************/
#ifndef __gc_hal_dump_h_
#define __gc_hal_dump_h_
/*
gcdDUMP_KEY
Set this to a string that appears in 'cat /proc/<pid>/cmdline'. E.g. 'camera'.
HAL will create dumps for the processes matching this key.
*/
#ifndef gcdDUMP_KEY
# define gcdDUMP_KEY "process"
#endif
/*
gcdDUMP_PATH
The dump file location. Some processes cannot write to the sdcard.
Try apps' data dir, e.g. /data/data/com.android.launcher
*/
#ifndef gcdDUMP_PATH
#if defined(ANDROID)
# define gcdDUMP_PATH "/mnt/sdcard/"
#else
# define gcdDUMP_PATH "./"
#endif
#endif
/*
gcdDUMP_FILE_IN_KERNEL
Default dump file for gcdDUMP_IN_KERNEL.
The file will be writen globally in kernel side.
Can be overwriten in runtime by debugfs:/gc/dump/dump_file
2 pseudo files:
[dmesg]: means dump to kernel debug message.
[ignored]: means dump ignored, nothing will be dumpped.
*/
#ifndef gcdDUMP_FILE_IN_KERNEL
# define gcdDUMP_FILE_IN_KERNEL "[dmesg]"
#endif
/*
gcdDUMP_VERIFY_PER_DRAW
Sub feature of gcdDUMP.
When set to 1, verify RT and images(if used) for every single draw to ease simulation debug.
Only valid for ES3 driver for now.
*/
#ifndef gcdDUMP_VERIFY_PER_DRAW
# define gcdDUMP_VERIFY_PER_DRAW 0
#endif
/* Standalone dump features below. */
/*
gcdDUMP_FRAMERATE
When set to a value other than zero, averaqe frame rate will be dumped.
The value set is the starting frame that the average will be calculated.
This is needed because sometimes first few frames are too slow to be included
in the average. Frame count starts from 1.
*/
#ifndef gcdDUMP_FRAMERATE
# define gcdDUMP_FRAMERATE 0
#endif
/*
gcdDUMP_FRAME_TGA
When set to a value other than 0, a dump of the frame specified by the value,
will be done into frame.tga. Frame count starts from 1.
*/
#ifndef gcdDUMP_FRAME_TGA
# define gcdDUMP_FRAME_TGA 0
#endif
/*
gcdDUMP_AHB_ACCESS
When set to 1, a dump of all AHB register access will be printed to kernel
message.
*/
#ifndef gcdDUMP_AHB_ACCESS
# define gcdDUMP_AHB_ACCESS 0
#endif
#endif /* __gc_hal_dump_h_ */

View File

@ -0,0 +1,589 @@
/****************************************************************************
*
* The MIT License (MIT)
*
* Copyright (c) 2014 - 2019 Vivante Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
*****************************************************************************
*
* The GPL License (GPL)
*
* Copyright (C) 2014 - 2019 Vivante Corporation
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*****************************************************************************
*
* Note: This software is released under dual MIT and GPL licenses. A
* recipient may use this file under the terms of either the MIT license or
* GPL License. If you wish to use only one license not the other, you can
* indicate your decision by deleting one of the above license notices in your
* version of this file.
*
*****************************************************************************/
#ifndef __gc_hal_eglplatform_h_
#define __gc_hal_eglplatform_h_
#include "gc_hal_types.h"
#include "gc_hal_base.h"
#ifdef __cplusplus
extern "C" {
#endif
#if defined(_WIN32) || defined(__VC32__) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__)
#ifndef WIN32_LEAN_AND_MEAN
/* #define WIN32_LEAN_AND_MEAN 1 */
#endif
#include <windows.h>
typedef HDC HALNativeDisplayType;
typedef HWND HALNativeWindowType;
typedef HBITMAP HALNativePixmapType;
typedef struct __BITFIELDINFO
{
BITMAPINFO bmi;
RGBQUAD bmiColors[2];
}
BITFIELDINFO;
#elif /* defined(__APPLE__) || */ defined(__WINSCW__) || defined(__SYMBIAN32__) /* Symbian */
#elif defined(WL_EGL_PLATFORM) || defined(EGL_API_WL) /* Wayland */
#elif defined(__GBM__) /* GBM */
#elif defined(__ANDROID__) || defined(ANDROID)
#elif defined(MIR_EGL_PLATFORM) /* Mir */
#elif defined(__QNXNTO__)
#elif defined(__unix__) || defined(__APPLE__)
#if defined(EGL_API_DFB)
#elif defined(EGL_API_FB)
#elif defined(EGL_API_NULLWS)
#else
/* X11 (tetative). */
#endif
#else
#error "Platform not recognized"
#endif
#if defined(_WIN32) || defined(__VC32__) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__)
#include "gc_hal_eglplatform_type.h"
/*******************************************************************************
** Display. ********************************************************************
*/
gceSTATUS
gcoOS_GetDisplay(
OUT HALNativeDisplayType * Display,
IN gctPOINTER Context
);
gceSTATUS
gcoOS_GetDisplayByIndex(
IN gctINT DisplayIndex,
OUT HALNativeDisplayType * Display,
IN gctPOINTER Context
);
gceSTATUS
gcoOS_GetDisplayInfo(
IN HALNativeDisplayType Display,
OUT gctINT * Width,
OUT gctINT * Height,
OUT gctSIZE_T * Physical,
OUT gctINT * Stride,
OUT gctINT * BitsPerPixel
);
gceSTATUS
gcoOS_GetDisplayInfoEx(
IN HALNativeDisplayType Display,
IN HALNativeWindowType Window,
IN gctUINT DisplayInfoSize,
OUT halDISPLAY_INFO * DisplayInfo
);
gceSTATUS
gcoOS_GetDisplayVirtual(
IN HALNativeDisplayType Display,
OUT gctINT * Width,
OUT gctINT * Height
);
gceSTATUS
gcoOS_GetDisplayBackbuffer(
IN HALNativeDisplayType Display,
IN HALNativeWindowType Window,
OUT gctPOINTER * context,
OUT gcoSURF * surface,
OUT gctUINT * Offset,
OUT gctINT * X,
OUT gctINT * Y
);
gceSTATUS
gcoOS_SetDisplayVirtual(
IN HALNativeDisplayType Display,
IN HALNativeWindowType Window,
IN gctUINT Offset,
IN gctINT X,
IN gctINT Y
);
gceSTATUS
gcoOS_SetDisplayVirtualEx(
IN HALNativeDisplayType Display,
IN HALNativeWindowType Window,
IN gctPOINTER Context,
IN gcoSURF Surface,
IN gctUINT Offset,
IN gctINT X,
IN gctINT Y
);
gceSTATUS
gcoOS_CancelDisplayBackbuffer(
IN HALNativeDisplayType Display,
IN HALNativeWindowType Window,
IN gctPOINTER Context,
IN gcoSURF Surface,
IN gctUINT Offset,
IN gctINT X,
IN gctINT Y
);
gceSTATUS
gcoOS_SetSwapInterval(
IN HALNativeDisplayType Display,
IN gctINT Interval
);
gceSTATUS
gcoOS_SetSwapIntervalEx(
IN HALNativeDisplayType Display,
IN gctINT Interval,
IN gctPOINTER localDisplay);
gceSTATUS
gcoOS_GetSwapInterval(
IN HALNativeDisplayType Display,
IN gctINT_PTR Min,
IN gctINT_PTR Max
);
gceSTATUS
gcoOS_DisplayBufferRegions(
IN HALNativeDisplayType Display,
IN HALNativeWindowType Window,
IN gctINT NumRects,
IN gctINT_PTR Rects
);
gceSTATUS
gcoOS_DestroyDisplay(
IN HALNativeDisplayType Display
);
gceSTATUS
gcoOS_InitLocalDisplayInfo(
IN HALNativeDisplayType Display,
IN OUT gctPOINTER * localDisplay
);
gceSTATUS
gcoOS_DeinitLocalDisplayInfo(
IN HALNativeDisplayType Display,
IN OUT gctPOINTER * localDisplay
);
gceSTATUS
gcoOS_GetDisplayInfoEx2(
IN HALNativeDisplayType Display,
IN HALNativeWindowType Window,
IN gctPOINTER localDisplay,
IN gctUINT DisplayInfoSize,
OUT halDISPLAY_INFO * DisplayInfo
);
gceSTATUS
gcoOS_GetDisplayBackbufferEx(
IN HALNativeDisplayType Display,
IN HALNativeWindowType Window,
IN gctPOINTER localDisplay,
OUT gctPOINTER * context,
OUT gcoSURF * surface,
OUT gctUINT * Offset,
OUT gctINT * X,
OUT gctINT * Y
);
gceSTATUS
gcoOS_IsValidDisplay(
IN HALNativeDisplayType Display
);
gceSTATUS
gcoOS_GetNativeVisualId(
IN HALNativeDisplayType Display,
OUT gctINT* nativeVisualId
);
gctBOOL
gcoOS_SynchronousFlip(
IN HALNativeDisplayType Display
);
/*******************************************************************************
** Windows. ********************************************************************
*/
gceSTATUS
gcoOS_CreateWindow(
IN HALNativeDisplayType Display,
IN gctINT X,
IN gctINT Y,
IN gctINT Width,
IN gctINT Height,
OUT HALNativeWindowType * Window
);
gceSTATUS
gcoOS_GetWindowInfo(
IN HALNativeDisplayType Display,
IN HALNativeWindowType Window,
OUT gctINT * X,
OUT gctINT * Y,
OUT gctINT * Width,
OUT gctINT * Height,
OUT gctINT * BitsPerPixel,
OUT gctUINT * Offset
);
gceSTATUS
gcoOS_DestroyWindow(
IN HALNativeDisplayType Display,
IN HALNativeWindowType Window
);
gceSTATUS
gcoOS_DrawImage(
IN HALNativeDisplayType Display,
IN HALNativeWindowType Window,
IN gctINT Left,
IN gctINT Top,
IN gctINT Right,
IN gctINT Bottom,
IN gctINT Width,
IN gctINT Height,
IN gctINT BitsPerPixel,
IN gctPOINTER Bits
);
gceSTATUS
gcoOS_GetImage(
IN HALNativeWindowType Window,
IN gctINT Left,
IN gctINT Top,
IN gctINT Right,
IN gctINT Bottom,
OUT gctINT * BitsPerPixel,
OUT gctPOINTER * Bits
);
gceSTATUS
gcoOS_GetWindowInfoEx(
IN HALNativeDisplayType Display,
IN HALNativeWindowType Window,
OUT gctINT * X,
OUT gctINT * Y,
OUT gctINT * Width,
OUT gctINT * Height,
OUT gctINT * BitsPerPixel,
OUT gctUINT * Offset,
OUT gceSURF_FORMAT * Format,
OUT gceSURF_TYPE * Type
);
gceSTATUS
gcoOS_DrawImageEx(
IN HALNativeDisplayType Display,
IN HALNativeWindowType Window,
IN gctINT Left,
IN gctINT Top,
IN gctINT Right,
IN gctINT Bottom,
IN gctINT Width,
IN gctINT Height,
IN gctINT BitsPerPixel,
IN gctPOINTER Bits,
IN gceSURF_FORMAT Format
);
/*
* Possiable types:
* gcvSURF_BITMAP
* gcvSURF_RENDER_TARGET
* gcvSURF_RENDER_TARGET_NO_COMPRESSION
* gcvSURF_RENDER_TARGET_NO_TILE_STATUS
*/
gceSTATUS
gcoOS_SetWindowFormat(
IN HALNativeDisplayType Display,
IN HALNativeWindowType Window,
IN gceSURF_TYPE Type,
IN gceSURF_FORMAT Format
);
/*******************************************************************************
** Pixmaps. ********************************************************************
*/
gceSTATUS
gcoOS_CreatePixmap(
IN HALNativeDisplayType Display,
IN gctINT Width,
IN gctINT Height,
IN gctINT BitsPerPixel,
OUT HALNativePixmapType * Pixmap
);
gceSTATUS
gcoOS_GetPixmapInfo(
IN HALNativeDisplayType Display,
IN HALNativePixmapType Pixmap,
OUT gctINT * Width,
OUT gctINT * Height,
OUT gctINT * BitsPerPixel,
OUT gctINT * Stride,
OUT gctPOINTER * Bits
);
gceSTATUS
gcoOS_DrawPixmap(
IN HALNativeDisplayType Display,
IN HALNativePixmapType Pixmap,
IN gctINT Left,
IN gctINT Top,
IN gctINT Right,
IN gctINT Bottom,
IN gctINT Width,
IN gctINT Height,
IN gctINT BitsPerPixel,
IN gctPOINTER Bits
);
gceSTATUS
gcoOS_DestroyPixmap(
IN HALNativeDisplayType Display,
IN HALNativePixmapType Pixmap
);
gceSTATUS
gcoOS_GetPixmapInfoEx(
IN HALNativeDisplayType Display,
IN HALNativePixmapType Pixmap,
OUT gctINT * Width,
OUT gctINT * Height,
OUT gctINT * BitsPerPixel,
OUT gctINT * Stride,
OUT gctPOINTER * Bits,
OUT gceSURF_FORMAT * Format
);
gceSTATUS
gcoOS_CopyPixmapBits(
IN HALNativeDisplayType Display,
IN HALNativePixmapType Pixmap,
IN gctUINT DstWidth,
IN gctUINT DstHeight,
IN gctINT DstStride,
IN gceSURF_FORMAT DstFormat,
OUT gctPOINTER DstBits
);
/*******************************************************************************
** OS relative. ****************************************************************
*/
gceSTATUS
gcoOS_LoadEGLLibrary(
OUT gctHANDLE * Handle
);
gceSTATUS
gcoOS_FreeEGLLibrary(
IN gctHANDLE Handle
);
gceSTATUS
gcoOS_ShowWindow(
IN HALNativeDisplayType Display,
IN HALNativeWindowType Window
);
gceSTATUS
gcoOS_HideWindow(
IN HALNativeDisplayType Display,
IN HALNativeWindowType Window
);
gceSTATUS
gcoOS_SetWindowTitle(
IN HALNativeDisplayType Display,
IN HALNativeWindowType Window,
IN gctCONST_STRING Title
);
gceSTATUS
gcoOS_CapturePointer(
IN HALNativeDisplayType Display,
IN HALNativeWindowType Window
);
gceSTATUS
gcoOS_GetEvent(
IN HALNativeDisplayType Display,
IN HALNativeWindowType Window,
OUT halEvent * Event
);
gceSTATUS
gcoOS_CreateClientBuffer(
IN gctINT Width,
IN gctINT Height,
IN gctINT Format,
IN gctINT Type,
OUT gctPOINTER * ClientBuffer
);
gceSTATUS
gcoOS_GetClientBufferInfo(
IN gctPOINTER ClientBuffer,
OUT gctINT * Width,
OUT gctINT * Height,
OUT gctINT * Stride,
OUT gctPOINTER * Bits
);
gceSTATUS
gcoOS_DestroyClientBuffer(
IN gctPOINTER ClientBuffer
);
gceSTATUS
gcoOS_DestroyContext(
IN gctPOINTER Display,
IN gctPOINTER Context
);
gceSTATUS
gcoOS_CreateContext(
IN gctPOINTER LocalDisplay,
IN gctPOINTER Context
);
gceSTATUS
gcoOS_MakeCurrent(
IN gctPOINTER LocalDisplay,
IN HALNativeWindowType DrawDrawable,
IN HALNativeWindowType ReadDrawable,
IN gctPOINTER Context,
IN gcoSURF ResolveTarget
);
gceSTATUS
gcoOS_CreateDrawable(
IN gctPOINTER LocalDisplay,
IN HALNativeWindowType Drawable
);
gceSTATUS
gcoOS_DestroyDrawable(
IN gctPOINTER LocalDisplay,
IN HALNativeWindowType Drawable
);
gceSTATUS
gcoOS_SwapBuffers(
IN gctPOINTER LocalDisplay,
IN HALNativeWindowType Drawable,
IN gcoSURF RenderTarget,
IN gcoSURF ResolveTarget,
IN gctPOINTER ResolveBits,
OUT gctUINT *Width,
OUT gctUINT *Height
);
gceSTATUS
gcoOS_ResizeWindow(
IN gctPOINTER localDisplay,
IN HALNativeWindowType Drawable,
IN gctUINT Width,
IN gctUINT Height
);
gceSTATUS
gcoOS_RSForSwap(
IN gctPOINTER localDisplay,
IN HALNativeWindowType Drawable,
IN gctPOINTER resolve
);
#endif
#ifdef __cplusplus
}
#endif
#endif /* __gc_hal_eglplatform_h_ */

View File

@ -0,0 +1,326 @@
/****************************************************************************
*
* The MIT License (MIT)
*
* Copyright (c) 2014 - 2019 Vivante Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
*****************************************************************************
*
* The GPL License (GPL)
*
* Copyright (C) 2014 - 2019 Vivante Corporation
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*****************************************************************************
*
* Note: This software is released under dual MIT and GPL licenses. A
* recipient may use this file under the terms of either the MIT license or
* GPL License. If you wish to use only one license not the other, you can
* indicate your decision by deleting one of the above license notices in your
* version of this file.
*
*****************************************************************************/
#ifndef __gc_hal_eglplatform_type_h_
#define __gc_hal_eglplatform_type_h_
#ifdef __cplusplus
extern "C" {
#endif
/*******************************************************************************
** Events. *********************************************************************
*/
typedef enum _halEventType
{
/* Keyboard event. */
HAL_KEYBOARD,
/* Mouse move event. */
HAL_POINTER,
/* Mouse button event. */
HAL_BUTTON,
/* Application close event. */
HAL_CLOSE,
/* Application window has been updated. */
HAL_WINDOW_UPDATE
}
halEventType;
/* Scancodes for keyboard. */
typedef enum _halKeys
{
HAL_UNKNOWN = -1,
HAL_BACKSPACE = 0x08,
HAL_TAB,
HAL_ENTER = 0x0D,
HAL_ESCAPE = 0x1B,
HAL_SPACE = 0x20,
HAL_SINGLEQUOTE = 0x27,
HAL_PAD_ASTERISK = 0x2A,
HAL_COMMA = 0x2C,
HAL_HYPHEN,
HAL_PERIOD,
HAL_SLASH,
HAL_0,
HAL_1,
HAL_2,
HAL_3,
HAL_4,
HAL_5,
HAL_6,
HAL_7,
HAL_8,
HAL_9,
HAL_SEMICOLON = 0x3B,
HAL_EQUAL = 0x3D,
HAL_A = 0x41,
HAL_B,
HAL_C,
HAL_D,
HAL_E,
HAL_F,
HAL_G,
HAL_H,
HAL_I,
HAL_J,
HAL_K,
HAL_L,
HAL_M,
HAL_N,
HAL_O,
HAL_P,
HAL_Q,
HAL_R,
HAL_S,
HAL_T,
HAL_U,
HAL_V,
HAL_W,
HAL_X,
HAL_Y,
HAL_Z,
HAL_LBRACKET,
HAL_BACKSLASH,
HAL_RBRACKET,
HAL_BACKQUOTE = 0x60,
HAL_F1 = 0x80,
HAL_F2,
HAL_F3,
HAL_F4,
HAL_F5,
HAL_F6,
HAL_F7,
HAL_F8,
HAL_F9,
HAL_F10,
HAL_F11,
HAL_F12,
HAL_LCTRL,
HAL_RCTRL,
HAL_LSHIFT,
HAL_RSHIFT,
HAL_LALT,
HAL_RALT,
HAL_CAPSLOCK,
HAL_NUMLOCK,
HAL_SCROLLLOCK,
HAL_PAD_0,
HAL_PAD_1,
HAL_PAD_2,
HAL_PAD_3,
HAL_PAD_4,
HAL_PAD_5,
HAL_PAD_6,
HAL_PAD_7,
HAL_PAD_8,
HAL_PAD_9,
HAL_PAD_HYPHEN,
HAL_PAD_PLUS,
HAL_PAD_SLASH,
HAL_PAD_PERIOD,
HAL_PAD_ENTER,
HAL_SYSRQ,
HAL_PRNTSCRN,
HAL_BREAK,
HAL_UP,
HAL_LEFT,
HAL_RIGHT,
HAL_DOWN,
HAL_HOME,
HAL_END,
HAL_PGUP,
HAL_PGDN,
HAL_INSERT,
HAL_DELETE,
HAL_LWINDOW,
HAL_RWINDOW,
HAL_MENU,
HAL_POWER,
HAL_SLEEP,
HAL_WAKE
}
halKeys;
/* Structure that defined keyboard mapping. */
typedef struct _halKeyMap
{
/* Normal key. */
halKeys normal;
/* Extended key. */
halKeys extended;
}
halKeyMap;
/* Event structure. */
typedef struct _halEvent
{
/* Event type. */
halEventType type;
/* Event data union. */
union _halEventData
{
/* Event data for keyboard. */
struct _halKeyboard
{
/* Scancode. */
halKeys scancode;
/* ASCII characte of the key pressed. */
char key;
/* Flag whether the key was pressed (1) or released (0). */
char pressed;
}
keyboard;
/* Event data for pointer. */
struct _halPointer
{
/* Current pointer coordinate. */
int x;
int y;
}
pointer;
/* Event data for mouse buttons. */
struct _halButton
{
/* Left button state. */
int left;
/* Middle button state. */
int middle;
/* Right button state. */
int right;
/* Current pointer coordinate. */
int x;
int y;
}
button;
}
data;
}
halEvent;
/* VFK_DISPLAY_INFO structure defining information returned by
vdkGetDisplayInfoEx. */
typedef struct _halDISPLAY_INFO
{
/* The size of the display in pixels. */
int width;
int height;
/* The stride of the dispay. -1 is returned if the stride is not known
** for the specified display.*/
int stride;
/* The color depth of the display in bits per pixel. */
int bitsPerPixel;
/* The logical pointer to the display memory buffer. NULL is returned
** if the pointer is not known for the specified display. */
void * logical;
/* The physical address of the display memory buffer. ~0 is returned
** if the address is not known for the specified display. */
unsigned long physical;
/* Can be wraped as surface. */
int wrapFB;
/* FB_MULTI_BUFFER support */
int multiBuffer;
int backBufferY;
/* Tiled buffer / tile status support. */
int tiledBuffer;
int tileStatus;
int compression;
/* The color info of the display. */
unsigned int alphaLength;
unsigned int alphaOffset;
unsigned int redLength;
unsigned int redOffset;
unsigned int greenLength;
unsigned int greenOffset;
unsigned int blueLength;
unsigned int blueOffset;
/* Display flip support. */
int flip;
}
halDISPLAY_INFO;
#ifdef __cplusplus
}
#endif
#endif /* __gc_hal_eglplatform_type_h_ */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,326 @@
/****************************************************************************
*
* The MIT License (MIT)
*
* Copyright (c) 2014 - 2019 Vivante Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
*****************************************************************************
*
* The GPL License (GPL)
*
* Copyright (C) 2014 - 2019 Vivante Corporation
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*****************************************************************************
*
* Note: This software is released under dual MIT and GPL licenses. A
* recipient may use this file under the terms of either the MIT license or
* GPL License. If you wish to use only one license not the other, you can
* indicate your decision by deleting one of the above license notices in your
* version of this file.
*
*****************************************************************************/
#ifndef __gc_hal_kernel_buffer_h_
#define __gc_hal_kernel_buffer_h_
#ifdef __cplusplus
extern "C" {
#endif
/******************************************************************************\
************************ Command Buffer and Event Objects **********************
\******************************************************************************/
/* The number of context buffers per user. */
#define gcdCONTEXT_BUFFER_COUNT 2
#define gcdRENDER_FENCE_LENGTH (6 * gcmSIZEOF(gctUINT32))
#define gcdBLT_FENCE_LENGTH (10 * gcmSIZEOF(gctUINT32))
#define gcdRESERVED_FLUSHCACHE_LENGTH (2 * gcmSIZEOF(gctUINT32))
#define gcdRESERVED_PAUSE_OQ_LENGTH (2 * gcmSIZEOF(gctUINT32))
#define gcdRESERVED_PAUSE_XFBWRITTEN_QUERY_LENGTH (4 * gcmSIZEOF(gctUINT32))
#define gcdRESERVED_PAUSE_PRIMGEN_QUERY_LENGTH (4 * gcmSIZEOF(gctUINT32))
#define gcdRESERVED_PAUSE_XFB_LENGTH (2 * gcmSIZEOF(gctUINT32))
#define gcdRESERVED_HW_FENCE_32BIT (4 * gcmSIZEOF(gctUINT32))
#define gcdRESERVED_HW_FENCE_64BIT (6 * gcmSIZEOF(gctUINT32))
#define gcdRESERVED_PAUSE_PROBE_LENGTH (TOTAL_PROBE_NUMBER * 2 * gcmSIZEOF(gctUINT32))
#define gcdRESUME_OQ_LENGTH (2 * gcmSIZEOF(gctUINT32))
#define gcdRESUME_XFBWRITTEN_QUERY_LENGTH (4 * gcmSIZEOF(gctUINT32))
#define gcdRESUME_PRIMGEN_QUERY_LENGTH (4 * gcmSIZEOF(gctUINT32))
#define gcdRESUME_XFB_LENGH (2 * gcmSIZEOF(gctUINT32))
#define gcdRESUME_PROBE_LENGH (TOTAL_PROBE_NUMBER * 2 * gcmSIZEOF(gctUINT32))
/* State delta record. */
typedef struct _gcsSTATE_DELTA_RECORD * gcsSTATE_DELTA_RECORD_PTR;
typedef struct _gcsSTATE_DELTA_RECORD
{
/* State address. */
gctUINT address;
/* State mask. */
gctUINT32 mask;
/* State data. */
gctUINT32 data;
}
gcsSTATE_DELTA_RECORD;
/* State delta. */
typedef struct _gcsSTATE_DELTA
{
/* For debugging: the number of delta in the order of creation. */
gctUINT num;
/* Main state delta ID. Every time state delta structure gets reinitialized,
main ID is incremented. If main state ID overflows, all map entry IDs get
reinitialized to make sure there is no potential erroneous match after
the overflow.*/
gctUINT id;
/* Vertex element count for the delta buffer. */
gctUINT elementCount;
/* Number of states currently stored in the record array. */
gctUINT recordCount;
/* Record array; holds all modified states in gcsSTATE_DELTA_RECORD. */
gctUINT64 recordArray;
gctUINT recordSize;
/* Map entry ID is used for map entry validation. If map entry ID does not
match the main state delta ID, the entry and the corresponding state are
considered not in use. */
gctUINT64 mapEntryID;
gctUINT mapEntryIDSize;
/* If the map entry ID matches the main state delta ID, index points to
the state record in the record array. */
gctUINT64 mapEntryIndex;
}
gcsSTATE_DELTA;
#define FENCE_NODE_LIST_INIT_COUNT 100
typedef struct _gcsFENCE_APPEND_NODE
{
gcsSURF_NODE_PTR node;
gceFENCE_TYPE type;
}gcsFENCE_APPEND_NODE;
typedef gcsFENCE_APPEND_NODE * gcsFENCE_APPEND_NODE_PTR;
typedef struct _gcsFENCE_LIST * gcsFENCE_LIST_PTR;
typedef struct _gcsFENCE_LIST
{
/* Resource that need get fence, but command used this resource not generated */
gcsFENCE_APPEND_NODE_PTR pendingList;
gctUINT pendingCount;
gctUINT pendingAllocCount;
/* Resoure that already generated command in this command buffer but not get fence */
gcsFENCE_APPEND_NODE_PTR onIssueList;
gctUINT onIssueCount;
gctUINT onIssueAllocCount;
}
gcsFENCE_LIST;
/* Command buffer object. */
/*
* Initial (before put commands):
*
* +-------------------------------------------
* ...|reservedHead|
* +-------------------------------------------
* ^ ^
* | |
* startOffset offset
*
*
* After put command, in commit:
*
* +------------------------------------------+
* .. |reservedHead| .. commands .. |reservedTail| ..
* +------------------------------------------+
* ^ ^
* | |
* startOffset offset
*
*
* Commit done, becomes initial state:
*
* +------------------------------------------+-----------------
* .. |reservedHead| .. commands .. |reservedTail|reservedHead| ..
* +------------------------------------------+-----------------
* ^ ^
* | |
* startOffset offset
*
* reservedHead:
* Select pipe commands.
*
* reservedTail:
* Link, Fence, ChipEnable
*
*/
struct _gcoCMDBUF
{
/* The object. */
gcsOBJECT object;
/* Commit count. */
gctUINT64 commitCount;
/* Command buffer entry and exit pipes. */
gcePIPE_SELECT entryPipe;
gcePIPE_SELECT exitPipe;
/* Feature usage flags. */
gctBOOL using2D;
gctBOOL using3D;
/* Size of reserved head and tail for each commit. */
gctUINT32 reservedHead;
gctUINT32 reservedTail;
/* Video memory handle of command buffer. */
gctUINT32 videoMemNode;
/* GPU address of command buffer. */
gctUINT32 address;
/* Logical address of command buffer. */
gctUINT64 logical;
/* Number of bytes in command buffer. */
gctUINT32 bytes;
/* Start offset into the command buffer. */
gctUINT32 startOffset;
/* Current offset into the command buffer. */
gctUINT32 offset;
/* Number of free bytes in command buffer. */
gctUINT32 free;
/* Location of the last reserved area. */
gctUINT64 lastReserve;
gctUINT32 lastOffset;
/* Last load state command location and hardware address. */
gctUINT64 lastLoadStatePtr;
gctUINT32 lastLoadStateAddress;
gctUINT32 lastLoadStateCount;
/*
* Put pointer type member after this line.
*/
/* Completion signal. */
gctSIGNAL signal;
/* Link to the siblings. */
gcoCMDBUF prev;
gcoCMDBUF next;
/* Mirror command buffer(s). */
gcoCMDBUF *mirrors;
gctUINT32 mirrorCount;
};
typedef struct _gcsQUEUE
{
/* Pointer to next gcsQUEUE structure in gcsQUEUE. */
gctUINT64 next;
/* Event information. */
gcsHAL_INTERFACE iface;
}
gcsQUEUE;
/* A record chunk include multiple records to save allocation. */
typedef struct _gcsQUEUE_CHUNK
{
struct _gcsQUEUE_CHUNK * next;
gcsQUEUE record[16];
}
gcsQUEUE_CHUNK;
/* Event queue. */
struct _gcoQUEUE
{
/* The object. */
gcsOBJECT object;
/* Pointer to current event queue. */
gcsQUEUE_PTR head;
gcsQUEUE_PTR tail;
/* List of free records. */
gcsQUEUE_PTR freeList;
/* chunks of the records. */
gcsQUEUE_CHUNK * chunks;
#define gcdIN_QUEUE_RECORD_LIMIT 16
/* Number of records currently in queue */
gctUINT32 recordCount;
/* Number of records which release resource currently in queue */
gctUINT32 tmpBufferRecordCount;
/* Max size of pending unlock node in vidmem pool not committed */
gctUINT maxUnlockBytes;
gceENGINE engine;
};
struct _gcsTEMPCMDBUF
{
gctUINT32 currentByteSize;
gctPOINTER buffer;
gctBOOL inUse;
};
#ifdef __cplusplus
}
#endif
#endif /* __gc_hal_kernel_buffer_h_ */

View File

@ -0,0 +1,566 @@
/****************************************************************************
*
* The MIT License (MIT)
*
* Copyright (c) 2014 - 2019 Vivante Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
*****************************************************************************
*
* The GPL License (GPL)
*
* Copyright (C) 2014 - 2019 Vivante Corporation
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*****************************************************************************
*
* Note: This software is released under dual MIT and GPL licenses. A
* recipient may use this file under the terms of either the MIT license or
* GPL License. If you wish to use only one license not the other, you can
* indicate your decision by deleting one of the above license notices in your
* version of this file.
*
*****************************************************************************/
/*
** Include file for the local memory management.
*/
#ifndef __gc_hal_mem_h_
#define __gc_hal_mem_h_
#if (gcdENABLE_3D || gcdENABLE_VG)
#ifdef __cplusplus
extern "C" {
#endif
/*******************************************************************************
** Usage:
The macros to declare MemPool type and functions are
gcmMEM_DeclareFSMemPool (Type, TypeName, Prefix)
gcmMEM_DeclareVSMemPool (Type, TypeName, Prefix)
gcmMEM_DeclareAFSMemPool(Type, TypeName, Prefix)
The data structures for MemPool are
typedef struct _gcsMEM_FS_MEM_POOL * gcsMEM_FS_MEM_POOL;
typedef struct _gcsMEM_VS_MEM_POOL * gcsMEM_VS_MEM_POOL;
typedef struct _gcsMEM_AFS_MEM_POOL * gcsMEM_AFS_MEM_POOL;
The MemPool constructor and destructor functions are
gcfMEM_InitFSMemPool(gcsMEM_FS_MEM_POOL *, gcoOS, gctUINT, gctUINT);
gcfMEM_FreeFSMemPool(gcsMEM_FS_MEM_POOL *);
gcfMEM_InitVSMemPool(gcsMEM_VS_MEM_POOL *, gcoOS, gctUINT, gctBOOL);
gcfMEM_FreeVSMemPool(gcsMEM_VS_MEM_POOL *);
gcfMEM_InitAFSMemPool(gcsMEM_AFS_MEM_POOL *, gcoOS, gctUINT);
gcfMEM_FreeAFSMemPool(gcsMEM_AFS_MEM_POOL *);
FS: for Fixed-Size data structures
VS: for Variable-size data structures
AFS: for Array of Fixed-Size data structures
// Example 1: For a fixed-size data structure, struct gcsNode.
// It is used locally in a file, so the functions are static without prefix.
// At top level, declear allocate and free functions.
// The first argument is the data type.
// The second armument is the short name used in the fuctions.
gcmMEM_DeclareFSMemPool(struct gcsNode, Node, );
// The previous macro creates two inline functions,
// _AllocateNode and _FreeNode.
// In function or struct
gcsMEM_FS_MEM_POOL nodeMemPool;
// In function,
struct gcsNode * node;
gceSTATUS status;
// Before using the memory pool, initialize it.
// The second argument is the gcoOS object.
// The third argument is the number of data structures to allocate for each chunk.
status = gcfMEM_InitFSMemPool(&nodeMemPool, os, 100, sizeof(struct gcsNode));
...
// Allocate a node.
status = _AllocateNode(nodeMemPool, &node);
...
// Free a node.
_FreeNode(nodeMemPool, node);
// After using the memory pool, free it.
gcfMEM_FreeFSMemPool(&nodeMemPool);
// Example 2: For array of fixed-size data structures, struct gcsNode.
// It is used in several files, so the functions are extern with prefix.
// At top level, declear allocate and free functions.
// The first argument is the data type, and the second one is the short name
// used in the fuctions.
gcmMEM_DeclareAFSMemPool(struct gcsNode, NodeArray, gcfOpt);
// The previous macro creates two inline functions,
// gcfOpt_AllocateNodeArray and gcfOpt_FreeNodeArray.
// In function or struct
gcsMEM_AFS_MEM_POOL nodeArrayMemPool;
// In function,
struct gcsNode * nodeArray;
gceSTATUS status;
// Before using the array memory pool, initialize it.
// The second argument is the gcoOS object, the third is the number of data
// structures to allocate for each chunk.
status = gcfMEM_InitAFSMemPool(&nodeArrayMemPool, os, sizeof(struct gcsNode));
...
// Allocate a node array of size 100.
status = gcfOpt_AllocateNodeArray(nodeArrayMemPool, &nodeArray, 100);
...
// Free a node array.
gcfOpt_FreeNodeArray(&nodeArrayMemPool, nodeArray);
// After using the array memory pool, free it.
gcfMEM_FreeAFSMemPool(&nodeArrayMemPool);
*******************************************************************************/
/*******************************************************************************
** To switch back to use gcoOS_Allocate and gcoOS_Free, add
** #define USE_LOCAL_MEMORY_POOL 0
** before including this file.
*******************************************************************************/
#ifndef USE_LOCAL_MEMORY_POOL
/*
USE_LOCAL_MEMORY_POOL
This define enables the local memory management to improve performance.
*/
#define USE_LOCAL_MEMORY_POOL 1
#endif
/*******************************************************************************
** Memory Pool Data Structures
*******************************************************************************/
#if USE_LOCAL_MEMORY_POOL
typedef struct _gcsMEM_FS_MEM_POOL * gcsMEM_FS_MEM_POOL;
typedef struct _gcsMEM_VS_MEM_POOL * gcsMEM_VS_MEM_POOL;
typedef struct _gcsMEM_AFS_MEM_POOL * gcsMEM_AFS_MEM_POOL;
#else
typedef gcoOS gcsMEM_FS_MEM_POOL;
typedef gcoOS gcsMEM_VS_MEM_POOL;
typedef gcoOS gcsMEM_AFS_MEM_POOL;
#endif
/*******************************************************************************
** Memory Pool Macros
*******************************************************************************/
#if USE_LOCAL_MEMORY_POOL
#define gcmMEM_DeclareFSMemPool(Type, TypeName, Prefix) \
gceSTATUS \
Prefix##_Allocate##TypeName(\
gcsMEM_FS_MEM_POOL MemPool, \
Type ** Pointer \
) \
{ \
return(gcfMEM_FSMemPoolGetANode(MemPool, (gctPOINTER *) Pointer)); \
} \
\
gceSTATUS \
Prefix##_CAllocate##TypeName(\
gcsMEM_FS_MEM_POOL MemPool, \
Type ** Pointer \
) \
{ \
gceSTATUS status; \
gcmHEADER_ARG("MemPool=0x%x Pointer=0x%x", MemPool, Pointer); \
gcmERR_RETURN(gcfMEM_FSMemPoolGetANode(MemPool, (gctPOINTER *) Pointer)); \
gcoOS_ZeroMemory(*(gctPOINTER *) Pointer, gcmSIZEOF(Type)); \
gcmFOOTER(); \
return gcvSTATUS_OK; \
} \
\
gceSTATUS \
Prefix##_Free##TypeName(\
gcsMEM_FS_MEM_POOL MemPool, \
Type * Pointer \
) \
{ \
gceSTATUS status; \
gcmHEADER_ARG("MemPool=0x%x Pointer=0x%x", MemPool, Pointer); \
status = gcfMEM_FSMemPoolFreeANode(MemPool, (gctPOINTER) Pointer); \
gcmFOOTER(); \
return status; \
} \
\
gceSTATUS \
Prefix##_Free##TypeName##List(\
gcsMEM_FS_MEM_POOL MemPool, \
Type * FirstPointer, \
Type * LastPointer \
) \
{ \
gceSTATUS status; \
gcmHEADER_ARG("MemPool=0x%x FirstPointer=0x%x LastPointer=0x%x", MemPool, FirstPointer, LastPointer); \
status = gcfMEM_FSMemPoolFreeAList(MemPool, (gctPOINTER) FirstPointer, (gctPOINTER) LastPointer); \
gcmFOOTER(); \
return status; \
}
#define gcmMEM_DeclareVSMemPool(Type, TypeName, Prefix) \
gceSTATUS \
Prefix##_Allocate##TypeName(\
gcsMEM_FS_MEM_POOL MemPool, \
Type ** Pointer, \
gctUINT Size \
) \
{ \
gceSTATUS status;\
gcmHEADER_ARG("MemPool=0x%x Pointer=0x%x Size=%u", MemPool, Pointer, Size); \
status = gcfMEM_VSMemPoolGetANode(MemPool, Size, (gctPOINTER *) Pointer); \
gcmFOOTER(); \
return status; \
} \
\
gceSTATUS \
Prefix##_CAllocate##TypeName(\
gcsMEM_FS_MEM_POOL MemPool, \
Type ** Pointer, \
gctUINT Size \
) \
{ \
gceSTATUS status; \
gcmHEADER_ARG("MemPool=0x%x Pointer=0x%x Size=%u", MemPool, Pointer, Size); \
gcmERR_RETURN(gcfMEM_VSMemPoolGetANode(MemPool, Size, (gctPOINTER *) Pointer)); \
gcoOS_ZeroMemory(*(gctPOINTER *) Pointer, size); \
gcmFOOTER(); \
return gcvSTATUS_OK; \
} \
\
gceSTATUS \
Prefix##_Free##TypeName(\
gcsMEM_FS_MEM_POOL MemPool, \
Type * Pointer \
) \
{ \
gceSTATUS status; \
gcmHEADER_ARG("MemPool=0x%x Pointer=0x%x", MemPool, Pinter); \
status = gcfMEM_VSMemPoolFreeANode(MemPool, (gctPOINTER) Pointer); \
gcmFOOTER(); \
return status; \
}
#define gcmMEM_DeclareAFSMemPool(Type, TypeName, Prefix) \
gceSTATUS \
Prefix##_Allocate##TypeName(\
gcsMEM_AFS_MEM_POOL MemPool, \
Type ** Pointer, \
gctUINT Count \
) \
{ \
gceSTATUS status; \
gcmHEADER_ARG("MemPool=0x%x Pointer=0x%x Count=%u", MemPool, Pointer, Count); \
status = gcfMEM_AFSMemPoolGetANode(MemPool, Count, (gctPOINTER *) Pointer); \
gcmFOOTER(); \
return status; \
} \
\
gceSTATUS \
Prefix##_CAllocate##TypeName(\
gcsMEM_AFS_MEM_POOL MemPool, \
Type ** Pointer, \
gctUINT Count \
) \
{ \
gceSTATUS status; \
gcmHEADER_ARG("MemPool=0x%x Pointer=0x%x Count=%u", MemPool, Pointer, Count); \
gcmERR_RETURN(gcfMEM_AFSMemPoolGetANode(MemPool, Count, (gctPOINTER *) Pointer)); \
gcoOS_ZeroMemory(*(gctPOINTER *) Pointer, Count * gcmSIZEOF(Type)); \
gcmFOOTER(); \
return gcvSTATUS_OK; \
} \
\
gceSTATUS \
Prefix##_Free##TypeName(\
gcsMEM_AFS_MEM_POOL MemPool, \
Type * Pointer \
) \
{ \
gceSTATUS status; \
gcmHEADER_ARG("MemPool=0x%x Pointer=0x%x", MemPool, Pointer); \
status = gcfMEM_AFSMemPoolFreeANode(MemPool, (gctPOINTER) Pointer); \
gcmFOOTER(); \
return status; \
}
#else
#define gcmMEM_DeclareFSMemPool(Type, TypeName, Prefix) \
gceSTATUS \
Prefix##_Allocate##TypeName(\
gcsMEM_FS_MEM_POOL MemPool, \
Type ** Pointer \
) \
{ \
gceSTATUS status; \
gcmHEADER_ARG("MemPool=0x%x Pointer=0x%x", MemPool, Pointer); \
status = gcoOS_Allocate(MemPool, \
gcmSIZEOF(Type), \
(gctPOINTER *) Pointer); \
gcmFOOTER(); \
return status; \
} \
\
gceSTATUS \
Prefix##_CAllocate##TypeName(\
gcsMEM_FS_MEM_POOL MemPool, \
Type ** Pointer \
) \
{ \
gceSTATUS status; \
gcmHEADER_ARG("MemPool=0x%x Pointer=0x%x", MemPool, Pointer); \
gcmERR_RETURN(gcoOS_Allocate(MemPool, \
gcmSIZEOF(Type), \
(gctPOINTER *) Pointer)); \
gcoOS_ZeroMemory(*(gctPOINTER *) Pointer, gcmSIZEOF(Type)); \
gcmFOOTER(); \
return gcvSTATUS_OK; \
} \
\
gceSTATUS \
Prefix##_Free##TypeName(\
gcsMEM_FS_MEM_POOL MemPool, \
Type * Pointer \
) \
{ \
gceSTATUS status; \
gcmHEADER_ARG("MemPool=0x%x Pointer=0x%x", MemPool, Pointer); \
status = gcmOS_SAFE_FREE(MemPool, Pointer); \
gcmFOOTER(); \
return status; \
}
#define gcmMEM_DeclareVSMemPool(Type, TypeName, Prefix) \
gceSTATUS \
Prefix##_Allocate##TypeName(\
gcsMEM_VS_MEM_POOL MemPool, \
Type ** Pointer, \
gctUINT Size \
) \
{ \
gceSTATUS status; \
gcmHEADER_ARG("MemPool=0x%x Pointer=0x%x Size=%u", MemPool, Pointer, Size); \
status = gcoOS_Allocate(MemPool, \
Size, \
(gctPOINTER *) Pointer); \
gcmFOOTER(); \
return status; \
} \
\
gceSTATUS \
Prefix##_CAllocate##TypeName(\
gcsMEM_VS_MEM_POOL MemPool, \
Type ** Pointer, \
gctUINT Size \
) \
{ \
gceSTATUS status; \
gcmHEADER_ARG("MemPool=0x%x Pointer=0x%x Size=%u", MemPool, Pointer, Size); \
gcmERR_RETURN(gcoOS_Allocate(MemPool, \
Size, \
(gctPOINTER *) Pointer)); \
gcoOS_ZeroMemory(*(gctPOINTER *) Pointer, Size); \
gcmFOOTER(); \
return gcvSTATUS_OK; \
} \
\
gceSTATUS \
Prefix##_Free##TypeName(\
gcsMEM_VS_MEM_POOL MemPool, \
Type * Pointer \
) \
{ \
gceSTATUS status; \
gcmHEADER_ARG("MemPool=0x%x Pointer=0x%x", MemPool, Pointer); \
status = gcmOS_SAFE_FREE(MemPool, Pointer); \
gcmFOOTER(); \
return status; \
}
#define gcmMEM_DeclareAFSMemPool(Type, TypeName, Prefix) \
gceSTATUS \
Prefix##_Allocate##TypeName(\
gcsMEM_AFS_MEM_POOL MemPool, \
Type ** Pointer, \
gctUINT Count \
) \
{ \
gceSTATUS status; \
gcmHEADER_ARG("MemPool=0x%x Pointer=0x%x Count=%u", MemPool, Pointer, Count); \
status = gcoOS_Allocate(MemPool, \
Count * gcmSIZEOF(Type), \
(gctPOINTER *) Pointer); \
gcmFOOTER(); \
return status; \
} \
\
gceSTATUS \
Prefix##_CAllocate##TypeName(\
gcsMEM_AFS_MEM_POOL MemPool, \
Type ** Pointer, \
gctUINT Count \
) \
{ \
gceSTATUS status; \
gcmHEADER_ARG("MemPool=0x%x Pointer=0x%x Count=%u", MemPool, Pointer, Count); \
gcmERR_RETURN(gcoOS_Allocate(MemPool, \
Count * gcmSIZEOF(Type), \
(gctPOINTER *) Pointer)); \
gcoOS_ZeroMemory(*(gctPOINTER *) Pointer, Count * gcmSIZEOF(Type)); \
gcmFOOTER(); \
return gcvSTATUS_OK; \
} \
\
gceSTATUS \
Prefix##_Free##TypeName(\
gcsMEM_AFS_MEM_POOL MemPool, \
Type * Pointer \
) \
{ \
gceSTATUS status; \
gcmHEADER_ARG("MemPool=0x%x Pointer=0x%x", MemPool, Pointer); \
status = gcmOS_SAFE_FREE(MemPool, Pointer); \
gcmFOOTER(); \
return status; \
}
#endif
/*******************************************************************************
** Memory Pool Data Functions
*******************************************************************************/
gceSTATUS
gcfMEM_InitFSMemPool(
IN gcsMEM_FS_MEM_POOL * MemPool,
IN gcoOS OS,
IN gctUINT NodeCount,
IN gctUINT NodeSize
);
gceSTATUS
gcfMEM_FreeFSMemPool(
IN gcsMEM_FS_MEM_POOL * MemPool
);
gceSTATUS
gcfMEM_FSMemPoolGetANode(
IN gcsMEM_FS_MEM_POOL MemPool,
OUT gctPOINTER * Node
);
gceSTATUS
gcfMEM_FSMemPoolFreeANode(
IN gcsMEM_FS_MEM_POOL MemPool,
IN gctPOINTER Node
);
gceSTATUS
gcfMEM_FSMemPoolFreeAList(
IN gcsMEM_FS_MEM_POOL MemPool,
IN gctPOINTER FirstNode,
IN gctPOINTER LastNode
);
gceSTATUS
gcfMEM_InitVSMemPool(
IN gcsMEM_VS_MEM_POOL * MemPool,
IN gcoOS OS,
IN gctUINT BlockSize,
IN gctBOOL RecycleFreeNode
);
gceSTATUS
gcfMEM_FreeVSMemPool(
IN gcsMEM_VS_MEM_POOL * MemPool
);
gceSTATUS
gcfMEM_VSMemPoolGetANode(
IN gcsMEM_VS_MEM_POOL MemPool,
IN gctUINT Size,
IN gctUINT Alignment,
OUT gctPOINTER * Node
);
gceSTATUS
gcfMEM_VSMemPoolFreeANode(
IN gcsMEM_VS_MEM_POOL MemPool,
IN gctPOINTER Node
);
gceSTATUS
gcfMEM_InitAFSMemPool(
IN gcsMEM_AFS_MEM_POOL *MemPool,
IN gcoOS OS,
IN gctUINT NodeCount,
IN gctUINT NodeSize
);
gceSTATUS
gcfMEM_FreeAFSMemPool(
IN gcsMEM_AFS_MEM_POOL *MemPool
);
gceSTATUS
gcfMEM_AFSMemPoolGetANode(
IN gcsMEM_AFS_MEM_POOL MemPool,
IN gctUINT Count,
OUT gctPOINTER * Node
);
gceSTATUS
gcfMEM_AFSMemPoolFreeANode(
IN gcsMEM_AFS_MEM_POOL MemPool,
IN gctPOINTER Node
);
#ifdef __cplusplus
}
#endif
#endif /* (gcdENABLE_3D || gcdENABLE_VG) */
#endif /* __gc_hal_mem_h_ */

View File

@ -0,0 +1,121 @@
/****************************************************************************
*
* The MIT License (MIT)
*
* Copyright (c) 2014 - 2019 Vivante Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
*****************************************************************************
*
* The GPL License (GPL)
*
* Copyright (C) 2014 - 2019 Vivante Corporation
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*****************************************************************************
*
* Note: This software is released under dual MIT and GPL licenses. A
* recipient may use this file under the terms of either the MIT license or
* GPL License. If you wish to use only one license not the other, you can
* indicate your decision by deleting one of the above license notices in your
* version of this file.
*
*****************************************************************************/
#ifndef __gc_hal_kernel_metadata_h_
#define __gc_hal_kernel_metadata_h_
#ifdef __cplusplus
extern "C" {
#endif
/* Macro to combine four characters into a Character Code. */
#define __FOURCC(a, b, c, d) \
((uint32_t)(a) | ((uint32_t)(b) << 8) | ((uint32_t)(c) << 16) | ((uint32_t)(d) << 24))
#define VIV_VIDMEM_METADATA_MAGIC __FOURCC('v', 'i', 'v', 'm')
/* Compressed format now was defined same as dec400d, should be general. */
typedef enum _VIV_COMPRESS_FMT
{
_VIV_CFMT_ARGB8 = 0,
_VIV_CFMT_XRGB8,
_VIV_CFMT_AYUV,
_VIV_CFMT_UYVY,
_VIV_CFMT_YUY2,
_VIV_CFMT_YUV_ONLY,
_VIV_CFMT_UV_MIX,
_VIV_CFMT_ARGB4,
_VIV_CFMT_XRGB4,
_VIV_CFMT_A1R5G5B5,
_VIV_CFMT_X1R5G5B5,
_VIV_CFMT_R5G6B5,
_VIV_CFMT_Z24S8,
_VIV_CFMT_Z24,
_VIV_CFMT_Z16,
_VIV_CFMT_A2R10G10B10,
_VIV_CFMT_BAYER,
_VIV_CFMT_SIGNED_BAYER,
_VIV_CFMT_VAA16,
_VIV_CFMT_S8,
_VIV_CFMT_MAX,
} _VIV_COMPRESS_FMT;
/* Metadata for cross-device fd share with additional (ts) info. */
typedef struct _VIV_VIDMEM_METADATA
{
uint32_t magic;
int32_t ts_fd;
void * ts_dma_buf;
#ifdef gcdANDROID
dma_addr_t ts_address;
#endif
uint32_t fc_enabled;
uint32_t fc_value;
uint32_t fc_value_upper;
uint32_t compressed;
uint32_t compress_format;
} _VIV_VIDMEM_METADATA;
#ifdef __cplusplus
}
#endif
#endif /* __gc_hal_kernel_metadata_h_ */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,186 @@
/****************************************************************************
*
* The MIT License (MIT)
*
* Copyright (c) 2014 - 2019 Vivante Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
*****************************************************************************
*
* The GPL License (GPL)
*
* Copyright (C) 2014 - 2019 Vivante Corporation
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*****************************************************************************
*
* Note: This software is released under dual MIT and GPL licenses. A
* recipient may use this file under the terms of either the MIT license or
* GPL License. If you wish to use only one license not the other, you can
* indicate your decision by deleting one of the above license notices in your
* version of this file.
*
*****************************************************************************/
#ifndef _GC_HAL_SECURITY_INTERFACE_H_
#define _GC_HAL_SECURITY_INTERFACE_H_
/*!
@brief Command codes between kernel module and TrustZone
@discussion
Critical services must be done in TrustZone to avoid sensitive content leak. Most of kernel module is kept in non-Secure os to minimize
code in TrustZone.
*/
typedef enum kernel_packet_command {
KERNEL_START_COMMAND,
KERNEL_SUBMIT,
KERNEL_MAP_MEMORY, /* */
KERNEL_UNMAP_MEMORY,
KERNEL_ALLOCATE_SECRUE_MEMORY, /*! Security memory management. */
KERNEL_FREE_SECURE_MEMORY,
KERNEL_EXECUTE, /* Execute a command buffer. */
KERNEL_DUMP_MMU_EXCEPTION,
KERNEL_HANDLE_MMU_EXCEPTION,
KERNEL_READ_MMU_EXCEPTION,
} kernel_packet_command_t;
struct kernel_start_command {
kernel_packet_command_t command; /*! The command (always needs to be the first entry in a structure). */
gctUINT8 gpu; /*! Which GPU. */
gctUINT32 address;
gctUINT32 bytes;
};
/*!
@brief gckCOMMAND Object requests TrustZone to submit command buffer.
@discussion
Code in trustzone will check content of command buffer after copying command buffer to TrustZone.
*/
struct kernel_submit {
kernel_packet_command_t command; /*! The command (always needs to be the first entry in a structure). */
gctUINT8 gpu; /*! Which GPU. */
gctUINT8 kernel_command; /*! Whether it is a kernel command. */
gctUINT32 command_buffer_handle; /*! Handle to command buffer. */
gctUINT32 offset; /* Offset in command buffer. */
gctUINT32 * command_buffer; /*! Content of command buffer need to be submit. */
gctUINT32 command_buffer_length; /*! Length of command buffer. */
};
/*!
@brief gckVIDMEM Object requests TrustZone to allocate security memory.
@discussion
Allocate a buffer from security GPU memory.
*/
struct kernel_allocate_security_memory {
kernel_packet_command_t command; /*! The command (always needs to be the first entry in a structure). */
gctUINT32 bytes; /*! Requested bytes. */
gctUINT32 memory_handle; /*! Handle of allocated memory. */
};
/*!
@brief gckVIDMEM Object requests TrustZone to allocate security memory.
@discussion
Free a video memory buffer from security GPU memory.
*/
struct kernel_free_security_memory {
kernel_packet_command_t command; /*! The command (always needs to be the first entry in a structure). */
gctUINT32 memory_handle; /*! Handle of allocated memory. */
};
struct kernel_execute {
kernel_packet_command_t command; /*! The command (always needs to be the first entry in a structure). */
gctUINT8 gpu; /*! Which GPU. */
gctUINT8 kernel_command; /*! Whether it is a kernel command. */
gctUINT32 * command_buffer; /*! Content of command buffer need to be submit. */
gctUINT32 command_buffer_length; /*! Length of command buffer. */
};
typedef struct kernel_map_scatter_gather {
gctUINT32 bytes;
gctUINT32 physical;
struct kernel_map_scatter_gather *next;
}
kernel_map_scatter_gather_t;
struct kernel_map_memory {
kernel_packet_command_t command;
kernel_map_scatter_gather_t *scatter;
gctUINT32 *physicals;
gctPHYS_ADDR_T physical; /*! Contiguous physical address range. */
gctUINT32 pageCount;
gctUINT32 gpuAddress;
};
struct kernel_unmap_memory {
gctUINT32 gpuAddress;
gctUINT32 pageCount;
};
struct kernel_read_mmu_exception {
gctUINT32 mmuStatus;
gctUINT32 mmuException;
};
struct kernel_handle_mmu_exception {
gctUINT32 mmuStatus;
gctPHYS_ADDR_T physical;
gctUINT32 gpuAddress;
};
typedef struct _gcsTA_INTERFACE {
kernel_packet_command_t command;
union {
struct kernel_submit Submit;
struct kernel_start_command StartCommand;
struct kernel_allocate_security_memory AllocateSecurityMemory;
struct kernel_execute Execute;
struct kernel_map_memory MapMemory;
struct kernel_unmap_memory UnmapMemory;
struct kernel_read_mmu_exception ReadMMUException;
struct kernel_handle_mmu_exception HandleMMUException;
} u;
gceSTATUS result;
} gcsTA_INTERFACE;
enum {
gcvTA_COMMAND_INIT,
gcvTA_COMMAND_DISPATCH,
gcvTA_CALLBACK_ALLOC_SECURE_MEM,
gcvTA_CALLBACK_FREE_SECURE_MEM,
};
#endif

View File

@ -0,0 +1,135 @@
/****************************************************************************
*
* The MIT License (MIT)
*
* Copyright (c) 2014 - 2019 Vivante Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
*****************************************************************************
*
* The GPL License (GPL)
*
* Copyright (C) 2014 - 2019 Vivante Corporation
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*****************************************************************************
*
* Note: This software is released under dual MIT and GPL licenses. A
* recipient may use this file under the terms of either the MIT license or
* GPL License. If you wish to use only one license not the other, you can
* indicate your decision by deleting one of the above license notices in your
* version of this file.
*
*****************************************************************************/
#ifndef __gc_hal_statistics_h_
#define __gc_hal_statistics_h_
#define VIV_STAT_ENABLE_STATISTICS 0
/* Toal number of frames for which the frame time is accounted. We have storage
to keep frame times for last this many frames.
*/
#define VIV_STAT_FRAME_BUFFER_SIZE 30
/*
Total number of frames sampled for a mode. This means
# of frames for HZ Current : VIV_STAT_EARLY_Z_SAMPLE_FRAMES
# of frames for HZ Switched : VIV_STAT_EARLY_Z_SAMPLE_FRAMES
+
--------------------------------------------------------
: (2 * VIV_STAT_EARLY_Z_SAMPLE_FRAMES) frames needed
IMPORTANT: This total must be smaller than VIV_STAT_FRAME_BUFFER_SIZE
*/
#define VIV_STAT_EARLY_Z_SAMPLE_FRAMES 7
#define VIV_STAT_EARLY_Z_LATENCY_FRAMES 2
/* Multiplication factor for previous Hz off mode. Make it more than 1.0 to advertise HZ on.*/
#define VIV_STAT_EARLY_Z_FACTOR (1.05f)
/* Defines the statistical data keys monitored by the statistics module */
typedef enum _gceSTATISTICS
{
gcvFRAME_FPS = 1,
}
gceSTATISTICS;
/* HAL statistics information. */
typedef struct _gcsSTATISTICS_EARLYZ
{
gctUINT switchBackCount;
gctUINT nextCheckPoint;
gctBOOL disabled;
}
gcsSTATISTICS_EARLYZ;
/* HAL statistics information. */
typedef struct _gcsSTATISTICS
{
gctUINT64 frameTime[VIV_STAT_FRAME_BUFFER_SIZE];
gctUINT64 previousFrameTime;
gctUINT frame;
gcsSTATISTICS_EARLYZ earlyZ;
}
gcsSTATISTICS;
/* Add a frame based data into current statistics. */
void
gcfSTATISTICS_AddData(
IN gceSTATISTICS Key,
IN gctUINT Value
);
/* Marks the frame end and triggers statistical calculations and decisions.*/
void
gcfSTATISTICS_MarkFrameEnd (
void
);
/* Sets whether the dynmaic HZ is disabled or not .*/
void
gcfSTATISTICS_DisableDynamicEarlyZ (
IN gctBOOL Disabled
);
#endif /*__gc_hal_statistics_h_ */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,71 @@
/****************************************************************************
*
* The MIT License (MIT)
*
* Copyright (c) 2014 - 2019 Vivante Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
*****************************************************************************
*
* The GPL License (GPL)
*
* Copyright (C) 2014 - 2019 Vivante Corporation
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*****************************************************************************
*
* Note: This software is released under dual MIT and GPL licenses. A
* recipient may use this file under the terms of either the MIT license or
* GPL License. If you wish to use only one license not the other, you can
* indicate your decision by deleting one of the above license notices in your
* version of this file.
*
*****************************************************************************/
#ifndef __gc_hal_version_h_
#define __gc_hal_version_h_
#define gcvVERSION_MAJOR 6
#define gcvVERSION_MINOR 4
#define gcvVERSION_PATCH 0
#define gcvVERSION_BUILD 234062
#define gcvVERSION_STRING "6.4.0.p2.234062"
#endif /* __gc_hal_version_h_ */

View File

@ -0,0 +1,886 @@
/****************************************************************************
*
* The MIT License (MIT)
*
* Copyright (c) 2014 - 2019 Vivante Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
*****************************************************************************
*
* The GPL License (GPL)
*
* Copyright (C) 2014 - 2019 Vivante Corporation
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*****************************************************************************
*
* Note: This software is released under dual MIT and GPL licenses. A
* recipient may use this file under the terms of either the MIT license or
* GPL License. If you wish to use only one license not the other, you can
* indicate your decision by deleting one of the above license notices in your
* version of this file.
*
*****************************************************************************/
#ifndef __gc_hal_vg_h_
#define __gc_hal_vg_h_
#ifdef __cplusplus
extern "C" {
#endif
#include "gc_hal_types.h"
#include "gc_hal_enum.h"
#include "gc_hal_base.h"
#if gcdENABLE_VG
/* Thread routine type. */
#if defined(LINUX)
typedef gctINT gctTHREADFUNCRESULT;
typedef gctPOINTER gctTHREADFUNCPARAMETER;
# define gctTHREADFUNCTYPE
#elif defined(WIN32)
typedef gctUINT gctTHREADFUNCRESULT;
typedef gctPOINTER gctTHREADFUNCPARAMETER;
# define gctTHREADFUNCTYPE __stdcall
#elif defined(__QNXNTO__)
typedef void * gctTHREADFUNCRESULT;
typedef gctPOINTER gctTHREADFUNCPARAMETER;
# define gctTHREADFUNCTYPE
#endif
typedef gctTHREADFUNCRESULT (gctTHREADFUNCTYPE * gctTHREADFUNC) (
gctTHREADFUNCPARAMETER ThreadParameter
);
#if defined(gcvDEBUG)
# undef gcvDEBUG
#endif
#define gcdFORCE_DEBUG 0
#define gcdFORCE_MESSAGES 0
#if DBG || defined(DEBUG) || defined(_DEBUG) || gcdFORCE_DEBUG
# define gcvDEBUG 1
#else
# define gcvDEBUG 0
#endif
#define _gcmERROR_RETURN(prefix, func) \
status = func; \
if (gcmIS_ERROR(status)) \
{ \
prefix##PRINT_VERSION(); \
prefix##TRACE(gcvLEVEL_ERROR, \
#prefix "ERR_RETURN: status=%d(%s) @ %s(%d)", \
status, gcoOS_DebugStatus2Name(status), __FUNCTION__, __LINE__); \
return status; \
} \
do { } while (gcvFALSE)
#define gcmERROR_RETURN(func) _gcmERROR_RETURN(gcm, func)
#define gcmLOG_LOCATION()
#define gcmkIS_ERROR(status) (status < 0)
#define gcmALIGNDOWN(n, align) \
(\
(n) & ~((align) - 1) \
)
#define gcmIS_VALID_INDEX(Index, Array) \
(((gctUINT) (Index)) < gcmCOUNTOF(Array))
#define gcmIS_NAN(x) \
(\
((* (gctUINT32_PTR) &(x)) & 0x7FFFFFFF) == 0x7FFFFFFF \
)
#define gcmLERP(v1, v2, w) \
((v1) * (w) + (v2) * (1.0f - (w)))
#define gcmINTERSECT(Start1, Start2, Length) \
(gcmABS((Start1) - (Start2)) < (Length))
/*******************************************************************************
**
** gcmERR_GOTO
**
** Prints a message and terminates the current loop on error.
**
** ASSUMPTIONS:
**
** 'status' variable of gceSTATUS type must be defined.
**
** ARGUMENTS:
**
** Function
** Function to evaluate.
*/
#define gcmERR_GOTO(Function) \
status = Function; \
if (gcmIS_ERROR(status)) \
{ \
gcmTRACE(\
gcvLEVEL_ERROR, \
"gcmERR_GOTO: status=%d @ line=%d in function %s.\n", \
status, __LINE__, __FUNCTION__ \
); \
goto ErrorHandler; \
}
#if gcvDEBUG || gcdFORCE_MESSAGES
# define gcmVERIFY_BOOLEAN(Expression) \
gcmASSERT(\
((Expression) == gcvFALSE ) || \
((Expression) == gcvTRUE ) \
)
#else
# define gcmVERIFY_BOOLEAN(Expression)
#endif
/*******************************************************************************
**
** gcmVERIFYFIELDFIT
**
** Verify whether the value fits in the field.
**
** ARGUMENTS:
**
** data Data value.
** reg Name of register.
** field Name of field within register.
** value Value for field.
*/
#define gcmVERIFYFIELDFIT(reg, field, value) \
gcmASSERT(\
(value) <= gcmFIELDMAX(reg, field) \
)
/*******************************************************************************
**
** gcmFIELDMAX
**
** Get field maximum value.
**
** ARGUMENTS:
**
** reg Name of register.
** field Name of field within register.
*/
#define gcmFIELDMAX(reg, field) \
(\
(gctUINT32) \
(\
(__gcmGETSIZE(reg##_##field) == 32) \
? ~0U \
: (~(~0U << __gcmGETSIZE(reg##_##field))) \
) \
)
/* ANSI C does not have the 'f' functions, define replacements here. */
#define gcmSINF(x) ((gctFLOAT) sin(x))
#define gcmCOSF(x) ((gctFLOAT) cos(x))
#define gcmASINF(x) ((gctFLOAT) asin(x))
#define gcmACOSF(x) ((gctFLOAT) acos(x))
#define gcmSQRTF(x) ((gctFLOAT) sqrt(x))
#define gcmFABSF(x) ((gctFLOAT) fabs(x))
#define gcmFMODF(x, y) ((gctFLOAT) fmod((x), (y)))
#define gcmCEILF(x) ((gctFLOAT) ceil(x))
#define gcmFLOORF(x) ((gctFLOAT) floor(x))
/* Fixed point constants. */
#define gcvZERO_X ((gctFIXED_POINT) 0x00000000)
#define gcvHALF_X ((gctFIXED_POINT) 0x00008000)
#define gcvONE_X ((gctFIXED_POINT) 0x00010000)
#define gcvNEGONE_X ((gctFIXED_POINT) 0xFFFF0000)
#define gcvTWO_X ((gctFIXED_POINT) 0x00020000)
/* Integer constants. */
#define gcvMAX_POS_INT ((gctINT) 0x7FFFFFFF)
#define gcvMAX_NEG_INT ((gctINT) 0x80000000)
/* Float constants. */
#define gcvMAX_POS_FLOAT ((gctFLOAT) 3.4028235e+038)
#define gcvMAX_NEG_FLOAT ((gctFLOAT) -3.4028235e+038)
/******************************************************************************\
***************************** Miscellaneous Macro ******************************
\******************************************************************************/
#define gcmKB2BYTES(Kilobyte) \
(\
(Kilobyte) << 10 \
)
#define gcmMB2BYTES(Megabyte) \
(\
(Megabyte) << 20 \
)
#define gcmMAT(Matrix, Row, Column) \
(\
(Matrix) [(Row) * 3 + (Column)] \
)
#define gcmMAKE2CHAR(Char1, Char2) \
(\
((gctUINT16) (gctUINT8) (Char1) << 0) | \
((gctUINT16) (gctUINT8) (Char2) << 8) \
)
#define gcmMAKE4CHAR(Char1, Char2, Char3, Char4) \
(\
((gctUINT32)(gctUINT8) (Char1) << 0) | \
((gctUINT32)(gctUINT8) (Char2) << 8) | \
((gctUINT32)(gctUINT8) (Char3) << 16) | \
((gctUINT32)(gctUINT8) (Char4) << 24) \
)
/* some platforms need to fix the physical address for HW to access*/
#define gcmFIXADDRESS(address) \
(\
(address)\
)
#define gcmkFIXADDRESS(address) \
(\
(address)\
)
/*----------------------------------------------------------------------------*/
/*----------------------------- Semaphore Object -----------------------------*/
/* Increment the value of a semaphore. */
gceSTATUS
gckOS_IncrementSemaphore(
IN gckOS Os,
IN gctSEMAPHORE Semaphore
);
/* Decrement the value of a semaphore (waiting might occur). */
gceSTATUS
gckOS_DecrementSemaphore(
IN gckOS Os,
IN gctSEMAPHORE Semaphore
);
/*----------------------------------------------------------------------------*/
/*------------------------------- Thread Object ------------------------------*/
/* Start a thread. */
gceSTATUS
gckOS_StartThread(
IN gckOS Os,
IN gctTHREADFUNC ThreadFunction,
IN gctPOINTER ThreadParameter,
OUT gctTHREAD * Thread
);
/* Stop a thread. */
gceSTATUS
gckOS_StopThread(
IN gckOS Os,
IN gctTHREAD Thread
);
/* Verify whether the thread is still running. */
gceSTATUS
gckOS_VerifyThread(
IN gckOS Os,
IN gctTHREAD Thread
);
/* Construct a new gckVGKERNEL object. */
gceSTATUS
gckVGKERNEL_Construct(
IN gckOS Os,
IN gctPOINTER Context,
IN gckKERNEL inKernel,
OUT gckVGKERNEL * Kernel
);
/* Destroy an gckVGKERNEL object. */
gceSTATUS
gckVGKERNEL_Destroy(
IN gckVGKERNEL Kernel
);
/* Unmap memory. */
gceSTATUS
gckKERNEL_UnmapMemory(
IN gckKERNEL Kernel,
IN gctPHYS_ADDR Physical,
IN gctSIZE_T Bytes,
IN gctPOINTER Logical,
IN gctUINT32 ProcessID
);
/* Dispatch a user-level command. */
gceSTATUS
gckVGKERNEL_Dispatch(
IN gckKERNEL Kernel,
IN OUT struct _gcsHAL_INTERFACE * Interface
);
/* Query command buffer requirements. */
gceSTATUS
gckKERNEL_QueryCommandBuffer(
IN gckKERNEL Kernel,
OUT gcsCOMMAND_BUFFER_INFO_PTR Information
);
/******************************************************************************\
******************************* gckVGHARDWARE Object ******************************
\******************************************************************************/
/* Construct a new gckVGHARDWARE object. */
gceSTATUS
gckVGHARDWARE_Construct(
IN gckOS Os,
OUT gckVGHARDWARE * Hardware
);
/* Destroy an gckVGHARDWARE object. */
gceSTATUS
gckVGHARDWARE_Destroy(
IN gckVGHARDWARE Hardware
);
/* Query system memory requirements. */
gceSTATUS
gckVGHARDWARE_QuerySystemMemory(
IN gckVGHARDWARE Hardware,
OUT gctSIZE_T * SystemSize,
OUT gctUINT32 * SystemBaseAddress
);
/* Build virtual address. */
gceSTATUS
gckVGHARDWARE_BuildVirtualAddress(
IN gckVGHARDWARE Hardware,
IN gctUINT32 Index,
IN gctUINT32 Offset,
OUT gctUINT32 * Address
);
/* Kickstart the command processor. */
gceSTATUS
gckVGHARDWARE_Execute(
IN gckVGHARDWARE Hardware,
IN gctUINT32 Address,
IN gctUINT32 Count
);
/* Query the available memory. */
gceSTATUS
gckVGHARDWARE_QueryMemory(
IN gckVGHARDWARE Hardware,
OUT gctSIZE_T * InternalSize,
OUT gctUINT32 * InternalBaseAddress,
OUT gctUINT32 * InternalAlignment,
OUT gctSIZE_T * ExternalSize,
OUT gctUINT32 * ExternalBaseAddress,
OUT gctUINT32 * ExternalAlignment,
OUT gctUINT32 * HorizontalTileSize,
OUT gctUINT32 * VerticalTileSize
);
/* Query the identity of the hardware. */
gceSTATUS
gckVGHARDWARE_QueryChipIdentity(
IN gckVGHARDWARE Hardware,
OUT gceCHIPMODEL* ChipModel,
OUT gctUINT32* ChipRevision,
OUT gctUINT32* ProductID,
OUT gctUINT32* EcoID,
OUT gctUINT32* CustomerID,
OUT gctUINT32* ChipFeatures,
OUT gctUINT32* ChipMinorFeatures,
OUT gctUINT32* ChipMinorFeatures1
);
/* Convert an API format. */
gceSTATUS
gckVGHARDWARE_ConvertFormat(
IN gckVGHARDWARE Hardware,
IN gceSURF_FORMAT Format,
OUT gctUINT32 * BitsPerPixel,
OUT gctUINT32 * BytesPerTile
);
/* Split a harwdare specific address into API stuff. */
gceSTATUS
gckVGHARDWARE_SplitMemory(
IN gckVGHARDWARE Hardware,
IN gctUINT32 Address,
OUT gcePOOL * Pool,
OUT gctUINT32 * Offset
);
/* Convert logical address to hardware specific address. */
gceSTATUS
gckVGHARDWARE_ConvertLogical(
IN gckVGHARDWARE Hardware,
IN gctPOINTER Logical,
IN gctBOOL InUserSpace,
OUT gctUINT32 * Address
);
/* Program MMU. */
gceSTATUS
gckVGHARDWARE_SetMMU(
IN gckVGHARDWARE Hardware,
IN gctPOINTER Logical
);
/* Flush the MMU. */
gceSTATUS
gckVGHARDWARE_FlushMMU(
IN gckVGHARDWARE Hardware
);
/* Get idle register. */
gceSTATUS
gckVGHARDWARE_GetIdle(
IN gckVGHARDWARE Hardware,
OUT gctUINT32 * Data
);
/* Flush the caches. */
gceSTATUS
gckVGHARDWARE_Flush(
IN gckVGHARDWARE Hardware,
IN gceKERNEL_FLUSH Flush,
IN gctPOINTER Logical,
IN OUT gctSIZE_T * Bytes
);
/* Enable/disable fast clear. */
gceSTATUS
gckVGHARDWARE_SetFastClear(
IN gckVGHARDWARE Hardware,
IN gctINT Enable
);
gceSTATUS
gckVGHARDWARE_ReadInterrupt(
IN gckVGHARDWARE Hardware,
OUT gctUINT32_PTR IDs
);
/* Power management. */
gceSTATUS
gckVGHARDWARE_SetPowerState(
IN gckVGHARDWARE Hardware,
IN gceCHIPPOWERSTATE State
);
gceSTATUS
gckVGHARDWARE_QueryPowerManagementState(
IN gckVGHARDWARE Hardware,
OUT gceCHIPPOWERSTATE* State
);
gceSTATUS
gckVGHARDWARE_EnablePowerManagement(
IN gckVGHARDWARE Hardware,
IN gctBOOL Enable
);
gceSTATUS
gckVGHARDWARE_SetPowerOffTimeout(
IN gckVGHARDWARE Hardware,
IN gctUINT32 Timeout
);
gceSTATUS
gckVGHARDWARE_QueryPowerOffTimeout(
IN gckVGHARDWARE Hardware,
OUT gctUINT32* Timeout
);
gceSTATUS
gckVGHARDWARE_QueryIdle(
IN gckVGHARDWARE Hardware,
OUT gctBOOL_PTR IsIdle
);
/******************************************************************************\
*************************** Command Buffer Structures **************************
\******************************************************************************/
/* Vacant command buffer marker. */
#define gcvVACANT_BUFFER ((gcsCOMPLETION_SIGNAL_PTR) ((gctSIZE_T)1))
/* Command buffer header. */
typedef struct _gcsCMDBUFFER * gcsCMDBUFFER_PTR;
typedef struct _gcsCMDBUFFER
{
/* Pointer to the completion signal. */
gcsCOMPLETION_SIGNAL_PTR completion;
/* The user sets this to the node of the container buffer whitin which
this particular command buffer resides. The kernel sets this to the
node of the internally allocated buffer. */
gcuVIDMEM_NODE_PTR node;
/* Command buffer hardware address. */
gctUINT32 address;
/* The offset of the buffer from the beginning of the header. */
gctUINT32 bufferOffset;
/* Size of the area allocated for the data portion of this particular
command buffer (headers and tail reserves are excluded). */
gctUINT32 size;
/* Offset into the buffer [0..size]; reflects exactly how much data has
been put into the command buffer. */
gctUINT offset;
/* The number of command units in the buffer for the hardware to
execute. */
gctUINT32 dataCount;
/* MANAGED BY : user HAL (gcoBUFFER object).
USED BY : user HAL (gcoBUFFER object).
Points to the immediate next allocated command buffer. */
gcsCMDBUFFER_PTR nextAllocated;
/* MANAGED BY : user layers (HAL and drivers).
USED BY : kernel HAL (gcoBUFFER object).
Points to the next subbuffer if any. A family of subbuffers are chained
together and are meant to be executed inseparably as a unit. Meaning
that context switching cannot occur while a chain of subbuffers is being
executed. */
gcsCMDBUFFER_PTR nextSubBuffer;
}
gcsCMDBUFFER;
/* Command queue element. */
typedef struct _gcsVGCMDQUEUE
{
/* Pointer to the command buffer header. */
gcsCMDBUFFER_PTR commandBuffer;
/* Dynamic vs. static command buffer state. */
gctBOOL dynamic;
}
gcsVGCMDQUEUE;
/* Context map entry. */
typedef struct _gcsVGCONTEXT_MAP
{
/* State index. */
gctUINT32 index;
/* New state value. */
gctUINT32 data;
/* Points to the next entry in the mod list. */
gcsVGCONTEXT_MAP_PTR next;
}
gcsVGCONTEXT_MAP;
/* gcsVGCONTEXT structure that holds the current context. */
typedef struct _gcsVGCONTEXT
{
/* Context ID. */
gctUINT64 id;
/* State caching ebable flag. */
gctBOOL stateCachingEnabled;
/* Current pipe. */
gctUINT32 currentPipe;
/* State map/mod buffer. */
gctUINT32 mapFirst;
gctUINT32 mapLast;
gcsVGCONTEXT_MAP_PTR mapContainer;
gcsVGCONTEXT_MAP_PTR mapPrev;
gcsVGCONTEXT_MAP_PTR mapCurr;
gcsVGCONTEXT_MAP_PTR firstPrevMap;
gcsVGCONTEXT_MAP_PTR firstCurrMap;
/* Main context buffer. */
gcsCMDBUFFER_PTR header;
gctUINT32_PTR buffer;
/* Completion signal. */
gctHANDLE process;
gctSIGNAL signal;
#if defined(__QNXNTO__)
gctSIGNAL userSignal;
gctINT32 coid;
gctINT32 rcvid;
#endif
}
gcsVGCONTEXT;
/* User space task header. */
typedef struct _gcsTASK * gcsTASK_PTR;
typedef struct _gcsTASK
{
/* Pointer to the next task for the same interrupt in user space. */
gcsTASK_PTR next;
/* Size of the task data that immediately follows the structure. */
gctUINT size;
/* Task data starts here. */
/* ... */
}
gcsTASK;
/* User space task master table entry. */
typedef struct _gcsTASK_MASTER_ENTRY * gcsTASK_MASTER_ENTRY_PTR;
typedef struct _gcsTASK_MASTER_ENTRY
{
/* Pointers to the head and to the tail of the task chain. */
gcsTASK_PTR head;
gcsTASK_PTR tail;
}
gcsTASK_MASTER_ENTRY;
/* User space task master table entry. */
typedef struct _gcsTASK_MASTER_TABLE
{
/* Table with one entry per block. */
gcsTASK_MASTER_ENTRY table[gcvBLOCK_COUNT];
/* The total number of tasks sckeduled. */
gctUINT count;
/* The total size of event data in bytes. */
gctUINT size;
#if defined(__QNXNTO__)
gctINT32 coid;
gctINT32 rcvid;
#endif
}
gcsTASK_MASTER_TABLE;
/******************************************************************************\
***************************** gckVGINTERRUPT Object ******************************
\******************************************************************************/
typedef struct _gckVGINTERRUPT * gckVGINTERRUPT;
typedef gceSTATUS (* gctINTERRUPT_HANDLER)(
IN gckVGKERNEL Kernel
);
gceSTATUS
gckVGINTERRUPT_Construct(
IN gckVGKERNEL Kernel,
OUT gckVGINTERRUPT * Interrupt
);
gceSTATUS
gckVGINTERRUPT_Destroy(
IN gckVGINTERRUPT Interrupt
);
gceSTATUS
gckVGINTERRUPT_Enable(
IN gckVGINTERRUPT Interrupt,
IN OUT gctINT32_PTR Id,
IN gctINTERRUPT_HANDLER Handler
);
gceSTATUS
gckVGINTERRUPT_Disable(
IN gckVGINTERRUPT Interrupt,
IN gctINT32 Id
);
#ifndef __QNXNTO__
gceSTATUS
gckVGINTERRUPT_Enque(
IN gckVGINTERRUPT Interrupt
);
#else
gceSTATUS
gckVGINTERRUPT_Enque(
IN gckVGINTERRUPT Interrupt,
OUT gckOS *Os,
OUT gctSEMAPHORE *Semaphore
);
#endif
gceSTATUS
gckVGINTERRUPT_DumpState(
IN gckVGINTERRUPT Interrupt
);
/******************************************************************************\
******************************* gckVGCOMMAND Object *******************************
\******************************************************************************/
typedef struct _gckVGCOMMAND * gckVGCOMMAND;
/* Construct a new gckVGCOMMAND object. */
gceSTATUS
gckVGCOMMAND_Construct(
IN gckVGKERNEL Kernel,
IN gctUINT TaskGranularity,
IN gctUINT QueueSize,
OUT gckVGCOMMAND * Command
);
/* Destroy an gckVGCOMMAND object. */
gceSTATUS
gckVGCOMMAND_Destroy(
IN gckVGCOMMAND Command
);
/* Query command buffer attributes. */
gceSTATUS
gckVGCOMMAND_QueryCommandBuffer(
IN gckVGCOMMAND Command,
OUT gcsCOMMAND_BUFFER_INFO_PTR Information
);
/* Allocate a command queue. */
gceSTATUS
gckVGCOMMAND_Allocate(
IN gckVGCOMMAND Command,
IN gctSIZE_T Size,
OUT gcsCMDBUFFER_PTR * CommandBuffer,
OUT gctPOINTER * Data
);
/* Release memory held by the command queue. */
gceSTATUS
gckVGCOMMAND_Free(
IN gckVGCOMMAND Command,
IN gcsCMDBUFFER_PTR CommandBuffer
);
/* Schedule the command queue for execution. */
gceSTATUS
gckVGCOMMAND_Execute(
IN gckVGCOMMAND Command,
IN gcsCMDBUFFER_PTR CommandBuffer
);
/* Commit a buffer to the command queue. */
gceSTATUS
gckVGCOMMAND_Commit(
IN gckVGCOMMAND Command,
IN gcsVGCONTEXT_PTR Context,
IN gcsVGCMDQUEUE_PTR Queue,
IN gctUINT EntryCount,
IN gcsTASK_MASTER_TABLE_PTR TaskTable
);
/******************************************************************************\
********************************* gckVGMMU Object ********************************
\******************************************************************************/
typedef struct _gckVGMMU * gckVGMMU;
/* Construct a new gckVGMMU object. */
gceSTATUS
gckVGMMU_Construct(
IN gckVGKERNEL Kernel,
IN gctUINT32 MmuSize,
OUT gckVGMMU * Mmu
);
/* Destroy an gckVGMMU object. */
gceSTATUS
gckVGMMU_Destroy(
IN gckVGMMU Mmu
);
/* Allocate pages inside the MMU. */
gceSTATUS
gckVGMMU_AllocatePages(
IN gckVGMMU Mmu,
IN gctSIZE_T PageCount,
OUT gctPOINTER * PageTable,
OUT gctUINT32 * Address
);
/* Remove a page table from the MMU. */
gceSTATUS
gckVGMMU_FreePages(
IN gckVGMMU Mmu,
IN gctPOINTER PageTable,
IN gctSIZE_T PageCount
);
/* Set the MMU page with info. */
gceSTATUS
gckVGMMU_SetPage(
IN gckVGMMU Mmu,
IN gctUINT32 PageAddress,
IN gctUINT32 *PageEntry
);
/* Flush MMU */
gceSTATUS
gckVGMMU_Flush(
IN gckVGMMU Mmu
);
#endif /* gcdENABLE_VG */
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* __gc_hal_h_ */

View File

@ -0,0 +1,119 @@
/****************************************************************************
*
* The MIT License (MIT)
*
* Copyright (c) 2014 - 2019 Vivante Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
*****************************************************************************
*
* The GPL License (GPL)
*
* Copyright (C) 2014 - 2019 Vivante Corporation
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*****************************************************************************
*
* Note: This software is released under dual MIT and GPL licenses. A
* recipient may use this file under the terms of either the MIT license or
* GPL License. If you wish to use only one license not the other, you can
* indicate your decision by deleting one of the above license notices in your
* version of this file.
*
*****************************************************************************/
#ifndef __gc_hal_kernel_allocator_array_h_
#define __gc_hal_kernel_allocator_array_h_
extern gceSTATUS
_GFPAlloctorInit(
IN gckOS Os,
IN gcsDEBUGFS_DIR *Parent,
OUT gckALLOCATOR * Allocator
);
extern gceSTATUS
_UserMemoryAlloctorInit(
IN gckOS Os,
IN gcsDEBUGFS_DIR *Parent,
OUT gckALLOCATOR * Allocator
);
extern gceSTATUS
_ReservedMemoryAllocatorInit(
IN gckOS Os,
IN gcsDEBUGFS_DIR *Parent,
OUT gckALLOCATOR * Allocator
);
#ifdef CONFIG_DMA_SHARED_BUFFER
extern gceSTATUS
_DmabufAlloctorInit(
IN gckOS Os,
IN gcsDEBUGFS_DIR *Parent,
OUT gckALLOCATOR * Allocator
);
#endif
#ifndef NO_DMA_COHERENT
extern gceSTATUS
_DmaAlloctorInit(
IN gckOS Os,
IN gcsDEBUGFS_DIR *Parent,
OUT gckALLOCATOR * Allocator
);
#endif
/* Default allocator entry. */
gcsALLOCATOR_DESC allocatorArray[] =
{
/* GFP allocator. */
gcmkDEFINE_ALLOCATOR_DESC("gfp", _GFPAlloctorInit),
/* User memory importer. */
gcmkDEFINE_ALLOCATOR_DESC("user", _UserMemoryAlloctorInit),
#ifdef CONFIG_DMA_SHARED_BUFFER
/* Dmabuf allocator. */
gcmkDEFINE_ALLOCATOR_DESC("dmabuf", _DmabufAlloctorInit),
#endif
#ifndef NO_DMA_COHERENT
gcmkDEFINE_ALLOCATOR_DESC("dma", _DmaAlloctorInit),
#endif
gcmkDEFINE_ALLOCATOR_DESC("reserved-mem", _ReservedMemoryAllocatorInit),
};
#endif

View File

@ -0,0 +1,605 @@
/****************************************************************************
*
* The MIT License (MIT)
*
* Copyright (c) 2014 - 2019 Vivante Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
*****************************************************************************
*
* The GPL License (GPL)
*
* Copyright (C) 2014 - 2019 Vivante Corporation
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*****************************************************************************
*
* Note: This software is released under dual MIT and GPL licenses. A
* recipient may use this file under the terms of either the MIT license or
* GPL License. If you wish to use only one license not the other, you can
* indicate your decision by deleting one of the above license notices in your
* version of this file.
*
*****************************************************************************/
#include "gc_hal_kernel_linux.h"
#include "gc_hal_kernel_allocator.h"
#include <linux/pagemap.h>
#include <linux/seq_file.h>
#include <linux/mman.h>
#include <asm/atomic.h>
#include <linux/dma-mapping.h>
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,19,0)
#include <linux/dma-direct.h>
#endif
#include <linux/slab.h>
#include <linux/platform_device.h>
#define _GC_OBJ_ZONE gcvZONE_OS
typedef struct _gcsDMA_PRIV * gcsDMA_PRIV_PTR;
typedef struct _gcsDMA_PRIV {
atomic_t usage;
}
gcsDMA_PRIV;
struct mdl_dma_priv {
gctPOINTER kvaddr;
dma_addr_t dmaHandle;
};
/*
* Debugfs support.
*/
static int gc_dma_usage_show(struct seq_file* m, void* data)
{
gcsINFO_NODE *node = m->private;
gckALLOCATOR Allocator = node->device;
gcsDMA_PRIV_PTR priv = Allocator->privateData;
long long usage = (long long)atomic_read(&priv->usage);
seq_printf(m, "type n pages bytes\n");
seq_printf(m, "normal %10llu %12llu\n", usage, usage * PAGE_SIZE);
return 0;
}
static gcsINFO InfoList[] =
{
{"dmausage", gc_dma_usage_show},
};
static void
_DebugfsInit(
IN gckALLOCATOR Allocator,
IN gckDEBUGFS_DIR Root
)
{
gcmkVERIFY_OK(
gckDEBUGFS_DIR_Init(&Allocator->debugfsDir, Root->root, "dma"));
gcmkVERIFY_OK(gckDEBUGFS_DIR_CreateFiles(
&Allocator->debugfsDir,
InfoList,
gcmCOUNTOF(InfoList),
Allocator
));
}
static void
_DebugfsCleanup(
IN gckALLOCATOR Allocator
)
{
gcmkVERIFY_OK(gckDEBUGFS_DIR_RemoveFiles(
&Allocator->debugfsDir,
InfoList,
gcmCOUNTOF(InfoList)
));
gckDEBUGFS_DIR_Deinit(&Allocator->debugfsDir);
}
static gceSTATUS
_DmaAlloc(
IN gckALLOCATOR Allocator,
INOUT PLINUX_MDL Mdl,
IN gctSIZE_T NumPages,
IN gctUINT32 Flags
)
{
gceSTATUS status;
u32 gfp = GFP_KERNEL | gcdNOWARN;
gcsDMA_PRIV_PTR allocatorPriv = (gcsDMA_PRIV_PTR)Allocator->privateData;
struct mdl_dma_priv *mdlPriv=gcvNULL;
gckOS os = Allocator->os;
gcmkHEADER_ARG("Mdl=%p NumPages=0x%zx Flags=0x%x", Mdl, NumPages, Flags);
gcmkONERROR(gckOS_Allocate(os, sizeof(struct mdl_dma_priv), (gctPOINTER *)&mdlPriv));
mdlPriv->kvaddr = gcvNULL;
#if defined(CONFIG_ZONE_DMA32) && LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)
if (Flags & gcvALLOC_FLAG_4GB_ADDR)
{
gfp |= __GFP_DMA32;
}
#endif
mdlPriv->kvaddr
#if defined CONFIG_MIPS || defined CONFIG_CPU_CSKYV2 || defined CONFIG_PPC || defined CONFIG_ARM64
= dma_alloc_coherent(galcore_device, NumPages * PAGE_SIZE, &mdlPriv->dmaHandle, gfp);
#else
= dma_alloc_writecombine(galcore_device, NumPages * PAGE_SIZE, &mdlPriv->dmaHandle, gfp);
#endif
#ifdef CONFLICT_BETWEEN_BASE_AND_PHYS
if ((os->device->baseAddress & 0x80000000) != (mdlPriv->dmaHandle & 0x80000000))
{
mdlPriv->dmaHandle = (mdlPriv->dmaHandle & ~0x80000000)
| (os->device->baseAddress & 0x80000000);
}
#endif
if (mdlPriv->kvaddr == gcvNULL)
{
gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
}
Mdl->priv = mdlPriv;
Mdl->dmaHandle = mdlPriv->dmaHandle;
/* Statistic. */
atomic_add(NumPages, &allocatorPriv->usage);
gcmkFOOTER_NO();
return gcvSTATUS_OK;
OnError:
if (mdlPriv)
{
gckOS_Free(os, mdlPriv);
}
gcmkFOOTER();
return status;
}
static gceSTATUS
_DmaGetSGT(
IN gckALLOCATOR Allocator,
IN PLINUX_MDL Mdl,
IN gctSIZE_T Offset,
IN gctSIZE_T Bytes,
OUT gctPOINTER *SGT
)
{
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)
struct page ** pages = gcvNULL;
struct page * page = gcvNULL;
struct sg_table *sgt = NULL;
struct mdl_dma_priv *mdlPriv = (struct mdl_dma_priv*)Mdl->priv;
gceSTATUS status = gcvSTATUS_OK;
gctSIZE_T offset = Offset & ~PAGE_MASK; /* Offset to the first page */
gctSIZE_T skipPages = Offset >> PAGE_SHIFT; /* skipped pages */
gctSIZE_T numPages = (PAGE_ALIGN(Offset + Bytes) >> PAGE_SHIFT) - skipPages;
gctSIZE_T i;
gcmkASSERT(Offset + Bytes <= Mdl->numPages << PAGE_SHIFT);
sgt = kmalloc(sizeof(struct sg_table), GFP_KERNEL | gcdNOWARN);
if (!sgt)
{
gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
}
pages = kmalloc(sizeof(struct page*) * numPages, GFP_KERNEL | gcdNOWARN);
if (!pages)
{
gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
}
#if !defined(phys_to_page)
page = virt_to_page(mdlPriv->kvaddr);
#elif LINUX_VERSION_CODE < KERNEL_VERSION(3,13,0)
page = phys_to_page(mdlPriv->dmaHandle);
#else
page = phys_to_page(dma_to_phys(&Allocator->os->device->platform->device->dev, mdlPriv->dmaHandle));
#endif
for (i = 0; i < numPages; ++i)
{
pages[i] = nth_page(page, i + skipPages);
}
if (sg_alloc_table_from_pages(sgt, pages, numPages, offset, Bytes, GFP_KERNEL) < 0)
{
gcmkONERROR(gcvSTATUS_GENERIC_IO);
}
*SGT = (gctPOINTER)sgt;
OnError:
if (pages)
{
kfree(pages);
}
if (gcmIS_ERROR(status) && sgt)
{
kfree(sgt);
}
return status;
#else
return gcvSTATUS_NOT_SUPPORTED;
#endif
}
static void
_DmaFree(
IN gckALLOCATOR Allocator,
IN OUT PLINUX_MDL Mdl
)
{
gckOS os = Allocator->os;
struct mdl_dma_priv *mdlPriv=(struct mdl_dma_priv *)Mdl->priv;
gcsDMA_PRIV_PTR allocatorPriv = (gcsDMA_PRIV_PTR)Allocator->privateData;
#if defined CONFIG_MIPS || defined CONFIG_CPU_CSKYV2 || defined CONFIG_PPC || defined CONFIG_ARM64
dma_free_coherent(galcore_device, Mdl->numPages * PAGE_SIZE, mdlPriv->kvaddr, mdlPriv->dmaHandle);
#else
dma_free_writecombine(galcore_device, Mdl->numPages * PAGE_SIZE, mdlPriv->kvaddr, mdlPriv->dmaHandle);
#endif
gckOS_Free(os, mdlPriv);
/* Statistic. */
atomic_sub(Mdl->numPages, &allocatorPriv->usage);
}
static gceSTATUS
_DmaMmap(
IN gckALLOCATOR Allocator,
IN PLINUX_MDL Mdl,
IN gctBOOL Cacheable,
IN gctSIZE_T skipPages,
IN gctSIZE_T numPages,
IN struct vm_area_struct *vma
)
{
struct mdl_dma_priv *mdlPriv = (struct mdl_dma_priv*)Mdl->priv;
gceSTATUS status = gcvSTATUS_OK;
gcmkHEADER_ARG("Allocator=%p Mdl=%p vma=%p", Allocator, Mdl, vma);
gcmkASSERT(skipPages + numPages <= Mdl->numPages);
/* map kernel memory to user space.. */
#if defined CONFIG_MIPS || defined CONFIG_CPU_CSKYV2 || defined CONFIG_PPC
if (remap_pfn_range(
vma,
vma->vm_start,
(mdlPriv->dmaHandle >> PAGE_SHIFT) + skipPages,
numPages << PAGE_SHIFT,
pgprot_writecombine(vma->vm_page_prot)) < 0)
#else
/* map kernel memory to user space.. */
if (dma_mmap_writecombine(galcore_device,
vma,
(gctINT8_PTR)mdlPriv->kvaddr + (skipPages << PAGE_SHIFT),
mdlPriv->dmaHandle + (skipPages << PAGE_SHIFT),
numPages << PAGE_SHIFT) < 0)
#endif
{
gcmkTRACE_ZONE(
gcvLEVEL_WARNING, gcvZONE_OS,
"%s(%d): dma_mmap_attrs error",
__FUNCTION__, __LINE__
);
status = gcvSTATUS_OUT_OF_MEMORY;
}
gcmkFOOTER();
return status;
}
static void
_DmaUnmapUser(
IN gckALLOCATOR Allocator,
IN PLINUX_MDL Mdl,
IN PLINUX_MDL_MAP MdlMap,
IN gctUINT32 Size
)
{
if (unlikely(current->mm == gcvNULL))
{
/* Do nothing if process is exiting. */
return;
}
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0)
if (vm_munmap((unsigned long)MdlMap->vmaAddr, Size) < 0)
{
gcmkTRACE_ZONE(
gcvLEVEL_WARNING, gcvZONE_OS,
"%s(%d): vm_munmap failed",
__FUNCTION__, __LINE__
);
}
#else
down_write(&current->mm->mmap_sem);
if (do_munmap(current->mm, (unsigned long)MdlMap->vmaAddr, Size) < 0)
{
gcmkTRACE_ZONE(
gcvLEVEL_WARNING, gcvZONE_OS,
"%s(%d): do_munmap failed",
__FUNCTION__, __LINE__
);
}
up_write(&current->mm->mmap_sem);
#endif
}
static gceSTATUS
_DmaMapUser(
gckALLOCATOR Allocator,
PLINUX_MDL Mdl,
PLINUX_MDL_MAP MdlMap,
gctBOOL Cacheable
)
{
gctPOINTER userLogical = gcvNULL;
gceSTATUS status = gcvSTATUS_OK;
gcmkHEADER_ARG("Allocator=%p Mdl=%p Cacheable=%d", Allocator, Mdl, Cacheable);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
userLogical = (gctPOINTER)vm_mmap(gcvNULL,
0L,
Mdl->numPages * PAGE_SIZE,
PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_NORESERVE,
0);
#else
down_write(&current->mm->mmap_sem);
userLogical = (gctPOINTER)do_mmap_pgoff(gcvNULL,
0L,
Mdl->numPages * PAGE_SIZE,
PROT_READ | PROT_WRITE,
MAP_SHARED,
0);
up_write(&current->mm->mmap_sem);
#endif
gcmkTRACE_ZONE(
gcvLEVEL_INFO, gcvZONE_OS,
"%s(%d): vmaAddr->%p for phys_addr->%p",
__FUNCTION__, __LINE__, userLogical, Mdl
);
if (IS_ERR(userLogical))
{
gcmkTRACE_ZONE(
gcvLEVEL_INFO, gcvZONE_OS,
"%s(%d): do_mmap_pgoff error",
__FUNCTION__, __LINE__
);
gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
}
down_write(&current->mm->mmap_sem);
do
{
struct vm_area_struct *vma = find_vma(current->mm, (unsigned long)userLogical);
if (vma == gcvNULL)
{
gcmkTRACE_ZONE(
gcvLEVEL_INFO, gcvZONE_OS,
"%s(%d): find_vma error",
__FUNCTION__, __LINE__
);
gcmkERR_BREAK(gcvSTATUS_OUT_OF_RESOURCES);
}
gcmkERR_BREAK(_DmaMmap(Allocator, Mdl, Cacheable, 0, Mdl->numPages, vma));
MdlMap->vmaAddr = userLogical;
MdlMap->cacheable = gcvFALSE;
MdlMap->vma = vma;
}
while (gcvFALSE);
up_write(&current->mm->mmap_sem);
OnError:
if (gcmIS_ERROR(status) && userLogical)
{
_DmaUnmapUser(Allocator, Mdl, userLogical, Mdl->numPages * PAGE_SIZE);
}
gcmkFOOTER();
return status;
}
static gceSTATUS
_DmaMapKernel(
IN gckALLOCATOR Allocator,
IN PLINUX_MDL Mdl,
IN gctSIZE_T Offset,
IN gctSIZE_T Bytes,
OUT gctPOINTER *Logical
)
{
struct mdl_dma_priv *mdlPriv=(struct mdl_dma_priv *)Mdl->priv;
*Logical = (uint8_t *)mdlPriv->kvaddr + Offset;
return gcvSTATUS_OK;
}
static gceSTATUS
_DmaUnmapKernel(
IN gckALLOCATOR Allocator,
IN PLINUX_MDL Mdl,
IN gctPOINTER Logical
)
{
return gcvSTATUS_OK;
}
static gceSTATUS
_DmaCache(
IN gckALLOCATOR Allocator,
IN PLINUX_MDL Mdl,
IN gctSIZE_T Offset,
IN gctPOINTER Logical,
IN gctSIZE_T Bytes,
IN gceCACHEOPERATION Operation
)
{
switch (Operation)
{
case gcvCACHE_CLEAN:
case gcvCACHE_FLUSH:
_MemoryBarrier();
break;
case gcvCACHE_INVALIDATE:
break;
default:
return gcvSTATUS_INVALID_ARGUMENT;
}
return gcvSTATUS_OK;
}
static gceSTATUS
_DmaPhysical(
IN gckALLOCATOR Allocator,
IN PLINUX_MDL Mdl,
IN gctUINT32 Offset,
OUT gctPHYS_ADDR_T * Physical
)
{
struct mdl_dma_priv *mdlPriv=(struct mdl_dma_priv *)Mdl->priv;
*Physical = mdlPriv->dmaHandle + Offset;
return gcvSTATUS_OK;
}
static void
_DmaAllocatorDestructor(
gcsALLOCATOR *Allocator
)
{
_DebugfsCleanup(Allocator);
if (Allocator->privateData)
{
kfree(Allocator->privateData);
}
kfree(Allocator);
}
/* Default allocator operations. */
gcsALLOCATOR_OPERATIONS DmaAllocatorOperations = {
.Alloc = _DmaAlloc,
.Free = _DmaFree,
.Mmap = _DmaMmap,
.MapUser = _DmaMapUser,
.UnmapUser = _DmaUnmapUser,
.MapKernel = _DmaMapKernel,
.UnmapKernel = _DmaUnmapKernel,
.Cache = _DmaCache,
.Physical = _DmaPhysical,
.GetSGT = _DmaGetSGT,
};
/* Default allocator entry. */
gceSTATUS
_DmaAlloctorInit(
IN gckOS Os,
IN gcsDEBUGFS_DIR *Parent,
OUT gckALLOCATOR * Allocator
)
{
gceSTATUS status;
gckALLOCATOR allocator = gcvNULL;
gcsDMA_PRIV_PTR priv = gcvNULL;
gcmkONERROR(gckALLOCATOR_Construct(Os, &DmaAllocatorOperations, &allocator));
priv = kzalloc(gcmSIZEOF(gcsDMA_PRIV), GFP_KERNEL | gcdNOWARN);
if (!priv)
{
gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
}
atomic_set(&priv->usage, 0);
/* Register private data. */
allocator->privateData = priv;
allocator->destructor = _DmaAllocatorDestructor;
_DebugfsInit(allocator, Parent);
/*
* DMA allocator is only used for NonPaged memory
* when NO_DMA_COHERENT is not defined.
*/
allocator->capability = gcvALLOC_FLAG_CONTIGUOUS
| gcvALLOC_FLAG_DMABUF_EXPORTABLE
#if defined(CONFIG_ZONE_DMA32) && LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)
| gcvALLOC_FLAG_4GB_ADDR
#endif
;
*Allocator = allocator;
return gcvSTATUS_OK;
OnError:
if (allocator)
{
kfree(allocator);
}
return status;
}

View File

@ -0,0 +1,552 @@
/****************************************************************************
*
* The MIT License (MIT)
*
* Copyright (c) 2014 - 2019 Vivante Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
*****************************************************************************
*
* The GPL License (GPL)
*
* Copyright (C) 2014 - 2019 Vivante Corporation
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*****************************************************************************
*
* Note: This software is released under dual MIT and GPL licenses. A
* recipient may use this file under the terms of either the MIT license or
* GPL License. If you wish to use only one license not the other, you can
* indicate your decision by deleting one of the above license notices in your
* version of this file.
*
*****************************************************************************/
#include "gc_hal_kernel_linux.h"
#include "gc_hal_kernel_allocator.h"
#include <linux/pagemap.h>
#include <linux/seq_file.h>
#include <linux/mman.h>
#include <linux/slab.h>
#include <linux/mutex.h>
#include <asm/atomic.h>
#include <linux/dma-mapping.h>
#include <linux/dma-buf.h>
#include <linux/platform_device.h>
#define _GC_OBJ_ZONE gcvZONE_OS
/* Descriptor of a dma_buf imported. */
typedef struct _gcsDMABUF
{
struct dma_buf * dmabuf;
struct dma_buf_attachment * attachment;
struct sg_table * sgt;
unsigned long * pagearray;
int npages;
int pid;
struct list_head list;
}
gcsDMABUF;
struct allocator_priv
{
struct mutex lock;
struct list_head buf_list;
};
/*
* Debugfs support.
*/
static int dma_buf_info_show(struct seq_file* m, void* data)
{
int ret;
gcsDMABUF *buf_desc;
struct dma_buf_attachment *attach_obj;
int count = 0;
size_t size = 0;
int npages = 0;
const char *exp_name;
gcsINFO_NODE *node = m->private;
gckALLOCATOR allocator = node->device;
struct allocator_priv *priv = allocator->privateData;
ret = mutex_lock_interruptible(&priv->lock);
if (ret)
return ret;
seq_puts(m, "Attached dma-buf objects:\n");
seq_puts(m, " pid fd pages size exporter attached-devices\n");
list_for_each_entry(buf_desc, &priv->buf_list, list) {
struct dma_buf *buf_obj = buf_desc->dmabuf;
ret = mutex_lock_interruptible(&buf_obj->lock);
if (ret) {
seq_puts(m,
"ERROR locking buffer object: skipping\n");
continue;
}
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)
exp_name = buf_obj->exp_name;
#else
exp_name = "unknown";
#endif
seq_printf(m, "%6d %p %8d %8zu %10s",
buf_desc->pid,
buf_desc->dmabuf,
buf_desc->npages,
buf_obj->size,
exp_name);
list_for_each_entry(attach_obj, &buf_obj->attachments, node) {
seq_printf(m, " %s", dev_name(attach_obj->dev));
}
seq_puts(m, "\n");
count++;
size += buf_obj->size;
npages += buf_desc->npages;
mutex_unlock(&buf_obj->lock);
}
seq_printf(m, "\nTotal %d objects, %d pages, %zu bytes\n", count, npages, size);
mutex_unlock(&priv->lock);
return 0;
}
static gcsINFO _InfoList[] =
{
{"bufinfo", dma_buf_info_show},
};
static void
_DebugfsInit(
IN gckALLOCATOR Allocator,
IN gckDEBUGFS_DIR Root
)
{
gcmkVERIFY_OK(
gckDEBUGFS_DIR_Init(&Allocator->debugfsDir, Root->root, "dma_buf"));
gcmkVERIFY_OK(gckDEBUGFS_DIR_CreateFiles(
&Allocator->debugfsDir,
_InfoList,
gcmCOUNTOF(_InfoList),
Allocator
));
}
static void
_DebugfsCleanup(
IN gckALLOCATOR Allocator
)
{
gcmkVERIFY_OK(gckDEBUGFS_DIR_RemoveFiles(
&Allocator->debugfsDir,
_InfoList,
gcmCOUNTOF(_InfoList)
));
gckDEBUGFS_DIR_Deinit(&Allocator->debugfsDir);
}
static gceSTATUS
_DmabufAttach(
IN gckALLOCATOR Allocator,
IN gcsATTACH_DESC_PTR Desc,
IN PLINUX_MDL Mdl
)
{
gceSTATUS status;
gckOS os = Allocator->os;
struct dma_buf *dmabuf = Desc->dmaBuf.dmabuf;
struct sg_table *sgt = NULL;
struct dma_buf_attachment *attachment = NULL;
int npages = 0;
unsigned long *pagearray = NULL;
int i, j, k = 0;
struct scatterlist *s;
struct allocator_priv *priv = Allocator->privateData;
gcsDMABUF *buf_desc = NULL;
gcmkHEADER();
gcmkVERIFY_OBJECT(os, gcvOBJ_OS);
if (!dmabuf)
{
gcmkONERROR(gcvSTATUS_NOT_SUPPORTED);
}
get_dma_buf(dmabuf);
attachment = dma_buf_attach(dmabuf, &os->device->platform->device->dev);
if (!attachment)
{
gcmkONERROR(gcvSTATUS_NOT_SUPPORTED);
}
sgt = dma_buf_map_attachment(attachment, DMA_BIDIRECTIONAL);
if (!sgt)
{
gcmkONERROR(gcvSTATUS_NOT_SUPPORTED);
}
/* Prepare page array. */
/* Get number of pages. */
for_each_sg(sgt->sgl, s, sgt->orig_nents, i)
{
npages += (sg_dma_len(s) + PAGE_SIZE - 1) / PAGE_SIZE;
}
/* Allocate page array. */
gcmkONERROR(gckOS_Allocate(os, npages * gcmSIZEOF(*pagearray), (gctPOINTER *)&pagearray));
/* Fill page array. */
for_each_sg(sgt->sgl, s, sgt->orig_nents, i)
{
for (j = 0; j < (sg_dma_len(s) + PAGE_SIZE - 1) / PAGE_SIZE; j++)
{
pagearray[k++] = sg_dma_address(s) + j * PAGE_SIZE;
}
}
/* Prepare descriptor. */
gcmkONERROR(gckOS_Allocate(os, sizeof(gcsDMABUF), (gctPOINTER *)&buf_desc));
buf_desc->dmabuf = dmabuf;
buf_desc->pagearray = pagearray;
buf_desc->attachment = attachment;
buf_desc->sgt = sgt;
/* Record in buffer list to support debugfs. */
buf_desc->npages = npages;
buf_desc->pid = _GetProcessID();
mutex_lock(&priv->lock);
list_add(&buf_desc->list, &priv->buf_list);
mutex_unlock(&priv->lock);
/* Record page number. */
Mdl->numPages = npages;
Mdl->priv = buf_desc;
Mdl->contiguous = (sgt->nents == 1) ? gcvTRUE : gcvFALSE;
gcmkFOOTER_NO();
return gcvSTATUS_OK;
OnError:
if (pagearray)
{
gcmkOS_SAFE_FREE(os, pagearray);
}
if (sgt)
{
dma_buf_unmap_attachment(attachment, sgt, DMA_BIDIRECTIONAL);
}
gcmkFOOTER();
return status;
}
static void
_DmabufFree(
IN gckALLOCATOR Allocator,
IN PLINUX_MDL Mdl
)
{
gcsDMABUF *buf_desc = Mdl->priv;
gckOS os = Allocator->os;
struct allocator_priv *priv = Allocator->privateData;
mutex_lock(&priv->lock);
list_del(&buf_desc->list);
mutex_unlock(&priv->lock);
dma_buf_unmap_attachment(buf_desc->attachment, buf_desc->sgt, DMA_BIDIRECTIONAL);
dma_buf_detach(buf_desc->dmabuf, buf_desc->attachment);
dma_buf_put(buf_desc->dmabuf);
gckOS_Free(os, buf_desc->pagearray);
gckOS_Free(os, buf_desc);
}
static void
_DmabufUnmapUser(
IN gckALLOCATOR Allocator,
IN PLINUX_MDL Mdl,
IN PLINUX_MDL_MAP MdlMap,
IN gctUINT32 Size
)
{
gcsDMABUF *buf_desc = Mdl->priv;
gctINT8_PTR userLogical = MdlMap->vmaAddr;
if (unlikely(current->mm == gcvNULL))
{
/* Do nothing if process is exiting. */
return;
}
userLogical -= buf_desc->sgt->sgl->offset;
vm_munmap((unsigned long)userLogical, Mdl->numPages << PAGE_SHIFT);
}
static gceSTATUS
_DmabufMapUser(
IN gckALLOCATOR Allocator,
IN PLINUX_MDL Mdl,
IN PLINUX_MDL_MAP MdlMap,
IN gctBOOL Cacheable
)
{
gcsDMABUF *buf_desc = Mdl->priv;
gctINT8_PTR userLogical = gcvNULL;
gceSTATUS status = gcvSTATUS_OK;
userLogical = (gctINT8_PTR)vm_mmap(buf_desc->dmabuf->file,
0L,
Mdl->numPages << PAGE_SHIFT,
PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_NORESERVE,
0);
if (IS_ERR(userLogical))
{
gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
}
userLogical += buf_desc->sgt->sgl->offset;
/* To make sure the mapping is created. */
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0)
if (access_ok(userLogical, 4))
#else
if (access_ok(VERIFY_READ, userLogical, 4))
#endif
{
uint32_t mem;
get_user(mem, (uint32_t *)userLogical);
(void)mem;
}
MdlMap->vmaAddr = (gctPOINTER)userLogical;
MdlMap->cacheable = Cacheable;
OnError:
if (gcmIS_ERROR(status) && MdlMap->vmaAddr)
{
_DmabufUnmapUser(Allocator, Mdl, MdlMap, Mdl->numPages << PAGE_SHIFT);
}
return status;
}
static gceSTATUS
_DmabufMapKernel(
IN gckALLOCATOR Allocator,
IN PLINUX_MDL Mdl,
IN gctSIZE_T Offset,
IN gctSIZE_T Bytes,
OUT gctPOINTER *Logical
)
{
/* Kernel doesn't acess video memory. */
return gcvSTATUS_NOT_SUPPORTED;
}
static gceSTATUS
_DmabufUnmapKernel(
IN gckALLOCATOR Allocator,
IN PLINUX_MDL Mdl,
IN gctPOINTER Logical
)
{
/* Kernel doesn't acess video memory. */
return gcvSTATUS_NOT_SUPPORTED;
}
static gceSTATUS
_DmabufCache(
IN gckALLOCATOR Allocator,
IN PLINUX_MDL Mdl,
IN gctSIZE_T Offset,
IN gctPOINTER Logical,
IN gctSIZE_T Bytes,
IN gceCACHEOPERATION Operation
)
{
gcsDMABUF *buf_desc = Mdl->priv;
struct sg_table *sgt = buf_desc->sgt;
enum dma_data_direction dir;
switch (Operation)
{
case gcvCACHE_CLEAN:
dir = DMA_TO_DEVICE;
dma_sync_sg_for_device(galcore_device, sgt->sgl, sgt->nents, dir);
break;
case gcvCACHE_FLUSH:
dir = DMA_TO_DEVICE;
dma_sync_sg_for_device(galcore_device, sgt->sgl, sgt->nents, dir);
dir = DMA_FROM_DEVICE;
dma_sync_sg_for_cpu(galcore_device, sgt->sgl, sgt->nents, dir);
break;
case gcvCACHE_INVALIDATE:
dir = DMA_FROM_DEVICE;
dma_sync_sg_for_cpu(galcore_device, sgt->sgl, sgt->nents, dir);
break;
default:
return gcvSTATUS_INVALID_ARGUMENT;
}
return gcvSTATUS_OK;
}
static gceSTATUS
_DmabufPhysical(
IN gckALLOCATOR Allocator,
IN PLINUX_MDL Mdl,
IN gctUINT32 Offset,
OUT gctPHYS_ADDR_T * Physical
)
{
gcsDMABUF *buf_desc = Mdl->priv;
gctUINT32 offsetInPage = Offset & ~PAGE_MASK;
gctUINT32 index = Offset / PAGE_SIZE;
*Physical = buf_desc->pagearray[index] + offsetInPage;
return gcvSTATUS_OK;
}
/* Default allocator operations. */
static gcsALLOCATOR_OPERATIONS DmabufAllocatorOperations =
{
.Attach = _DmabufAttach,
.Free = _DmabufFree,
.MapUser = _DmabufMapUser,
.UnmapUser = _DmabufUnmapUser,
.MapKernel = _DmabufMapKernel,
.UnmapKernel = _DmabufUnmapKernel,
.Cache = _DmabufCache,
.Physical = _DmabufPhysical,
};
static void
_DmabufAllocatorDestructor(
gcsALLOCATOR *Allocator
)
{
_DebugfsCleanup(Allocator);
if (Allocator->privateData)
{
kfree(Allocator->privateData);
}
kfree(Allocator);
}
/* Default allocator entry. */
gceSTATUS
_DmabufAlloctorInit(
IN gckOS Os,
IN gcsDEBUGFS_DIR *Parent,
OUT gckALLOCATOR * Allocator
)
{
gceSTATUS status;
gckALLOCATOR allocator;
struct allocator_priv *priv = NULL;
priv = kmalloc(sizeof (struct allocator_priv), GFP_KERNEL | gcdNOWARN);
if (!priv)
{
gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
}
mutex_init(&priv->lock);
INIT_LIST_HEAD(&priv->buf_list);
gcmkONERROR(
gckALLOCATOR_Construct(Os, &DmabufAllocatorOperations, &allocator));
allocator->capability = gcvALLOC_FLAG_DMABUF
| gcvALLOC_FLAG_DMABUF_EXPORTABLE
;
/* Register private data. */
allocator->privateData = priv;
allocator->destructor = _DmabufAllocatorDestructor;
_DebugfsInit(allocator, Parent);
*Allocator = allocator;
return gcvSTATUS_OK;
OnError:
if (priv)
{
kfree(priv);
}
return status;
}

View File

@ -0,0 +1,544 @@
/****************************************************************************
*
* The MIT License (MIT)
*
* Copyright (c) 2014 - 2019 Vivante Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
*****************************************************************************
*
* The GPL License (GPL)
*
* Copyright (C) 2014 - 2019 Vivante Corporation
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*****************************************************************************
*
* Note: This software is released under dual MIT and GPL licenses. A
* recipient may use this file under the terms of either the MIT license or
* GPL License. If you wish to use only one license not the other, you can
* indicate your decision by deleting one of the above license notices in your
* version of this file.
*
*****************************************************************************/
#include "gc_hal_kernel_linux.h"
#include "gc_hal_kernel_allocator.h"
#include <linux/pagemap.h>
#include <linux/seq_file.h>
#include <linux/mman.h>
#include <asm/atomic.h>
#include <linux/dma-mapping.h>
#include <linux/slab.h>
#include <linux/io.h>
#include <linux/ioport.h>
#define _GC_OBJ_ZONE gcvZONE_OS
/*
* reserved_mem is for contiguous pool, internal pool and external pool, etc.
*/
/* mdl private. */
struct reserved_mem
{
unsigned long start;
unsigned long size;
unsigned int offset_in_page;
char name[32];
int release;
/* Link together. */
struct list_head link;
};
/* allocator info. */
struct reserved_mem_alloc
{
/* Record allocated reserved memory regions. */
struct list_head region;
struct mutex lock;
};
static int reserved_mem_show(struct seq_file* m, void* data)
{
struct list_head *pos;
gcsINFO_NODE *node = m->private;
gckALLOCATOR Allocator = node->device;
struct reserved_mem_alloc *alloc = Allocator->privateData;
list_for_each(pos, &alloc->region)
{
struct reserved_mem * res= list_entry(pos, struct reserved_mem, link);
seq_printf(m, "0x%08lx-0x%08lx : %s\n",
res->start, res->start + res->size -1, res->name);
}
return 0;
}
static gcsINFO info_list[] =
{
{"reserved-mem", reserved_mem_show},
};
static void
reserved_mem_debugfs_init(
IN gckALLOCATOR Allocator,
IN gckDEBUGFS_DIR Root
)
{
gcmkVERIFY_OK(
gckDEBUGFS_DIR_Init(&Allocator->debugfsDir, Root->root, "reserved-mem"));
gcmkVERIFY_OK(gckDEBUGFS_DIR_CreateFiles(
&Allocator->debugfsDir,
info_list,
gcmCOUNTOF(info_list),
Allocator
));
}
static void
reserved_mem_debugfs_cleanup(
IN gckALLOCATOR Allocator
)
{
gcmkVERIFY_OK(gckDEBUGFS_DIR_RemoveFiles(
&Allocator->debugfsDir,
info_list,
gcmCOUNTOF(info_list)
));
gckDEBUGFS_DIR_Deinit(&Allocator->debugfsDir);
}
static gceSTATUS
reserved_mem_alloc(
IN gckALLOCATOR Allocator,
INOUT PLINUX_MDL Mdl,
IN gctSIZE_T NumPages,
IN gctUINT32 Flags
)
{
return gcvSTATUS_NOT_SUPPORTED;
}
static gceSTATUS
reserved_mem_attach(
IN gckALLOCATOR Allocator,
IN gcsATTACH_DESC_PTR Desc,
IN PLINUX_MDL Mdl
)
{
struct reserved_mem_alloc *alloc = Allocator->privateData;
struct reserved_mem *res;
struct resource *region = NULL;
if (Desc == gcvNULL)
{
return gcvSTATUS_INVALID_ARGUMENT;
}
res = kzalloc(sizeof(struct reserved_mem), GFP_KERNEL | gcdNOWARN);
if (!res)
return gcvSTATUS_OUT_OF_MEMORY;
res->start = Desc->reservedMem.start;
res->size = Desc->reservedMem.size;
res->offset_in_page = Desc->reservedMem.start & (PAGE_SIZE - 1);
strncpy(res->name, Desc->reservedMem.name, sizeof(res->name)-1);
res->release = 0;
if (!Desc->reservedMem.requested)
{
region = request_mem_region(res->start, res->size, res->name);
if (!region)
{
printk("request mem %s(0x%lx - 0x%lx) failed\n",
res->name, res->start, res->start + res->size - 1);
kfree(res);
return gcvSTATUS_OUT_OF_RESOURCES;
}
res->release = 1;
}
mutex_lock(&alloc->lock);
list_add(&res->link, &alloc->region);
mutex_unlock(&alloc->lock);
Mdl->priv = res;
if (res->start < 0xFFFFFFFF)
{
Allocator->capability |= gcvALLOC_FLAG_4GB_ADDR;
}
return gcvSTATUS_OK;
}
static void
reserved_mem_detach(
IN gckALLOCATOR Allocator,
IN OUT PLINUX_MDL Mdl
)
{
struct reserved_mem_alloc *alloc = Allocator->privateData;
struct reserved_mem *res = Mdl->priv;
/* unlink from region list. */
mutex_lock(&alloc->lock);
list_del_init(&res->link);
mutex_unlock(&alloc->lock);
if (res->release)
{
release_mem_region(res->start, res->size);
}
kfree(res);
}
static gceSTATUS
reserved_mem_mmap(
IN gckALLOCATOR Allocator,
IN PLINUX_MDL Mdl,
IN gctBOOL Cacheable,
IN gctSIZE_T skipPages,
IN gctSIZE_T numPages,
IN struct vm_area_struct *vma
)
{
struct reserved_mem *res = (struct reserved_mem*)Mdl->priv;
unsigned long pfn;
gceSTATUS status = gcvSTATUS_OK;
gcmkHEADER_ARG("Allocator=%p Mdl=%p vma=%p", Allocator, Mdl, vma);
gcmkASSERT(skipPages + numPages <= Mdl->numPages);
pfn = (res->start >> PAGE_SHIFT) + skipPages;
/* Make this mapping non-cached. */
vma->vm_flags |= gcdVM_FLAGS;
vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
if (remap_pfn_range(vma, vma->vm_start,
pfn, numPages << PAGE_SHIFT, vma->vm_page_prot) < 0)
{
gcmkTRACE(
gcvLEVEL_ERROR,
"%s(%d): remap_pfn_range error.",
__FUNCTION__, __LINE__
);
status = gcvSTATUS_OUT_OF_MEMORY;
}
gcmkFOOTER();
return status;
}
static void
reserved_mem_unmap_user(
IN gckALLOCATOR Allocator,
IN PLINUX_MDL Mdl,
IN PLINUX_MDL_MAP MdlMap,
IN gctUINT32 Size
)
{
struct reserved_mem *res = (struct reserved_mem*)Mdl->priv;
if (unlikely(!current->mm))
return;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0)
if (vm_munmap((unsigned long)MdlMap->vmaAddr - res->offset_in_page, res->size) < 0)
{
printk("%s: vm_munmap failed\n", __func__);
}
#else
down_write(&current->mm->mmap_sem);
if (do_munmap(current->mm, (unsigned long)MdlMap->vmaAddr - res->offset_in_page, res->size) < 0)
{
printk("%s: do_munmap failed\n", __func__);
}
up_write(&current->mm->mmap_sem);
#endif
}
static gceSTATUS
reserved_mem_map_user(
gckALLOCATOR Allocator,
PLINUX_MDL Mdl,
PLINUX_MDL_MAP MdlMap,
gctBOOL Cacheable
)
{
struct reserved_mem *res = (struct reserved_mem*)Mdl->priv;
gctPOINTER userLogical = gcvNULL;
gceSTATUS status = gcvSTATUS_OK;
gcmkHEADER_ARG("Allocator=%p Mdl=%p Cacheable=%d", Allocator, Mdl, Cacheable);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
userLogical = (gctPOINTER)vm_mmap(NULL, 0L, res->size,
PROT_READ | PROT_WRITE, MAP_SHARED | MAP_NORESERVE, 0);
#else
down_write(&current->mm->mmap_sem);
userLogical = (gctPOINTER)do_mmap_pgoff(NULL, 0L, res->size,
PROT_READ | PROT_WRITE, MAP_SHARED, 0);
up_write(&current->mm->mmap_sem);
#endif
gcmkTRACE_ZONE(
gcvLEVEL_INFO, gcvZONE_OS,
"%s(%d): vmaAddr->%p for phys_addr->%p",
__FUNCTION__, __LINE__, userLogical, Mdl
);
if (IS_ERR(userLogical))
{
gcmkTRACE_ZONE(
gcvLEVEL_INFO, gcvZONE_OS,
"%s(%d): do_mmap_pgoff error",
__FUNCTION__, __LINE__
);
gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
}
down_write(&current->mm->mmap_sem);
do
{
struct vm_area_struct *vma = find_vma(current->mm, (unsigned long)userLogical);
if (vma == gcvNULL)
{
gcmkTRACE_ZONE(
gcvLEVEL_INFO, gcvZONE_OS,
"%s(%d): find_vma error",
__FUNCTION__, __LINE__
);
gcmkERR_BREAK(gcvSTATUS_OUT_OF_RESOURCES);
}
gcmkERR_BREAK(reserved_mem_mmap(Allocator, Mdl, gcvFALSE, 0, Mdl->numPages, vma));
MdlMap->vmaAddr = userLogical + res->offset_in_page;
MdlMap->cacheable = gcvFALSE;
MdlMap->vma = vma;
}
while (gcvFALSE);
up_write(&current->mm->mmap_sem);
OnError:
if (gcmIS_ERROR(status) && userLogical)
{
reserved_mem_unmap_user(Allocator, Mdl, userLogical, res->size);
}
gcmkFOOTER();
return status;
}
static gceSTATUS
reserved_mem_map_kernel(
IN gckALLOCATOR Allocator,
IN PLINUX_MDL Mdl,
IN gctSIZE_T Offset,
IN gctSIZE_T Bytes,
OUT gctPOINTER *Logical
)
{
struct reserved_mem *res = Mdl->priv;
void *vaddr;
if (Offset + Bytes > res->size)
{
return gcvSTATUS_INVALID_ARGUMENT;
}
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,6,0)
vaddr = memremap(res->start + Offset, Bytes, MEMREMAP_WC);
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(4,3,0)
vaddr = memremap(res->start + Offset, Bytes, MEMREMAP_WT);
#else
vaddr = ioremap_nocache(res->start + Offset, Bytes);
#endif
if (!vaddr)
{
return gcvSTATUS_OUT_OF_MEMORY;
}
*Logical = vaddr;
return gcvSTATUS_OK;;
}
static gceSTATUS
reserved_mem_unmap_kernel(
IN gckALLOCATOR Allocator,
IN PLINUX_MDL Mdl,
IN gctPOINTER Logical
)
{
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,3,0)
memunmap((void *)Logical);
#else
iounmap((void *)Logical);
#endif
return gcvSTATUS_OK;
}
static gceSTATUS
reserved_mem_cache_op(
IN gckALLOCATOR Allocator,
IN PLINUX_MDL Mdl,
IN gctSIZE_T Offset,
IN gctPOINTER Logical,
IN gctSIZE_T Bytes,
IN gceCACHEOPERATION Operation
)
{
/* Always WC or UC, safe to use mb. */
switch (Operation)
{
case gcvCACHE_CLEAN:
case gcvCACHE_FLUSH:
_MemoryBarrier();
break;
case gcvCACHE_INVALIDATE:
break;
default:
return gcvSTATUS_INVALID_ARGUMENT;
}
return gcvSTATUS_OK;
}
static gceSTATUS
reserved_mem_get_physical(
IN gckALLOCATOR Allocator,
IN PLINUX_MDL Mdl,
IN gctUINT32 Offset,
OUT gctPHYS_ADDR_T * Physical
)
{
struct reserved_mem *res = Mdl->priv;
*Physical = res->start + Offset;
return gcvSTATUS_OK;
}
static void
reserved_mem_dtor(
gcsALLOCATOR *Allocator
)
{
reserved_mem_debugfs_cleanup(Allocator);
if (Allocator->privateData)
{
kfree(Allocator->privateData);
}
kfree(Allocator);
}
/* GFP allocator operations. */
static gcsALLOCATOR_OPERATIONS reserved_mem_ops = {
.Alloc = reserved_mem_alloc,
.Attach = reserved_mem_attach,
.Free = reserved_mem_detach,
.Mmap = reserved_mem_mmap,
.MapUser = reserved_mem_map_user,
.UnmapUser = reserved_mem_unmap_user,
.MapKernel = reserved_mem_map_kernel,
.UnmapKernel = reserved_mem_unmap_kernel,
.Cache = reserved_mem_cache_op,
.Physical = reserved_mem_get_physical,
};
/* GFP allocator entry. */
gceSTATUS
_ReservedMemoryAllocatorInit(
IN gckOS Os,
IN gcsDEBUGFS_DIR *Parent,
OUT gckALLOCATOR * Allocator
)
{
gceSTATUS status;
gckALLOCATOR allocator = gcvNULL;
struct reserved_mem_alloc *alloc = NULL;
gcmkONERROR(
gckALLOCATOR_Construct(Os, &reserved_mem_ops, &allocator));
alloc = kzalloc(sizeof(*alloc), GFP_KERNEL | gcdNOWARN);
if (!alloc)
{
gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
}
INIT_LIST_HEAD(&alloc->region);
mutex_init(&alloc->lock);
/* Register private data. */
allocator->privateData = alloc;
allocator->destructor = reserved_mem_dtor;
reserved_mem_debugfs_init(allocator, Parent);
allocator->capability = gcvALLOC_FLAG_LINUX_RESERVED_MEM
| gcvALLOC_FLAG_CONTIGUOUS
| gcvALLOC_FLAG_CPU_ACCESS;
*Allocator = allocator;
return gcvSTATUS_OK;
OnError:
if (allocator)
{
kfree(allocator);
}
return status;
}

View File

@ -0,0 +1,876 @@
/****************************************************************************
*
* The MIT License (MIT)
*
* Copyright (c) 2014 - 2019 Vivante Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
*****************************************************************************
*
* The GPL License (GPL)
*
* Copyright (C) 2014 - 2019 Vivante Corporation
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*****************************************************************************
*
* Note: This software is released under dual MIT and GPL licenses. A
* recipient may use this file under the terms of either the MIT license or
* GPL License. If you wish to use only one license not the other, you can
* indicate your decision by deleting one of the above license notices in your
* version of this file.
*
*****************************************************************************/
#include "gc_hal_kernel_linux.h"
#include "gc_hal_kernel_allocator.h"
#include <linux/scatterlist.h>
#include <linux/slab.h>
#include <linux/pagemap.h>
#include <linux/cache.h>
#define _GC_OBJ_ZONE gcvZONE_ALLOCATOR
enum um_desc_type
{
UM_PHYSICAL_MAP,
UM_PAGE_MAP,
UM_PFN_MAP,
};
#if LINUX_VERSION_CODE < KERNEL_VERSION (2,6,24)
struct sg_table
{
struct scatterlist *sgl;
unsigned int nents;
unsigned int orig_nents;
};
#endif
/* Descriptor of a user memory imported. */
struct um_desc
{
int type;
union
{
/* UM_PHYSICAL_MAP. */
unsigned long physical;
/* UM_PAGE_MAP. */
struct
{
struct page **pages;
struct sg_table sgt;
};
/* UM_PFN_MAP. */
struct
{
unsigned long *pfns;
int *refs;
};
};
/* contiguous chunks, does not include padding pages. */
int chunk_count;
unsigned long vm_flags;
unsigned long user_vaddr;
size_t size;
unsigned long offset;
size_t pageCount;
size_t extraPage;
};
static int import_physical_map(struct um_desc *um, unsigned long phys)
{
um->type = UM_PHYSICAL_MAP;
um->physical = phys & PAGE_MASK;
um->chunk_count = 1;
return 0;
}
static int import_page_map(struct um_desc *um,
unsigned long addr, size_t page_count, size_t size)
{
int i;
int result;
struct page **pages;
if ((addr & (cache_line_size() - 1)) || (size & (cache_line_size() - 1)))
{
/* Not cpu cacheline size aligned, can not support. */
return -EINVAL;
}
pages = kzalloc(page_count * sizeof(void *), GFP_KERNEL | gcdNOWARN);
if (!pages)
return -ENOMEM;
down_read(&current->mm->mmap_sem);
result = get_user_pages(
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 6, 0)
current,
current->mm,
#endif
addr & PAGE_MASK,
page_count,
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0)
FOLL_WRITE,
#else
1,
0,
#endif
pages,
NULL);
up_read(&current->mm->mmap_sem);
if (result < page_count)
{
for (i = 0; i < result; i++)
{
if (pages[i])
{
put_page(pages[i]);
}
}
kfree(pages);
return -ENODEV;
}
um->chunk_count = 1;
for (i = 1; i < page_count; i++)
{
if (page_to_pfn(pages[i]) != page_to_pfn(pages[i - 1]) + 1)
{
++um->chunk_count;
}
}
#if LINUX_VERSION_CODE >= KERNEL_VERSION (3,6,0) \
&& (defined(ARCH_HAS_SG_CHAIN) || defined(CONFIG_ARCH_HAS_SG_CHAIN))
result = sg_alloc_table_from_pages(&um->sgt, pages, page_count,
addr & ~PAGE_MASK, size, GFP_KERNEL | gcdNOWARN);
#else
result = alloc_sg_list_from_pages(&um->sgt.sgl, pages, page_count,
addr & ~PAGE_MASK, size, &um->sgt.nents);
um->sgt.orig_nents = um->sgt.nents;
#endif
if (unlikely(result < 0))
{
printk("[galcore]: %s: sg_alloc_table_from_pages failed\n", __FUNCTION__);
goto error;
}
result = dma_map_sg(galcore_device, um->sgt.sgl, um->sgt.nents, DMA_TO_DEVICE);
if (unlikely(result != um->sgt.nents))
{
printk("[galcore]: %s: dma_map_sg failed\n", __FUNCTION__);
goto error;
}
um->type = UM_PAGE_MAP;
um->pages = pages;
return 0;
error:
#if LINUX_VERSION_CODE >= KERNEL_VERSION (3,6,0) \
&& (defined(ARCH_HAS_SG_CHAIN) || defined(CONFIG_ARCH_HAS_SG_CHAIN))
sg_free_table(&um->sgt);
#else
kfree(um->sgt.sgl);
#endif
if (pages)
{
kfree(pages);
}
return result;
}
static int import_pfn_map(struct um_desc *um,
unsigned long addr, size_t pfn_count)
{
int i;
struct vm_area_struct *vma;
unsigned long *pfns;
int *refs;
if (!current->mm)
return -ENOTTY;
down_read(&current->mm->mmap_sem);
vma = find_vma(current->mm, addr);
up_read(&current->mm->mmap_sem);
if (!vma)
return -ENOTTY;
pfns = kzalloc(pfn_count * sizeof(unsigned long), GFP_KERNEL | gcdNOWARN);
if (!pfns)
return -ENOMEM;
refs = kzalloc(pfn_count * sizeof(int), GFP_KERNEL | gcdNOWARN);
if (!refs)
{
kfree(pfns);
return -ENOMEM;
}
for (i = 0; i < pfn_count; i++)
{
spinlock_t *ptl;
pgd_t *pgd;
pud_t *pud;
pmd_t *pmd;
pte_t *pte;
pgd = pgd_offset(current->mm, addr);
if (pgd_none(*pgd) || pgd_bad(*pgd))
goto err;
#if (defined(CONFIG_CPU_CSKYV2) || defined(CONFIG_X86)) \
&& LINUX_VERSION_CODE >= KERNEL_VERSION (4,12,0)
pud = pud_offset((p4d_t*)pgd, addr);
#elif (defined(CONFIG_CPU_CSKYV2)) \
&& LINUX_VERSION_CODE >= KERNEL_VERSION (4,11,0)
pud = pud_offset((p4d_t*)pgd, addr);
#else
pud = pud_offset(pgd, addr);
#endif
if (pud_none(*pud) || pud_bad(*pud))
goto err;
pmd = pmd_offset(pud, addr);
if (pmd_none(*pmd) || pmd_bad(*pmd))
goto err;
pte = pte_offset_map_lock(current->mm, pmd, addr, &ptl);
if (!pte)
{
spin_unlock(ptl);
goto err;
}
if (!pte_present(*pte))
{
pte_unmap_unlock(pte, ptl);
goto err;
}
pfns[i] = pte_pfn(*pte);
pte_unmap_unlock(pte, ptl);
/* Advance to next. */
addr += PAGE_SIZE;
}
for (i = 0; i < pfn_count; i++)
{
if (pfn_valid(pfns[i]))
{
struct page *page = pfn_to_page(pfns[i]);
refs[i] = get_page_unless_zero(page);
}
}
um->chunk_count = 1;
for (i = 1; i < pfn_count; i++)
{
if (pfns[i] != pfns[i - 1] + 1)
{
++um->chunk_count;
}
}
um->type = UM_PFN_MAP;
um->pfns = pfns;
um->refs = refs;
return 0;
err:
if (pfns)
kfree(pfns);
if (refs)
kfree(refs);
return -ENOTTY;
}
static gceSTATUS
_Import(
IN gckOS Os,
IN gctPOINTER Memory,
IN gctPHYS_ADDR_T Physical,
IN gctSIZE_T Size,
IN struct um_desc * UserMemory
)
{
gceSTATUS status = gcvSTATUS_OK;
unsigned long vm_flags = 0;
struct vm_area_struct *vma = NULL;
unsigned long start, end, memory;
int result = 0;
gctSIZE_T extraPage;
gctSIZE_T pageCount, i;
gcmkHEADER_ARG("Os=%p Memory=%p Physical=0x%llx Size=%lu", Os, Memory, Physical, Size);
/* Verify the arguments. */
gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
gcmkVERIFY_ARGUMENT(Memory != gcvNULL || Physical != ~0ULL);
gcmkVERIFY_ARGUMENT(Size > 0);
memory = (unsigned long)Memory;
/* Get the number of required pages. */
end = (memory + Size + PAGE_SIZE - 1) >> PAGE_SHIFT;
start = memory >> PAGE_SHIFT;
pageCount = end - start;
/* Allocate extra page to avoid cache overflow */
#if gcdENABLE_2D
extraPage = 2;
#else
extraPage = (((memory + gcmALIGN(Size + 64, 64) + PAGE_SIZE - 1) >> PAGE_SHIFT) > end) ? 1 : 0;
#endif
gcmkTRACE_ZONE(
gcvLEVEL_INFO, _GC_OBJ_ZONE,
"%s(%d): pageCount: %d. extraPage: %d",
__FUNCTION__, __LINE__,
pageCount, extraPage
);
/* Overflow. */
if ((memory + Size) < memory)
{
gcmkFOOTER_ARG("status=%d", gcvSTATUS_INVALID_ARGUMENT);
return gcvSTATUS_INVALID_ARGUMENT;
}
if (memory)
{
unsigned long vaddr = memory;
for (i = 0; i < pageCount; i++)
{
u32 data = 0;
get_user(data, (u32 *)vaddr);
put_user(data, (u32 *)vaddr);
vaddr += PAGE_SIZE;
/* Fix QM crash with test_buffers */
if (vaddr > memory + Size - 4)
{
vaddr = memory + Size - 4;
}
}
vma = find_vma(current->mm, memory);
if (!vma)
{
/* No such memory, or across vmas. */
gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
}
#ifdef CONFIG_ARM
/* coherent cache in case vivt or vipt-aliasing cache. */
__cpuc_flush_user_range(memory, memory + Size, vma->vm_flags);
#endif
vm_flags = vma->vm_flags;
vaddr = vma->vm_end;
while (vaddr < memory + Size)
{
vma = find_vma(current->mm, vaddr);
if (!vma)
{
/* No such memory. */
gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
}
if ((vma->vm_flags & VM_PFNMAP) != (vm_flags & VM_PFNMAP))
{
/* Can not support different map type: both PFN and PAGE detected. */
gcmkONERROR(gcvSTATUS_NOT_SUPPORTED);
}
vaddr = vma->vm_end;
}
}
if (Physical != gcvINVALID_PHYSICAL_ADDRESS)
{
result = import_physical_map(UserMemory, Physical);
}
else
{
if (vm_flags & VM_PFNMAP)
{
result = import_pfn_map(UserMemory, memory, pageCount);
}
else
{
result = import_page_map(UserMemory, memory, pageCount, Size);
}
}
if (result == -EINVAL)
{
gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
}
else if (result == -ENOMEM)
{
gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
}
else if (result < 0)
{
gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
}
if(Os->device->platform->flagBits & gcvPLATFORM_FLAG_LIMIT_4G_ADDRESS )
{
gctPHYS_ADDR_T addr;
if (Physical != gcvINVALID_PHYSICAL_ADDRESS)
{
if(Physical > 0xFFFFFFFFu || Physical + Size > 0xFFFFFFFFu )
{
gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
}
}
else if (vm_flags & VM_PFNMAP)
{
for(i = 0; i < pageCount; i++)
{
addr = UserMemory->pfns[i] << PAGE_SHIFT;
if( addr > 0xFFFFFFFFu)
{
kfree(UserMemory->pfns);
UserMemory->pfns = gcvNULL;
kfree(UserMemory->refs) ;
UserMemory->refs = gcvNULL;
gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
}
}
}
else
{
for (i = 0; i< pageCount; i++)
{
addr = page_to_phys(UserMemory->pages[i]);
if(addr > 0xFFFFFFFFu )
{
kfree(UserMemory->pages);
UserMemory->pages = gcvNULL;
gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
}
}
}
}
UserMemory->vm_flags = vm_flags;
UserMemory->user_vaddr = (unsigned long)Memory;
UserMemory->size = Size;
UserMemory->offset = (Physical != gcvINVALID_PHYSICAL_ADDRESS)
? (Physical & ~PAGE_MASK)
: (memory & ~PAGE_MASK);
UserMemory->pageCount = pageCount;
UserMemory->extraPage = extraPage;
if (extraPage && UserMemory->type == UM_PAGE_MAP)
{
/*Add the padding pages */
UserMemory->chunk_count++;
}
/* Success. */
gcmkFOOTER();
return gcvSTATUS_OK;
OnError:
gcmkFOOTER();
return status;
}
static gceSTATUS
_UserMemoryAttach(
IN gckALLOCATOR Allocator,
IN gcsATTACH_DESC_PTR Desc,
IN PLINUX_MDL Mdl
)
{
gceSTATUS status;
struct um_desc * userMemory = gcvNULL;
gckOS os = Allocator->os;
gcmkHEADER();
/* Handle is meangless for this importer. */
gcmkVERIFY_ARGUMENT(Desc != gcvNULL);
gcmkONERROR(gckOS_Allocate(os, gcmSIZEOF(struct um_desc), (gctPOINTER *)&userMemory));
gckOS_ZeroMemory(userMemory, gcmSIZEOF(struct um_desc));
gcmkONERROR(_Import(os, Desc->userMem.memory, Desc->userMem.physical, Desc->userMem.size, userMemory));
Mdl->priv = userMemory;
Mdl->numPages = userMemory->pageCount + userMemory->extraPage;
Mdl->contiguous = (userMemory->chunk_count == 1);
gcmkFOOTER_NO();
return gcvSTATUS_OK;
OnError:
if (userMemory != gcvNULL)
{
gckOS_Free(os,(gctPOINTER)userMemory);
}
gcmkFOOTER();
return status;
}
static void release_physical_map(struct um_desc *um)
{
}
static void release_page_map(struct um_desc *um)
{
int i;
dma_sync_sg_for_device(galcore_device,
um->sgt.sgl, um->sgt.nents, DMA_TO_DEVICE);
dma_sync_sg_for_cpu(galcore_device,
um->sgt.sgl, um->sgt.nents, DMA_FROM_DEVICE);
dma_unmap_sg(galcore_device, um->sgt.sgl, um->sgt.nents, DMA_FROM_DEVICE);
#if LINUX_VERSION_CODE >= KERNEL_VERSION (3,6,0) \
&& (defined(ARCH_HAS_SG_CHAIN) || defined(CONFIG_ARCH_HAS_SG_CHAIN))
sg_free_table(&um->sgt);
#else
kfree(um->sgt.sgl);
#endif
for (i = 0; i < um->pageCount; i++)
{
if (!PageReserved(um->pages[i]))
{
SetPageDirty(um->pages[i]);
}
put_page(um->pages[i]);
}
kfree(um->pages);
}
static void release_pfn_map(struct um_desc *um)
{
int i;
for (i = 0; i < um->pageCount; i++)
{
if (pfn_valid(um->pfns[i]))
{
struct page *page = pfn_to_page(um->pfns[i]);
if (!PageReserved(page))
{
SetPageDirty(page);
}
if (um->refs[i])
{
put_page(page);
}
}
}
kfree(um->pfns);
kfree(um->refs);
}
static void
_UserMemoryFree(
IN gckALLOCATOR Allocator,
IN PLINUX_MDL Mdl
)
{
gckOS os = Allocator->os;
struct um_desc *userMemory = Mdl->priv;
gcmkHEADER();
if (userMemory)
{
switch (userMemory->type)
{
case UM_PHYSICAL_MAP:
release_physical_map(userMemory);
break;
case UM_PAGE_MAP:
release_page_map(userMemory);
break;
case UM_PFN_MAP:
release_pfn_map(userMemory);
break;
}
gcmkOS_SAFE_FREE(os, userMemory);
}
gcmkFOOTER_NO();
}
static gceSTATUS
_UserMemoryMapUser(
IN gckALLOCATOR Allocator,
IN PLINUX_MDL Mdl,
IN PLINUX_MDL_MAP MdlMap,
IN gctBOOL Cacheable
)
{
struct um_desc *userMemory = Mdl->priv;
MdlMap->vmaAddr = (gctPOINTER)userMemory->user_vaddr;
MdlMap->cacheable = gcvTRUE;
return gcvSTATUS_OK;
}
static void
_UserMemoryUnmapUser(
IN gckALLOCATOR Allocator,
IN PLINUX_MDL Mdl,
IN PLINUX_MDL_MAP MdlMap,
IN gctUINT32 Size
)
{
return;
}
static gceSTATUS
_UserMemoryMapKernel(
IN gckALLOCATOR Allocator,
IN PLINUX_MDL Mdl,
IN gctSIZE_T Offset,
IN gctSIZE_T Bytes,
OUT gctPOINTER *Logical
)
{
/* Kernel doesn't acess video memory. */
return gcvSTATUS_NOT_SUPPORTED;
}
static gceSTATUS
_UserMemoryUnmapKernel(
IN gckALLOCATOR Allocator,
IN PLINUX_MDL Mdl,
IN gctPOINTER Logical
)
{
/* Kernel doesn't acess video memory. */
return gcvSTATUS_NOT_SUPPORTED;
}
static gceSTATUS
_UserMemoryCache(
IN gckALLOCATOR Allocator,
IN PLINUX_MDL Mdl,
IN gctSIZE_T Offset,
IN gctPOINTER Logical,
IN gctSIZE_T Bytes,
IN gceCACHEOPERATION Operation
)
{
struct um_desc *um = Mdl->priv;
enum dma_data_direction dir;
if (um->type != UM_PAGE_MAP)
{
_MemoryBarrier();
return gcvSTATUS_OK;
}
#ifdef CONFIG_ARM
/* coherent cache in case vivt or vipt-aliasing cache. */
__cpuc_flush_user_range(um->user_vaddr,
um->user_vaddr + um->size, um->vm_flags);
#endif
switch (Operation)
{
case gcvCACHE_CLEAN:
dir = DMA_TO_DEVICE;
dma_sync_sg_for_device(galcore_device, um->sgt.sgl, um->sgt.nents, dir);
break;
case gcvCACHE_FLUSH:
dir = DMA_TO_DEVICE;
dma_sync_sg_for_device(galcore_device, um->sgt.sgl, um->sgt.nents, dir);
dir = DMA_FROM_DEVICE;
dma_sync_sg_for_cpu(galcore_device, um->sgt.sgl, um->sgt.nents, dir);
break;
case gcvCACHE_INVALIDATE:
dir = DMA_FROM_DEVICE;
dma_sync_sg_for_cpu(galcore_device, um->sgt.sgl, um->sgt.nents, dir);
break;
default:
return gcvSTATUS_INVALID_ARGUMENT;
}
return gcvSTATUS_OK;
}
static gceSTATUS
_UserMemoryPhysical(
IN gckALLOCATOR Allocator,
IN PLINUX_MDL Mdl,
IN gctUINT32 Offset,
OUT gctPHYS_ADDR_T * Physical
)
{
gckOS os = Allocator->os;
struct um_desc *userMemory = Mdl->priv;
unsigned long offset = Offset + userMemory->offset;
gctUINT32 offsetInPage = offset & ~PAGE_MASK;
gctUINT32 index = offset / PAGE_SIZE;
if (index >= userMemory->pageCount)
{
if (index < userMemory->pageCount + userMemory->extraPage)
{
*Physical = page_to_phys(os->paddingPage);
}
else
{
return gcvSTATUS_INVALID_ARGUMENT;
}
}
else
{
switch (userMemory->type)
{
case UM_PHYSICAL_MAP:
*Physical = userMemory->physical + (gctPHYS_ADDR_T)index * PAGE_SIZE;
break;
case UM_PAGE_MAP:
*Physical = page_to_phys(userMemory->pages[index]);
break;
case UM_PFN_MAP:
*Physical = (gctPHYS_ADDR_T)userMemory->pfns[index] << PAGE_SHIFT;
break;
}
}
*Physical += offsetInPage;
return gcvSTATUS_OK;
}
static void
_UserMemoryAllocatorDestructor(
gcsALLOCATOR *Allocator
)
{
if (Allocator->privateData)
{
kfree(Allocator->privateData);
}
kfree(Allocator);
}
/* User memory allocator (importer) operations. */
static gcsALLOCATOR_OPERATIONS UserMemoryAllocatorOperations =
{
.Attach = _UserMemoryAttach,
.Free = _UserMemoryFree,
.MapUser = _UserMemoryMapUser,
.UnmapUser = _UserMemoryUnmapUser,
.MapKernel = _UserMemoryMapKernel,
.UnmapKernel = _UserMemoryUnmapKernel,
.Cache = _UserMemoryCache,
.Physical = _UserMemoryPhysical,
};
/* Default allocator entry. */
gceSTATUS
_UserMemoryAlloctorInit(
IN gckOS Os,
IN gcsDEBUGFS_DIR *Parent,
OUT gckALLOCATOR * Allocator
)
{
gceSTATUS status;
gckALLOCATOR allocator;
gcmkONERROR(
gckALLOCATOR_Construct(Os, &UserMemoryAllocatorOperations, &allocator));
allocator->destructor = _UserMemoryAllocatorDestructor;
allocator->capability = gcvALLOC_FLAG_USERMEMORY;
*Allocator = allocator;
return gcvSTATUS_OK;
OnError:
return status;
}

View File

@ -0,0 +1,131 @@
/****************************************************************************
*
* The MIT License (MIT)
*
* Copyright (c) 2014 - 2019 Vivante Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
*****************************************************************************
*
* The GPL License (GPL)
*
* Copyright (C) 2014 - 2019 Vivante Corporation
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*****************************************************************************
*
* Note: This software is released under dual MIT and GPL licenses. A
* recipient may use this file under the terms of either the MIT license or
* GPL License. If you wish to use only one license not the other, you can
* indicate your decision by deleting one of the above license notices in your
* version of this file.
*
*****************************************************************************/
#ifndef __gc_hal_kernel_allocator_array_h_
#define __gc_hal_kernel_allocator_array_h_
extern gceSTATUS
_GFPAlloctorInit(
IN gckOS Os,
IN gcsDEBUGFS_DIR *Parent,
OUT gckALLOCATOR * Allocator
);
extern gceSTATUS
_UserMemoryAlloctorInit(
IN gckOS Os,
IN gcsDEBUGFS_DIR *Parent,
OUT gckALLOCATOR * Allocator
);
extern gceSTATUS
_ReservedMemoryAllocatorInit(
IN gckOS Os,
IN gcsDEBUGFS_DIR *Parent,
OUT gckALLOCATOR * Allocator
);
#if LINUX_CMA_FSL
extern gceSTATUS
_CMAFSLAlloctorInit(
IN gckOS Os,
IN gcsDEBUGFS_DIR *Parent,
OUT gckALLOCATOR * Allocator
);
#endif
#ifdef CONFIG_DMA_SHARED_BUFFER
extern gceSTATUS
_DmabufAlloctorInit(
IN gckOS Os,
IN gcsDEBUGFS_DIR *Parent,
OUT gckALLOCATOR * Allocator
);
#endif
#ifndef NO_DMA_COHERENT
extern gceSTATUS
_DmaAlloctorInit(
IN gckOS Os,
IN gcsDEBUGFS_DIR *Parent,
OUT gckALLOCATOR * Allocator
);
#endif
gcsALLOCATOR_DESC allocatorArray[] =
{
/* GFP allocator. */
gcmkDEFINE_ALLOCATOR_DESC("gfp", _GFPAlloctorInit),
#if LINUX_CMA_FSL
gcmkDEFINE_ALLOCATOR_DESC("cmafsl", _CMAFSLAlloctorInit),
#endif
/* User memory importer. */
gcmkDEFINE_ALLOCATOR_DESC("user", _UserMemoryAlloctorInit),
#ifdef CONFIG_DMA_SHARED_BUFFER
/* Dmabuf allocator. */
gcmkDEFINE_ALLOCATOR_DESC("dmabuf", _DmabufAlloctorInit),
#endif
#ifndef NO_DMA_COHERENT
gcmkDEFINE_ALLOCATOR_DESC("dma", _DmaAlloctorInit),
#endif
gcmkDEFINE_ALLOCATOR_DESC("reserved-mem", _ReservedMemoryAllocatorInit),
};
#endif

View File

@ -0,0 +1,611 @@
/****************************************************************************
*
* The MIT License (MIT)
*
* Copyright (c) 2014 - 2019 Vivante Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
*****************************************************************************
*
* The GPL License (GPL)
*
* Copyright (C) 2014 - 2019 Vivante Corporation
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*****************************************************************************
*
* Note: This software is released under dual MIT and GPL licenses. A
* recipient may use this file under the terms of either the MIT license or
* GPL License. If you wish to use only one license not the other, you can
* indicate your decision by deleting one of the above license notices in your
* version of this file.
*
*****************************************************************************/
#include "gc_hal_kernel_linux.h"
#include "gc_hal_kernel_allocator.h"
#include <linux/pagemap.h>
#include <linux/seq_file.h>
#include <linux/mman.h>
#include <asm/atomic.h>
#include <linux/dma-mapping.h>
#include <linux/slab.h>
#include <linux/platform_device.h>
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,16,0)
#include <linux/dma-direct.h>
#endif
#define _GC_OBJ_ZONE gcvZONE_OS
typedef struct _gcsCMA_PRIV * gcsCMA_PRIV_PTR;
typedef struct _gcsCMA_PRIV {
atomic_t cmasize;
gctBOOL cmaLimitRequest;
}
gcsCMA_PRIV;
struct mdl_cma_priv {
gctPOINTER kvaddr;
dma_addr_t physical;
};
static int gc_cma_usage_show(struct seq_file* m, void* data)
{
gcsINFO_NODE *node = m->private;
gckALLOCATOR Allocator = node->device;
gcsCMA_PRIV_PTR priv = Allocator->privateData;
long long size = (long long)atomic_read(&priv->cmasize);
seq_printf(m, "type n pages bytes\n");
seq_printf(m, "cma %10llu %12llu\n", size, size * PAGE_SIZE);
return 0;
}
static gcsINFO InfoList[] =
{
{"cmausage", gc_cma_usage_show},
};
static void
_CMAAllocatorDebugfsInit(
IN gckALLOCATOR Allocator,
IN gckDEBUGFS_DIR Root
)
{
gcmkVERIFY_OK(
gckDEBUGFS_DIR_Init(&Allocator->debugfsDir, Root->root, "cma"));
gcmkVERIFY_OK(gckDEBUGFS_DIR_CreateFiles(
&Allocator->debugfsDir,
InfoList,
gcmCOUNTOF(InfoList),
Allocator
));
}
static void
_CMAAllocatorDebugfsCleanup(
IN gckALLOCATOR Allocator
)
{
gcmkVERIFY_OK(gckDEBUGFS_DIR_RemoveFiles(
&Allocator->debugfsDir,
InfoList,
gcmCOUNTOF(InfoList)
));
gckDEBUGFS_DIR_Deinit(&Allocator->debugfsDir);
}
static gceSTATUS
_CMAFSLAlloc(
IN gckALLOCATOR Allocator,
INOUT PLINUX_MDL Mdl,
IN gctSIZE_T NumPages,
IN gctUINT32 Flags
)
{
gceSTATUS status;
u32 gfp = GFP_KERNEL | gcdNOWARN;
gcsCMA_PRIV_PTR priv = (gcsCMA_PRIV_PTR)Allocator->privateData;
struct mdl_cma_priv *mdl_priv=gcvNULL;
gckOS os = Allocator->os;
gcmkHEADER_ARG("Mdl=%p NumPages=0x%zx", Mdl, NumPages);
if (os->allocatorLimitMarker && !(Flags & gcvALLOC_FLAG_CMA_PREEMPT))
{
if (Flags & gcvALLOC_FLAG_CMA_LIMIT)
{
priv->cmaLimitRequest = gcvTRUE;
}
else if (priv->cmaLimitRequest == gcvTRUE)
{
gcmkONERROR(gcvSTATUS_NOT_SUPPORTED);
}
}
gcmkONERROR(gckOS_Allocate(os, sizeof(struct mdl_cma_priv), (gctPOINTER *)&mdl_priv));
mdl_priv->kvaddr = gcvNULL;
#if defined(CONFIG_ZONE_DMA32) && LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)
if (Flags & gcvALLOC_FLAG_4GB_ADDR)
{
gfp |= __GFP_DMA32;
}
#endif
mdl_priv->kvaddr = dma_alloc_writecombine(&os->device->platform->device->dev,
NumPages * PAGE_SIZE,
&mdl_priv->physical,
gfp);
if (mdl_priv->kvaddr == gcvNULL)
{
gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
}
Mdl->priv = mdl_priv;
Mdl->dmaHandle = mdl_priv->physical;
atomic_add(NumPages, &priv->cmasize);
gcmkFOOTER_NO();
return gcvSTATUS_OK;
OnError:
if (mdl_priv)
{
gckOS_Free(os, mdl_priv);
}
gcmkFOOTER();
return status;
}
static gceSTATUS
_CMAFSLGetSGT(
IN gckALLOCATOR Allocator,
IN PLINUX_MDL Mdl,
IN gctSIZE_T Offset,
IN gctSIZE_T Bytes,
OUT gctPOINTER *SGT
)
{
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)
struct page ** pages = gcvNULL;
struct page * page = gcvNULL;
struct sg_table *sgt = NULL;
struct mdl_cma_priv *mdl_priv = (struct mdl_cma_priv*)Mdl->priv;
gceSTATUS status = gcvSTATUS_OK;
gctSIZE_T offset = Offset & ~PAGE_MASK; /* Offset to the first page */
gctINT skipPages = Offset >> PAGE_SHIFT; /* skipped pages */
gctINT numPages = (PAGE_ALIGN(Offset + Bytes) >> PAGE_SHIFT) - skipPages;
gctINT i;
gcmkASSERT(Offset + Bytes <= Mdl->numPages << PAGE_SHIFT);
sgt = kmalloc(sizeof(struct sg_table), GFP_KERNEL | gcdNOWARN);
if (!sgt)
{
gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
}
pages = kmalloc(sizeof(struct page*) * numPages, GFP_KERNEL | gcdNOWARN);
if (!pages)
{
gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
}
#if !defined(phys_to_page)
page = virt_to_page(mdlPriv->kvaddr);
#elif LINUX_VERSION_CODE < KERNEL_VERSION(3,13,0)
page = phys_to_page(mdlPriv->physical);
#else
page = phys_to_page(dma_to_phys(&Allocator->os->device->platform->device->dev, mdl_priv->physical));
#endif
for (i = 0; i < numPages; ++i)
{
pages[i] = nth_page(page, i + skipPages);
}
if (sg_alloc_table_from_pages(sgt, pages, numPages, offset, Bytes, GFP_KERNEL) < 0)
{
gcmkONERROR(gcvSTATUS_GENERIC_IO);
}
*SGT = (gctPOINTER)sgt;
OnError:
if (pages)
{
kfree(pages);
}
if (gcmIS_ERROR(status) && sgt)
{
kfree(sgt);
}
return status;
#else
return gcvSTATUS_NOT_SUPPORTED;
#endif
}
static void
_CMAFSLFree(
IN gckALLOCATOR Allocator,
IN OUT PLINUX_MDL Mdl
)
{
gckOS os = Allocator->os;
struct mdl_cma_priv *mdlPriv=(struct mdl_cma_priv *)Mdl->priv;
gcsCMA_PRIV_PTR priv = (gcsCMA_PRIV_PTR)Allocator->privateData;
dma_free_writecombine(&os->device->platform->device->dev,
Mdl->numPages * PAGE_SIZE,
mdlPriv->kvaddr,
mdlPriv->physical);
gckOS_Free(os, mdlPriv);
atomic_sub(Mdl->numPages, &priv->cmasize);
}
static gceSTATUS
_CMAFSLMmap(
IN gckALLOCATOR Allocator,
IN PLINUX_MDL Mdl,
IN gctBOOL Cacheable,
IN gctSIZE_T skipPages,
IN gctSIZE_T numPages,
IN struct vm_area_struct *vma
)
{
gckOS os = Allocator->os;
struct mdl_cma_priv *mdlPriv = (struct mdl_cma_priv*)Mdl->priv;
gceSTATUS status = gcvSTATUS_OK;
gcmkHEADER_ARG("Allocator=%p Mdl=%p vma=%p", Allocator, Mdl, vma);
gcmkASSERT(skipPages + numPages <= Mdl->numPages);
/* Now map all the vmalloc pages to this user address. */
if (Mdl->contiguous)
{
/* map kernel memory to user space.. */
if (dma_mmap_writecombine(&os->device->platform->device->dev,
vma,
(gctINT8_PTR)mdlPriv->kvaddr + (skipPages << PAGE_SHIFT),
mdlPriv->physical + (skipPages << PAGE_SHIFT),
numPages << PAGE_SHIFT) < 0)
{
gcmkTRACE_ZONE(
gcvLEVEL_WARNING, gcvZONE_OS,
"%s(%d): dma_mmap_attrs error",
__FUNCTION__, __LINE__
);
gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
}
}
else
{
gcmkFATAL("%s(%d): unexpected noncontiguous mdl\n");
gcmkONERROR(gcvSTATUS_HEAP_CORRUPTED);
}
OnError:
gcmkFOOTER();
return status;
}
static void
_CMAFSLUnmapUser(
IN gckALLOCATOR Allocator,
IN PLINUX_MDL Mdl,
IN PLINUX_MDL_MAP MdlMap,
IN gctUINT32 Size
)
{
if (unlikely(current->mm == gcvNULL))
{
/* Do nothing if process is exiting. */
return;
}
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0)
if (vm_munmap((unsigned long)MdlMap->vmaAddr, Size) < 0)
{
gcmkTRACE_ZONE(
gcvLEVEL_WARNING, gcvZONE_OS,
"%s(%d): vm_munmap failed",
__FUNCTION__, __LINE__
);
}
#else
down_write(&current->mm->mmap_sem);
if (do_munmap(current->mm, (unsigned long)MdlMap->vmaAddr, Size) < 0)
{
gcmkTRACE_ZONE(
gcvLEVEL_WARNING, gcvZONE_OS,
"%s(%d): do_munmap failed",
__FUNCTION__, __LINE__
);
}
up_write(&current->mm->mmap_sem);
#endif
}
static gceSTATUS
_CMAFSLMapUser(
IN gckALLOCATOR Allocator,
IN PLINUX_MDL Mdl,
IN PLINUX_MDL_MAP MdlMap,
IN gctBOOL Cacheable
)
{
gctPOINTER userLogical = gcvNULL;
gceSTATUS status = gcvSTATUS_OK;
gcmkHEADER_ARG("Allocator=%p Mdl=%p Cacheable=%d", Allocator, Mdl, Cacheable);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
userLogical = (gctPOINTER)vm_mmap(gcvNULL,
0L,
Mdl->numPages * PAGE_SIZE,
PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_NORESERVE,
0);
#else
down_write(&current->mm->mmap_sem);
userLogical = (gctPOINTER)do_mmap_pgoff(gcvNULL,
0L,
Mdl->numPages * PAGE_SIZE,
PROT_READ | PROT_WRITE,
MAP_SHARED,
0);
up_write(&current->mm->mmap_sem);
#endif
gcmkTRACE_ZONE(
gcvLEVEL_INFO, gcvZONE_OS,
"%s(%d): vmaAddr->%p for phys_addr->%p",
__FUNCTION__, __LINE__, userLogical, Mdl
);
if (IS_ERR(userLogical))
{
gcmkTRACE_ZONE(
gcvLEVEL_INFO, gcvZONE_OS,
"%s(%d): do_mmap_pgoff error",
__FUNCTION__, __LINE__
);
gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
}
down_write(&current->mm->mmap_sem);
do
{
struct vm_area_struct *vma = find_vma(current->mm, (unsigned long)userLogical);
if (vma == gcvNULL)
{
gcmkTRACE_ZONE(
gcvLEVEL_INFO, gcvZONE_OS,
"%s(%d): find_vma error",
__FUNCTION__, __LINE__
);
gcmkERR_BREAK(gcvSTATUS_OUT_OF_RESOURCES);
}
gcmkERR_BREAK(_CMAFSLMmap(Allocator, Mdl, Cacheable, 0, Mdl->numPages, vma));
MdlMap->vmaAddr = userLogical;
MdlMap->cacheable = Cacheable;
MdlMap->vma = vma;
}
while (gcvFALSE);
up_write(&current->mm->mmap_sem);
OnError:
if (gcmIS_ERROR(status) && userLogical && !IS_ERR(userLogical))
{
_CMAFSLUnmapUser(Allocator, Mdl, userLogical, Mdl->numPages * PAGE_SIZE);
}
gcmkFOOTER();
return status;
}
static gceSTATUS
_CMAMapKernel(
IN gckALLOCATOR Allocator,
IN PLINUX_MDL Mdl,
IN gctSIZE_T Offset,
IN gctSIZE_T Bytes,
OUT gctPOINTER *Logical
)
{
struct mdl_cma_priv *mdl_priv=(struct mdl_cma_priv *)Mdl->priv;
*Logical = (uint8_t *)mdl_priv->kvaddr + Offset;
return gcvSTATUS_OK;
}
static gceSTATUS
_CMAUnmapKernel(
IN gckALLOCATOR Allocator,
IN PLINUX_MDL Mdl,
IN gctPOINTER Logical
)
{
return gcvSTATUS_OK;
}
static gceSTATUS
_CMACache(
IN gckALLOCATOR Allocator,
IN PLINUX_MDL Mdl,
IN gctSIZE_T Offset,
IN gctPOINTER Logical,
IN gctSIZE_T Bytes,
IN gceCACHEOPERATION Operation
)
{
switch (Operation)
{
case gcvCACHE_CLEAN:
case gcvCACHE_FLUSH:
_MemoryBarrier();
break;
case gcvCACHE_INVALIDATE:
break;
default:
return gcvSTATUS_INVALID_ARGUMENT;
}
return gcvSTATUS_OK;
}
static gceSTATUS
_CMAPhysical(
IN gckALLOCATOR Allocator,
IN PLINUX_MDL Mdl,
IN gctUINT32 Offset,
OUT gctPHYS_ADDR_T * Physical
)
{
struct mdl_cma_priv *mdl_priv=(struct mdl_cma_priv *)Mdl->priv;
*Physical = mdl_priv->physical + Offset;
return gcvSTATUS_OK;
}
static void
_CMAAllocatorDestructor(
gcsALLOCATOR *Allocator
)
{
_CMAAllocatorDebugfsCleanup(Allocator);
if (Allocator->privateData)
{
kfree(Allocator->privateData);
}
kfree(Allocator);
}
/* Default allocator operations. */
static gcsALLOCATOR_OPERATIONS CMAFSLAllocatorOperations =
{
.Alloc = _CMAFSLAlloc,
.Free = _CMAFSLFree,
.Mmap = _CMAFSLMmap,
.MapUser = _CMAFSLMapUser,
.UnmapUser = _CMAFSLUnmapUser,
.MapKernel = _CMAMapKernel,
.UnmapKernel = _CMAUnmapKernel,
.Cache = _CMACache,
.Physical = _CMAPhysical,
.GetSGT = _CMAFSLGetSGT,
};
/* Default allocator entry. */
gceSTATUS
_CMAFSLAlloctorInit(
IN gckOS Os,
IN gcsDEBUGFS_DIR *Parent,
OUT gckALLOCATOR * Allocator
)
{
gceSTATUS status;
gckALLOCATOR allocator = gcvNULL;
gcsCMA_PRIV_PTR priv = gcvNULL;
gcmkONERROR(
gckALLOCATOR_Construct(Os, &CMAFSLAllocatorOperations, &allocator));
priv = kzalloc(gcmSIZEOF(gcsCMA_PRIV), GFP_KERNEL | gcdNOWARN);
if (!priv)
{
gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
}
atomic_set(&priv->cmasize, 0);
/* Register private data. */
allocator->privateData = priv;
allocator->destructor = _CMAAllocatorDestructor;
_CMAAllocatorDebugfsInit(allocator, Parent);
allocator->capability = gcvALLOC_FLAG_CONTIGUOUS
| gcvALLOC_FLAG_DMABUF_EXPORTABLE
#if defined(CONFIG_ZONE_DMA32) && LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)
| gcvALLOC_FLAG_4GB_ADDR
#endif
;
#if defined(CONFIG_ARM64)
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,0,0)
Os->allocatorLimitMarker = (Os->device->baseAddress + totalram_pages() * PAGE_SIZE) > 0x100000000;
#else
Os->allocatorLimitMarker = (Os->device->baseAddress + totalram_pages * PAGE_SIZE) > 0x100000000;
#endif
#else
Os->allocatorLimitMarker = gcvFALSE;
#endif
priv->cmaLimitRequest = gcvFALSE;
if (Os->allocatorLimitMarker)
{
allocator->capability |= gcvALLOC_FLAG_CMA_LIMIT;
}
allocator->capability |= gcvALLOC_FLAG_CMA_PREEMPT;
*Allocator = allocator;
return gcvSTATUS_OK;
OnError:
if (allocator)
{
kfree(allocator);
}
return status;
}

View File

@ -0,0 +1,260 @@
/****************************************************************************
*
* The MIT License (MIT)
*
* Copyright (c) 2014 - 2019 Vivante Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
*****************************************************************************
*
* The GPL License (GPL)
*
* Copyright (C) 2014 - 2019 Vivante Corporation
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*****************************************************************************
*
* Note: This software is released under dual MIT and GPL licenses. A
* recipient may use this file under the terms of either the MIT license or
* GPL License. If you wish to use only one license not the other, you can
* indicate your decision by deleting one of the above license notices in your
* version of this file.
*
*****************************************************************************/
#include "gc_hal_kernel_linux.h"
#include "gc_hal_kernel_allocator.h"
#include <linux/pagemap.h>
#include <linux/seq_file.h>
#include <linux/mman.h>
#include <asm/atomic.h>
#include <linux/dma-mapping.h>
#include <linux/slab.h>
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32)
#include <linux/anon_inodes.h>
#endif
#include <linux/file.h>
#include "gc_hal_kernel_allocator_array.h"
#include "gc_hal_kernel_platform.h"
#define _GC_OBJ_ZONE gcvZONE_OS
/******************************************************************************\
******************************** Debugfs Support *******************************
\******************************************************************************/
static gceSTATUS
_AllocatorDebugfsInit(
IN gckOS Os
)
{
gceSTATUS status;
gckGALDEVICE device = Os->device;
gckDEBUGFS_DIR dir = &Os->allocatorDebugfsDir;
gcmkONERROR(gckDEBUGFS_DIR_Init(dir, device->debugfsDir.root, "allocators"));
return gcvSTATUS_OK;
OnError:
return status;
}
static void
_AllocatorDebugfsCleanup(
IN gckOS Os
)
{
gckDEBUGFS_DIR dir = &Os->allocatorDebugfsDir;
gckDEBUGFS_DIR_Deinit(dir);
}
/***************************************************************************\
************************ Allocator management *******************************
\***************************************************************************/
gceSTATUS
gckOS_ImportAllocators(
gckOS Os
)
{
gceSTATUS status;
gctUINT i;
gckALLOCATOR allocator;
_AllocatorDebugfsInit(Os);
INIT_LIST_HEAD(&Os->allocatorList);
for (i = 0; i < gcmCOUNTOF(allocatorArray); i++)
{
if (allocatorArray[i].construct)
{
/* Construct allocator. */
status = allocatorArray[i].construct(Os, &Os->allocatorDebugfsDir, &allocator);
if (gcmIS_ERROR(status))
{
gcmkPRINT("["DEVICE_NAME"]: Can't construct allocator(%s)",
allocatorArray[i].name);
continue;
}
allocator->name = allocatorArray[i].name;
list_add_tail(&allocator->link, &Os->allocatorList);
}
}
#if gcdDEBUG
list_for_each_entry(allocator, &Os->allocatorList, link)
{
gcmkTRACE_ZONE(
gcvLEVEL_WARNING, gcvZONE_OS,
"%s(%d) Allocator: %s",
__FUNCTION__, __LINE__,
allocator->name
);
}
#endif
return gcvSTATUS_OK;
}
gceSTATUS
gckOS_FreeAllocators(
gckOS Os
)
{
gckALLOCATOR allocator;
gckALLOCATOR temp;
list_for_each_entry_safe(allocator, temp, &Os->allocatorList, link)
{
list_del(&allocator->link);
/* Destroy allocator. */
allocator->destructor(allocator);
}
_AllocatorDebugfsCleanup(Os);
return gcvSTATUS_OK;
}
#if LINUX_VERSION_CODE < KERNEL_VERSION (3,6,0) \
|| (!defined (ARCH_HAS_SG_CHAIN) && !defined (CONFIG_ARCH_HAS_SG_CHAIN))
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,23)
static inline void sg_set_page(struct scatterlist *sg, struct page *page,
unsigned int len, unsigned int offset)
{
sg->page = page;
sg->offset = offset;
sg->length = len;
}
static inline void sg_mark_end(struct scatterlist *sg)
{
(void)sg;
}
# endif
int
alloc_sg_list_from_pages(
struct scatterlist **sgl,
struct page **pages,
unsigned int n_pages,
unsigned long offset,
unsigned long size,
unsigned int *nents
)
{
unsigned int chunks;
unsigned int i;
unsigned int cur_page;
struct scatterlist *s;
chunks = 1;
for (i = 1; i < n_pages; ++i)
{
if (page_to_pfn(pages[i]) != page_to_pfn(pages[i - 1]) + 1)
{
++chunks;
}
}
s = kzalloc(sizeof(struct scatterlist) * chunks, GFP_KERNEL);
if (unlikely(!s))
{
return -ENOMEM;
}
*sgl = s;
*nents = chunks;
cur_page = 0;
for (i = 0; i < chunks; i++, s++)
{
unsigned long chunk_size;
unsigned int j;
for (j = cur_page + 1; j < n_pages; j++)
{
if (page_to_pfn(pages[j]) != page_to_pfn(pages[j - 1]) + 1)
{
break;
}
}
chunk_size = ((j - cur_page) << PAGE_SHIFT) - offset;
sg_set_page(s, pages[cur_page], min(size, chunk_size), offset);
size -= chunk_size;
offset = 0;
cur_page = j;
}
sg_mark_end(s - 1);
return 0;
}
#endif

View File

@ -0,0 +1,608 @@
/****************************************************************************
*
* The MIT License (MIT)
*
* Copyright (c) 2014 - 2019 Vivante Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
*****************************************************************************
*
* The GPL License (GPL)
*
* Copyright (C) 2014 - 2019 Vivante Corporation
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*****************************************************************************
*
* Note: This software is released under dual MIT and GPL licenses. A
* recipient may use this file under the terms of either the MIT license or
* GPL License. If you wish to use only one license not the other, you can
* indicate your decision by deleting one of the above license notices in your
* version of this file.
*
*****************************************************************************/
#ifndef __gc_hal_kernel_allocator_h_
#define __gc_hal_kernel_allocator_h_
#include "gc_hal_kernel_linux.h"
#include <linux/slab.h>
#include <linux/mm_types.h>
typedef struct _gcsALLOCATOR * gckALLOCATOR;
typedef union _gcsATTACH_DESC * gcsATTACH_DESC_PTR;
typedef struct _gcsALLOCATOR_OPERATIONS
{
/**************************************************************************
**
** Alloc
**
** Allocte memory, request size is page aligned.
**
** INPUT:
**
** gckALLOCATOR Allocator
** Pointer to an gckALLOCATOER object.
**
** PLINUX_Mdl
** Pointer to Mdl whichs stores information
** about allocated memory.
**
** gctSIZE_T NumPages
** Number of pages need to allocate.
**
** gctUINT32 Flag
** Allocation option.
**
** OUTPUT:
**
** Nothing.
**
*/
gceSTATUS
(*Alloc)(
IN gckALLOCATOR Allocator,
IN PLINUX_MDL Mdl,
IN gctSIZE_T NumPages,
IN gctUINT32 Flag
);
/**************************************************************************
**
** Free
**
** Free memory.
**
** INPUT:
**
** gckALLOCATOR Allocator
** Pointer to an gckALLOCATOER object.
**
** PLINUX_MDL Mdl
** Mdl which stores information.
**
** OUTPUT:
**
** Nothing.
**
*/
void
(*Free)(
IN gckALLOCATOR Allocator,
IN PLINUX_MDL Mdl
);
/**************************************************************************
**
** Mmap
**
** Map a page range of the memory to user space.
**
** INPUT:
** gckALLOCATOR Allocator
** Pointer to an gckALLOCATOER object.
**
** PLINUX_MDL Mdl
** Pointer to a Mdl.
**
** gctSIZE_T skipPages
** Number of page to be skipped from beginning of this memory.
**
** gctSIZE_T numPages
** Number of pages to be mapped from skipPages.
**
** INOUT:
**
** struct vm_area_struct *vma
** Pointer to VMM memory area.
**
*/
gceSTATUS
(*Mmap)(
IN gckALLOCATOR Allocator,
IN PLINUX_MDL Mdl,
IN gctBOOL Cacheable,
IN gctSIZE_T skipPages,
IN gctSIZE_T numPages,
IN struct vm_area_struct *vma
);
/**************************************************************************
**
** MapUser
**
** Map memory to user space.
**
** INPUT:
** gckALLOCATOR Allocator
** Pointer to an gckALLOCATOER object.
**
** PLINUX_MDL Mdl
** Pointer to a Mdl.
**
** gctBOOL Cacheable
** Whether this mapping is cacheable.
**
** OUTPUT:
**
** gctPOINTER * UserLogical
** Pointer to user logical address.
**
** Nothing.
**
*/
gceSTATUS
(*MapUser)(
IN gckALLOCATOR Allocator,
IN PLINUX_MDL Mdl,
IN PLINUX_MDL_MAP MdlMap,
IN gctBOOL Cacheable
);
/**************************************************************************
**
** UnmapUser
**
** Unmap address from user address space.
**
** INPUT:
** gckALLOCATOR Allocator
** Pointer to an gckALLOCATOER object.
**
** gctPOINTER Logical
** Address to be unmap
**
** gctUINT32 Size
** Size of address space
**
** OUTPUT:
**
** Nothing.
**
*/
void
(*UnmapUser)(
IN gckALLOCATOR Allocator,
IN PLINUX_MDL Mdl,
IN PLINUX_MDL_MAP MdlMap,
IN gctUINT32 Size
);
/**************************************************************************
**
** MapKernel
**
** Map memory to kernel space.
**
** INPUT:
** gckALLOCATOR Allocator
** Pointer to an gckALLOCATOER object.
**
** PLINUX_MDL Mdl
** Pointer to a Mdl object.
**
** OUTPUT:
** gctPOINTER * Logical
** Mapped kernel address.
*/
gceSTATUS
(*MapKernel)(
IN gckALLOCATOR Allocator,
IN PLINUX_MDL Mdl,
IN gctSIZE_T Offset,
IN gctSIZE_T Bytes,
OUT gctPOINTER *Logical
);
/**************************************************************************
**
** UnmapKernel
**
** Unmap memory from kernel space.
**
** INPUT:
** gckALLOCATOR Allocator
** Pointer to an gckALLOCATOER object.
**
** PLINUX_MDL Mdl
** Pointer to a Mdl object.
**
** gctPOINTER Logical
** Mapped kernel address.
**
** OUTPUT:
**
** Nothing.
**
*/
gceSTATUS
(*UnmapKernel)(
IN gckALLOCATOR Allocator,
IN PLINUX_MDL Mdl,
IN gctPOINTER Logical
);
/**************************************************************************
**
** Cache
**
** Maintain cache coherency.
**
** INPUT:
** gckALLOCATOR Allocator
** Pointer to an gckALLOCATOER object.
**
** PLINUX_MDL Mdl
** Pointer to a Mdl object.
**
** gctPOINTER Logical
** Logical address, could be user address or kernel address
**
** gctSIZE_T Offset
** Physical address.
**
** gctUINT32 Bytes
** Size of memory region.
**
** gceCACHEOPERATION Opertaion
** Cache operation.
**
** OUTPUT:
**
** Nothing.
**
*/
gceSTATUS (*Cache)(
IN gckALLOCATOR Allocator,
IN PLINUX_MDL Mdl,
IN gctSIZE_T Offset,
IN gctPOINTER Logical,
IN gctSIZE_T Bytes,
IN gceCACHEOPERATION Operation
);
/**************************************************************************
**
** Physical
**
** Get physical address from a offset in memory region.
**
** INPUT:
** gckALLOCATOR Allocator
** Pointer to an gckALLOCATOER object.
**
** PLINUX_MDL Mdl
** Pointer to a Mdl object.
**
** gctUINT32 Offset
** Offset in this memory region.
**
** OUTPUT:
** gctUINT32_PTR Physical
** Physical address.
**
*/
gceSTATUS (*Physical)(
IN gckALLOCATOR Allocator,
IN PLINUX_MDL Mdl,
IN gctUINT32 Offset,
OUT gctPHYS_ADDR_T * Physical
);
/**************************************************************************
**
** Attach
**
** Import memory allocated by an external allocator.
**
** INPUT:
** gckALLOCATOR Allocator
** Pointer to an gckALLOCATOER object.
**
** gctUINT32 Handle
** Handle of the memory.
**
** OUTPUT:
** None.
**
*/
gceSTATUS (*Attach)(
IN gckALLOCATOR Allocator,
IN gcsATTACH_DESC_PTR Desc,
OUT PLINUX_MDL Mdl
);
/**************************************************************************
**
** GetSGT
**
** Get scatter-gather table from a range of the memory.
**
** INPUT:
** gckALLOCATOR Allocator
** Pointer to an gckALLOCATOER object.
**
** gctUINT32 Handle
** Handle of the memory.
**
** gctSIZE_T Offset
** Offset to the beginning of this mdl.
**
** gctSIZE_T Bytes
** Total bytes form Offset.
**
** OUTPUT:
** gctPOINTER *SGT
** scatter-gather table
**
*/
gceSTATUS (*GetSGT)(
IN gckALLOCATOR Allocator,
IN PLINUX_MDL Mdl,
IN gctSIZE_T Offset,
IN gctSIZE_T Bytes,
OUT gctPOINTER *SGT
);
}
gcsALLOCATOR_OPERATIONS;
/* defination of allocator operations wrapper*/
#define gcmALLOCATOR_Alloc(Allocator, Mdl, NumPages, Flag) \
(Allocator)->ops->Alloc((Allocator), (Mdl), (NumPages), (Flag))
#define gcmALLOCATOR_Free(Allocator, Mdl) \
(Allocator)->ops->Free((Allocator), (Mdl))
#define gcmALLOCATOR_Mmap(Allocator, Mdl, Cacheable, skipPages, numPages, vma) \
(Allocator)->ops->Mmap((Allocator), (Mdl), (Cacheable), (skipPages), (numPages), (vma))
#define gcmALLOCATOR_MapUser(Allocator, Mdl, MdlMap, Cacheable) \
(Allocator)->ops->MapUser((Allocator), (Mdl), (MdlMap), (Cacheable))
#define gcmALLOCATOR_UnmapUser(Allocator, Mdl, MdlMap, Size) \
(Allocator)->ops->UnmapUser((Allocator), (Mdl), (MdlMap), (Size))
#define gcmALLOCATOR_MapKernel(Allocator, Mdl, Offset, Bytes, Logical) \
(Allocator)->ops->MapKernel((Allocator), (Mdl), (Offset), (Bytes), (Logical))
#define gcmALLOCATOR_UnmapKernel(Allocator, Mdl, Logical) \
(Allocator)->ops->UnmapKernel((Allocator), (Mdl), (Logical))
#define gcmALLOCATOR_Cache(Allocator, Mdl, Offset, Logical, Bytes, Operation) \
(Allocator)->ops->Cache((Allocator), (Mdl), (Offset), (Logical), (Bytes), (Operation))
#define gcmALLOCATOR_Physical(Allocator, Mdl, Offset, Phys) \
(Allocator)->ops->Physical((Allocator), (Mdl), (Offset), (Phys))
#define gcmALLOCATOR_Attach(Allocator, Desc, Mdl) \
(Allocator)->ops->Attach((Allocator), (Desc), (Mdl))
#define gcmALLOCATOR_GetSGT(Allocator, Mdl, Offset, Bytes, SGT) \
(Allocator)->ops->GetSGT((Allocator), (Mdl), (Offset), (Bytes), (SGT))
typedef struct _gcsALLOCATOR
{
/* Pointer to gckOS Object. */
gckOS os;
/* Name. */
gctSTRING name;
/* Operations. */
gcsALLOCATOR_OPERATIONS * ops;
/* Capability of this allocator. */
gctUINT32 capability;
/* Debugfs entry of this allocator. */
gcsDEBUGFS_DIR debugfsDir;
/* Private data used by customer allocator. */
void * privateData;
/* Allocator destructor. */
void (*destructor)(struct _gcsALLOCATOR *);
struct list_head link;
}
gcsALLOCATOR;
typedef struct _gcsALLOCATOR_DESC
{
/* Name of a allocator. */
char * name;
/* Entry function to construct a allocator. */
gceSTATUS (*construct)(gckOS, gcsDEBUGFS_DIR *, gckALLOCATOR *);
}
gcsALLOCATOR_DESC;
typedef union _gcsATTACH_DESC
{
/* gcvALLOC_FLAG_DMABUF */
struct
{
gctPOINTER dmabuf;
}
dmaBuf;
/* gcvALLOC_FLAG_USERMEMORY */
struct
{
gctPOINTER memory;
gctPHYS_ADDR_T physical;
gctSIZE_T size;
}
userMem;
/* gcvALLOC_FLAG_EXTERNAL_MEMORY */
struct
{
gcsEXTERNAL_MEMORY_INFO info;
}
externalMem;
/* Reserved memory. */
struct
{
unsigned long start;
unsigned long size;
const char * name;
int requested;
}
reservedMem;
}
gcsATTACH_DESC;
/*
* Helpers
*/
/* Fill a gcsALLOCATOR_DESC structure. */
#define gcmkDEFINE_ALLOCATOR_DESC(Name, Construct) \
{ \
.name = Name, \
.construct = Construct, \
}
/* Construct a allocator. */
static inline gceSTATUS
gckALLOCATOR_Construct(
IN gckOS Os,
IN gcsALLOCATOR_OPERATIONS * Operations,
OUT gckALLOCATOR * Allocator
)
{
gceSTATUS status;
gckALLOCATOR allocator;
gcmkASSERT(Allocator != gcvNULL);
gcmkASSERT
( Operations
&& (Operations->Alloc || Operations->Attach)
&& (Operations->Free)
&& Operations->MapUser
&& Operations->UnmapUser
&& Operations->MapKernel
&& Operations->UnmapKernel
&& Operations->Cache
&& Operations->Physical
);
allocator = kzalloc(sizeof(gcsALLOCATOR), GFP_KERNEL | gcdNOWARN);
if (unlikely(!allocator))
{
gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
}
/* Record os. */
allocator->os = Os;
/* Set operations. */
allocator->ops = Operations;
*Allocator = allocator;
return gcvSTATUS_OK;
OnError:
return status;
}
#if LINUX_VERSION_CODE < KERNEL_VERSION (3,6,0) \
|| (!defined (ARCH_HAS_SG_CHAIN) && !defined (CONFIG_ARCH_HAS_SG_CHAIN))
int
alloc_sg_list_from_pages(
struct scatterlist **sgl,
struct page **pages,
unsigned int n_pages,
unsigned long offset,
unsigned long size,
unsigned int *nents
);
#endif
/*
How to implement customer allocator
Build in customer alloctor
It is recommanded that customer allocator is implmented in independent
source file(s) which is specified by CUSOMTER_ALLOCATOR_OBJS in Kbuld.
Register gcsALLOCATOR
For each customer specified allocator, a desciption entry must be added
to allocatorArray defined in gc_hal_kernel_allocator_array.h.
An entry in allocatorArray is a gcsALLOCATOR_DESC structure which describes
name and constructor of a gckALLOCATOR object.
Implement gcsALLOCATOR_DESC.init()
In gcsALLOCATOR_DESC.init(), gckALLOCATOR_Construct should be called
to create a gckALLOCATOR object, customer specified private data can
be put in gcsALLOCATOR.privateData.
Implement gcsALLOCATOR_OPERATIONS
When call gckALLOCATOR_Construct to create a gckALLOCATOR object, a
gcsALLOCATOR_OPERATIONS structure must be provided whose all members
implemented.
*/
#endif

View File

@ -0,0 +1,176 @@
/****************************************************************************
*
* The MIT License (MIT)
*
* Copyright (c) 2014 - 2019 Vivante Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
*****************************************************************************
*
* The GPL License (GPL)
*
* Copyright (C) 2014 - 2019 Vivante Corporation
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*****************************************************************************
*
* Note: This software is released under dual MIT and GPL licenses. A
* recipient may use this file under the terms of either the MIT license or
* GPL License. If you wish to use only one license not the other, you can
* indicate your decision by deleting one of the above license notices in your
* version of this file.
*
*****************************************************************************/
#ifndef __gc_hal_kernel_debug_h_
#define __gc_hal_kernel_debug_h_
#include <gc_hal_kernel_linux.h>
#include <linux/spinlock.h>
#include <linux/time.h>
#include <stdarg.h>
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,14,0)
#include <linux/nmi.h>
#endif
#ifdef __cplusplus
extern "C" {
#endif
/******************************************************************************\
****************************** OS-dependent Macros *****************************
\******************************************************************************/
typedef va_list gctARGUMENTS;
#define gcmkARGUMENTS_START(Arguments, Pointer) \
va_start(Arguments, Pointer)
#define gcmkARGUMENTS_END(Arguments) \
va_end(Arguments)
#define gcmkARGUMENTS_ARG(Arguments, Type) \
va_arg(Arguments, Type)
#define gcmkDECLARE_MUTEX(__mutex__) \
DEFINE_MUTEX(__mutex__)
#define gcmkMUTEX_LOCK(__mutex__) \
mutex_lock(&__mutex__)
#define gcmkMUTEX_UNLOCK(__mutex__) \
mutex_unlock(&__mutex__)
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
# define gcmkGETPROCESSID() \
task_tgid_vnr(current)
#else
# define gcmkGETPROCESSID() \
current->tgid
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
# define gcmkGETTHREADID() \
task_pid_vnr(current)
#else
# define gcmkGETTHREADID() \
current->pid
#endif
#define gcmkOUTPUT_STRING(String) \
printk("%s", String); \
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,14,0)
#define gcmkDUMP_STRING(Os, String) \
do \
{ \
mutex_lock(&Os->dumpFilpMutex); \
if (Os->dumpTarget == 0) \
{ \
printk("%s", String); \
} \
else if (Os->dumpFilp && Os->dumpTarget == 1) \
{ \
kernel_write(Os->dumpFilp, String, strlen(String), &Os->dumpFilp->f_pos); \
} \
mutex_unlock(&Os->dumpFilpMutex); \
} \
while (0)
#else
#define gcmkDUMP_STRING(Os, String) \
do \
{ \
mutex_lock(&Os->dumpFilpMutex); \
if (Os->dumpTarget == 0) \
{ \
printk("%s", String); \
} \
else if (Os->dumpFilp && Os->dumpTarget == 1) \
{ \
mm_segment_t oldFs; \
oldFs = get_fs(); \
set_fs(KERNEL_DS); \
vfs_write(Os->dumpFilp, String, strlen(String), &Os->dumpFilp->f_pos); \
set_fs(oldFs); \
} \
mutex_unlock(&Os->dumpFilpMutex); \
} \
while (0)
#endif
#define gcmkSPRINTF(Destination, Size, ...) \
snprintf(Destination, Size, __VA_ARGS__)
#define gcmkVSPRINTF(Destination, Size, Message, Arguments) \
vsnprintf(Destination, Size, Message, *((va_list*)Arguments))
#define gcmkSTRCATSAFE(Destination, Size, String) \
strncat(Destination, String, (Size) - 1)
#define gcmkMEMCPY(Destination, Source, Size) \
memcpy(Destination, Source, Size)
#define gcmkSTRLEN(String) \
strlen(String)
/* If not zero, forces data alignment in the variable argument list
by its individual size. */
#define gcdALIGNBYSIZE 1
#ifdef __cplusplus
}
#endif
#endif /* __gc_hal_kernel_debug_h_ */

View File

@ -0,0 +1,229 @@
/****************************************************************************
*
* The MIT License (MIT)
*
* Copyright (c) 2014 - 2019 Vivante Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
*****************************************************************************
*
* The GPL License (GPL)
*
* Copyright (C) 2014 - 2019 Vivante Corporation
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*****************************************************************************
*
* Note: This software is released under dual MIT and GPL licenses. A
* recipient may use this file under the terms of either the MIT license or
* GPL License. If you wish to use only one license not the other, you can
* indicate your decision by deleting one of the above license notices in your
* version of this file.
*
*****************************************************************************/
#ifdef MODULE
#include <linux/module.h>
#endif
#include <linux/init.h>
#include <linux/debugfs.h>
#include <linux/slab.h>
#ifdef MODVERSIONS
#include <linux/modversions.h>
#endif
#include <linux/stddef.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/timer.h>
#include <linux/delay.h>
#include <linux/errno.h>
#include <linux/mutex.h>
#include <linux/vmalloc.h>
#include <linux/types.h>
#include <linux/fs.h>
#include <linux/poll.h>
#include <asm/uaccess.h>
#include <linux/completion.h>
#include <linux/seq_file.h>
#include "gc_hal_kernel_linux.h"
#include "gc_hal_kernel.h"
#include "gc_hal_kernel_debug.h"
#define _GC_OBJ_ZONE gcvZONE_KERNEL
static int gc_debugfs_open(struct inode *inode, struct file *file)
{
gcsINFO_NODE *node = inode->i_private;
return single_open(file, node->info->show, node);
}
static ssize_t
gc_debugfs_write(
struct file *file,
const char __user *buf,
size_t count,
loff_t *pos
)
{
struct seq_file *s = file->private_data;
gcsINFO_NODE *node = s->private;
gcsINFO *info = node->info;
if (info->write)
{
info->write(buf, count, node);
}
return count;
}
static const struct file_operations gc_debugfs_operations = {
.owner = THIS_MODULE,
.open = gc_debugfs_open,
.write = gc_debugfs_write,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
gceSTATUS
gckDEBUGFS_DIR_Init(
IN gckDEBUGFS_DIR Dir,
IN struct dentry *root,
IN gctCONST_STRING Name
)
{
Dir->root = debugfs_create_dir(Name, root);
if (!Dir->root)
{
return gcvSTATUS_NOT_SUPPORTED;
}
INIT_LIST_HEAD(&Dir->nodeList);
return gcvSTATUS_OK;
}
gceSTATUS
gckDEBUGFS_DIR_CreateFiles(
IN gckDEBUGFS_DIR Dir,
IN gcsINFO * List,
IN int count,
IN gctPOINTER Data
)
{
int i;
gcsINFO_NODE * node;
gceSTATUS status = gcvSTATUS_OK;
gcmkHEADER_ARG("Dir=%p List=%p count=%d Data=%p", Dir, List, count, Data);
for (i = 0; i < count; i++)
{
umode_t mode = 0;
/* Create a node. */
node = (gcsINFO_NODE *)kzalloc(sizeof(gcsINFO_NODE), GFP_KERNEL);
node->info = &List[i];
node->device = Data;
mode |= List[i].show ? S_IRUGO : 0;
mode |= List[i].write ? S_IWUSR : 0;
node->entry = debugfs_create_file(
List[i].name, mode, Dir->root, node, &gc_debugfs_operations);
if (!node->entry)
{
gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
}
list_add(&(node->head), &(Dir->nodeList));
}
OnError:
if (gcmIS_ERROR(status))
{
gcmkVERIFY_OK(gckDEBUGFS_DIR_RemoveFiles(Dir, List, count));
}
gcmkFOOTER();
return status;
}
gceSTATUS
gckDEBUGFS_DIR_RemoveFiles(
IN gckDEBUGFS_DIR Dir,
IN gcsINFO * List,
IN int count
)
{
int i;
gcsINFO_NODE * node;
gcsINFO_NODE * temp;
gcmkHEADER_ARG("Dir=%p List=%p count=%d", Dir, List, count);
for (i = 0; i < count; i++)
{
list_for_each_entry_safe(node, temp, &Dir->nodeList, head)
{
if (node->info == &List[i])
{
debugfs_remove(node->entry);
list_del(&node->head);
kfree(node);
}
}
}
gcmkFOOTER_NO();
return gcvSTATUS_OK;
}
void
gckDEBUGFS_DIR_Deinit(
IN gckDEBUGFS_DIR Dir
)
{
if (Dir->root != NULL)
{
debugfs_remove(Dir->root);
Dir->root = NULL;
}
}

View File

@ -0,0 +1,115 @@
/****************************************************************************
*
* The MIT License (MIT)
*
* Copyright (c) 2014 - 2019 Vivante Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
*****************************************************************************
*
* The GPL License (GPL)
*
* Copyright (C) 2014 - 2019 Vivante Corporation
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*****************************************************************************
*
* Note: This software is released under dual MIT and GPL licenses. A
* recipient may use this file under the terms of either the MIT license or
* GPL License. If you wish to use only one license not the other, you can
* indicate your decision by deleting one of the above license notices in your
* version of this file.
*
*****************************************************************************/
#include <stdarg.h>
#ifndef __gc_hal_kernel_debugfs_h_
#define __gc_hal_kernel_debugfs_h_
#define MAX_LINE_SIZE 768 /* Max bytes for a line of debug info */
typedef struct _gcsDEBUGFS_DIR *gckDEBUGFS_DIR;
typedef struct _gcsDEBUGFS_DIR
{
struct dentry * root;
struct list_head nodeList;
}
gcsDEBUGFS_DIR;
typedef struct _gcsINFO
{
const char * name;
int (*show)(struct seq_file*, void*);
int (*write)(const char __user *buf, size_t count, void*);
}
gcsINFO;
typedef struct _gcsINFO_NODE
{
gcsINFO * info;
gctPOINTER device;
struct dentry * entry;
struct list_head head;
}
gcsINFO_NODE;
gceSTATUS
gckDEBUGFS_DIR_Init(
IN gckDEBUGFS_DIR Dir,
IN struct dentry *root,
IN gctCONST_STRING Name
);
gceSTATUS
gckDEBUGFS_DIR_CreateFiles(
IN gckDEBUGFS_DIR Dir,
IN gcsINFO * List,
IN int count,
IN gctPOINTER Data
);
gceSTATUS
gckDEBUGFS_DIR_RemoveFiles(
IN gckDEBUGFS_DIR Dir,
IN gcsINFO * List,
IN int count
);
void
gckDEBUGFS_DIR_Deinit(
IN gckDEBUGFS_DIR Dir
);
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,209 @@
/****************************************************************************
*
* The MIT License (MIT)
*
* Copyright (c) 2014 - 2019 Vivante Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
*****************************************************************************
*
* The GPL License (GPL)
*
* Copyright (C) 2014 - 2019 Vivante Corporation
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*****************************************************************************
*
* Note: This software is released under dual MIT and GPL licenses. A
* recipient may use this file under the terms of either the MIT license or
* GPL License. If you wish to use only one license not the other, you can
* indicate your decision by deleting one of the above license notices in your
* version of this file.
*
*****************************************************************************/
#ifndef __gc_hal_kernel_device_h_
#define __gc_hal_kernel_device_h_
#include "gc_hal_kernel_debugfs.h"
#include "gc_hal_ta.h"
/******************************************************************************\
************************** gckGALDEVICE Structure ******************************
\******************************************************************************/
typedef struct _gckGALDEVICE
{
/* Objects. */
gckOS os;
gckKERNEL kernels[gcdMAX_GPU_COUNT];
gcsPLATFORM* platform;
/* Attributes. */
gctPHYS_ADDR_T internalBase;
gctSIZE_T internalSize;
gctPHYS_ADDR internalPhysical;
gctUINT32 internalPhysName;
gctPOINTER internalLogical;
gckVIDMEM internalVidMem;
gctPHYS_ADDR_T externalBase;
gctSIZE_T externalSize;
gctPHYS_ADDR externalPhysical;
gctUINT32 externalPhysName;
gctPOINTER externalLogical;
gckVIDMEM externalVidMem;
/* Shared external SRAMs. */
gctPHYS_ADDR_T extSRAMBases[gcvSRAM_EXT_COUNT];
gctSIZE_T extSRAMSizes[gcvSRAM_EXT_COUNT];
gctPHYS_ADDR extSRAMPhysical[gcvSRAM_EXT_COUNT];
gckVIDMEM extSRAMVidMem[gcvSRAM_EXT_COUNT];
gctPHYS_ADDR_T contiguousBase;
gctSIZE_T contiguousSize;
gctPHYS_ADDR contiguousPhysical;
gctUINT32 contiguousPhysName;
gctPOINTER contiguousLogical;
gckVIDMEM contiguousVidMem;
/* By request_mem_region. */
gctUINT64 requestedContiguousBase;
gctSIZE_T requestedContiguousSize;
/* IRQ management. */
gctINT irqLines[gcdMAX_GPU_COUNT];
gctBOOL isrInitializeds[gcdMAX_GPU_COUNT];
/* Register memory. */
gctPOINTER registerBases[gcdMAX_GPU_COUNT];
gctSIZE_T registerSizes[gcdMAX_GPU_COUNT];
/* By request_mem_region. */
gctUINT64 requestedRegisterMemBases[gcdMAX_GPU_COUNT];
gctSIZE_T requestedRegisterMemSizes[gcdMAX_GPU_COUNT];
gctUINT32 baseAddress;
gctUINT32 physBase;
gctUINT32 physSize;
/* PCIE Bar */
gctINT bars[gcdMAX_GPU_COUNT];
/* Thread management. */
struct task_struct *threadCtxts[gcdMAX_GPU_COUNT];
struct semaphore semas[gcdMAX_GPU_COUNT];
gctBOOL threadInitializeds[gcdMAX_GPU_COUNT];
gctBOOL killThread;
/* States before suspend. */
gceCHIPPOWERSTATE statesStored[gcdMAX_GPU_COUNT];
gcsDEBUGFS_DIR debugfsDir;
gckDEVICE device;
gcsMODULE_PARAMETERS args;
/* gctsOs object for trust application. */
gctaOS taos;
#if gcdENABLE_DRM
void * drm;
#endif
}
* gckGALDEVICE;
typedef struct _gcsHAL_PRIVATE_DATA
{
gckGALDEVICE device;
/*
* 'fput' schedules actual work in '__fput' in a different thread.
* So the process opens the device may not be the same as the one that
* closes it.
*/
gctUINT32 pidOpen;
gctBOOL isLocked;
}
gcsHAL_PRIVATE_DATA, * gcsHAL_PRIVATE_DATA_PTR;
gceSTATUS
gckGALDEVICE_Start(
IN gckGALDEVICE Device
);
gceSTATUS
gckGALDEVICE_Stop(
gckGALDEVICE Device
);
gceSTATUS
gckGALDEVICE_Construct(
IN gcsPLATFORM * Platform,
IN const gcsMODULE_PARAMETERS * Args,
OUT gckGALDEVICE *Device
);
gceSTATUS
gckGALDEVICE_Destroy(
IN gckGALDEVICE Device
);
static gcmINLINE gckKERNEL
_GetValidKernel(
gckGALDEVICE Device
)
{
if (Device->kernels[gcvCORE_MAJOR])
{
return Device->kernels[gcvCORE_MAJOR];
}
else if (Device->kernels[gcvCORE_2D])
{
return Device->kernels[gcvCORE_2D];
}
else if (Device->kernels[gcvCORE_VG])
{
return Device->kernels[gcvCORE_VG];
}
else
{
gcmkASSERT(gcvFALSE);
return gcvNULL;
}
}
#endif /* __gc_hal_kernel_device_h_ */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,858 @@
/****************************************************************************
*
* The MIT License (MIT)
*
* Copyright (c) 2014 - 2019 Vivante Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
*****************************************************************************
*
* The GPL License (GPL)
*
* Copyright (C) 2014 - 2019 Vivante Corporation
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*****************************************************************************
*
* Note: This software is released under dual MIT and GPL licenses. A
* recipient may use this file under the terms of either the MIT license or
* GPL License. If you wish to use only one license not the other, you can
* indicate your decision by deleting one of the above license notices in your
* version of this file.
*
*****************************************************************************/
#if gcdENABLE_DRM
#include <drm/drmP.h>
#include <drm/drm_gem.h>
#include <linux/dma-buf.h>
#include "gc_hal_kernel_linux.h"
#include "gc_hal_drm.h"
#define _GC_OBJ_ZONE gcvZONE_KERNEL
/******************************************************************************\
******************************* gckKERNEL DRM Code ******************************
\******************************************************************************/
struct viv_gem_object {
struct drm_gem_object base;
uint32_t node_handle;
gckVIDMEM_NODE node_object;
gctBOOL cacheable;
};
struct dma_buf *viv_gem_prime_export(struct drm_device *drm,
struct drm_gem_object *gem_obj,
int flags)
{
struct viv_gem_object *viv_obj = container_of(gem_obj, struct viv_gem_object, base);
struct dma_buf *dmabuf = gcvNULL;
gckGALDEVICE gal_dev = (gckGALDEVICE)drm->dev_private;
if (gal_dev)
{
gckKERNEL kernel = gal_dev->device->map[gal_dev->device->defaultHwType].kernels[0];
gcmkVERIFY_OK(gckVIDMEM_NODE_Export(kernel, viv_obj->node_object, flags,
(gctPOINTER*)&dmabuf, gcvNULL));
}
return dmabuf;
}
struct drm_gem_object *viv_gem_prime_import(struct drm_device *drm,
struct dma_buf *dmabuf)
{
struct drm_gem_object *gem_obj = gcvNULL;
struct viv_gem_object *viv_obj;
gcsHAL_INTERFACE iface;
gckGALDEVICE gal_dev;
gckKERNEL kernel;
gctUINT32 processID;
gckVIDMEM_NODE nodeObject;
gceSTATUS status = gcvSTATUS_OK;
gal_dev = (gckGALDEVICE)drm->dev_private;
if (!gal_dev)
{
gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
}
gckOS_ZeroMemory(&iface, sizeof(iface));
iface.command = gcvHAL_WRAP_USER_MEMORY;
iface.hardwareType = gal_dev->device->defaultHwType;
iface.u.WrapUserMemory.desc.flag = gcvALLOC_FLAG_DMABUF;
iface.u.WrapUserMemory.desc.handle = -1;
iface.u.WrapUserMemory.desc.dmabuf = gcmPTR_TO_UINT64(dmabuf);
gcmkONERROR(gckDEVICE_Dispatch(gal_dev->device, &iface));
kernel = gal_dev->device->map[gal_dev->device->defaultHwType].kernels[0];
gcmkONERROR(gckOS_GetProcessID(&processID));
gcmkONERROR(gckVIDMEM_HANDLE_Lookup(kernel, processID, iface.u.WrapUserMemory.node, &nodeObject));
/* ioctl output */
gem_obj = kzalloc(sizeof(struct viv_gem_object), GFP_KERNEL);
drm_gem_private_object_init(drm, gem_obj, dmabuf->size);
viv_obj = container_of(gem_obj, struct viv_gem_object, base);
viv_obj->node_handle = iface.u.WrapUserMemory.node;
viv_obj->node_object = nodeObject;
OnError:
return gem_obj;
}
void viv_gem_free_object(struct drm_gem_object *gem_obj)
{
struct viv_gem_object *viv_obj = container_of(gem_obj, struct viv_gem_object, base);
struct drm_device *drm = gem_obj->dev;
gcsHAL_INTERFACE iface;
gckGALDEVICE gal_dev = (gckGALDEVICE)drm->dev_private;
gckOS_ZeroMemory(&iface, sizeof(iface));
iface.command = gcvHAL_RELEASE_VIDEO_MEMORY;
iface.hardwareType = gal_dev->device->defaultHwType;
iface.u.ReleaseVideoMemory.node = viv_obj->node_handle;
gcmkVERIFY_OK(gckDEVICE_Dispatch(gal_dev->device, &iface));
drm_gem_object_release(gem_obj);
kfree(gem_obj);
}
static int viv_ioctl_gem_create(struct drm_device *drm, void *data,
struct drm_file *file)
{
int ret = 0;
struct drm_viv_gem_create *args = (struct drm_viv_gem_create*)data;
struct drm_gem_object *gem_obj = gcvNULL;
struct viv_gem_object *viv_obj = gcvNULL;
gcsHAL_INTERFACE iface;
gckGALDEVICE gal_dev;
gckKERNEL kernel;
gctUINT32 processID;
gckVIDMEM_NODE nodeObject;
gctUINT32 flags = gcvALLOC_FLAG_DMABUF_EXPORTABLE;
gceSTATUS status = gcvSTATUS_OK;
gctUINT64 alignSize = PAGE_ALIGN(args->size);
gal_dev = (gckGALDEVICE)drm->dev_private;
if (!gal_dev)
{
gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
}
if (args->flags & DRM_VIV_GEM_CONTIGUOUS)
{
flags |= gcvALLOC_FLAG_CONTIGUOUS;
}
if (args->flags & DRM_VIV_GEM_CACHED)
{
flags |= gcvALLOC_FLAG_CACHEABLE;
}
if (args->flags & DRM_VIV_GEM_SECURE)
{
flags |= gcvALLOC_FLAG_SECURITY;
}
if (args->flags & DRM_VIV_GEM_CMA_LIMIT)
{
flags |= gcvALLOC_FLAG_CMA_LIMIT;
}
gckOS_ZeroMemory(&iface, sizeof(iface));
iface.command = gcvHAL_ALLOCATE_LINEAR_VIDEO_MEMORY;
iface.hardwareType = gal_dev->device->defaultHwType;
iface.u.AllocateLinearVideoMemory.bytes = alignSize;
iface.u.AllocateLinearVideoMemory.alignment = 256;
iface.u.AllocateLinearVideoMemory.type = gcvVIDMEM_TYPE_GENERIC;
iface.u.AllocateLinearVideoMemory.flag = flags;
iface.u.AllocateLinearVideoMemory.pool = gcvPOOL_DEFAULT;
gcmkONERROR(gckDEVICE_Dispatch(gal_dev->device, &iface));
kernel = gal_dev->device->map[gal_dev->device->defaultHwType].kernels[0];
gcmkONERROR(gckOS_GetProcessID(&processID));
gcmkONERROR(gckVIDMEM_HANDLE_Lookup(kernel, processID, iface.u.AllocateLinearVideoMemory.node, &nodeObject));
/* ioctl output */
gem_obj = kzalloc(sizeof(struct viv_gem_object), GFP_KERNEL);
drm_gem_private_object_init(drm, gem_obj, (size_t)alignSize);
ret = drm_gem_handle_create(file, gem_obj, &args->handle);
viv_obj = container_of(gem_obj, struct viv_gem_object, base);
viv_obj->node_handle = iface.u.AllocateLinearVideoMemory.node;
viv_obj->node_object = nodeObject;
viv_obj->cacheable = flags & gcvALLOC_FLAG_CACHEABLE;
/* drop reference from allocate - handle holds it now */
drm_gem_object_unreference_unlocked(gem_obj);
OnError:
return gcmIS_ERROR(status) ? -ENOTTY : 0;
}
static int viv_ioctl_gem_lock(struct drm_device *drm, void *data,
struct drm_file *file)
{
struct drm_viv_gem_lock *args = (struct drm_viv_gem_lock*)data;
struct drm_gem_object *gem_obj = gcvNULL;
struct viv_gem_object *viv_obj = gcvNULL;
gcsHAL_INTERFACE iface;
gceSTATUS status = gcvSTATUS_OK;
gckGALDEVICE gal_dev = gcvNULL;
gal_dev = (gckGALDEVICE)drm->dev_private;
if (!gal_dev)
{
gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
}
gem_obj = drm_gem_object_lookup(file, args->handle);
if (!gem_obj)
{
gcmkONERROR(gcvSTATUS_NOT_FOUND);
}
viv_obj = container_of(gem_obj, struct viv_gem_object, base);
gckOS_ZeroMemory(&iface, sizeof(iface));
iface.command = gcvHAL_LOCK_VIDEO_MEMORY;
iface.hardwareType = gal_dev->device->defaultHwType;
iface.u.LockVideoMemory.node = viv_obj->node_handle;
iface.u.LockVideoMemory.cacheable = args->cacheable;
gcmkONERROR(gckDEVICE_Dispatch(gal_dev->device, &iface));
args->logical = iface.u.LockVideoMemory.memory;
OnError:
if (gem_obj)
{
drm_gem_object_unreference_unlocked(gem_obj);
}
return gcmIS_ERROR(status) ? -ENOTTY : 0;
}
static int viv_ioctl_gem_unlock(struct drm_device *drm, void *data,
struct drm_file *file)
{
struct drm_viv_gem_unlock *args = (struct drm_viv_gem_unlock*)data;
struct drm_gem_object *gem_obj = gcvNULL;
struct viv_gem_object *viv_obj = gcvNULL;
gcsHAL_INTERFACE iface;
gceSTATUS status = gcvSTATUS_OK;
gckGALDEVICE gal_dev = gcvNULL;
gal_dev = (gckGALDEVICE)drm->dev_private;
if (!gal_dev)
{
gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
}
gem_obj = drm_gem_object_lookup(file, args->handle);
if (!gem_obj)
{
gcmkONERROR(gcvSTATUS_NOT_FOUND);
}
viv_obj = container_of(gem_obj, struct viv_gem_object, base);
memset(&iface, 0, sizeof(iface));
iface.command = gcvHAL_UNLOCK_VIDEO_MEMORY;
iface.hardwareType = gal_dev->device->defaultHwType;
iface.u.UnlockVideoMemory.node = (gctUINT64)viv_obj->node_handle;
iface.u.UnlockVideoMemory.type = gcvVIDMEM_TYPE_GENERIC;
gcmkONERROR(gckDEVICE_Dispatch(gal_dev->device, &iface));
memset(&iface, 0, sizeof(iface));
iface.command = gcvHAL_BOTTOM_HALF_UNLOCK_VIDEO_MEMORY;
iface.hardwareType = gal_dev->device->defaultHwType;
iface.u.BottomHalfUnlockVideoMemory.node = (gctUINT64)viv_obj->node_handle;
iface.u.BottomHalfUnlockVideoMemory.type = gcvVIDMEM_TYPE_GENERIC;
gcmkONERROR(gckDEVICE_Dispatch(gal_dev->device, &iface));
OnError:
if (gem_obj)
{
drm_gem_object_unreference_unlocked(gem_obj);
}
return gcmIS_ERROR(status) ? -ENOTTY : 0;
}
static int viv_ioctl_gem_cache(struct drm_device *drm, void *data,
struct drm_file *file)
{
struct drm_viv_gem_cache *args = (struct drm_viv_gem_cache*)data;
struct drm_gem_object *gem_obj = gcvNULL;
struct viv_gem_object *viv_obj = gcvNULL;
gcsHAL_INTERFACE iface;
gceSTATUS status = gcvSTATUS_OK;
gckGALDEVICE gal_dev = gcvNULL;
gceCACHEOPERATION cache_op = 0;
gal_dev = (gckGALDEVICE)drm->dev_private;
if (!gal_dev)
{
gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
}
gem_obj = drm_gem_object_lookup(file, args->handle);
if (!gem_obj)
{
gcmkONERROR(gcvSTATUS_NOT_FOUND);
}
viv_obj = container_of(gem_obj, struct viv_gem_object, base);
switch (args->op)
{
case DRM_VIV_GEM_CLEAN_CACHE:
cache_op = gcvCACHE_CLEAN;
break;
case DRM_VIV_GEM_INVALIDATE_CACHE:
cache_op = gcvCACHE_INVALIDATE;
break;
case DRM_VIV_GEM_FLUSH_CACHE:
cache_op = gcvCACHE_FLUSH;
break;
case DRM_VIV_GEM_MEMORY_BARRIER:
cache_op = gcvCACHE_MEMORY_BARRIER;
break;
default:
break;
}
gckOS_ZeroMemory(&iface, sizeof(iface));
iface.command = gcvHAL_CACHE;
iface.hardwareType = gal_dev->device->defaultHwType;
iface.u.Cache.node = viv_obj->node_handle;
iface.u.Cache.operation = cache_op;
iface.u.Cache.logical = args->logical;
iface.u.Cache.bytes = args->bytes;
gcmkONERROR(gckDEVICE_Dispatch(gal_dev->device, &iface));
OnError:
if (gem_obj)
{
drm_gem_object_unreference_unlocked(gem_obj);
}
return gcmIS_ERROR(status) ? -ENOTTY : 0;
}
static int viv_ioctl_gem_query(struct drm_device *drm, void *data,
struct drm_file *file)
{
struct drm_viv_gem_query *args = (struct drm_viv_gem_query*)data;
struct drm_gem_object *gem_obj = gcvNULL;
struct viv_gem_object *viv_obj = gcvNULL;
gceSTATUS status = gcvSTATUS_OK;
gckGALDEVICE gal_dev = gcvNULL;
gal_dev = (gckGALDEVICE)drm->dev_private;
if (!gal_dev)
{
gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
}
gem_obj = drm_gem_object_lookup(file, args->handle);
if (!gem_obj)
{
gcmkONERROR(gcvSTATUS_NOT_FOUND);
}
viv_obj = container_of(gem_obj, struct viv_gem_object, base);
switch (args->param)
{
case DRM_VIV_GEM_PARAM_POOL:
args->value = (__u64)viv_obj->node_object->pool;
break;
case DRM_VIV_GEM_PARAM_SIZE:
args->value = (__u64)gem_obj->size;
break;
default:
gcmkONERROR(gcvSTATUS_NOT_SUPPORTED);
}
OnError:
if (gem_obj)
{
drm_gem_object_unreference_unlocked(gem_obj);
}
return gcmIS_ERROR(status) ? -ENOTTY : 0;
}
static int viv_ioctl_gem_timestamp(struct drm_device *drm, void *data,
struct drm_file *file)
{
struct drm_viv_gem_timestamp *args = (struct drm_viv_gem_timestamp *)data;
struct drm_gem_object *gem_obj = gcvNULL;
struct viv_gem_object *viv_obj = gcvNULL;
gceSTATUS status = gcvSTATUS_OK;
gckGALDEVICE gal_dev = gcvNULL;
gal_dev = (gckGALDEVICE)drm->dev_private;
if (!gal_dev)
{
gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
}
gem_obj = drm_gem_object_lookup(file, args->handle);
if (!gem_obj)
{
gcmkONERROR(gcvSTATUS_NOT_FOUND);
}
viv_obj = container_of(gem_obj, struct viv_gem_object, base);
viv_obj->node_object->timeStamp += args->inc;
args->timestamp = viv_obj->node_object->timeStamp;
OnError:
if (gem_obj)
{
drm_gem_object_unreference_unlocked(gem_obj);
}
return gcmIS_ERROR(status) ? -ENOTTY : 0;
}
static int viv_ioctl_gem_set_tiling(struct drm_device *drm, void *data,
struct drm_file *file)
{
struct drm_viv_gem_set_tiling *args = (struct drm_viv_gem_set_tiling*)data;
struct drm_gem_object *gem_obj = gcvNULL;
struct viv_gem_object *viv_obj = gcvNULL;
gceSTATUS status = gcvSTATUS_OK;
gckGALDEVICE gal_dev = gcvNULL;
gal_dev = (gckGALDEVICE)drm->dev_private;
if (!gal_dev)
{
gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
}
gem_obj = drm_gem_object_lookup(file, args->handle);
if (!gem_obj)
{
gcmkONERROR(gcvSTATUS_NOT_FOUND);
}
viv_obj = container_of(gem_obj, struct viv_gem_object, base);
viv_obj->node_object->tilingMode = args->tiling_mode;
viv_obj->node_object->tsMode = args->ts_mode;
viv_obj->node_object->clearValue = args->clear_value;
OnError:
if (gem_obj)
{
drm_gem_object_unreference_unlocked(gem_obj);
}
return gcmIS_ERROR(status) ? -ENOTTY : 0;
}
static int viv_ioctl_gem_get_tiling(struct drm_device *drm, void *data,
struct drm_file *file)
{
struct drm_viv_gem_get_tiling *args = (struct drm_viv_gem_get_tiling*)data;
struct drm_gem_object *gem_obj = gcvNULL;
struct viv_gem_object *viv_obj = gcvNULL;
gceSTATUS status = gcvSTATUS_OK;
gckGALDEVICE gal_dev = gcvNULL;
gal_dev = (gckGALDEVICE)drm->dev_private;
if (!gal_dev)
{
gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
}
gem_obj = drm_gem_object_lookup(file, args->handle);
if (!gem_obj)
{
gcmkONERROR(gcvSTATUS_NOT_FOUND);
}
viv_obj = container_of(gem_obj, struct viv_gem_object, base);
args->tiling_mode = viv_obj->node_object->tilingMode;
args->ts_mode = viv_obj->node_object->tsMode;
args->clear_value = viv_obj->node_object->clearValue;
OnError:
if (gem_obj)
{
drm_gem_object_unreference_unlocked(gem_obj);
}
return gcmIS_ERROR(status) ? -ENOTTY : 0;
}
static int viv_ioctl_gem_attach_aux(struct drm_device *drm, void *data,
struct drm_file *file)
{
struct drm_viv_gem_attach_aux *args = (struct drm_viv_gem_attach_aux*)data;
struct drm_gem_object *gem_obj = gcvNULL;
struct viv_gem_object *viv_obj = gcvNULL;
struct drm_gem_object *gem_ts_obj = gcvNULL;
gceSTATUS status = gcvSTATUS_OK;
gckGALDEVICE gal_dev = gcvNULL;
gckVIDMEM_NODE nodeObj = gcvNULL;
gal_dev = (gckGALDEVICE)drm->dev_private;
if (!gal_dev)
{
gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
}
gem_obj = drm_gem_object_lookup(file, args->handle);
if (!gem_obj)
{
gcmkONERROR(gcvSTATUS_NOT_FOUND);
}
viv_obj = container_of(gem_obj, struct viv_gem_object, base);
nodeObj = viv_obj->node_object;
/* do not support re-attach */
if (nodeObj->tsNode)
{
gcmkONERROR(gcvSTATUS_NOT_SUPPORTED);
}
if (args->ts_handle)
{
struct viv_gem_object *viv_ts_obj;
gckKERNEL kernel = gal_dev->device->map[gal_dev->device->defaultHwType].kernels[0];
gcsHAL_INTERFACE iface;
gctBOOL is128BTILE = gckHARDWARE_IsFeatureAvailable(kernel->hardware , gcvFEATURE_128BTILE);
gctBOOL is2BitPerTile = is128BTILE ? gcvFALSE : gckHARDWARE_IsFeatureAvailable(kernel->hardware , gcvFEATURE_TILE_STATUS_2BITS);
gctBOOL isCompressionDEC400 = gckHARDWARE_IsFeatureAvailable(kernel->hardware , gcvFEATURE_COMPRESSION_DEC400);
gctPOINTER entry = gcvNULL;
gckVIDMEM_NODE ObjNode = gcvNULL;
gctUINT32 processID = 0;
gctUINT32 tileStatusFiller = (isCompressionDEC400 || ((kernel->hardware->identity.chipModel == gcv500) && (kernel->hardware->identity.chipRevision > 2)))
? 0xFFFFFFFF
: is2BitPerTile ? 0x55555555 : 0x11111111;
gem_ts_obj = drm_gem_object_lookup(file, args->ts_handle);
if (!gem_ts_obj)
{
gcmkONERROR(gcvSTATUS_NOT_FOUND);
}
viv_ts_obj = container_of(gem_ts_obj, struct viv_gem_object, base);
gcmkONERROR(gckVIDMEM_NODE_Reference(kernel, viv_ts_obj->node_object));
nodeObj->tsNode = viv_ts_obj->node_object;
/* Fill tile status node with tileStatusFiller value first time to avoid GPU hang. */
/* Lock tile status node. */
gckOS_ZeroMemory(&iface, sizeof(iface));
iface.command = gcvHAL_LOCK_VIDEO_MEMORY;
iface.hardwareType = gal_dev->device->defaultHwType;
iface.u.LockVideoMemory.node = viv_ts_obj->node_handle;
iface.u.LockVideoMemory.cacheable = viv_ts_obj->cacheable;
gcmkONERROR(gckDEVICE_Dispatch(gal_dev->device, &iface));
gcmkONERROR(gckOS_GetProcessID(&processID));
gcmkONERROR(gckVIDMEM_HANDLE_Lookup(kernel, processID, viv_ts_obj->node_handle, &ObjNode));
gcmkONERROR(gckVIDMEM_NODE_LockCPU(kernel, ObjNode, gcvFALSE, gcvFALSE, &entry));
/* Fill tile status node with tileStatusFiller. */
memset(entry , tileStatusFiller , (__u64)gem_ts_obj->size);
gcmkONERROR(gckVIDMEM_NODE_UnlockCPU(kernel, ObjNode, 0, gcvFALSE, gcvFALSE));
/* UnLock tile status node. */
memset(&iface, 0, sizeof(iface));
iface.command = gcvHAL_UNLOCK_VIDEO_MEMORY;
iface.hardwareType = gal_dev->device->defaultHwType;
iface.u.UnlockVideoMemory.node = (gctUINT64)viv_ts_obj->node_handle;
iface.u.UnlockVideoMemory.type = gcvSURF_TYPE_UNKNOWN;
gcmkONERROR(gckDEVICE_Dispatch(gal_dev->device, &iface));
memset(&iface, 0, sizeof(iface));
iface.command = gcvHAL_BOTTOM_HALF_UNLOCK_VIDEO_MEMORY;
iface.hardwareType = gal_dev->device->defaultHwType;
iface.u.BottomHalfUnlockVideoMemory.node = (gctUINT64)viv_ts_obj->node_handle;
iface.u.BottomHalfUnlockVideoMemory.type = gcvSURF_TYPE_UNKNOWN;
gcmkONERROR(gckDEVICE_Dispatch(gal_dev->device, &iface));
}
OnError:
if (gem_obj)
{
drm_gem_object_unreference_unlocked(gem_obj);
if (gem_ts_obj)
{
drm_gem_object_unreference_unlocked(gem_ts_obj);
}
}
return gcmIS_ERROR(status) ? -ENOTTY : 0;
}
static int viv_ioctl_gem_ref_node(struct drm_device *drm, void *data,
struct drm_file *file)
{
struct drm_viv_gem_ref_node *args = (struct drm_viv_gem_ref_node*)data;
struct drm_gem_object *gem_obj = gcvNULL;
struct viv_gem_object *viv_obj = gcvNULL;
gceSTATUS status = gcvSTATUS_OK;
gckGALDEVICE gal_dev = gcvNULL;
gckKERNEL kernel = gcvNULL;
gctUINT32 processID;
gckVIDMEM_NODE nodeObj;
gctUINT32 nodeHandle = 0, tsNodeHandle = 0;
gctBOOL refered = gcvFALSE;
int ret = 0;
gal_dev = (gckGALDEVICE)drm->dev_private;
if (!gal_dev)
{
gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
}
kernel = gal_dev->device->map[gal_dev->device->defaultHwType].kernels[0];
gem_obj = drm_gem_object_lookup(file, args->handle);
if (!gem_obj)
{
gcmkONERROR(gcvSTATUS_NOT_FOUND);
}
viv_obj = container_of(gem_obj, struct viv_gem_object, base);
nodeObj = viv_obj->node_object;
gcmkONERROR(gckOS_GetProcessID(&processID));
gcmkONERROR(gckVIDMEM_HANDLE_Allocate(kernel, nodeObj, &nodeHandle));
gcmkONERROR(
gckKERNEL_AddProcessDB(kernel,
processID, gcvDB_VIDEO_MEMORY,
gcmINT2PTR(nodeHandle),
gcvNULL,
0));
gcmkONERROR(gckVIDMEM_NODE_Reference(kernel, nodeObj));
refered = gcvTRUE;
if (nodeObj->tsNode)
{
gcmkONERROR(gckVIDMEM_HANDLE_Allocate(kernel, nodeObj->tsNode, &tsNodeHandle));
gcmkONERROR(
gckKERNEL_AddProcessDB(kernel,
processID, gcvDB_VIDEO_MEMORY,
gcmINT2PTR(tsNodeHandle),
gcvNULL,
0));
gcmkONERROR(gckVIDMEM_NODE_Reference(kernel, nodeObj->tsNode));
}
args->node = nodeHandle;
args->ts_node = tsNodeHandle;
OnError:
if (gcmIS_ERROR(status) && kernel)
{
gctUINT32 processID;
gcmkVERIFY_OK(gckOS_GetProcessID(&processID));
if (tsNodeHandle)
{
gckVIDMEM_HANDLE_Dereference(kernel, processID, tsNodeHandle);
}
if (nodeHandle)
{
gckVIDMEM_HANDLE_Dereference(kernel, processID, nodeHandle);
}
if (refered)
{
gcmkONERROR(gckVIDMEM_NODE_Dereference(kernel, nodeObj));
}
args->node = 0;
args->ts_node = 0;
ret = -ENOTTY;
}
if (gem_obj)
{
drm_gem_object_unreference_unlocked(gem_obj);
}
return ret;
}
static const struct drm_ioctl_desc viv_ioctls[] =
{
DRM_IOCTL_DEF_DRV(VIV_GEM_CREATE, viv_ioctl_gem_create, DRM_AUTH | DRM_RENDER_ALLOW),
DRM_IOCTL_DEF_DRV(VIV_GEM_LOCK, viv_ioctl_gem_lock, DRM_AUTH | DRM_RENDER_ALLOW),
DRM_IOCTL_DEF_DRV(VIV_GEM_UNLOCK, viv_ioctl_gem_unlock, DRM_AUTH | DRM_RENDER_ALLOW),
DRM_IOCTL_DEF_DRV(VIV_GEM_CACHE, viv_ioctl_gem_cache, DRM_AUTH | DRM_RENDER_ALLOW),
DRM_IOCTL_DEF_DRV(VIV_GEM_QUERY, viv_ioctl_gem_query, DRM_AUTH | DRM_RENDER_ALLOW),
DRM_IOCTL_DEF_DRV(VIV_GEM_TIMESTAMP, viv_ioctl_gem_timestamp, DRM_AUTH | DRM_RENDER_ALLOW),
DRM_IOCTL_DEF_DRV(VIV_GEM_SET_TILING, viv_ioctl_gem_set_tiling, DRM_AUTH | DRM_RENDER_ALLOW),
DRM_IOCTL_DEF_DRV(VIV_GEM_GET_TILING, viv_ioctl_gem_get_tiling, DRM_AUTH | DRM_RENDER_ALLOW),
DRM_IOCTL_DEF_DRV(VIV_GEM_ATTACH_AUX, viv_ioctl_gem_attach_aux, DRM_AUTH | DRM_RENDER_ALLOW),
DRM_IOCTL_DEF_DRV(VIV_GEM_REF_NODE, viv_ioctl_gem_ref_node, DRM_AUTH | DRM_RENDER_ALLOW),
};
int viv_drm_open(struct drm_device *drm, struct drm_file *file)
{
gctINT i;
gctUINT32 pid = _GetProcessID();
gckGALDEVICE gal_dev = (gckGALDEVICE)drm->dev_private;
gceSTATUS status = gcvSTATUS_OK;
for (i = 0; i < gcdMAX_GPU_COUNT; ++i)
{
if (gal_dev->kernels[i])
{
gcmkONERROR(gckKERNEL_AttachProcessEx(gal_dev->kernels[i], gcvTRUE, pid));
}
}
file->driver_priv = gcmINT2PTR(pid);
OnError:
return gcmIS_ERROR(status) ? -ENODEV : 0;
}
void viv_drm_postclose(struct drm_device *drm, struct drm_file *file)
{
gctINT i;
gctUINT32 pid = gcmPTR2SIZE(file->driver_priv);
gckGALDEVICE gal_dev = (gckGALDEVICE)drm->dev_private;
for (i = 0; i < gcdMAX_GPU_COUNT; ++i)
{
if (gal_dev->kernels[i])
{
gcmkVERIFY_OK(gckKERNEL_AttachProcessEx(gal_dev->kernels[i], gcvFALSE, pid));
}
}
}
static const struct file_operations viv_drm_fops = {
.owner = THIS_MODULE,
.open = drm_open,
.release = drm_release,
.unlocked_ioctl = drm_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl = drm_compat_ioctl,
#endif
.poll = drm_poll,
.read = drm_read,
.llseek = no_llseek,
};
static struct drm_driver viv_drm_driver = {
.driver_features = DRIVER_GEM | DRIVER_PRIME | DRIVER_RENDER,
.open = viv_drm_open,
.postclose = viv_drm_postclose,
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,7,0)
.gem_free_object_unlocked = viv_gem_free_object,
#else
.gem_free_object = viv_gem_free_object,
#endif
.prime_handle_to_fd = drm_gem_prime_handle_to_fd,
.prime_fd_to_handle = drm_gem_prime_fd_to_handle,
.gem_prime_export = viv_gem_prime_export,
.gem_prime_import = viv_gem_prime_import,
.ioctls = viv_ioctls,
.num_ioctls = DRM_VIV_NUM_IOCTLS,
.fops = &viv_drm_fops,
.name = "vivante",
.desc = "vivante DRM",
.date = "20170808",
.major = 1,
.minor = 0,
};
int viv_drm_probe(struct device *dev)
{
int ret = 0;
gceSTATUS status = gcvSTATUS_OK;
gckGALDEVICE gal_dev = gcvNULL;
struct drm_device *drm = gcvNULL;
gal_dev = (gckGALDEVICE)dev_get_drvdata(dev);
if (!gal_dev)
{
ret = -ENODEV;
gcmkONERROR(gcvSTATUS_INVALID_OBJECT);
}
drm = drm_dev_alloc(&viv_drm_driver, dev);
if (IS_ERR(drm))
{
ret = PTR_ERR(drm);
gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
}
drm->dev_private = (void*)gal_dev;
ret = drm_dev_register(drm, 0);
if (ret)
{
gcmkONERROR(gcvSTATUS_GENERIC_IO);
}
gal_dev->drm = (void*)drm;
OnError:
if (gcmIS_ERROR(status))
{
if (drm)
{
drm_dev_unref(drm);
}
printk(KERN_ERR "galcore: Failed to setup drm device.\n");
}
return ret;
}
int viv_drm_remove(struct device *dev)
{
gckGALDEVICE gal_dev = (gckGALDEVICE)dev_get_drvdata(dev);
if (gal_dev)
{
struct drm_device *drm = (struct drm_device*)gal_dev->drm;
drm_dev_unregister(drm);
drm_dev_unref(drm);
}
return 0;
}
#endif

View File

@ -0,0 +1,236 @@
/****************************************************************************
*
* The MIT License (MIT)
*
* Copyright (c) 2014 - 2019 Vivante Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
*****************************************************************************
*
* The GPL License (GPL)
*
* Copyright (C) 2014 - 2019 Vivante Corporation
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*****************************************************************************
*
* Note: This software is released under dual MIT and GPL licenses. A
* recipient may use this file under the terms of either the MIT license or
* GPL License. If you wish to use only one license not the other, you can
* indicate your decision by deleting one of the above license notices in your
* version of this file.
*
*****************************************************************************/
#include "gc_hal_kernel_linux.h"
#include "gc_hal_kernel_device.h"
#include <linux/iommu.h>
#include <linux/platform_device.h>
#define _GC_OBJ_ZONE gcvZONE_OS
typedef struct _gcsIOMMU
{
struct iommu_domain * domain;
struct device * device;
}
gcsIOMMU;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0)
static int
_IOMMU_Fault_Handler(
struct iommu_domain * Domain,
struct device * Dev,
unsigned long DomainAddress,
int flags,
void * args
)
#else
static int
_IOMMU_Fault_Handler(
struct iommu_domain * Domain,
struct device * Dev,
unsigned long DomainAddress,
int flags
)
#endif
{
return 0;
}
static int
_FlatMapping(
IN gckIOMMU Iommu
)
{
gceSTATUS status = gcvSTATUS_OK;
gctUINT32 physical;
gcmkHEADER_ARG("Iommu=%p", Iommu);
for (physical = 0; physical < 0x80000000; physical += PAGE_SIZE)
{
gcmkTRACE_ZONE(
gcvLEVEL_INFO, gcvZONE_OS,
"Map %x => %x bytes = %d",
physical, physical, PAGE_SIZE
);
gcmkONERROR(gckIOMMU_Map(Iommu, physical, physical, PAGE_SIZE));
}
OnError:
gcmkFOOTER();
return status;
}
void
gckIOMMU_Destory(
IN gckOS Os,
IN gckIOMMU Iommu
)
{
gcmkHEADER_ARG("Os=%p Iommu=%p", Os, Iommu);
if (Iommu->domain && Iommu->device)
{
iommu_attach_device(Iommu->domain, Iommu->device);
}
if (Iommu->domain)
{
iommu_domain_free(Iommu->domain);
}
if (Iommu)
{
gcmkOS_SAFE_FREE(Os, Iommu);
}
gcmkFOOTER_NO();
}
gceSTATUS
gckIOMMU_Construct(
IN gckOS Os,
OUT gckIOMMU * Iommu
)
{
gceSTATUS status = gcvSTATUS_OK;
gckIOMMU iommu = gcvNULL;
struct device *dev;
gcmkHEADER_ARG("Os=%p", Os);
dev = &Os->device->platform->device->dev;
gcmkONERROR(gckOS_Allocate(Os, gcmSIZEOF(gcsIOMMU), (gctPOINTER *)&iommu));
gckOS_ZeroMemory(iommu, gcmSIZEOF(gcsIOMMU));
iommu->domain = iommu_domain_alloc(&platform_bus_type);
if (!iommu->domain)
{
gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_OS, "iommu_domain_alloc() fail");
gcmkONERROR(gcvSTATUS_NOT_SUPPORTED);
}
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0)
iommu_set_fault_handler(iommu->domain, _IOMMU_Fault_Handler, dev);
#else
iommu_set_fault_handler(iommu->domain, _IOMMU_Fault_Handler);
#endif
if (iommu_attach_device(iommu->domain, dev))
{
gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_OS, "iommu_attach_device() fail");
gcmkONERROR(gcvSTATUS_NOT_SUPPORTED);
}
iommu->device = dev;
_FlatMapping(iommu);
*Iommu = iommu;
OnError:
if (gcmIS_ERROR(status))
{
gckIOMMU_Destory(Os, iommu);
}
gcmkFOOTER();
return status;
}
gceSTATUS
gckIOMMU_Map(
IN gckIOMMU Iommu,
IN gctUINT32 DomainAddress,
IN gctUINT32 Physical,
IN gctUINT32 Bytes
)
{
gceSTATUS status = gcvSTATUS_OK;
gcmkHEADER_ARG("DomainAddress=%#X, Physical=%#X, Bytes=%d",
DomainAddress, Physical, Bytes);
if (iommu_map(Iommu->domain, DomainAddress, Physical, Bytes, 0))
{
gcmkONERROR(gcvSTATUS_NOT_SUPPORTED);
}
OnError:
gcmkFOOTER();
return status;
}
gceSTATUS
gckIOMMU_Unmap(
IN gckIOMMU Iommu,
IN gctUINT32 DomainAddress,
IN gctUINT32 Bytes
)
{
gcmkHEADER();
iommu_unmap(Iommu->domain, DomainAddress, Bytes);
gcmkFOOTER_NO();
return gcvSTATUS_OK;
}

View File

@ -0,0 +1,575 @@
/****************************************************************************
*
* The MIT License (MIT)
*
* Copyright (c) 2014 - 2019 Vivante Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
*****************************************************************************
*
* The GPL License (GPL)
*
* Copyright (C) 2014 - 2019 Vivante Corporation
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*****************************************************************************
*
* Note: This software is released under dual MIT and GPL licenses. A
* recipient may use this file under the terms of either the MIT license or
* GPL License. If you wish to use only one license not the other, you can
* indicate your decision by deleting one of the above license notices in your
* version of this file.
*
*****************************************************************************/
#include "gc_hal_kernel_linux.h"
#define _GC_OBJ_ZONE gcvZONE_KERNEL
/******************************************************************************\
******************************* gckKERNEL API Code ******************************
\******************************************************************************/
/*******************************************************************************
**
** gckKERNEL_QueryVideoMemory
**
** Query the amount of video memory.
**
** INPUT:
**
** gckKERNEL Kernel
** Pointer to an gckKERNEL object.
**
** OUTPUT:
**
** gcsHAL_INTERFACE * Interface
** Pointer to an gcsHAL_INTERFACE structure that will be filled in with
** the memory information.
*/
gceSTATUS
gckKERNEL_QueryVideoMemory(
IN gckKERNEL Kernel,
OUT gcsHAL_INTERFACE * Interface
)
{
gckGALDEVICE device;
gcmkHEADER_ARG("Kernel=%p", Kernel);
/* Verify the arguments. */
gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
gcmkVERIFY_ARGUMENT(Interface != NULL);
/* Extract the pointer to the gckGALDEVICE class. */
device = (gckGALDEVICE) Kernel->context;
/* Get internal memory size and physical address. */
Interface->u.QueryVideoMemory.internalSize = device->internalSize;
Interface->u.QueryVideoMemory.internalPhysName = device->internalPhysName;
/* Get external memory size and physical address. */
Interface->u.QueryVideoMemory.externalSize = device->externalSize;
Interface->u.QueryVideoMemory.externalPhysName = device->externalPhysName;
/* Get contiguous memory size and physical address. */
Interface->u.QueryVideoMemory.contiguousSize = device->contiguousSize;
Interface->u.QueryVideoMemory.contiguousPhysName = device->contiguousPhysName;
/* Success. */
gcmkFOOTER_NO();
return gcvSTATUS_OK;
}
/*******************************************************************************
**
** gckKERNEL_GetVideoMemoryPool
**
** Get the gckVIDMEM object belonging to the specified pool.
**
** INPUT:
**
** gckKERNEL Kernel
** Pointer to an gckKERNEL object.
**
** gcePOOL Pool
** Pool to query gckVIDMEM object for.
**
** OUTPUT:
**
** gckVIDMEM * VideoMemory
** Pointer to a variable that will hold the pointer to the gckVIDMEM
** object belonging to the requested pool.
*/
gceSTATUS
gckKERNEL_GetVideoMemoryPool(
IN gckKERNEL Kernel,
IN gcePOOL Pool,
OUT gckVIDMEM * VideoMemory
)
{
gckGALDEVICE device;
gckVIDMEM videoMemory;
gcmkHEADER_ARG("Kernel=%p Pool=%d", Kernel, Pool);
/* Verify the arguments. */
gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
gcmkVERIFY_ARGUMENT(VideoMemory != NULL);
/* Extract the pointer to the gckGALDEVICE class. */
device = (gckGALDEVICE) Kernel->context;
/* Dispatch on pool. */
switch (Pool)
{
case gcvPOOL_LOCAL_INTERNAL:
/* Internal memory. */
videoMemory = device->internalVidMem;
break;
case gcvPOOL_LOCAL_EXTERNAL:
/* External memory. */
videoMemory = device->externalVidMem;
break;
case gcvPOOL_SYSTEM:
/* System memory. */
videoMemory = device->contiguousVidMem;
break;
case gcvPOOL_INTERNAL_SRAM:
/* Internal SRAM memory. */
videoMemory = Kernel->sRAMVidMem[Kernel->sRAMIndex];
break;
case gcvPOOL_EXTERNAL_SRAM:
/* External SRAM memory. */
videoMemory = device->extSRAMVidMem[Kernel->extSRAMIndex];
break;
default:
/* Unknown pool. */
videoMemory = NULL;
}
/* Return pointer to the gckVIDMEM object. */
*VideoMemory = videoMemory;
/* Return status. */
gcmkFOOTER_ARG("*VideoMemory=%p", *VideoMemory);
return (videoMemory == NULL) ? gcvSTATUS_OUT_OF_MEMORY : gcvSTATUS_OK;
}
/*******************************************************************************
**
** gckKERNEL_MapMemory
**
** Map video memory into the current process space.
**
** INPUT:
**
** gckKERNEL Kernel
** Pointer to an gckKERNEL object.
**
** gctPHYS_ADDR Physical
** Physical address of video memory to map.
**
** gctSIZE_T Bytes
** Number of bytes to map.
**
** OUTPUT:
**
** gctPOINTER * Logical
** Pointer to a variable that will hold the base address of the mapped
** memory region.
*/
gceSTATUS
gckKERNEL_MapMemory(
IN gckKERNEL Kernel,
IN gctPHYS_ADDR Physical,
IN gctSIZE_T Bytes,
OUT gctPOINTER * Logical
)
{
gckKERNEL kernel = Kernel;
gctPHYS_ADDR physical = gcmNAME_TO_PTR(Physical);
return gckOS_MapMemory(Kernel->os, physical, Bytes, Logical);
}
/*******************************************************************************
**
** gckKERNEL_UnmapMemory
**
** Unmap video memory from the current process space.
**
** INPUT:
**
** gckKERNEL Kernel
** Pointer to an gckKERNEL object.
**
** gctPHYS_ADDR Physical
** Physical address of video memory to map.
**
** gctSIZE_T Bytes
** Number of bytes to map.
**
** gctPOINTER Logical
** Base address of the mapped memory region.
**
** OUTPUT:
**
** Nothing.
*/
gceSTATUS
gckKERNEL_UnmapMemory(
IN gckKERNEL Kernel,
IN gctPHYS_ADDR Physical,
IN gctSIZE_T Bytes,
IN gctPOINTER Logical,
IN gctUINT32 ProcessID
)
{
gckKERNEL kernel = Kernel;
gctPHYS_ADDR physical = gcmNAME_TO_PTR(Physical);
return gckOS_UnmapMemoryEx(Kernel->os, physical, Bytes, Logical, ProcessID);
}
/*******************************************************************************
**
** gckKERNEL_MapVideoMemory
**
** Get the logical address for a hardware specific memory address for the
** current process.
**
** INPUT:
**
** gckKERNEL Kernel
** Pointer to an gckKERNEL object.
**
** gctBOOL InUserSpace
** gcvTRUE to map the memory into the user space.
**
** gcePOOL Pool
** Specify pool type.
**
** gctUINT32 Offset
** Offset to pool start.
**
** gctUINT32 Bytes
** Number of bytes to map.
**
** OUTPUT:
**
** gctPOINTER * Logical
** Pointer to a variable that will hold the logical address of the
** specified memory address.
*/
gceSTATUS
gckKERNEL_MapVideoMemory(
IN gckKERNEL Kernel,
IN gctBOOL InUserSpace,
IN gcePOOL Pool,
IN gctPHYS_ADDR Physical,
IN gctUINT32 Offset,
IN gctUINT32 Bytes,
OUT gctPOINTER * Logical
)
{
gckGALDEVICE device = gcvNULL;
gctSIZE_T bytes = 0;
gctPHYS_ADDR physHandle = gcvNULL;
gceSTATUS status = gcvSTATUS_OK;
gctPOINTER logical = gcvNULL;
gctUINT64 mappingInOne = 1;
gcmkHEADER_ARG("Kernel=%p InUserSpace=%d Pool=%d Offset=%X Bytes=%X",
Kernel, InUserSpace, Pool, Offset, Bytes);
/* Verify the arguments. */
gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
gcmkVERIFY_ARGUMENT(Logical != NULL);
if (Physical)
{
gcmkONERROR(gckOS_QueryOption(Kernel->os, "allMapInOne", &mappingInOne));
}
if (mappingInOne)
{
/* Extract the pointer to the gckGALDEVICE class. */
device = (gckGALDEVICE) Kernel->context;
/* Dispatch on pool. */
switch (Pool)
{
case gcvPOOL_LOCAL_INTERNAL:
physHandle = (PLINUX_MDL)device->internalPhysical;
bytes = device->internalSize;
break;
case gcvPOOL_LOCAL_EXTERNAL:
physHandle = (PLINUX_MDL)device->externalPhysical;
bytes = device->externalSize;
break;
case gcvPOOL_SYSTEM:
/* System memory. */
physHandle = (PLINUX_MDL)device->contiguousPhysical;
bytes = device->contiguousSize;
break;
case gcvPOOL_EXTERNAL_SRAM:
/* External shared SRAM memory. */
physHandle = (PLINUX_MDL)device->extSRAMPhysical[Kernel->extSRAMIndex];
bytes = device->extSRAMSizes[Kernel->extSRAMIndex];
break;
case gcvPOOL_INTERNAL_SRAM:
/* Per core SRAM reserved usage. */
if (Kernel->sRAMPhysFaked[Kernel->sRAMIndex])
{
*Logical = gcvNULL;
gcmkFOOTER_NO();
return gcvSTATUS_OK;
}
/* Per core SRAM memory block. */
else
{
physHandle = (PLINUX_MDL)Kernel->sRAMPhysical[Kernel->sRAMIndex];
bytes = Kernel->sRAMSizes[Kernel->sRAMIndex];
break;
}
default:
/* Invalid memory pool. */
gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
}
}
else
{
physHandle = (PLINUX_MDL)Physical;
bytes = Bytes;
Offset = 0;
}
gcmkONERROR(gckOS_LockPages(Kernel->os, physHandle, bytes, gcvFALSE, &logical));
/* Build logical address of specified address. */
*Logical = (gctPOINTER)((gctUINT8_PTR)logical + Offset);
OnError:
/* Retunn the status. */
gcmkFOOTER_ARG("*Logical=%p", gcmOPT_POINTER(Logical));
return status;
}
/*******************************************************************************
**
** gckKERNEL_UnmapVideoMemory
**
** Unmap video memory for the current process.
**
** INPUT:
**
** gckKERNEL Kernel
** Pointer to an gckKERNEL object.
**
** gcePOOL Pool
** Specify pool type.
** gctUINT32 Address
** Hardware specific memory address.
**
** gctUINT32 Pid
** Process ID of the current process.
**
** gctSIZE_T Bytes
** Number of bytes to map.
**
** OUTPUT:
**
** Nothing.
*/
gceSTATUS
gckKERNEL_UnmapVideoMemory(
IN gckKERNEL Kernel,
IN gcePOOL Pool,
IN gctPHYS_ADDR Physical,
IN gctPOINTER Logical,
IN gctUINT32 Pid,
IN gctSIZE_T Bytes
)
{
gceSTATUS status = gcvSTATUS_OK;
gckGALDEVICE device = gcvNULL;
gctSIZE_T bytes = 0;
gctPHYS_ADDR physHandle = gcvNULL;
gctUINT64 mappingInOne = 1;
gcmkHEADER_ARG("Logical=0x%08x pid=%u Bytes=%u",
Logical, Pid, Bytes);
/* Verify the arguments. */
gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
if (Logical == gcvNULL)
{
return gcvSTATUS_OK;
}
if (Physical)
{
gcmkONERROR(gckOS_QueryOption(Kernel->os, "allMapInOne", &mappingInOne));
}
if (mappingInOne)
{
/* Extract the pointer to the gckGALDEVICE class. */
device = (gckGALDEVICE) Kernel->context;
/* Dispatch on pool. */
switch (Pool)
{
case gcvPOOL_LOCAL_INTERNAL:
physHandle = (PLINUX_MDL)device->internalPhysical;
bytes = device->internalSize;
break;
case gcvPOOL_LOCAL_EXTERNAL:
physHandle = (PLINUX_MDL)device->externalPhysical;
bytes = device->externalSize;
break;
case gcvPOOL_SYSTEM:
/* System memory. */
physHandle = (PLINUX_MDL)device->contiguousPhysical;
bytes = device->contiguousSize;
break;
case gcvPOOL_EXTERNAL_SRAM:
/* External shared SRAM memory. */
physHandle = (PLINUX_MDL)device->extSRAMPhysical[Kernel->extSRAMIndex];
bytes = device->extSRAMSizes[Kernel->extSRAMIndex];
break;
case gcvPOOL_INTERNAL_SRAM:
/* Per core SRAM reserved usage. */
if (Kernel->sRAMPhysFaked[Kernel->sRAMIndex])
{
gcmkFOOTER_NO();
return gcvSTATUS_OK;
}
/* Per core SRAM memory block. */
else
{
physHandle = (PLINUX_MDL)Kernel->sRAMPhysical[Kernel->sRAMIndex];
bytes = Kernel->sRAMSizes[Kernel->sRAMIndex];
break;
}
default:
/* Invalid memory pool. */
gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
}
}
else
{
physHandle = (PLINUX_MDL)Physical;
bytes = Bytes;
}
gcmkONERROR(gckOS_UnlockPages(Kernel->os, physHandle, bytes, Logical));
OnError:
/* Retunn the status. */
gcmkFOOTER_NO();
return status;
}
/*******************************************************************************
**
** gckKERNEL_Notify
**
** This function iscalled by clients to notify the gckKERNRL object of an event.
**
** INPUT:
**
** gckKERNEL Kernel
** Pointer to an gckKERNEL object.
**
** gceNOTIFY Notification
** Notification event.
**
** OUTPUT:
**
** Nothing.
*/
gceSTATUS
gckKERNEL_Notify(
IN gckKERNEL Kernel,
IN gceNOTIFY Notification
)
{
gceSTATUS status = gcvSTATUS_OK;
gcmkHEADER_ARG("Kernel=%p Notification=%d", Kernel, Notification);
/* Verify the arguments. */
gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
/* Dispatch on notifcation. */
switch (Notification)
{
case gcvNOTIFY_INTERRUPT:
/* Process the interrupt. */
#if COMMAND_PROCESSOR_VERSION > 1
status = gckINTERRUPT_Notify(Kernel->interrupt, 0);
#else
status = gckHARDWARE_Notify(Kernel->hardware);
#endif
break;
default:
break;
}
/* Success. */
gcmkFOOTER();
return status;
}

View File

@ -0,0 +1,393 @@
/****************************************************************************
*
* The MIT License (MIT)
*
* Copyright (c) 2014 - 2019 Vivante Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
*****************************************************************************
*
* The GPL License (GPL)
*
* Copyright (C) 2014 - 2019 Vivante Corporation
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*****************************************************************************
*
* Note: This software is released under dual MIT and GPL licenses. A
* recipient may use this file under the terms of either the MIT license or
* GPL License. If you wish to use only one license not the other, you can
* indicate your decision by deleting one of the above license notices in your
* version of this file.
*
*****************************************************************************/
#ifndef __gc_hal_kernel_linux_h_
#define __gc_hal_kernel_linux_h_
#include <linux/version.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/mm.h>
#include <linux/sched.h>
#include <linux/signal.h>
#include <linux/interrupt.h>
#include <linux/vmalloc.h>
#include <linux/dma-mapping.h>
#include <linux/kthread.h>
#include <linux/idr.h>
#ifdef MODVERSIONS
# include <linux/modversions.h>
#endif
#include <asm/io.h>
#if LINUX_VERSION_CODE > KERNEL_VERSION(4,7,0)
#include <linux/uaccess.h>
#else
#include <asm/uaccess.h>
#endif
#if ENABLE_GPU_CLOCK_BY_DRIVER && LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28)
#include <linux/clk.h>
#endif
#define NTSTRSAFE_NO_CCH_FUNCTIONS
#include "gc_hal.h"
#include "gc_hal_driver.h"
#include "gc_hal_kernel.h"
#include "gc_hal_kernel_platform.h"
#include "gc_hal_kernel_device.h"
#include "gc_hal_kernel_os.h"
#include "gc_hal_kernel_debugfs.h"
#include "gc_hal_ta.h"
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,31)
#define FIND_TASK_BY_PID(x) pid_task(find_vpid(x), PIDTYPE_PID)
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
#define FIND_TASK_BY_PID(x) find_task_by_vpid(x)
#else
#define FIND_TASK_BY_PID(x) find_task_by_pid(x)
#endif
#ifndef DEVICE_NAME
# define DEVICE_NAME "galcore"
#endif
#ifndef CLASS_NAME
# define CLASS_NAME "graphics_class"
#endif
#define GetPageCount(size, offset) ((((size) + ((offset) & ~PAGE_MASK)) + PAGE_SIZE - 1) >> PAGE_SHIFT)
#if LINUX_VERSION_CODE >= KERNEL_VERSION (3,7,0)
#define gcdVM_FLAGS (VM_IO | VM_DONTCOPY | VM_DONTEXPAND | VM_DONTDUMP)
#else
#define gcdVM_FLAGS (VM_IO | VM_DONTCOPY | VM_DONTEXPAND | VM_RESERVED)
#endif
/* Protection bit when mapping memroy to user sapce */
#define gcmkPAGED_MEMROY_PROT(x) pgprot_writecombine(x)
#define gcdSUPPRESS_OOM_MESSAGE 1
#if gcdSUPPRESS_OOM_MESSAGE
#define gcdNOWARN __GFP_NOWARN
#else
#define gcdNOWARN 0
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION (4, 1, 0)
#ifdef gcdIRQ_SHARED
# define gcdIRQF_FLAG (IRQF_SHARED | IRQF_TRIGGER_HIGH)
# else
# define gcdIRQF_FLAG (IRQF_TRIGGER_HIGH)
# endif
#else
#ifdef gcdIRQ_SHARED
# define gcdIRQF_FLAG (IRQF_DISABLED | IRQF_SHARED | IRQF_TRIGGER_HIGH)
# else
# define gcdIRQF_FLAG (IRQF_DISABLED | IRQF_TRIGGER_HIGH)
# endif
#endif
/* gcdLINUX_SYNC_FILE and CONFIG_SYNC_FILE. */
#if LINUX_VERSION_CODE < KERNEL_VERSION(4,10,0)
# define dma_fence fence
# define dma_fence_array fence_array
# define dma_fence_ops fence_ops
# define dma_fence_default_wait fence_default_wait
# define dma_fence_signal(f) fence_signal(f)
# define dma_fence_signal_locked(f) fence_signal_locked(f)
# define dma_fence_get(f) fence_get(f)
# define dma_fence_put(f) fence_put(f)
# define dma_fence_is_array(f) fence_is_array(f)
# define dma_fence_is_signaled(f) fence_is_signaled(f)
# define to_dma_fence_array(f) to_fence_array(f)
# define dma_fence_wait_timeout(f, n, t) fence_wait_timeout((f), (n), (t))
# define dma_fence_init(f, o, l, t, s) fence_init((f), (o), (l), (t), (s))
# define dma_fence_context_alloc(s) fence_context_alloc(s)
#endif
#if LINUX_VERSION_CODE > KERNEL_VERSION(5,0,0)
#ifndef dma_alloc_writecombine
#define dma_alloc_writecombine dma_alloc_wc
#endif
#ifndef dma_free_writecombine
#define dma_free_writecombine dma_free_wc
#endif
#ifndef dma_mmap_writecombine
#define dma_mmap_writecombine dma_mmap_wc
#endif
#endif
extern struct device *galcore_device;
/******************************************************************************\
********************************** Structures **********************************
\******************************************************************************/
typedef struct _gcsIOMMU * gckIOMMU;
typedef struct _gcsINTEGER_DB * gcsINTEGER_DB_PTR;
typedef struct _gcsINTEGER_DB
{
struct idr idr;
spinlock_t lock;
gctINT curr;
}
gcsINTEGER_DB;
struct _gckOS
{
/* Object. */
gcsOBJECT object;
/* Pointer to device */
gckGALDEVICE device;
/* Memory management */
struct mutex mdlMutex;
struct list_head mdlHead;
/* Kernel process ID. */
gctUINT32 kernelProcessID;
/* Signal management. */
/* Lock. */
spinlock_t signalLock;
/* signal id database. */
gcsINTEGER_DB signalDB;
/* workqueue for os timer. */
struct workqueue_struct * workqueue;
/* Allocate extra page to avoid cache overflow */
struct page* paddingPage;
/* Detect unfreed allocation. */
atomic_t allocateCount;
struct list_head allocatorList;
gcsDEBUGFS_DIR allocatorDebugfsDir;
gctBOOL allocatorLimitMarker;
/* Lock for register access check. */
spinlock_t registerAccessLock;
/* External power states. */
gctBOOL powerStates[gcdMAX_GPU_COUNT];
/* External clock states. */
gctBOOL clockStates[gcdMAX_GPU_COUNT];
/* IOMMU. */
gckIOMMU iommu;
/* Dump in kernel. */
struct file * dumpFilp;
struct mutex dumpFilpMutex;
int dumpTarget;
char dumpFileName[256];
gcsDEBUGFS_DIR dumpDebugfsDir;
};
typedef struct _gcsSIGNAL * gcsSIGNAL_PTR;
typedef struct _gcsSIGNAL
{
/* Kernel sync primitive. */
volatile unsigned int done;
spinlock_t lock;
wait_queue_head_t wait;
/* Manual reset flag. */
gctBOOL manualReset;
/* The reference counter. */
atomic_t ref;
/* The owner of the signal. */
gctHANDLE process;
/* ID. */
gctUINT32 id;
#if gcdLINUX_SYNC_FILE
#ifndef CONFIG_SYNC_FILE
/* Parent timeline. */
struct sync_timeline * timeline;
# else
struct dma_fence *fence;
# endif
#endif
}
gcsSIGNAL;
typedef struct _gcsOSTIMER * gcsOSTIMER_PTR;
typedef struct _gcsOSTIMER
{
struct delayed_work work;
gctTIMERFUNCTION function;
gctPOINTER data;
} gcsOSTIMER;
gceSTATUS
gckOS_ImportAllocators(
gckOS Os
);
gceSTATUS
gckOS_FreeAllocators(
gckOS Os
);
gceSTATUS
_ConvertLogical2Physical(
IN gckOS Os,
IN gctPOINTER Logical,
IN gctUINT32 ProcessID,
IN PLINUX_MDL Mdl,
OUT gctPHYS_ADDR_T * Physical
);
gctBOOL
_QuerySignal(
IN gckOS Os,
IN gctSIGNAL Signal
);
static inline gctINT
_GetProcessID(
void
)
{
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
return task_tgid_vnr(current);
#else
return current->tgid;
#endif
}
static inline void
_MemoryBarrier(
void
)
{
#if defined(CONFIG_ARM) && (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,34))
dsb();
#else
mb();
#endif
}
static inline void
_Barrier(
void
)
{
barrier();
}
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25)
static inline int
is_vmalloc_addr(
void *Addr
)
{
unsigned long addr = (unsigned long)Addr;
return addr >= VMALLOC_START && addr < VMALLOC_END;
}
#endif
#ifdef CONFIG_IOMMU_SUPPORT
void
gckIOMMU_Destory(
IN gckOS Os,
IN gckIOMMU Iommu
);
gceSTATUS
gckIOMMU_Construct(
IN gckOS Os,
OUT gckIOMMU * Iommu
);
gceSTATUS
gckIOMMU_Map(
IN gckIOMMU Iommu,
IN gctUINT32 DomainAddress,
IN gctUINT32 Physical,
IN gctUINT32 Bytes
);
gceSTATUS
gckIOMMU_Unmap(
IN gckIOMMU Iommu,
IN gctUINT32 DomainAddress,
IN gctUINT32 Bytes
);
#endif
#endif /* __gc_hal_kernel_linux_h_ */

View File

@ -0,0 +1,66 @@
/****************************************************************************
*
* The MIT License (MIT)
*
* Copyright (c) 2014 - 2019 Vivante Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
*****************************************************************************
*
* The GPL License (GPL)
*
* Copyright (C) 2014 - 2019 Vivante Corporation
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*****************************************************************************
*
* Note: This software is released under dual MIT and GPL licenses. A
* recipient may use this file under the terms of either the MIT license or
* GPL License. If you wish to use only one license not the other, you can
* indicate your decision by deleting one of the above license notices in your
* version of this file.
*
*****************************************************************************/
#include "gc_hal_kernel_linux.h"
gctINT
gckMATH_ModuloInt(
IN gctINT X,
IN gctINT Y
)
{
if(Y ==0) {return 0;}
else {return X % Y;}
}

View File

@ -0,0 +1,80 @@
/****************************************************************************
*
* The MIT License (MIT)
*
* Copyright (c) 2014 - 2019 Vivante Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
*****************************************************************************
*
* The GPL License (GPL)
*
* Copyright (C) 2014 - 2019 Vivante Corporation
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*****************************************************************************
*
* Note: This software is released under dual MIT and GPL licenses. A
* recipient may use this file under the terms of either the MIT license or
* GPL License. If you wish to use only one license not the other, you can
* indicate your decision by deleting one of the above license notices in your
* version of this file.
*
*****************************************************************************/
#ifndef _gc_hal_kernel_mutex_h_
#define _gc_hal_kernel_mutex_h_
#include "gc_hal.h"
#include <linux/mutex.h>
/* Create a new mutex. */
#define gckOS_CreateMutex(Os, Mutex) \
({ \
/* Allocate the mutex structure. */ \
gceSTATUS _status = gckOS_Allocate(Os, gcmSIZEOF(struct mutex), Mutex); \
\
if (gcmIS_SUCCESS(_status)) \
{ \
/* Initialize the mutex. */ \
mutex_init(*(struct mutex **)Mutex); \
} \
\
_status; \
})
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,124 @@
/****************************************************************************
*
* The MIT License (MIT)
*
* Copyright (c) 2014 - 2019 Vivante Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
*****************************************************************************
*
* The GPL License (GPL)
*
* Copyright (C) 2014 - 2019 Vivante Corporation
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*****************************************************************************
*
* Note: This software is released under dual MIT and GPL licenses. A
* recipient may use this file under the terms of either the MIT license or
* GPL License. If you wish to use only one license not the other, you can
* indicate your decision by deleting one of the above license notices in your
* version of this file.
*
*****************************************************************************/
#ifndef __gc_hal_kernel_os_h_
#define __gc_hal_kernel_os_h_
typedef struct _LINUX_MDL LINUX_MDL, *PLINUX_MDL;
typedef struct _LINUX_MDL_MAP LINUX_MDL_MAP, *PLINUX_MDL_MAP;
struct _LINUX_MDL_MAP
{
gctINT pid;
/* map references. */
gctUINT32 count;
struct vm_area_struct * vma;
gctPOINTER vmaAddr;
gctBOOL cacheable;
struct list_head link;
};
struct _LINUX_MDL
{
gckOS os;
atomic_t refs;
/* Kernel address. */
char * addr;
/* Size and covered page count. */
size_t bytes;
size_t numPages;
gctBOOL contiguous;
dma_addr_t dmaHandle;
gctBOOL cacheable;
struct mutex mapsMutex;
struct list_head mapsHead;
/* Pointer to allocator which allocates memory for this mdl. */
void * allocator;
/* Private data used by allocator. */
void * priv;
uint gid;
struct list_head link;
gctBOOL pageUnit1M;
};
extern PLINUX_MDL_MAP
FindMdlMap(
IN PLINUX_MDL Mdl,
IN gctINT PID
);
typedef struct _DRIVER_ARGS
{
gctUINT64 InputBuffer;
gctUINT64 InputBufferSize;
gctUINT64 OutputBuffer;
gctUINT64 OutputBufferSize;
}
DRIVER_ARGS;
#endif /* __gc_hal_kernel_os_h_ */

View File

@ -0,0 +1,315 @@
/****************************************************************************
*
* The MIT License (MIT)
*
* Copyright (c) 2014 - 2019 Vivante Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
*****************************************************************************
*
* The GPL License (GPL)
*
* Copyright (C) 2014 - 2019 Vivante Corporation
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*****************************************************************************
*
* Note: This software is released under dual MIT and GPL licenses. A
* recipient may use this file under the terms of either the MIT license or
* GPL License. If you wish to use only one license not the other, you can
* indicate your decision by deleting one of the above license notices in your
* version of this file.
*
*****************************************************************************/
#ifndef _gc_hal_kernel_platform_h_
#define _gc_hal_kernel_platform_h_
#include <linux/mm.h>
#include <linux/platform_device.h>
#if USE_LINUX_PCIE
#include <linux/pci.h>
#endif
typedef struct _gcsMODULE_PARAMETERS
{
gctINT irqs[gcvCORE_COUNT];
gctPHYS_ADDR_T registerBases[gcvCORE_COUNT];
gctSIZE_T registerSizes[gcvCORE_COUNT];
gctINT bars[gcvCORE_COUNT];
gctPOINTER registerBasesMapped[gcvCORE_COUNT];
gctUINT chipIDs[gcvCORE_COUNT];
/* Contiguous memory pool. */
gctPHYS_ADDR_T contiguousBase;
gctSIZE_T contiguousSize;
gctBOOL contiguousRequested;
/* External memory pool. */
gctPHYS_ADDR_T externalBase;
gctSIZE_T externalSize;
/* Per-core SRAM. */
gctPHYS_ADDR_T sRAMBases[gcvCORE_COUNT][gcvSRAM_INTER_COUNT];
gctUINT32 sRAMSizes[gcvCORE_COUNT][gcvSRAM_INTER_COUNT];
/* Shared SRAM. */
gctPHYS_ADDR_T extSRAMBases[gcvSRAM_EXT_COUNT];
gctUINT32 extSRAMSizes[gcvSRAM_EXT_COUNT];
#if USE_LINUX_PCIE
gctUINT32 regOffsets[gcvCORE_COUNT];
gctINT32 sRAMBars[gcvSRAM_EXT_COUNT];
gctINT32 sRAMOffsets[gcvSRAM_EXT_COUNT];
#endif
gctBOOL sRAMRequested;
gctUINT32 sRAMLoopMode;
gctPHYS_ADDR_T baseAddress;
gctSIZE_T physSize;
gctSIZE_T bankSize;
gctUINT recovery;
gctINT powerManagement;
gctINT enableMmu;
gctINT fastClear;
gceCOMPRESSION_OPTION compression;
gctUINT gpu3DMinClock;
gctUINT userClusterMask;
gctUINT smallBatch;
/* Debug or other information. */
gctUINT stuckDump;
gctINT gpuProfiler;
/* device type, 0 for char device, 1 for misc device. */
gctUINT deviceType;
gctUINT showArgs;
/* mmu page table pool, 0 mean auto, 1 means virsual*/
gctUINT mmuPageTablePool;
gctUINT mmuDynamicMap;
gctUINT allMapInOne;
}
gcsMODULE_PARAMETERS;
typedef struct _gcsPLATFORM gcsPLATFORM;
typedef struct _gcsPLATFORM_OPERATIONS
{
/*******************************************************************************
**
** adjustParam
**
** Override content of arguments, if a argument is not changed here, it will
** keep as default value or value set by insmod command line.
*/
gceSTATUS
(*adjustParam)(
IN gcsPLATFORM * Platform,
OUT gcsMODULE_PARAMETERS *Args
);
/*******************************************************************************
**
** getPower
**
** Prepare power and clock operation.
*/
gceSTATUS
(*getPower)(
IN gcsPLATFORM * Platform
);
/*******************************************************************************
**
** putPower
**
** Finish power and clock operation.
*/
gceSTATUS
(*putPower)(
IN gcsPLATFORM * Platform
);
/*******************************************************************************
**
** setPower
**
** Set power state of specified GPU.
**
** INPUT:
**
** gceCORE GPU
** GPU neeed to config.
**
** gceBOOL Enable
** Enable or disable power.
*/
gceSTATUS
(*setPower)(
IN gcsPLATFORM * Platform,
IN gceCORE GPU,
IN gctBOOL Enable
);
/*******************************************************************************
**
** setClock
**
** Set clock state of specified GPU.
**
** INPUT:
**
** gceCORE GPU
** GPU neeed to config.
**
** gceBOOL Enable
** Enable or disable clock.
*/
gceSTATUS
(*setClock)(
IN gcsPLATFORM * Platform,
IN gceCORE GPU,
IN gctBOOL Enable
);
/*******************************************************************************
**
** reset
**
** Reset GPU outside.
**
** INPUT:
**
** gceCORE GPU
** GPU neeed to reset.
*/
gceSTATUS
(*reset)(
IN gcsPLATFORM * Platform,
IN gceCORE GPU
);
/*******************************************************************************
**
** getGPUPhysical
**
** Convert CPU physical address to GPU physical address if they are
** different.
*/
gceSTATUS
(*getGPUPhysical)(
IN gcsPLATFORM * Platform,
IN gctPHYS_ADDR_T CPUPhysical,
OUT gctPHYS_ADDR_T * GPUPhysical
);
/*******************************************************************************
**
** getCPUPhysical
**
** Convert GPU physical address to CPU physical address if they are
** different.
*/
gceSTATUS
(*getCPUPhysical)(
IN gcsPLATFORM * Platform,
IN gctPHYS_ADDR_T GPUPhysical,
OUT gctPHYS_ADDR_T * CPUPhysical
);
/*******************************************************************************
**
** adjustProt
**
** Override Prot flag when mapping paged memory to userspace.
*/
gceSTATUS
(*adjustProt)(
IN struct vm_area_struct * vma
);
/*******************************************************************************
**
** shrinkMemory
**
** Do something to collect memory, eg, act as oom killer.
*/
gceSTATUS
(*shrinkMemory)(
IN gcsPLATFORM * Platform
);
/*******************************************************************************
**
** getPolicyID
**
** Get policyID for a specified surface type.
*/
gceSTATUS
(*getPolicyID)(
IN gcsPLATFORM *Platform,
IN gceVIDMEM_TYPE Type,
OUT gctUINT32_PTR PolicyID,
OUT gctUINT32_PTR AXIConfig
);
}
gcsPLATFORM_OPERATIONS;
struct _gcsPLATFORM
{
struct platform_device *device;
struct platform_driver *driver;
const char *name;
gcsPLATFORM_OPERATIONS* ops;
/* TODO: Remove AXI-SRAM size from feature database. */
gckDEVICE dev;
/* PLATFORM specific flags */
gctUINT32 flagBits;
void* priv;
};
int gckPLATFORM_Init(struct platform_driver *pdrv, gcsPLATFORM **platform);
int gckPLATFORM_Terminate(gcsPLATFORM *platform);
#endif

View File

@ -0,0 +1,426 @@
/****************************************************************************
*
* The MIT License (MIT)
*
* Copyright (c) 2014 - 2019 Vivante Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
*****************************************************************************
*
* The GPL License (GPL)
*
* Copyright (C) 2014 - 2019 Vivante Corporation
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*****************************************************************************
*
* Note: This software is released under dual MIT and GPL licenses. A
* recipient may use this file under the terms of either the MIT license or
* GPL License. If you wish to use only one license not the other, you can
* indicate your decision by deleting one of the above license notices in your
* version of this file.
*
*****************************************************************************/
#include "gc_hal_kernel_linux.h"
#include <linux/slab.h>
#include "tee_client_api.h"
#define _GC_OBJ_ZONE gcvZONE_OS
#define GPU3D_UUID { 0xcc9f80ea, 0xa836, 0x11e3, { 0x9b, 0x07, 0x78, 0x2b, 0xcb, 0x5c, 0xf3, 0xe3 } }
static const TEEC_UUID gpu3d_uuid = GPU3D_UUID;
TEEC_Context teecContext;
typedef struct _gcsSecurityChannel
{
gckOS os;
TEEC_Session session;
int * virtual;
TEEC_SharedMemory inputBuffer;
gctUINT32 bytes;
gctPOINTER mutex;
}
gcsSecurityChannel;
TEEC_SharedMemory *
gpu3d_allocate_secure_mem(
gckOS Os,
unsigned int size
)
{
TEEC_Result result;
TEEC_Context *context = &teecContext;
TEEC_SharedMemory *shm = NULL;
void *handle = NULL;
gctPHYS_ADDR_T phyAddr;
gceSTATUS status;
gctSIZE_T bytes = size;
shm = kmalloc(sizeof(TEEC_SharedMemory), GFP_KERNEL);
if (NULL == shm)
{
return NULL;
}
memset(shm, 0, sizeof(TEEC_SharedMemory));
status = gckOS_AllocatePagedMemory(
Os,
gcvALLOC_FLAG_SECURITY,
&bytes,
gcvNULL,
(gctPHYS_ADDR *)&handle);
if (gcmIS_ERROR(status))
{
kfree(shm);
return NULL;
}
status = gckOS_GetPhysicalFromHandle(
Os,
handle,
0,
&phyAddr);
if (gcmIS_ERROR(status))
{
kfree(shm);
return NULL;
}
/* record the handle into shm->user_data */
shm->userdata = handle;
/* [b] Bulk input buffer. */
shm->size = size;
shm->flags = TEEC_MEM_INPUT;
/* Use TEE Client API to register the underlying memory buffer. */
shm->phyAddr = (void *)(gctUINT32)phyAddr;
result = TEEC_RegisterSharedMemory(
context,
shm);
if (result != TEEC_SUCCESS)
{
gckOS_FreePagedMemory(Os, (gctPHYS_ADDR)handle, shm->size);
kfree(shm);
return NULL;
}
return shm;
}
void gpu3d_release_secure_mem(
gckOS Os,
void *shm_handle
)
{
TEEC_SharedMemory *shm = shm_handle;
void * handle;
if (!shm)
{
return;
}
handle = shm->userdata;
TEEC_ReleaseSharedMemory(shm);
gckOS_FreePagedMemory(Os, (gctPHYS_ADDR)handle, shm->size);
kfree(shm);
return;
}
static TEEC_Result gpu3d_session_callback(
TEEC_Session* session,
uint32_t commandID,
TEEC_Operation* operation,
void* userdata
)
{
gcsSecurityChannel *channel = userdata;
if (channel == gcvNULL)
{
return TEEC_ERROR_BAD_PARAMETERS;
}
switch (commandID)
{
case gcvTA_CALLBACK_ALLOC_SECURE_MEM:
{
uint32_t size = operation->params[0].value.a;
TEEC_SharedMemory *shm = NULL;
shm = gpu3d_allocate_secure_mem(channel->os, size);
if (shm == NULL)
{
return TEEC_ERROR_OUT_OF_MEMORY;
}
/* use the value to save the pointer in client side */
operation->params[0].value.a = (uint32_t)shm;
operation->params[0].value.b = (uint32_t)shm->phyAddr;
break;
}
case gcvTA_CALLBACK_FREE_SECURE_MEM:
{
TEEC_SharedMemory *shm = (TEEC_SharedMemory *)operation->params[0].value.a;
gpu3d_release_secure_mem(channel->os, shm);
break;
}
default:
break;
}
return TEEC_SUCCESS;
}
gceSTATUS
gckOS_OpenSecurityChannel(
IN gckOS Os,
IN gceCORE GPU,
OUT gctUINT32 *Channel
)
{
gceSTATUS status;
TEEC_Result result;
static bool initialized = gcvFALSE;
gcsSecurityChannel *channel = gcvNULL;
TEEC_Operation operation = {0};
/* Connect to TEE. */
if (initialized == gcvFALSE)
{
result = TEEC_InitializeContext(NULL, &teecContext);
if (result != TEEC_SUCCESS)
{
gcmkONERROR(gcvSTATUS_CHIP_NOT_READY);
}
initialized = gcvTRUE;
}
/* Construct channel. */
gcmkONERROR(
gckOS_Allocate(Os, gcmSIZEOF(*channel), (gctPOINTER *)&channel));
gckOS_ZeroMemory(channel, gcmSIZEOF(gcsSecurityChannel));
channel->os = Os;
gcmkONERROR(gckOS_CreateMutex(Os, &channel->mutex));
/* Allocate shared memory for passing gcTA_INTERFACE. */
channel->bytes = gcmSIZEOF(gcsTA_INTERFACE);
channel->virtual = kmalloc(channel->bytes, GFP_KERNEL | __GFP_NOWARN);
if (!channel->virtual)
{
gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
}
channel->inputBuffer.size = channel->bytes;
channel->inputBuffer.flags = TEEC_MEM_INPUT | TEEC_MEM_OUTPUT;
channel->inputBuffer.phyAddr = (void *)virt_to_phys(channel->virtual);
result = TEEC_RegisterSharedMemory(&teecContext, &channel->inputBuffer);
if (result != TEEC_SUCCESS)
{
gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
}
operation.paramTypes = TEEC_PARAM_TYPES(
TEEC_VALUE_INPUT,
TEEC_NONE,
TEEC_NONE,
TEEC_NONE);
operation.params[0].value.a = GPU;
/* Open session with TEE application. */
result = TEEC_OpenSession(
&teecContext,
&channel->session,
&gpu3d_uuid,
TEEC_LOGIN_USER,
NULL,
&operation,
NULL);
/* Prepare callback. */
TEEC_RegisterCallback(&channel->session, gpu3d_session_callback, channel);
*Channel = (gctUINT32)channel;
return gcvSTATUS_OK;
OnError:
if (channel)
{
if (channel->virtual)
{
}
if (channel->mutex)
{
gcmkVERIFY_OK(gckOS_DeleteMutex(Os, channel->mutex));
}
gcmkVERIFY_OK(gckOS_Free(Os, channel));
}
return status;
}
gceSTATUS
gckOS_CloseSecurityChannel(
IN gctUINT32 Channel
)
{
return gcvSTATUS_OK;
}
gceSTATUS
gckOS_CallSecurityService(
IN gctUINT32 Channel,
IN gcsTA_INTERFACE *Interface
)
{
gceSTATUS status;
TEEC_Result result;
gcsSecurityChannel *channel = (gcsSecurityChannel *)Channel;
TEEC_Operation operation = {0};
gcmkHEADER();
gcmkVERIFY_ARGUMENT(Channel != 0);
gckOS_AcquireMutex(channel->os, channel->mutex, gcvINFINITE);
gckOS_MemCopy(channel->virtual, Interface, channel->bytes);
operation.paramTypes = TEEC_PARAM_TYPES(
TEEC_MEMREF_PARTIAL_INPUT,
TEEC_NONE,
TEEC_NONE,
TEEC_NONE);
/* Note: we use the updated size in the MemRef output by the encryption. */
operation.params[0].memref.parent = &channel->inputBuffer;
operation.params[0].memref.offset = 0;
operation.params[0].memref.size = sizeof(gcsTA_INTERFACE);
operation.started = true;
/* Start the commit command within the TEE application. */
result = TEEC_InvokeCommand(
&channel->session,
gcvTA_COMMAND_DISPATCH,
&operation,
NULL);
gckOS_MemCopy(Interface, channel->virtual, channel->bytes);
gckOS_ReleaseMutex(channel->os, channel->mutex);
if (result != TEEC_SUCCESS)
{
gcmkONERROR(gcvSTATUS_GENERIC_IO);
}
gcmkFOOTER_NO();
return gcvSTATUS_OK;
OnError:
gcmkFOOTER();
return status;
}
gceSTATUS
gckOS_InitSecurityChannel(
IN gctUINT32 Channel
)
{
gceSTATUS status;
TEEC_Result result;
gcsSecurityChannel *channel = (gcsSecurityChannel *)Channel;
TEEC_Operation operation = {0};
gcmkHEADER();
gcmkVERIFY_ARGUMENT(Channel != 0);
operation.paramTypes = TEEC_PARAM_TYPES(
TEEC_MEMREF_PARTIAL_INPUT,
TEEC_NONE,
TEEC_NONE,
TEEC_NONE);
/* Note: we use the updated size in the MemRef output by the encryption. */
operation.params[0].memref.parent = &channel->inputBuffer;
operation.params[0].memref.offset = 0;
operation.params[0].memref.size = gcmSIZEOF(gcsTA_INTERFACE);
operation.started = true;
/* Start the commit command within the TEE application. */
result = TEEC_InvokeCommand(
&channel->session,
gcvTA_COMMAND_INIT,
&operation,
NULL);
if (result != TEEC_SUCCESS)
{
gcmkONERROR(gcvSTATUS_GENERIC_IO);
}
gcmkFOOTER_NO();
return gcvSTATUS_OK;
OnError:
gcmkFOOTER();
return status;
}

View File

@ -0,0 +1,116 @@
/****************************************************************************
*
* The MIT License (MIT)
*
* Copyright (c) 2014 - 2019 Vivante Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
*****************************************************************************
*
* The GPL License (GPL)
*
* Copyright (C) 2014 - 2019 Vivante Corporation
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*****************************************************************************
*
* Note: This software is released under dual MIT and GPL licenses. A
* recipient may use this file under the terms of either the MIT license or
* GPL License. If you wish to use only one license not the other, you can
* indicate your decision by deleting one of the above license notices in your
* version of this file.
*
*****************************************************************************/
#include "gc_hal_kernel_linux.h"
#define _GC_OBJ_ZONE gcvZONE_OS
#if gcdENABLE_TRUST_APPLICATION
gceSTATUS
gckOS_OpenSecurityChannel(
IN gckOS Os,
IN gceCORE Core,
OUT gctUINT32 *Channel
)
{
*Channel = Core + 1;
return gcvSTATUS_OK;
}
gceSTATUS
gckOS_InitSecurityChannel(
OUT gctUINT32 Channel
)
{
return gcvSTATUS_OK;
}
gceSTATUS
gckOS_CloseSecurityChannel(
IN gctUINT32 Channel
)
{
return gcvSTATUS_OK;
}
extern gceSTATUS
TAEmulator (
gceCORE,
void *
);
gceSTATUS
gckOS_CallSecurityService(
IN gctUINT32 Channel,
IN gcsTA_INTERFACE *Interface
)
{
gceCORE core;
gceSTATUS status;
gcmkHEADER();
gcmkVERIFY_ARGUMENT(Channel != 0);
core = (gceCORE)(Channel - 1);
TAEmulator(core, Interface);
status = Interface->result;
gcmkFOOTER();
return status;
}
#endif

View File

@ -0,0 +1,378 @@
/****************************************************************************
*
* The MIT License (MIT)
*
* Copyright (c) 2014 - 2019 Vivante Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
*****************************************************************************
*
* The GPL License (GPL)
*
* Copyright (C) 2014 - 2019 Vivante Corporation
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*****************************************************************************
*
* Note: This software is released under dual MIT and GPL licenses. A
* recipient may use this file under the terms of either the MIT license or
* GPL License. If you wish to use only one license not the other, you can
* indicate your decision by deleting one of the above license notices in your
* version of this file.
*
*****************************************************************************/
#include <gc_hal.h>
#include <gc_hal_base.h>
#if gcdLINUX_SYNC_FILE
#include <linux/kernel.h>
#include <linux/file.h>
#include <linux/fs.h>
#include <linux/miscdevice.h>
#include <linux/module.h>
#include <linux/syscalls.h>
#include <linux/uaccess.h>
#include <linux/slab.h>
#include "gc_hal_kernel_sync.h"
#include "gc_hal_kernel_linux.h"
#ifndef CONFIG_SYNC_FILE
static struct sync_pt * viv_sync_pt_dup(struct sync_pt *sync_pt)
{
gceSTATUS status;
struct viv_sync_pt *pt;
struct viv_sync_pt *src;
struct viv_sync_timeline *obj;
src = (struct viv_sync_pt *)sync_pt;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,17,0)
obj = (struct viv_sync_timeline *)sync_pt_parent(sync_pt);
#else
obj = (struct viv_sync_timeline *)sync_pt->parent;
#endif
/* Create the new sync_pt. */
pt = (struct viv_sync_pt *)
sync_pt_create(&obj->obj, sizeof(struct viv_sync_pt));
pt->stamp = src->stamp;
/* Reference signal. */
status = gckOS_MapSignal(obj->os,
src->signal,
gcvNULL /* (gctHANDLE) _GetProcessID() */,
&pt->signal);
if (gcmIS_ERROR(status)) {
sync_pt_free((struct sync_pt *)pt);
return NULL;
}
return (struct sync_pt *)pt;
}
static int viv_sync_pt_has_signaled(struct sync_pt *sync_pt)
{
gceSTATUS status;
struct viv_sync_pt *pt;
struct viv_sync_timeline *obj;
pt = (struct viv_sync_pt *)sync_pt;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,17,0)
obj = (struct viv_sync_timeline *)sync_pt_parent(sync_pt);
#else
obj = (struct viv_sync_timeline *)sync_pt->parent;
#endif
status = _QuerySignal(obj->os, pt->signal);
if (gcmIS_ERROR(status)) {
/* Error. */
return -1;
}
return (int) status;
}
static int viv_sync_pt_compare(struct sync_pt *a, struct sync_pt *b)
{
int ret;
struct viv_sync_pt *pt1 = (struct viv_sync_pt *)a;
struct viv_sync_pt *pt2 = (struct viv_sync_pt *)b;
ret = (pt1->stamp < pt2->stamp) ? -1
: (pt1->stamp == pt2->stamp) ? 0
: 1;
return ret;
}
static void viv_sync_pt_free(struct sync_pt *sync_pt)
{
struct viv_sync_pt *pt;
struct viv_sync_timeline *obj;
pt = (struct viv_sync_pt *)sync_pt;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,17,0)
obj = (struct viv_sync_timeline *)sync_pt_parent(sync_pt);
#else
obj = (struct viv_sync_timeline *)sync_pt->parent;
#endif
gckOS_DestroySignal(obj->os, pt->signal);
}
static void viv_timeline_value_str(struct sync_timeline *timeline,
char *str, int size)
{
struct viv_sync_timeline *obj;
obj = (struct viv_sync_timeline *)timeline;
snprintf(str, size, "stamp_%llu", obj->stamp);
}
static void viv_pt_value_str(struct sync_pt *sync_pt, char *str, int size)
{
struct viv_sync_pt *pt;
pt = (struct viv_sync_pt *)sync_pt;
snprintf(str, size, "signal_%lu@stamp_%llu",
(unsigned long)pt->signal, pt->stamp);
}
static struct sync_timeline_ops viv_timeline_ops =
{
.driver_name = "viv_gpu_sync",
.dup = viv_sync_pt_dup,
.has_signaled = viv_sync_pt_has_signaled,
.compare = viv_sync_pt_compare,
.free_pt = viv_sync_pt_free,
.timeline_value_str = viv_timeline_value_str,
.pt_value_str = viv_pt_value_str,
};
struct viv_sync_timeline * viv_sync_timeline_create(const char *name, gckOS os)
{
struct viv_sync_timeline * obj;
obj = (struct viv_sync_timeline *)
sync_timeline_create(&viv_timeline_ops, sizeof(struct viv_sync_timeline), name);
obj->os = os;
obj->stamp = 0;
return obj;
}
struct sync_pt * viv_sync_pt_create(struct viv_sync_timeline *obj,
gctSIGNAL Signal)
{
gceSTATUS status;
struct viv_sync_pt *pt;
pt = (struct viv_sync_pt *)
sync_pt_create(&obj->obj, sizeof(struct viv_sync_pt));
pt->stamp = obj->stamp++;
/* Dup signal. */
status = gckOS_MapSignal(obj->os,
Signal,
gcvNULL /* (gctHANDLE) _GetProcessID() */,
&pt->signal);
if (gcmIS_ERROR(status)) {
sync_pt_free((struct sync_pt *)pt);
return NULL;
}
return (struct sync_pt *)pt;
}
#else
struct viv_sync_timeline * viv_sync_timeline_create(const char *name, gckOS Os)
{
struct viv_sync_timeline *timeline;
timeline = kmalloc(sizeof(struct viv_sync_timeline),
gcdNOWARN | GFP_KERNEL);
if (!timeline)
return NULL;
strncpy(timeline->name, name, sizeof(timeline->name) - 1);
timeline->context = dma_fence_context_alloc(1);
atomic64_set(&timeline->seqno, 0);
timeline->os = Os;
return timeline;
}
void viv_sync_timeline_destroy(struct viv_sync_timeline *timeline)
{
kfree(timeline);
}
static const char * viv_fence_get_driver_name(struct dma_fence *fence)
{
return "viv_gpu_sync";
}
static const char * viv_fence_get_timeline_name(struct dma_fence *fence)
{
struct viv_fence *f = (struct viv_fence *)fence;
return f->parent->name;
}
/* Same as fence_signaled. */
static inline bool __viv_fence_signaled(struct dma_fence *fence)
{
struct viv_fence *f = (struct viv_fence *)fence;
struct viv_sync_timeline *timeline = f->parent;
gceSTATUS status;
status = _QuerySignal(timeline->os, f->signal);
return (status == gcvSTATUS_TRUE) ? true : false;
}
static bool viv_fence_enable_signaling(struct dma_fence *fence)
{
/* fence is locked already. */
return !__viv_fence_signaled(fence);
}
static bool viv_fence_signaled(struct dma_fence *fence)
{
/* fence could be locked, could be not. */
return __viv_fence_signaled(fence);
}
static void viv_fence_release(struct dma_fence *fence)
{
struct viv_fence *f = (struct viv_fence *)fence;
struct viv_sync_timeline *timeline = f->parent;
if (f->signal)
gckOS_DestroySignal(timeline->os, f->signal);
kfree(fence);
}
static struct dma_fence_ops viv_fence_ops =
{
.get_driver_name = viv_fence_get_driver_name,
.get_timeline_name = viv_fence_get_timeline_name,
.enable_signaling = viv_fence_enable_signaling,
.signaled = viv_fence_signaled,
.wait = dma_fence_default_wait,
.release = viv_fence_release,
};
struct dma_fence * viv_fence_create(struct viv_sync_timeline *timeline,
gcsSIGNAL *signal)
{
gceSTATUS status;
struct viv_fence *fence;
struct dma_fence *old_fence = NULL;
unsigned seqno;
fence = kzalloc(sizeof(struct viv_fence), gcdNOWARN | GFP_KERNEL);
if (!fence)
return NULL;
/* Reference signal in fence. */
status = gckOS_MapSignal(timeline->os, (gctSIGNAL)(uintptr_t)signal->id,
NULL, &fence->signal);
if (gcmIS_ERROR(status)) {
kfree(fence);
return NULL;
}
spin_lock_init(&fence->lock);
fence->parent = timeline;
seqno = (unsigned)atomic64_inc_return(&timeline->seqno);
dma_fence_init((struct dma_fence *)fence, &viv_fence_ops,
&fence->lock, timeline->context, seqno);
/*
* Reference fence in signal.
* Be aware of recursive reference!!
*/
spin_lock(&signal->lock);
if (signal->fence) {
old_fence = signal->fence;
signal->fence = NULL;
}
if (!signal->done) {
signal->fence = (struct dma_fence*)fence;
#if LINUX_VERSION_CODE < KERNEL_VERSION(4,9,68)
dma_fence_get((struct dma_fence*)fence);
#endif
}
spin_unlock(&signal->lock);
if (old_fence)
dma_fence_put(old_fence);
if (!signal->fence) {
/* Fence already signaled. */
gckOS_DestroySignal(timeline->os, fence->signal);
fence->signal = NULL;
dma_fence_signal_locked((struct dma_fence*)fence);
dma_fence_put((struct dma_fence*)fence);
fence = NULL;
}
return (struct dma_fence*)fence;
}
#endif
#endif

View File

@ -0,0 +1,151 @@
/****************************************************************************
*
* The MIT License (MIT)
*
* Copyright (c) 2014 - 2019 Vivante Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
*****************************************************************************
*
* The GPL License (GPL)
*
* Copyright (C) 2014 - 2019 Vivante Corporation
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*****************************************************************************
*
* Note: This software is released under dual MIT and GPL licenses. A
* recipient may use this file under the terms of either the MIT license or
* GPL License. If you wish to use only one license not the other, you can
* indicate your decision by deleting one of the above license notices in your
* version of this file.
*
*****************************************************************************/
#ifndef __gc_hal_kernel_sync_h_
#define __gc_hal_kernel_sync_h_
#include <linux/types.h>
#ifndef CONFIG_SYNC_FILE
/* sync.h is in drivers/staging/android/ for now. */
#include <sync.h>
#include <gc_hal.h>
#include <gc_hal_base.h>
struct viv_sync_timeline
{
/* Parent object. */
struct sync_timeline obj;
/* Timestamp when sync_pt is created. */
gctUINT64 stamp;
/* Pointer to os struct. */
gckOS os;
};
struct viv_sync_pt
{
/* Parent object. */
struct sync_pt pt;
/* Reference signal. */
gctSIGNAL signal;
/* Timestamp when sync_pt is created. */
gctUINT64 stamp;
};
/* Create viv_sync_timeline object. */
struct viv_sync_timeline * viv_sync_timeline_create(const char *name, gckOS Os);
/* Create viv_sync_pt object. */
struct sync_pt * viv_sync_pt_create(struct viv_sync_timeline *obj,
gctSIGNAL signal);
#else
#include <linux/sync_file.h>
#if LINUX_VERSION_CODE < KERNEL_VERSION(4,10,0)
# include <linux/fence.h>
# include <linux/fence-array.h>
#else
# include <linux/dma-fence.h>
# include <linux/dma-fence-array.h>
#endif
#include <gc_hal.h>
#include <gc_hal_base.h>
#include "gc_hal_kernel_linux.h"
struct viv_sync_timeline
{
char name[64];
/* Parent object. */
u64 context;
/* Timestamp when sync_pt is created. */
atomic64_t seqno;
/* Pointer to os struct. */
gckOS os;
};
struct viv_fence
{
/* must be the first. */
struct dma_fence base;
spinlock_t lock;
struct viv_sync_timeline *parent;
/* link with signal. */
gctSIGNAL signal;
};
struct viv_sync_timeline * viv_sync_timeline_create(const char *name, gckOS Os);
void viv_sync_timeline_destroy(struct viv_sync_timeline *timeline);
struct dma_fence * viv_fence_create(struct viv_sync_timeline *timeline,
gcsSIGNAL *signal);
#endif
#endif /* __gc_hal_kernel_sync_h_ */

Some files were not shown because too many files have changed in this diff Show More