950-0807-Revert-drm-vc4-hvs-Defer-dlist-slots-deallocation.patch 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342
  1. From a6ee757ad5ba809e8bc3fd6f14167425cff91498 Mon Sep 17 00:00:00 2001
  2. From: Maxime Ripard <[email protected]>
  3. Date: Thu, 31 Mar 2022 15:27:43 +0200
  4. Subject: [PATCH] Revert "drm/vc4: hvs: Defer dlist slots deallocation"
  5. This reverts commit e99a1b69da07ee3b89a6b8005b854e6c04bfb450.
  6. ---
  7. drivers/gpu/drm/vc4/vc4_crtc.c | 10 +-
  8. drivers/gpu/drm/vc4/vc4_drv.h | 15 +--
  9. drivers/gpu/drm/vc4/vc4_hvs.c | 181 +++------------------------------
  10. drivers/gpu/drm/vc4/vc4_regs.h | 1 -
  11. 4 files changed, 23 insertions(+), 184 deletions(-)
  12. --- a/drivers/gpu/drm/vc4/vc4_crtc.c
  13. +++ b/drivers/gpu/drm/vc4/vc4_crtc.c
  14. @@ -982,8 +982,14 @@ void vc4_crtc_destroy_state(struct drm_c
  15. struct vc4_dev *vc4 = to_vc4_dev(crtc->dev);
  16. struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(state);
  17. - vc4_hvs_mark_dlist_entry_stale(vc4->hvs, vc4_state->mm);
  18. - vc4_state->mm = NULL;
  19. + if (drm_mm_node_allocated(&vc4_state->mm)) {
  20. + unsigned long flags;
  21. +
  22. + spin_lock_irqsave(&vc4->hvs->mm_lock, flags);
  23. + drm_mm_remove_node(&vc4_state->mm);
  24. + spin_unlock_irqrestore(&vc4->hvs->mm_lock, flags);
  25. +
  26. + }
  27. drm_atomic_helper_crtc_destroy_state(crtc, state);
  28. }
  29. --- a/drivers/gpu/drm/vc4/vc4_drv.h
  30. +++ b/drivers/gpu/drm/vc4/vc4_drv.h
  31. @@ -335,9 +335,6 @@ struct vc4_hvs {
  32. struct drm_mm lbm_mm;
  33. spinlock_t mm_lock;
  34. - struct list_head stale_dlist_entries;
  35. - struct work_struct free_dlist_work;
  36. -
  37. struct drm_mm_node mitchell_netravali_filter;
  38. struct debugfs_regset32 regset;
  39. @@ -576,16 +573,10 @@ struct drm_connector *vc4_get_crtc_conne
  40. struct drm_encoder *vc4_get_crtc_encoder(struct drm_crtc *crtc,
  41. struct drm_crtc_state *state);
  42. -struct vc4_hvs_dlist_allocation {
  43. - struct list_head node;
  44. - struct drm_mm_node mm_node;
  45. - unsigned int channel;
  46. - u8 target_frame_count;
  47. -};
  48. -
  49. struct vc4_crtc_state {
  50. struct drm_crtc_state base;
  51. - struct vc4_hvs_dlist_allocation *mm;
  52. + /* Dlist area for this CRTC configuration. */
  53. + struct drm_mm_node mm;
  54. bool txp_armed;
  55. unsigned int assigned_channel;
  56. @@ -972,8 +963,6 @@ extern struct platform_driver vc4_hvs_dr
  57. void vc4_hvs_stop_channel(struct vc4_hvs *hvs, unsigned int output);
  58. int vc4_hvs_get_fifo_from_output(struct vc4_hvs *hvs, unsigned int output);
  59. u8 vc4_hvs_get_fifo_frame_count(struct vc4_hvs *hvs, unsigned int fifo);
  60. -void vc4_hvs_mark_dlist_entry_stale(struct vc4_hvs *hvs,
  61. - struct vc4_hvs_dlist_allocation *alloc);
  62. int vc4_hvs_atomic_check(struct drm_crtc *crtc, struct drm_atomic_state *state);
  63. void vc4_hvs_atomic_begin(struct drm_crtc *crtc, struct drm_atomic_state *state);
  64. void vc4_hvs_atomic_enable(struct drm_crtc *crtc, struct drm_atomic_state *state);
  65. --- a/drivers/gpu/drm/vc4/vc4_hvs.c
  66. +++ b/drivers/gpu/drm/vc4/vc4_hvs.c
  67. @@ -315,150 +315,6 @@ static void vc4_hvs_update_gamma_lut(str
  68. vc4_hvs_lut_load(hvs, vc4_crtc);
  69. }
  70. -static void vc4_hvs_irq_enable_eof(const struct vc4_hvs *hvs,
  71. - unsigned int channel)
  72. -{
  73. - u32 irq_mask = hvs->hvs5 ?
  74. - SCALER5_DISPCTRL_DSPEIEOF(channel) :
  75. - SCALER_DISPCTRL_DSPEIEOF(channel);
  76. -
  77. - HVS_WRITE(SCALER_DISPCTRL,
  78. - HVS_READ(SCALER_DISPCTRL) | irq_mask);
  79. -}
  80. -
  81. -static void vc4_hvs_irq_clear_eof(const struct vc4_hvs *hvs,
  82. - unsigned int channel)
  83. -{
  84. - u32 irq_mask = hvs->hvs5 ?
  85. - SCALER5_DISPCTRL_DSPEIEOF(channel) :
  86. - SCALER_DISPCTRL_DSPEIEOF(channel);
  87. -
  88. - HVS_WRITE(SCALER_DISPCTRL,
  89. - HVS_READ(SCALER_DISPCTRL) & ~irq_mask);
  90. -}
  91. -
  92. -static struct vc4_hvs_dlist_allocation *
  93. -vc4_hvs_alloc_dlist_entry(struct vc4_hvs *hvs,
  94. - unsigned int channel,
  95. - size_t dlist_count)
  96. -{
  97. - struct vc4_hvs_dlist_allocation *alloc;
  98. - unsigned long flags;
  99. - int ret;
  100. -
  101. - if (channel == VC4_HVS_CHANNEL_DISABLED)
  102. - return NULL;
  103. -
  104. - alloc = kzalloc(sizeof(*alloc), GFP_KERNEL);
  105. - if (!alloc)
  106. - return ERR_PTR(-ENOMEM);
  107. -
  108. - spin_lock_irqsave(&hvs->mm_lock, flags);
  109. - ret = drm_mm_insert_node(&hvs->dlist_mm, &alloc->mm_node,
  110. - dlist_count);
  111. - spin_unlock_irqrestore(&hvs->mm_lock, flags);
  112. - if (ret)
  113. - return ERR_PTR(ret);
  114. -
  115. - alloc->channel = channel;
  116. -
  117. - return alloc;
  118. -}
  119. -
  120. -void vc4_hvs_mark_dlist_entry_stale(struct vc4_hvs *hvs,
  121. - struct vc4_hvs_dlist_allocation *alloc)
  122. -{
  123. - unsigned long flags;
  124. - u8 frcnt;
  125. -
  126. - if (!alloc)
  127. - return;
  128. -
  129. - if (!drm_mm_node_allocated(&alloc->mm_node))
  130. - return;
  131. -
  132. - frcnt = vc4_hvs_get_fifo_frame_count(hvs, alloc->channel);
  133. - alloc->target_frame_count = (frcnt + 1) & ((1 << 6) - 1);
  134. -
  135. - spin_lock_irqsave(&hvs->mm_lock, flags);
  136. -
  137. - list_add_tail(&alloc->node, &hvs->stale_dlist_entries);
  138. -
  139. - HVS_WRITE(SCALER_DISPSTAT, SCALER_DISPSTAT_EOF(alloc->channel));
  140. - vc4_hvs_irq_enable_eof(hvs, alloc->channel);
  141. -
  142. - spin_unlock_irqrestore(&hvs->mm_lock, flags);
  143. -}
  144. -
  145. -static void vc4_hvs_schedule_dlist_sweep(struct vc4_hvs *hvs,
  146. - unsigned int channel)
  147. -{
  148. - unsigned long flags;
  149. -
  150. - spin_lock_irqsave(&hvs->mm_lock, flags);
  151. -
  152. - if (!list_empty(&hvs->stale_dlist_entries))
  153. - queue_work(system_unbound_wq, &hvs->free_dlist_work);
  154. -
  155. - vc4_hvs_irq_clear_eof(hvs, channel);
  156. -
  157. - spin_unlock_irqrestore(&hvs->mm_lock, flags);
  158. -}
  159. -
  160. -/*
  161. - * Frame counts are essentially sequence numbers over 6 bits, and we
  162. - * thus can use sequence number arithmetic and follow the RFC1982 to
  163. - * implement proper comparison between them.
  164. - */
  165. -static bool vc4_hvs_frcnt_lte(u8 cnt1, u8 cnt2)
  166. -{
  167. - return (s8)((cnt1 << 2) - (cnt2 << 2)) <= 0;
  168. -}
  169. -
  170. -/*
  171. - * Some atomic commits (legacy cursor updates, mostly) will not wait for
  172. - * the next vblank and will just return once the commit has been pushed
  173. - * to the hardware.
  174. - *
  175. - * On the hardware side, our HVS stores the planes parameters in its
  176. - * context RAM, and will use part of the RAM to store data during the
  177. - * frame rendering.
  178. - *
  179. - * This interacts badly if we get multiple commits before the next
  180. - * vblank since we could end up overwriting the DLIST entries used by
  181. - * previous commits if our dlist allocation reuses that entry. In such a
  182. - * case, we would overwrite the data currently being used by the
  183. - * hardware, resulting in a corrupted frame.
  184. - *
  185. - * In order to work around this, we'll queue the dlist entries in a list
  186. - * once the associated CRTC state is destroyed. The HVS only allows us
  187. - * to know which entry is being active, but not which one are no longer
  188. - * being used, so in order to avoid freeing entries that are still used
  189. - * by the hardware we add a guesstimate of the frame count where our
  190. - * entry will no longer be used, and thus will only free those entries
  191. - * when we will have reached that frame count.
  192. - */
  193. -static void vc4_hvs_dlist_free_work(struct work_struct *work)
  194. -{
  195. - struct vc4_hvs *hvs = container_of(work, struct vc4_hvs, free_dlist_work);
  196. - struct vc4_hvs_dlist_allocation *cur, *next;
  197. - unsigned long flags;
  198. -
  199. - spin_lock_irqsave(&hvs->mm_lock, flags);
  200. - list_for_each_entry_safe(cur, next, &hvs->stale_dlist_entries, node) {
  201. - u8 frcnt;
  202. -
  203. - frcnt = vc4_hvs_get_fifo_frame_count(hvs, cur->channel);
  204. - if (!vc4_hvs_frcnt_lte(cur->target_frame_count, frcnt))
  205. - continue;
  206. -
  207. - list_del(&cur->node);
  208. - drm_mm_remove_node(&cur->mm_node);
  209. - kfree(cur);
  210. - }
  211. - spin_unlock_irqrestore(&hvs->mm_lock, flags);
  212. -}
  213. -
  214. u8 vc4_hvs_get_fifo_frame_count(struct vc4_hvs *hvs, unsigned int fifo)
  215. {
  216. u8 field = 0;
  217. @@ -732,12 +588,13 @@ int vc4_hvs_atomic_check(struct drm_crtc
  218. {
  219. struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
  220. struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc_state);
  221. - struct vc4_hvs_dlist_allocation *alloc;
  222. struct drm_device *dev = crtc->dev;
  223. struct vc4_dev *vc4 = to_vc4_dev(dev);
  224. struct drm_plane *plane;
  225. + unsigned long flags;
  226. const struct drm_plane_state *plane_state;
  227. u32 dlist_count = 0;
  228. + int ret;
  229. /* The pixelvalve can only feed one encoder (and encoders are
  230. * 1:1 with connectors.)
  231. @@ -750,11 +607,12 @@ int vc4_hvs_atomic_check(struct drm_crtc
  232. dlist_count++; /* Account for SCALER_CTL0_END. */
  233. - alloc = vc4_hvs_alloc_dlist_entry(vc4->hvs, vc4_state->assigned_channel, dlist_count);
  234. - if (IS_ERR(alloc))
  235. - return PTR_ERR(alloc);
  236. -
  237. - vc4_state->mm = alloc;
  238. + spin_lock_irqsave(&vc4->hvs->mm_lock, flags);
  239. + ret = drm_mm_insert_node(&vc4->hvs->dlist_mm, &vc4_state->mm,
  240. + dlist_count);
  241. + spin_unlock_irqrestore(&vc4->hvs->mm_lock, flags);
  242. + if (ret)
  243. + return ret;
  244. return vc4_hvs_gamma_check(crtc, state);
  245. }
  246. @@ -766,9 +624,8 @@ static void vc4_hvs_install_dlist(struct
  247. struct vc4_hvs *hvs = vc4->hvs;
  248. struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc->state);
  249. - WARN_ON(!vc4_state->mm);
  250. HVS_WRITE(SCALER_DISPLISTX(vc4_state->assigned_channel),
  251. - vc4_state->mm->mm_node.start);
  252. + vc4_state->mm.start);
  253. }
  254. static void vc4_hvs_update_dlist(struct drm_crtc *crtc)
  255. @@ -793,10 +650,8 @@ static void vc4_hvs_update_dlist(struct
  256. spin_unlock_irqrestore(&dev->event_lock, flags);
  257. }
  258. - WARN_ON(!vc4_state->mm);
  259. -
  260. spin_lock_irqsave(&vc4_crtc->irq_lock, flags);
  261. - vc4_crtc->current_dlist = vc4_state->mm->mm_node.start;
  262. + vc4_crtc->current_dlist = vc4_state->mm.start;
  263. spin_unlock_irqrestore(&vc4_crtc->irq_lock, flags);
  264. }
  265. @@ -853,7 +708,8 @@ void vc4_hvs_atomic_flush(struct drm_crt
  266. struct vc4_plane_state *vc4_plane_state;
  267. bool debug_dump_regs = false;
  268. bool enable_bg_fill = false;
  269. - u32 __iomem *dlist_start, *dlist_next;
  270. + u32 __iomem *dlist_start = vc4->hvs->dlist + vc4_state->mm.start;
  271. + u32 __iomem *dlist_next = dlist_start;
  272. unsigned int zpos = 0;
  273. bool found = false;
  274. @@ -865,9 +721,6 @@ void vc4_hvs_atomic_flush(struct drm_crt
  275. vc4_hvs_dump_state(hvs);
  276. }
  277. - dlist_start = vc4->hvs->dlist + vc4_state->mm->mm_node.start;
  278. - dlist_next = dlist_start;
  279. -
  280. /* Copy all the active planes' dlist contents to the hardware dlist. */
  281. do {
  282. found = false;
  283. @@ -901,8 +754,7 @@ void vc4_hvs_atomic_flush(struct drm_crt
  284. writel(SCALER_CTL0_END, dlist_next);
  285. dlist_next++;
  286. - WARN_ON(!vc4_state->mm);
  287. - WARN_ON_ONCE(dlist_next - dlist_start != vc4_state->mm->mm_node.size);
  288. + WARN_ON_ONCE(dlist_next - dlist_start != vc4_state->mm.size);
  289. if (enable_bg_fill)
  290. /* This sets a black background color fill, as is the case
  291. @@ -1007,11 +859,6 @@ static irqreturn_t vc4_hvs_irq_handler(i
  292. irqret = IRQ_HANDLED;
  293. }
  294. -
  295. - if (status & SCALER_DISPSTAT_EOF(channel)) {
  296. - vc4_hvs_schedule_dlist_sweep(hvs, channel);
  297. - irqret = IRQ_HANDLED;
  298. - }
  299. }
  300. /* Clear every per-channel interrupt flag. */
  301. @@ -1069,8 +916,6 @@ static int vc4_hvs_bind(struct device *d
  302. hvs->dlist = hvs->regs + SCALER5_DLIST_START;
  303. spin_lock_init(&hvs->mm_lock);
  304. - INIT_LIST_HEAD(&hvs->stale_dlist_entries);
  305. - INIT_WORK(&hvs->free_dlist_work, vc4_hvs_dlist_free_work);
  306. /* Set up the HVS display list memory manager. We never
  307. * overwrite the setup from the bootloader (just 128b out of
  308. --- a/drivers/gpu/drm/vc4/vc4_regs.h
  309. +++ b/drivers/gpu/drm/vc4/vc4_regs.h
  310. @@ -240,7 +240,6 @@
  311. # define SCALER_DISPCTRL_DSPEIEOLN(x) BIT(8 + ((x) * 2))
  312. /* Enables Display 0 EOF contribution to SCALER_DISPSTAT_IRQDISP0 */
  313. # define SCALER_DISPCTRL_DSPEIEOF(x) BIT(7 + ((x) * 2))
  314. -# define SCALER5_DISPCTRL_DSPEIEOF(x) BIT(7 + ((x) * 4))
  315. # define SCALER_DISPCTRL_SLVRDEIRQ BIT(6)
  316. # define SCALER_DISPCTRL_SLVWREIRQ BIT(5)