staticinta6xx_gmu_first_open(structadreno_device*adreno_dev){structkgsl_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);return0;}
3.1 a6xx_first_boot
staticinta6xx_first_boot(structadreno_device*adreno_dev){structkgsl_device*device =KGSL_DEVICE(adreno_dev);structa6xx_gmu_device*gmu =to_a6xx_gmu(adreno_dev);int ret;unsignedlong priv =0;if(test_bit(GMU_PRIV_FIRST_BOOT_DONE,&gmu->flags))returna6xx_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");return0;}
4. adreno_dispatcher_init
/* Use a kmem cache to speed up allocations for dispatcher jobs */staticstructkmem_cache*jobs_cache;/**
* adreno_dispatcher_init() - Initialize the dispatcher
* @adreno_dev: pointer to the adreno device structure
*
* Initialize the dispatcher
*/// 见"adreno源码系列之adreno_dispatcher"intadreno_dispatcher_init(structadreno_device*adreno_dev){structkgsl_device*device =KGSL_DEVICE(adreno_dev);structadreno_dispatcher*dispatcher =&adreno_dev->dispatcher;int ret, i;if(test_bit(ADRENO_DISPATCHER_INIT,&dispatcher->priv))return0;// 初始化adreno_dispatchermemset(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_listtimer_setup(&dispatcher->timer, adreno_dispatcher_timer,0);timer_setup(&dispatcher->fault_timer, adreno_dispatcher_fault_timer,0);// 初始化kthread_work为adreno_dispatcher_workkthread_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_INITset_bit(ADRENO_DISPATCHER_INIT,&dispatcher->priv);return0;}
5. adreno_ringbuffer_init
// 见"adreno源码系列之adreno_ringbuffer"intadreno_ringbuffer_init(structadreno_device*adreno_dev){structkgsl_device*device =KGSL_DEVICE(adreno_dev);int i;int status =-ENOMEM;if(!adreno_is_a3xx(adreno_dev)){unsignedint 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))returnPTR_ERR(device->scratch);}}// 支持抢占则adreno_ringbuffer个数为4, 否则只有1个adreno_ringbufferif(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)){conststructadreno_gpudev*gpudev =ADRENO_GPU_DEVICE(adreno_dev);structadreno_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");}return0;}
6. a6xx_init
inta6xx_init(structadreno_device*adreno_dev){conststructadreno_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;elseif((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))returnPTR_ERR(adreno_dev->pwrup_reglist);}find_ddr_qos_device(adreno_dev);// 获取CP初始化指令, 保存到adreno_device->cp_init_cmdsreturna6xx_get_cp_init_cmds(adreno_dev);}
7. a6xx_gpu_boot
staticinta6xx_gpu_boot(structadreno_device*adreno_dev){structkgsl_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);return0;
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;}