adreno源码系列打开kgsl

Posted bubbleben

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了adreno源码系列打开kgsl相关的知识,希望对你有一定的参考价值。

// 接"adreno源码系列(二)kgsl driver"中第3.3节
static int kgsl_open_device(struct kgsl_device *device)

	int result = 0;

	mutex_lock(&device->mutex);
    // kgsl_device->open_count记录/dev/kgsl-3d0被open的次数
	if (device->open_count == 0) 
        // 如果是第一次打开, 则调用adreno_functable中定义的adreno_first_open[见第1节]
		result = device->ftbl->first_open(device);
		if (result)
			goto out;
	
    // /dev/kgsl-3d0每被打开一次, 增加1个对应的fd
	device->open_count++;
out:
	mutex_unlock(&device->mutex);
	return result;

1. adreno_first_open

static int adreno_first_open(struct kgsl_device *device)

	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
    // adreno_a6xx_gmu_gpudev中定义adreno_power_ops为a6xx_gmu_power_ops[见第2节]
	const struct adreno_power_ops *ops = ADRENO_POWER_OPS(adreno_dev);

    // 调用a6xx_gmu_power_ops定义的a6xx_gmu_first_open[见第3节]
	return ops->first_open(adreno_dev);

2. a6xx_gmu_power_ops

const struct adreno_power_ops a6xx_gmu_power_ops = 
    // 第一次打开
	.first_open = a6xx_gmu_first_open,
	.last_close = a6xx_gmu_last_close,
	.active_count_get = a6xx_gmu_active_count_get,
	.active_count_put = a6xx_gmu_active_count_put,
	.pm_suspend = a6xx_gmu_pm_suspend,
	.pm_resume = a6xx_gmu_pm_resume,
	.touch_wakeup = a6xx_gmu_touch_wakeup,
	.gpu_clock_set = a6xx_gmu_clock_set,
	.gpu_bus_set = a6xx_gmu_bus_set,
;

3. a6xx_gmu_first_open

static int a6xx_gmu_first_open(struct adreno_device *adreno_dev)

	struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
	int ret;

	/*
	 * Do the one time settings that need to happen when we
	 * attempt to boot the gpu the very first time
	 */
    // a6xx第一次启动[见3.1节]
	ret = a6xx_first_boot(adreno_dev);
	if (ret)
		return ret;

	/*
	 * A client that does a first_open but never closes the device
	 * may prevent us from going back to SLUMBER. So trigger the idle
	 * check by incrementing the active count and immediately releasing it.
	 */
	atomic_inc(&device->active_cnt);
	a6xx_gmu_active_count_put(adreno_dev);

	return 0;

3.1 a6xx_first_boot

static int a6xx_first_boot(struct adreno_device *adreno_dev)

	struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
	struct a6xx_gmu_device *gmu = to_a6xx_gmu(adreno_dev);
	int ret;
	unsigned long priv = 0;

	if (test_bit(GMU_PRIV_FIRST_BOOT_DONE, &gmu->flags))
		return a6xx_boot(adreno_dev);

	place_marker("M - DRIVER ADRENO Init");

    // 初始化adreno_dispatcher[见第4节]
	ret = adreno_dispatcher_init(adreno_dev);
	if (ret)
		return ret;

    // 初始化adreno_ringbuffer[见第5节]
	ret = adreno_ringbuffer_init(adreno_dev);
	if (ret)
		return ret;

	ret = a6xx_microcode_read(adreno_dev);
	if (ret)
		return ret;

    // 初始化a6xx[见第6节]
	ret = a6xx_init(adreno_dev);
	if (ret)
		return ret;

    // 初始化a6xx gmu: 见"adreno源码系列之GMU"
	ret = a6xx_gmu_init(adreno_dev);
	if (ret)
		return ret;

	trace_kgsl_pwr_request_state(device, KGSL_STATE_ACTIVE);

    // gmu第一次启动: 见"adreno源码系列之GMU"
	ret = a6xx_gmu_first_boot(adreno_dev);
	if (ret)
		return ret;

    // a6xx gpu启动[见第7节]
	ret = a6xx_gpu_boot(adreno_dev);
	if (ret)
		return ret;

	adreno_get_bus_counters(adreno_dev);

	adreno_dev->cooperative_reset = ADRENO_FEATURE(adreno_dev,
						 ADRENO_COOP_RESET);

	if (ADRENO_FEATURE(adreno_dev, ADRENO_APRIV))
		priv |= KGSL_MEMDESC_PRIVILEGED;

    // 分配adreno_device全局共享的大小为4k名为alwayson的内存
	adreno_dev->profile_buffer = kgsl_allocate_global(device, PAGE_SIZE, 0,
			0, priv, "alwayson");

    // profile_index初始化为0
	adreno_dev->profile_index = 0;

	if (!IS_ERR(adreno_dev->profile_buffer))
		set_bit(ADRENO_DEVICE_DRAWOBJ_PROFILE, &adreno_dev->priv);

	set_bit(GMU_PRIV_FIRST_BOOT_DONE, &gmu->flags);
	set_bit(GMU_PRIV_GPU_STARTED, &gmu->flags);

	device->pwrctrl.last_stat_updated = ktime_get();
	device->state = KGSL_STATE_ACTIVE;

	trace_kgsl_pwr_set_state(device, KGSL_STATE_ACTIVE);

	place_marker("M - DRIVER ADRENO Ready");

	return 0;

4. adreno_dispatcher_init

/* Use a kmem cache to speed up allocations for dispatcher jobs */
static struct kmem_cache *jobs_cache;

/**
 * adreno_dispatcher_init() - Initialize the dispatcher
 * @adreno_dev: pointer to the adreno device structure
 *
 * Initialize the dispatcher
 */
// 见"adreno源码系列之adreno_dispatcher"
int adreno_dispatcher_init(struct adreno_device *adreno_dev)

	struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
	struct adreno_dispatcher *dispatcher = &adreno_dev->dispatcher;
	int ret, i;

	if (test_bit(ADRENO_DISPATCHER_INIT, &dispatcher->priv))
		return 0;

    // 初始化adreno_dispatcher
	memset(dispatcher, 0, sizeof(*dispatcher));

	ret = kobject_init_and_add(&dispatcher->kobj, &ktype_dispatcher,
		&device->dev->kobj, "dispatch");
	if (ret)
		return ret;

	WARN_ON(sysfs_create_files(&device->dev->kobj, _preempt_attr_list));

	mutex_init(&dispatcher->mutex);

    // 设置timer_list
	timer_setup(&dispatcher->timer, adreno_dispatcher_timer, 0);

	timer_setup(&dispatcher->fault_timer, adreno_dispatcher_fault_timer, 0);

    // 初始化kthread_work为adreno_dispatcher_work
	kthread_init_work(&dispatcher->work, adreno_dispatcher_work);

	init_completion(&dispatcher->idle_gate);
	complete_all(&dispatcher->idle_gate);

    // 创建adreno_dispatch_job
	jobs_cache = KMEM_CACHE(adreno_dispatch_job, 0);

	for (i = 0; i < ARRAY_SIZE(dispatcher->jobs); i++) 
		init_llist_head(&dispatcher->jobs[i]);
		init_llist_head(&dispatcher->requeue[i]);
	

    // 设置adreno_dispatcher的标志位:ADRENO_DISPATCHER_INIT
	set_bit(ADRENO_DISPATCHER_INIT, &dispatcher->priv);

	return 0;

5. adreno_ringbuffer_init

// 见"adreno源码系列之adreno_ringbuffer"
int adreno_ringbuffer_init(struct adreno_device *adreno_dev)

	struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
	int i;
	int status = -ENOMEM;

	if (!adreno_is_a3xx(adreno_dev)) 
		unsigned int priv =
			KGSL_MEMDESC_RANDOM | KGSL_MEMDESC_PRIVILEGED;

		if (IS_ERR_OR_NULL(device->scratch)) 
            // 分配kgsl_device全局共享的大小为4k名为scratch的内存
			device->scratch = kgsl_allocate_global(device,
				PAGE_SIZE, 0, 0, priv, "scratch");

			if (IS_ERR(device->scratch))
				return PTR_ERR(device->scratch);
		
	

    // 支持抢占则adreno_ringbuffer个数为4, 否则只有1个adreno_ringbuffer
	if (ADRENO_FEATURE(adreno_dev, ADRENO_PREEMPTION))
		adreno_dev->num_ringbuffers =
			ARRAY_SIZE(adreno_dev->ringbuffers);
	else
		adreno_dev->num_ringbuffers = 1;

	for (i = 0; i < adreno_dev->num_ringbuffers; i++) 
        // 初始化每个adreno_ringbuffer
		status = _adreno_ringbuffer_init(adreno_dev, i);
		if (status) 
			adreno_ringbuffer_close(adreno_dev);
			return status;
		
	

    // 初始化当前adreno_ringbuffer
	adreno_dev->cur_rb = &(adreno_dev->ringbuffers[0]);

	if (ADRENO_FEATURE(adreno_dev, ADRENO_PREEMPTION)) 
		const struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev);
		struct adreno_preemption *preempt = &adreno_dev->preempt;
		int ret;

		timer_setup(&preempt->timer, adreno_preemption_timer, 0);

		ret = gpudev->preemption_init(adreno_dev);
		WARN(ret, "adreno GPU preemption is disabled\\n");
	

	return 0;

6. a6xx_init

int a6xx_init(struct adreno_device *adreno_dev)

	const struct adreno_a6xx_core *a6xx_core = to_a6xx_core(adreno_dev);

	adreno_dev->highest_bank_bit = a6xx_core->highest_bank_bit;

	/* If the memory type is DDR 4, override the existing configuration */
	if (of_fdt_get_ddrtype() == 0x7) 
		if (adreno_is_a642(adreno_dev) ||
			adreno_is_a642l(adreno_dev))
			adreno_dev->highest_bank_bit = 14;
		else if ((adreno_is_a650(adreno_dev) ||
				adreno_is_a660(adreno_dev)))
			adreno_dev->highest_bank_bit = 15;
	

	a6xx_crashdump_init(adreno_dev);

	if (IS_ERR_OR_NULL(adreno_dev->pwrup_reglist)) 
        // 分配adreno_device全局共享的大小为4k名为powerup_register_list的内存
		adreno_dev->pwrup_reglist =
				kgsl_allocate_global(KGSL_DEVICE(adreno_dev),
					PAGE_SIZE, 0, 0, KGSL_MEMDESC_PRIVILEGED,
					"powerup_register_list");
		if (IS_ERR(adreno_dev->pwrup_reglist))
			return PTR_ERR(adreno_dev->pwrup_reglist);
	

	find_ddr_qos_device(adreno_dev);

    // 获取CP初始化指令, 保存到adreno_device->cp_init_cmds
	return a6xx_get_cp_init_cmds(adreno_dev);

7. a6xx_gpu_boot

static int a6xx_gpu_boot(struct adreno_device *adreno_dev)

	struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
	int ret;

	/* Clear any GPU faults that might have been left over */
	adreno_clear_gpu_fault(adreno_dev);

	adreno_set_active_ctxs_null(adreno_dev);

	adreno_ringbuffer_set_global(adreno_dev, 0);

    // kgsl mmu启动
	ret = kgsl_mmu_start(device);
	if (ret)
		goto err;

	ret = a6xx_gmu_oob_set(device, oob_gpu);
	if (ret)
		goto oob_clear;

	ret = a6xx_gmu_hfi_start_msg(adreno_dev);
	if (ret)
		goto oob_clear;

	adreno_clear_dcvs_counters(adreno_dev);

	/* Restore performance counter registers with saved values */
	adreno_perfcounter_restore(adreno_dev);

    // a6xx gpu start:见"adreno源码系列(六)启动kgsl"
	a6xx_start(adreno_dev);

	/* Re-initialize the coresight registers if applicable */
	adreno_coresight_start(adreno_dev);

    // 启动性能计数器:见"adreno源码系列(六)启动kgsl"
	adreno_perfcounter_start(adreno_dev);

	/* Clear FSR here in case it is set from a previous pagefault */
	kgsl_mmu_clear_fsr(&device->mmu);

	a6xx_enable_gpu_irq(adreno_dev);

    // 启动adreno_ringbuffer:见"adreno源码系列(六)启动kgsl"
	ret = a6xx_rb_start(adreno_dev);
	if (ret) 
		a6xx_disable_gpu_irq(adreno_dev);
		goto oob_clear;
	

	/* Start the dispatcher */
    // 启动adreno_dispatcher:见"adreno源码系列(六)启动kgsl"
	adreno_dispatcher_start(device);

	device->reset_counter++;

	a6xx_gmu_oob_clear(device, oob_gpu);

	if (ADRENO_QUIRK(adreno_dev, ADRENO_QUIRK_HFI_USE_REG))
		gmu_core_dev_oob_clear(device, oob_boot_slumber);

	return 0;

oob_clear:
	a6xx_gmu_oob_clear(device, oob_gpu);

	if (ADRENO_QUIRK(adreno_dev, ADRENO_QUIRK_HFI_USE_REG))
		gmu_core_dev_oob_clear(device, oob_boot_slumber);

err:
	a6xx_gmu_power_off(adreno_dev);

	return ret;


以上是关于adreno源码系列打开kgsl的主要内容,如果未能解决你的问题,请参考以下文章

adreno源码系列启动kgsl

adreno源码系列启动kgsl

adreno源码系列私有内存申请

adreno源码系列私有内存申请

adreno源码系列全局内存申请

adreno源码系列全局内存申请