/drivers/gpu/mali/mali/common/mali_group.c

https://bitbucket.org/ndreys/linux-sunxi · C · 841 lines · 639 code · 144 blank · 58 comment · 122 complexity · d431b92d3073507f55fe78dce03ebea8 MD5 · raw file

  1. /*
  2. * Copyright (C) 2011-2012 ARM Limited. All rights reserved.
  3. *
  4. * This program is free software and is provided to you under the terms of the GNU General Public License version 2
  5. * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
  6. *
  7. * A copy of the licence is included with the program, and can also be obtained from Free Software
  8. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  9. */
  10. #include "mali_kernel_common.h"
  11. #include "mali_group.h"
  12. #include "mali_osk.h"
  13. #include "mali_cluster.h"
  14. #include "mali_gp.h"
  15. #include "mali_pp.h"
  16. #include "mali_mmu.h"
  17. #include "mali_gp_scheduler.h"
  18. #include "mali_pp_scheduler.h"
  19. #include "mali_pm.h"
  20. /*
  21. * The group object is the most important object in the device driver,
  22. * and acts as the center of many HW operations.
  23. * The reason for this is that operations on the MMU will affect all
  24. * cores connected to this MMU (a group is defined by the MMU and the
  25. * cores which are connected to this).
  26. * The group lock is thus the most important lock, followed by the
  27. * GP and PP scheduler locks. They must be taken in the following
  28. * order:
  29. * GP/PP lock first, then group lock(s).
  30. */
  31. /**
  32. * The structure represents a render group
  33. * A render group is defined by all the cores that share the same Mali MMU
  34. */
  35. struct mali_group
  36. {
  37. struct mali_cluster *cluster;
  38. struct mali_mmu_core *mmu;
  39. struct mali_session_data *session;
  40. int page_dir_ref_count;
  41. mali_bool power_is_on;
  42. #if defined(USING_MALI200)
  43. mali_bool pagedir_activation_failed;
  44. #endif
  45. struct mali_gp_core *gp_core;
  46. enum mali_group_core_state gp_state;
  47. struct mali_gp_job *gp_running_job;
  48. struct mali_pp_core *pp_core;
  49. enum mali_group_core_state pp_state;
  50. struct mali_pp_job *pp_running_job;
  51. u32 pp_running_sub_job;
  52. _mali_osk_lock_t *lock;
  53. };
  54. static struct mali_group *mali_global_groups[MALI_MAX_NUMBER_OF_GROUPS];
  55. static u32 mali_global_num_groups = 0;
  56. enum mali_group_activate_pd_status
  57. {
  58. MALI_GROUP_ACTIVATE_PD_STATUS_FAILED,
  59. MALI_GROUP_ACTIVATE_PD_STATUS_OK_KEPT_PD,
  60. MALI_GROUP_ACTIVATE_PD_STATUS_OK_SWITCHED_PD,
  61. };
  62. /* local helper functions */
  63. static enum mali_group_activate_pd_status mali_group_activate_page_directory(struct mali_group *group, struct mali_session_data *session);
  64. static void mali_group_deactivate_page_directory(struct mali_group *group, struct mali_session_data *session);
  65. static void mali_group_recovery_reset(struct mali_group *group);
  66. static void mali_group_complete_jobs(struct mali_group *group, mali_bool complete_gp, mali_bool complete_pp, bool success);
  67. void mali_group_lock(struct mali_group *group)
  68. {
  69. if(_MALI_OSK_ERR_OK != _mali_osk_lock_wait(group->lock, _MALI_OSK_LOCKMODE_RW))
  70. {
  71. /* Non-interruptable lock failed: this should never happen. */
  72. MALI_DEBUG_ASSERT(0);
  73. }
  74. MALI_DEBUG_PRINT(5, ("Mali group: Group lock taken 0x%08X\n", group));
  75. }
  76. void mali_group_unlock(struct mali_group *group)
  77. {
  78. MALI_DEBUG_PRINT(5, ("Mali group: Releasing group lock 0x%08X\n", group));
  79. _mali_osk_lock_signal(group->lock, _MALI_OSK_LOCKMODE_RW);
  80. }
  81. #ifdef DEBUG
  82. void mali_group_assert_locked(struct mali_group *group)
  83. {
  84. MALI_DEBUG_ASSERT_LOCK_HELD(group->lock);
  85. }
  86. #endif
  87. struct mali_group *mali_group_create(struct mali_cluster *cluster, struct mali_mmu_core *mmu)
  88. {
  89. struct mali_group *group = NULL;
  90. if (mali_global_num_groups >= MALI_MAX_NUMBER_OF_GROUPS)
  91. {
  92. MALI_PRINT_ERROR(("Mali group: Too many group objects created\n"));
  93. return NULL;
  94. }
  95. group = _mali_osk_malloc(sizeof(struct mali_group));
  96. if (NULL != group)
  97. {
  98. _mali_osk_memset(group, 0, sizeof(struct mali_group));
  99. group->lock = _mali_osk_lock_init(_MALI_OSK_LOCKFLAG_ORDERED | _MALI_OSK_LOCKFLAG_SPINLOCK_IRQ |_MALI_OSK_LOCKFLAG_NONINTERRUPTABLE, 0, _MALI_OSK_LOCK_ORDER_GROUP);
  100. if (NULL != group->lock)
  101. {
  102. group->cluster = cluster;
  103. group->mmu = mmu; /* This group object now owns the MMU object */
  104. group->session = NULL;
  105. group->page_dir_ref_count = 0;
  106. group->power_is_on = MALI_TRUE;
  107. group->gp_state = MALI_GROUP_CORE_STATE_IDLE;
  108. group->pp_state = MALI_GROUP_CORE_STATE_IDLE;
  109. #if defined(USING_MALI200)
  110. group->pagedir_activation_failed = MALI_FALSE;
  111. #endif
  112. mali_global_groups[mali_global_num_groups] = group;
  113. mali_global_num_groups++;
  114. return group;
  115. }
  116. _mali_osk_free(group);
  117. }
  118. return NULL;
  119. }
  120. void mali_group_add_gp_core(struct mali_group *group, struct mali_gp_core* gp_core)
  121. {
  122. /* This group object now owns the GP core object */
  123. group->gp_core = gp_core;
  124. }
  125. void mali_group_add_pp_core(struct mali_group *group, struct mali_pp_core* pp_core)
  126. {
  127. /* This group object now owns the PP core object */
  128. group->pp_core = pp_core;
  129. }
  130. void mali_group_delete(struct mali_group *group)
  131. {
  132. u32 i;
  133. /* Delete the resources that this group owns */
  134. if (NULL != group->gp_core)
  135. {
  136. mali_gp_delete(group->gp_core);
  137. }
  138. if (NULL != group->pp_core)
  139. {
  140. mali_pp_delete(group->pp_core);
  141. }
  142. if (NULL != group->mmu)
  143. {
  144. mali_mmu_delete(group->mmu);
  145. }
  146. for (i = 0; i < mali_global_num_groups; i++)
  147. {
  148. if (mali_global_groups[i] == group)
  149. {
  150. mali_global_groups[i] = NULL;
  151. mali_global_num_groups--;
  152. break;
  153. }
  154. }
  155. _mali_osk_lock_term(group->lock);
  156. _mali_osk_free(group);
  157. }
  158. /* Called from mali_cluster_reset() when the system is re-turned on */
  159. void mali_group_reset(struct mali_group *group)
  160. {
  161. mali_group_lock(group);
  162. group->session = NULL;
  163. if (NULL != group->mmu)
  164. {
  165. mali_mmu_reset(group->mmu);
  166. }
  167. if (NULL != group->gp_core)
  168. {
  169. mali_gp_reset(group->gp_core);
  170. }
  171. if (NULL != group->pp_core)
  172. {
  173. mali_pp_reset(group->pp_core);
  174. }
  175. mali_group_unlock(group);
  176. }
  177. struct mali_gp_core* mali_group_get_gp_core(struct mali_group *group)
  178. {
  179. return group->gp_core;
  180. }
  181. struct mali_pp_core* mali_group_get_pp_core(struct mali_group *group)
  182. {
  183. return group->pp_core;
  184. }
  185. _mali_osk_errcode_t mali_group_start_gp_job(struct mali_group *group, struct mali_gp_job *job)
  186. {
  187. struct mali_session_data *session;
  188. enum mali_group_activate_pd_status activate_status;
  189. MALI_DEBUG_ASSERT(MALI_GROUP_CORE_STATE_IDLE == group->gp_state);
  190. mali_pm_core_event(MALI_CORE_EVENT_GP_START);
  191. session = mali_gp_job_get_session(job);
  192. mali_group_lock(group);
  193. mali_cluster_l2_cache_invalidate_all(group->cluster, mali_gp_job_get_id(job));
  194. activate_status = mali_group_activate_page_directory(group, session);
  195. if (MALI_GROUP_ACTIVATE_PD_STATUS_FAILED != activate_status)
  196. {
  197. /* if session is NOT kept Zapping is done as part of session switch */
  198. if (MALI_GROUP_ACTIVATE_PD_STATUS_OK_KEPT_PD == activate_status)
  199. {
  200. mali_mmu_zap_tlb_without_stall(group->mmu);
  201. }
  202. mali_gp_job_start(group->gp_core, job);
  203. group->gp_running_job = job;
  204. group->gp_state = MALI_GROUP_CORE_STATE_WORKING;
  205. mali_group_unlock(group);
  206. return _MALI_OSK_ERR_OK;
  207. }
  208. #if defined(USING_MALI200)
  209. group->pagedir_activation_failed = MALI_TRUE;
  210. #endif
  211. mali_group_unlock(group);
  212. mali_pm_core_event(MALI_CORE_EVENT_GP_STOP); /* Failed to start, so "cancel" the MALI_CORE_EVENT_GP_START */
  213. return _MALI_OSK_ERR_FAULT;
  214. }
  215. _mali_osk_errcode_t mali_group_start_pp_job(struct mali_group *group, struct mali_pp_job *job, u32 sub_job)
  216. {
  217. struct mali_session_data *session;
  218. enum mali_group_activate_pd_status activate_status;
  219. MALI_DEBUG_ASSERT(MALI_GROUP_CORE_STATE_IDLE == group->pp_state);
  220. mali_pm_core_event(MALI_CORE_EVENT_PP_START);
  221. session = mali_pp_job_get_session(job);
  222. mali_group_lock(group);
  223. mali_cluster_l2_cache_invalidate_all(group->cluster, mali_pp_job_get_id(job));
  224. activate_status = mali_group_activate_page_directory(group, session);
  225. if (MALI_GROUP_ACTIVATE_PD_STATUS_FAILED != activate_status)
  226. {
  227. /* if session is NOT kept Zapping is done as part of session switch */
  228. if (MALI_GROUP_ACTIVATE_PD_STATUS_OK_KEPT_PD == activate_status)
  229. {
  230. MALI_DEBUG_PRINT(3, ("PP starting job PD_Switch 0 Flush 1 Zap 1\n"));
  231. mali_mmu_zap_tlb_without_stall(group->mmu);
  232. }
  233. mali_pp_job_start(group->pp_core, job, sub_job);
  234. group->pp_running_job = job;
  235. group->pp_running_sub_job = sub_job;
  236. group->pp_state = MALI_GROUP_CORE_STATE_WORKING;
  237. mali_group_unlock(group);
  238. return _MALI_OSK_ERR_OK;
  239. }
  240. #if defined(USING_MALI200)
  241. group->pagedir_activation_failed = MALI_TRUE;
  242. #endif
  243. mali_group_unlock(group);
  244. mali_pm_core_event(MALI_CORE_EVENT_PP_STOP); /* Failed to start, so "cancel" the MALI_CORE_EVENT_PP_START */
  245. return _MALI_OSK_ERR_FAULT;
  246. }
  247. void mali_group_resume_gp_with_new_heap(struct mali_group *group, u32 job_id, u32 start_addr, u32 end_addr)
  248. {
  249. mali_group_lock(group);
  250. if (group->gp_state != MALI_GROUP_CORE_STATE_OOM ||
  251. mali_gp_job_get_id(group->gp_running_job) != job_id)
  252. {
  253. mali_group_unlock(group);
  254. return; /* Illegal request or job has already been aborted */
  255. }
  256. mali_cluster_l2_cache_invalidate_all_force(group->cluster);
  257. mali_mmu_zap_tlb_without_stall(group->mmu);
  258. mali_gp_resume_with_new_heap(group->gp_core, start_addr, end_addr);
  259. group->gp_state = MALI_GROUP_CORE_STATE_WORKING;
  260. mali_group_unlock(group);
  261. }
  262. void mali_group_abort_gp_job(struct mali_group *group, u32 job_id)
  263. {
  264. mali_group_lock(group);
  265. if (group->gp_state == MALI_GROUP_CORE_STATE_IDLE ||
  266. mali_gp_job_get_id(group->gp_running_job) != job_id)
  267. {
  268. mali_group_unlock(group);
  269. return; /* No need to cancel or job has already been aborted or completed */
  270. }
  271. mali_group_complete_jobs(group, MALI_TRUE, MALI_FALSE, MALI_FALSE); /* Will release group lock */
  272. }
  273. void mali_group_abort_pp_job(struct mali_group *group, u32 job_id)
  274. {
  275. mali_group_lock(group);
  276. if (group->pp_state == MALI_GROUP_CORE_STATE_IDLE ||
  277. mali_pp_job_get_id(group->pp_running_job) != job_id)
  278. {
  279. mali_group_unlock(group);
  280. return; /* No need to cancel or job has already been aborted or completed */
  281. }
  282. mali_group_complete_jobs(group, MALI_FALSE, MALI_TRUE, MALI_FALSE); /* Will release group lock */
  283. }
  284. void mali_group_abort_session(struct mali_group *group, struct mali_session_data *session)
  285. {
  286. struct mali_gp_job *gp_job;
  287. struct mali_pp_job *pp_job;
  288. u32 gp_job_id = 0;
  289. u32 pp_job_id = 0;
  290. mali_bool abort_pp = MALI_FALSE;
  291. mali_bool abort_gp = MALI_FALSE;
  292. mali_group_lock(group);
  293. gp_job = group->gp_running_job;
  294. pp_job = group->pp_running_job;
  295. if (gp_job && mali_gp_job_get_session(gp_job) == session)
  296. {
  297. MALI_DEBUG_PRINT(4, ("Aborting GP job 0x%08x from session 0x%08x\n", gp_job, session));
  298. gp_job_id = mali_gp_job_get_id(gp_job);
  299. abort_gp = MALI_TRUE;
  300. }
  301. if (pp_job && mali_pp_job_get_session(pp_job) == session)
  302. {
  303. MALI_DEBUG_PRINT(4, ("Mali group: Aborting PP job 0x%08x from session 0x%08x\n", pp_job, session));
  304. pp_job_id = mali_pp_job_get_id(pp_job);
  305. abort_pp = MALI_TRUE;
  306. }
  307. mali_group_unlock(group);
  308. /* These functions takes and releases the group lock */
  309. if (0 != abort_gp)
  310. {
  311. mali_group_abort_gp_job(group, gp_job_id);
  312. }
  313. if (0 != abort_pp)
  314. {
  315. mali_group_abort_pp_job(group, pp_job_id);
  316. }
  317. mali_group_lock(group);
  318. mali_group_remove_session_if_unused(group, session);
  319. mali_group_unlock(group);
  320. }
  321. enum mali_group_core_state mali_group_gp_state(struct mali_group *group)
  322. {
  323. return group->gp_state;
  324. }
  325. enum mali_group_core_state mali_group_pp_state(struct mali_group *group)
  326. {
  327. return group->pp_state;
  328. }
  329. /* group lock need to be taken before calling mali_group_bottom_half */
  330. void mali_group_bottom_half(struct mali_group *group, enum mali_group_event_t event)
  331. {
  332. MALI_ASSERT_GROUP_LOCKED(group);
  333. switch (event)
  334. {
  335. case GROUP_EVENT_PP_JOB_COMPLETED:
  336. mali_group_complete_jobs(group, MALI_FALSE, MALI_TRUE, MALI_TRUE); /* PP job SUCCESS */
  337. /* group lock is released by mali_group_complete_jobs() call above */
  338. break;
  339. case GROUP_EVENT_PP_JOB_FAILED:
  340. mali_group_complete_jobs(group, MALI_FALSE, MALI_TRUE, MALI_FALSE); /* PP job FAIL */
  341. /* group lock is released by mali_group_complete_jobs() call above */
  342. break;
  343. case GROUP_EVENT_PP_JOB_TIMED_OUT:
  344. mali_group_complete_jobs(group, MALI_FALSE, MALI_TRUE, MALI_FALSE); /* PP job TIMEOUT */
  345. /* group lock is released by mali_group_complete_jobs() call above */
  346. break;
  347. case GROUP_EVENT_GP_JOB_COMPLETED:
  348. mali_group_complete_jobs(group, MALI_TRUE, MALI_FALSE, MALI_TRUE); /* GP job SUCCESS */
  349. /* group lock is released by mali_group_complete_jobs() call above */
  350. break;
  351. case GROUP_EVENT_GP_JOB_FAILED:
  352. mali_group_complete_jobs(group, MALI_TRUE, MALI_FALSE, MALI_FALSE); /* GP job FAIL */
  353. /* group lock is released by mali_group_complete_jobs() call above */
  354. break;
  355. case GROUP_EVENT_GP_JOB_TIMED_OUT:
  356. mali_group_complete_jobs(group, MALI_TRUE, MALI_FALSE, MALI_FALSE); /* GP job TIMEOUT */
  357. /* group lock is released by mali_group_complete_jobs() call above */
  358. break;
  359. case GROUP_EVENT_GP_OOM:
  360. group->gp_state = MALI_GROUP_CORE_STATE_OOM;
  361. mali_group_unlock(group); /* Nothing to do on the HW side, so just release group lock right away */
  362. mali_gp_scheduler_oom(group, group->gp_running_job);
  363. break;
  364. case GROUP_EVENT_MMU_PAGE_FAULT:
  365. mali_group_complete_jobs(group, MALI_TRUE, MALI_TRUE, MALI_FALSE); /* GP and PP job FAIL */
  366. /* group lock is released by mali_group_complete_jobs() call above */
  367. break;
  368. default:
  369. break;
  370. }
  371. }
  372. struct mali_mmu_core *mali_group_get_mmu(struct mali_group *group)
  373. {
  374. return group->mmu;
  375. }
  376. struct mali_session_data *mali_group_get_session(struct mali_group *group)
  377. {
  378. return group->session;
  379. }
  380. struct mali_group *mali_group_get_glob_group(u32 index)
  381. {
  382. if(mali_global_num_groups > index)
  383. {
  384. return mali_global_groups[index];
  385. }
  386. return NULL;
  387. }
  388. u32 mali_group_get_glob_num_groups(void)
  389. {
  390. return mali_global_num_groups;
  391. }
  392. /* Used to check if scheduler for the other core type needs to be called on job completion.
  393. *
  394. * Used only for Mali-200, where job start may fail if the only MMU is busy
  395. * with another session's address space.
  396. */
  397. static inline mali_bool mali_group_other_reschedule_needed(struct mali_group *group)
  398. {
  399. MALI_ASSERT_GROUP_LOCKED(group);
  400. #if defined(USING_MALI200)
  401. if (group->pagedir_activation_failed)
  402. {
  403. group->pagedir_activation_failed = MALI_FALSE;
  404. return MALI_TRUE;
  405. }
  406. else
  407. #endif
  408. {
  409. return MALI_FALSE;
  410. }
  411. }
  412. static enum mali_group_activate_pd_status mali_group_activate_page_directory(struct mali_group *group, struct mali_session_data *session)
  413. {
  414. enum mali_group_activate_pd_status retval;
  415. MALI_ASSERT_GROUP_LOCKED(group);
  416. MALI_DEBUG_PRINT(5, ("Mali group: Activating page directory 0x%08X from session 0x%08X on group 0x%08X\n", mali_session_get_page_directory(session), session, group));
  417. MALI_DEBUG_ASSERT(0 <= group->page_dir_ref_count);
  418. if (0 != group->page_dir_ref_count)
  419. {
  420. if (group->session != session)
  421. {
  422. MALI_DEBUG_PRINT(4, ("Mali group: Activating session FAILED: 0x%08x on group 0x%08X. Existing session: 0x%08x\n", session, group, group->session));
  423. return MALI_GROUP_ACTIVATE_PD_STATUS_FAILED;
  424. }
  425. else
  426. {
  427. MALI_DEBUG_PRINT(4, ("Mali group: Activating session already activated: 0x%08x on group 0x%08X. New Ref: %d\n", session, group, 1+group->page_dir_ref_count));
  428. retval = MALI_GROUP_ACTIVATE_PD_STATUS_OK_KEPT_PD;
  429. }
  430. }
  431. else
  432. {
  433. /* There might be another session here, but it is ok to overwrite it since group->page_dir_ref_count==0 */
  434. if (group->session != session)
  435. {
  436. mali_bool activate_success;
  437. MALI_DEBUG_PRINT(5, ("Mali group: Activate session: %08x previous: %08x on group 0x%08X. Ref: %d\n", session, group->session, group, 1+group->page_dir_ref_count));
  438. activate_success = mali_mmu_activate_page_directory(group->mmu, mali_session_get_page_directory(session));
  439. MALI_DEBUG_ASSERT(activate_success);
  440. if ( MALI_FALSE== activate_success ) return MALI_FALSE;
  441. group->session = session;
  442. retval = MALI_GROUP_ACTIVATE_PD_STATUS_OK_SWITCHED_PD;
  443. }
  444. else
  445. {
  446. MALI_DEBUG_PRINT(4, ("Mali group: Activate existing session 0x%08X on group 0x%08X. Ref: %d\n", session->page_directory, group, 1+group->page_dir_ref_count));
  447. retval = MALI_GROUP_ACTIVATE_PD_STATUS_OK_KEPT_PD;
  448. }
  449. }
  450. group->page_dir_ref_count++;
  451. return retval;
  452. }
  453. static void mali_group_deactivate_page_directory(struct mali_group *group, struct mali_session_data *session)
  454. {
  455. MALI_ASSERT_GROUP_LOCKED(group);
  456. MALI_DEBUG_ASSERT(0 < group->page_dir_ref_count);
  457. MALI_DEBUG_ASSERT(session == group->session);
  458. group->page_dir_ref_count--;
  459. /* As an optimization, the MMU still points to the group->session even if (0 == group->page_dir_ref_count),
  460. and we do not call mali_mmu_activate_empty_page_directory(group->mmu); */
  461. MALI_DEBUG_ASSERT(0 <= group->page_dir_ref_count);
  462. }
  463. void mali_group_remove_session_if_unused(struct mali_group *group, struct mali_session_data *session)
  464. {
  465. MALI_ASSERT_GROUP_LOCKED(group);
  466. if (0 == group->page_dir_ref_count)
  467. {
  468. MALI_DEBUG_ASSERT(MALI_GROUP_CORE_STATE_IDLE == group->gp_state);
  469. MALI_DEBUG_ASSERT(MALI_GROUP_CORE_STATE_IDLE == group->pp_state);
  470. if (group->session == session)
  471. {
  472. MALI_DEBUG_ASSERT(MALI_TRUE == group->power_is_on);
  473. MALI_DEBUG_PRINT(3, ("Mali group: Deactivating unused session 0x%08X on group %08X\n", session, group));
  474. mali_mmu_activate_empty_page_directory(group->mmu);
  475. group->session = NULL;
  476. }
  477. }
  478. }
  479. void mali_group_power_on(void)
  480. {
  481. int i;
  482. for (i = 0; i < mali_global_num_groups; i++)
  483. {
  484. struct mali_group *group = mali_global_groups[i];
  485. mali_group_lock(group);
  486. MALI_DEBUG_ASSERT(MALI_GROUP_CORE_STATE_IDLE == group->gp_state);
  487. MALI_DEBUG_ASSERT(MALI_GROUP_CORE_STATE_IDLE == group->pp_state);
  488. MALI_DEBUG_ASSERT_POINTER(group->cluster);
  489. group->power_is_on = MALI_TRUE;
  490. mali_cluster_power_is_enabled_set(group->cluster, MALI_TRUE);
  491. mali_group_unlock(group);
  492. }
  493. MALI_DEBUG_PRINT(3,("group: POWER ON\n"));
  494. }
  495. mali_bool mali_group_power_is_on(struct mali_group *group)
  496. {
  497. MALI_ASSERT_GROUP_LOCKED(group);
  498. return group->power_is_on;
  499. }
  500. void mali_group_power_off(void)
  501. {
  502. int i;
  503. /* It is necessary to set group->session = NULL; so that the powered off MMU is not written to on map /unmap */
  504. /* It is necessary to set group->power_is_on=MALI_FALSE so that pending bottom_halves does not access powered off cores. */
  505. for (i = 0; i < mali_global_num_groups; i++)
  506. {
  507. struct mali_group *group = mali_global_groups[i];
  508. mali_group_lock(group);
  509. MALI_DEBUG_ASSERT(MALI_GROUP_CORE_STATE_IDLE == group->gp_state);
  510. MALI_DEBUG_ASSERT(MALI_GROUP_CORE_STATE_IDLE == group->pp_state);
  511. MALI_DEBUG_ASSERT_POINTER(group->cluster);
  512. group->session = NULL;
  513. MALI_DEBUG_ASSERT(MALI_TRUE == group->power_is_on);
  514. group->power_is_on = MALI_FALSE;
  515. mali_cluster_power_is_enabled_set(group->cluster, MALI_FALSE);
  516. mali_group_unlock(group);
  517. }
  518. MALI_DEBUG_PRINT(3,("group: POWER OFF\n"));
  519. }
  520. static void mali_group_recovery_reset(struct mali_group *group)
  521. {
  522. MALI_ASSERT_GROUP_LOCKED(group);
  523. /* Stop cores, bus stop */
  524. if (NULL != group->pp_core)
  525. {
  526. mali_pp_stop_bus(group->pp_core);
  527. }
  528. if (NULL != group->gp_core)
  529. {
  530. mali_gp_stop_bus(group->gp_core);
  531. }
  532. /* Flush MMU */
  533. mali_mmu_activate_fault_flush_page_directory(group->mmu);
  534. mali_mmu_page_fault_done(group->mmu);
  535. /* Wait for cores to stop bus */
  536. if (NULL != group->pp_core)
  537. {
  538. mali_pp_stop_bus_wait(group->pp_core);
  539. }
  540. if (NULL != group->gp_core)
  541. {
  542. mali_gp_stop_bus_wait(group->gp_core);
  543. }
  544. /* Reset cores */
  545. if (NULL != group->pp_core)
  546. {
  547. mali_pp_hard_reset(group->pp_core);
  548. }
  549. if (NULL != group->gp_core)
  550. {
  551. mali_gp_hard_reset(group->gp_core);
  552. }
  553. /* Reset MMU */
  554. mali_mmu_reset(group->mmu);
  555. group->session = NULL;
  556. }
  557. /* Group lock need to be taken before calling mali_group_complete_jobs. Will release the lock here. */
  558. static void mali_group_complete_jobs(struct mali_group *group, mali_bool complete_gp, mali_bool complete_pp, bool success)
  559. {
  560. mali_bool need_group_reset = MALI_FALSE;
  561. mali_bool gp_success = success;
  562. mali_bool pp_success = success;
  563. MALI_ASSERT_GROUP_LOCKED(group);
  564. if (complete_gp && !complete_pp)
  565. {
  566. MALI_DEBUG_ASSERT_POINTER(group->gp_core);
  567. if (_MALI_OSK_ERR_OK == mali_gp_reset(group->gp_core))
  568. {
  569. struct mali_gp_job *gp_job_to_return = group->gp_running_job;
  570. group->gp_state = MALI_GROUP_CORE_STATE_IDLE;
  571. group->gp_running_job = NULL;
  572. MALI_DEBUG_ASSERT_POINTER(gp_job_to_return);
  573. mali_group_deactivate_page_directory(group, mali_gp_job_get_session(gp_job_to_return));
  574. if(mali_group_other_reschedule_needed(group))
  575. {
  576. mali_group_unlock(group);
  577. mali_pp_scheduler_do_schedule();
  578. }
  579. else
  580. {
  581. mali_group_unlock(group);
  582. }
  583. mali_gp_scheduler_job_done(group, gp_job_to_return, gp_success);
  584. mali_pm_core_event(MALI_CORE_EVENT_GP_STOP); /* It is ok to do this after schedule, since START/STOP is simply ++ and -- anyways */
  585. return;
  586. }
  587. else
  588. {
  589. need_group_reset = MALI_TRUE;
  590. MALI_DEBUG_PRINT(3, ("Mali group: Failed to reset GP, need to reset entire group\n"));
  591. pp_success = MALI_FALSE; /* This might kill PP as well, so this should fail */
  592. }
  593. }
  594. if (complete_pp && !complete_gp)
  595. {
  596. MALI_DEBUG_ASSERT_POINTER(group->pp_core);
  597. if (_MALI_OSK_ERR_OK == mali_pp_reset(group->pp_core))
  598. {
  599. struct mali_pp_job *pp_job_to_return = group->pp_running_job;
  600. u32 pp_sub_job_to_return = group->pp_running_sub_job;
  601. group->pp_state = MALI_GROUP_CORE_STATE_IDLE;
  602. group->pp_running_job = NULL;
  603. MALI_DEBUG_ASSERT_POINTER(pp_job_to_return);
  604. mali_group_deactivate_page_directory(group, mali_pp_job_get_session(pp_job_to_return));
  605. if(mali_group_other_reschedule_needed(group))
  606. {
  607. mali_group_unlock(group);
  608. mali_gp_scheduler_do_schedule();
  609. }
  610. else
  611. {
  612. mali_group_unlock(group);
  613. }
  614. mali_pp_scheduler_job_done(group, pp_job_to_return, pp_sub_job_to_return, pp_success);
  615. mali_pm_core_event(MALI_CORE_EVENT_PP_STOP); /* It is ok to do this after schedule, since START/STOP is simply ++ and -- anyways */
  616. return;
  617. }
  618. else
  619. {
  620. need_group_reset = MALI_TRUE;
  621. MALI_DEBUG_PRINT(3, ("Mali group: Failed to reset PP, need to reset entire group\n"));
  622. gp_success = MALI_FALSE; /* This might kill GP as well, so this should fail */
  623. }
  624. }
  625. else if (complete_gp && complete_pp)
  626. {
  627. need_group_reset = MALI_TRUE;
  628. }
  629. if (MALI_TRUE == need_group_reset)
  630. {
  631. struct mali_gp_job *gp_job_to_return = group->gp_running_job;
  632. struct mali_pp_job *pp_job_to_return = group->pp_running_job;
  633. u32 pp_sub_job_to_return = group->pp_running_sub_job;
  634. mali_bool schedule_other = MALI_FALSE;
  635. MALI_DEBUG_PRINT(3, ("Mali group: Resetting entire group\n"));
  636. group->gp_state = MALI_GROUP_CORE_STATE_IDLE;
  637. group->gp_running_job = NULL;
  638. if (NULL != gp_job_to_return)
  639. {
  640. mali_group_deactivate_page_directory(group, mali_gp_job_get_session(gp_job_to_return));
  641. }
  642. group->pp_state = MALI_GROUP_CORE_STATE_IDLE;
  643. group->pp_running_job = NULL;
  644. if (NULL != pp_job_to_return)
  645. {
  646. mali_group_deactivate_page_directory(group, mali_pp_job_get_session(pp_job_to_return));
  647. }
  648. /* The reset has to be done after mali_group_deactivate_page_directory() */
  649. mali_group_recovery_reset(group);
  650. if (mali_group_other_reschedule_needed(group) && (NULL == gp_job_to_return || NULL == pp_job_to_return))
  651. {
  652. schedule_other = MALI_TRUE;
  653. }
  654. mali_group_unlock(group);
  655. if (NULL != gp_job_to_return)
  656. {
  657. mali_gp_scheduler_job_done(group, gp_job_to_return, gp_success);
  658. mali_pm_core_event(MALI_CORE_EVENT_GP_STOP); /* It is ok to do this after schedule, since START/STOP is simply ++ and -- anyways */
  659. }
  660. else if (schedule_other)
  661. {
  662. mali_pp_scheduler_do_schedule();
  663. }
  664. if (NULL != pp_job_to_return)
  665. {
  666. mali_pp_scheduler_job_done(group, pp_job_to_return, pp_sub_job_to_return, pp_success);
  667. mali_pm_core_event(MALI_CORE_EVENT_PP_STOP); /* It is ok to do this after schedule, since START/STOP is simply ++ and -- anyways */
  668. }
  669. else if (schedule_other)
  670. {
  671. mali_gp_scheduler_do_schedule();
  672. }
  673. return;
  674. }
  675. mali_group_unlock(group);
  676. }
  677. #if MALI_STATE_TRACKING
  678. u32 mali_group_dump_state(struct mali_group *group, char *buf, u32 size)
  679. {
  680. int n = 0;
  681. n += _mali_osk_snprintf(buf + n, size - n, "Group: %p\n", group);
  682. if (group->gp_core)
  683. {
  684. n += mali_gp_dump_state(group->gp_core, buf + n, size - n);
  685. n += _mali_osk_snprintf(buf + n, size - n, "\tGP state: %d\n", group->gp_state);
  686. n += _mali_osk_snprintf(buf + n, size - n, "\tGP job: %p\n", group->gp_running_job);
  687. }
  688. if (group->pp_core)
  689. {
  690. n += mali_pp_dump_state(group->pp_core, buf + n, size - n);
  691. n += _mali_osk_snprintf(buf + n, size - n, "\tPP state: %d\n", group->pp_state);
  692. n += _mali_osk_snprintf(buf + n, size - n, "\tPP job: %p, subjob %d \n",
  693. group->pp_running_job, group->pp_running_sub_job);
  694. }
  695. return n;
  696. }
  697. #endif