pvr_cccb.c 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  1. // SPDX-License-Identifier: GPL-2.0-only OR MIT
  2. /* Copyright (c) 2023 Imagination Technologies Ltd. */
  3. #include "pvr_ccb.h"
  4. #include "pvr_cccb.h"
  5. #include "pvr_device.h"
  6. #include "pvr_gem.h"
  7. #include "pvr_hwrt.h"
  8. #include <linux/compiler.h>
  9. #include <linux/delay.h>
  10. #include <linux/jiffies.h>
  11. #include <linux/mutex.h>
  12. #include <linux/types.h>
  13. static __always_inline u32
  14. get_ccb_space(u32 w_off, u32 r_off, u32 ccb_size)
  15. {
  16. return (((r_off) - (w_off)) + ((ccb_size) - 1)) & ((ccb_size) - 1);
  17. }
  18. static void
  19. cccb_ctrl_init(void *cpu_ptr, void *priv)
  20. {
  21. struct rogue_fwif_cccb_ctl *ctrl = cpu_ptr;
  22. struct pvr_cccb *pvr_cccb = priv;
  23. WRITE_ONCE(ctrl->write_offset, 0);
  24. WRITE_ONCE(ctrl->read_offset, 0);
  25. WRITE_ONCE(ctrl->dep_offset, 0);
  26. WRITE_ONCE(ctrl->wrap_mask, pvr_cccb->wrap_mask);
  27. }
  28. /**
  29. * pvr_cccb_init() - Initialise a Client CCB
  30. * @pvr_dev: Device pointer.
  31. * @pvr_cccb: Pointer to Client CCB structure to initialise.
  32. * @size_log2: Log2 size of Client CCB in bytes.
  33. * @name: Name of owner of Client CCB. Used for fence context.
  34. *
  35. * Return:
  36. * * Zero on success, or
  37. * * Any error code returned by pvr_fw_object_create_and_map().
  38. */
  39. int
  40. pvr_cccb_init(struct pvr_device *pvr_dev, struct pvr_cccb *pvr_cccb,
  41. u32 size_log2, const char *name)
  42. {
  43. size_t size = 1 << size_log2;
  44. int err;
  45. pvr_cccb->size = size;
  46. pvr_cccb->write_offset = 0;
  47. pvr_cccb->wrap_mask = size - 1;
  48. /*
  49. * Map CCCB and control structure as uncached, so we don't have to flush
  50. * CPU cache repeatedly when polling for space.
  51. */
  52. pvr_cccb->ctrl = pvr_fw_object_create_and_map(pvr_dev, sizeof(*pvr_cccb->ctrl),
  53. PVR_BO_FW_FLAGS_DEVICE_UNCACHED,
  54. cccb_ctrl_init, pvr_cccb,
  55. &pvr_cccb->ctrl_obj);
  56. if (IS_ERR(pvr_cccb->ctrl))
  57. return PTR_ERR(pvr_cccb->ctrl);
  58. pvr_cccb->cccb = pvr_fw_object_create_and_map(pvr_dev, size,
  59. PVR_BO_FW_FLAGS_DEVICE_UNCACHED,
  60. NULL, NULL, &pvr_cccb->cccb_obj);
  61. if (IS_ERR(pvr_cccb->cccb)) {
  62. err = PTR_ERR(pvr_cccb->cccb);
  63. goto err_free_ctrl;
  64. }
  65. pvr_fw_object_get_fw_addr(pvr_cccb->ctrl_obj, &pvr_cccb->ctrl_fw_addr);
  66. pvr_fw_object_get_fw_addr(pvr_cccb->cccb_obj, &pvr_cccb->cccb_fw_addr);
  67. return 0;
  68. err_free_ctrl:
  69. pvr_fw_object_unmap_and_destroy(pvr_cccb->ctrl_obj);
  70. return err;
  71. }
  72. /**
  73. * pvr_cccb_fini() - Release Client CCB structure
  74. * @pvr_cccb: Client CCB to release.
  75. */
  76. void
  77. pvr_cccb_fini(struct pvr_cccb *pvr_cccb)
  78. {
  79. pvr_fw_object_unmap_and_destroy(pvr_cccb->cccb_obj);
  80. pvr_fw_object_unmap_and_destroy(pvr_cccb->ctrl_obj);
  81. }
  82. /**
  83. * pvr_cccb_cmdseq_fits() - Check if a command sequence fits in the CCCB
  84. * @pvr_cccb: Target Client CCB.
  85. * @size: Size of the command sequence.
  86. *
  87. * Check if a command sequence fits in the CCCB we have at hand.
  88. *
  89. * Return:
  90. * * true if the command sequence fits in the CCCB, or
  91. * * false otherwise.
  92. */
  93. bool pvr_cccb_cmdseq_fits(struct pvr_cccb *pvr_cccb, size_t size)
  94. {
  95. struct rogue_fwif_cccb_ctl *ctrl = pvr_cccb->ctrl;
  96. u32 read_offset, remaining;
  97. bool fits = false;
  98. read_offset = READ_ONCE(ctrl->read_offset);
  99. remaining = pvr_cccb->size - pvr_cccb->write_offset;
  100. /* Always ensure we have enough room for a padding command at the end of the CCCB.
  101. * If our command sequence does not fit, reserve the remaining space for a padding
  102. * command.
  103. */
  104. if (size + PADDING_COMMAND_SIZE > remaining)
  105. size += remaining;
  106. if (get_ccb_space(pvr_cccb->write_offset, read_offset, pvr_cccb->size) >= size)
  107. fits = true;
  108. return fits;
  109. }
  110. /**
  111. * pvr_cccb_write_command_with_header() - Write a command + command header to a
  112. * Client CCB
  113. * @pvr_cccb: Target Client CCB.
  114. * @cmd_type: Client CCB command type. Must be one of %ROGUE_FWIF_CCB_CMD_TYPE_*.
  115. * @cmd_size: Size of command in bytes.
  116. * @cmd_data: Pointer to command to write.
  117. * @ext_job_ref: External job reference.
  118. * @int_job_ref: Internal job reference.
  119. *
  120. * Caller must make sure there's enough space in CCCB to queue this command. This
  121. * can be done by calling pvr_cccb_cmdseq_fits().
  122. *
  123. * This function is not protected by any lock. The caller must ensure there's
  124. * no concurrent caller, which should be guaranteed by the drm_sched model (job
  125. * submission is serialized in drm_sched_main()).
  126. */
  127. void
  128. pvr_cccb_write_command_with_header(struct pvr_cccb *pvr_cccb, u32 cmd_type, u32 cmd_size,
  129. void *cmd_data, u32 ext_job_ref, u32 int_job_ref)
  130. {
  131. u32 sz_with_hdr = pvr_cccb_get_size_of_cmd_with_hdr(cmd_size);
  132. struct rogue_fwif_ccb_cmd_header cmd_header = {
  133. .cmd_type = cmd_type,
  134. .cmd_size = ALIGN(cmd_size, 8),
  135. .ext_job_ref = ext_job_ref,
  136. .int_job_ref = int_job_ref,
  137. };
  138. struct rogue_fwif_cccb_ctl *ctrl = pvr_cccb->ctrl;
  139. u32 remaining = pvr_cccb->size - pvr_cccb->write_offset;
  140. u32 required_size, cccb_space, read_offset;
  141. /*
  142. * Always ensure we have enough room for a padding command at the end of
  143. * the CCCB.
  144. */
  145. if (remaining < sz_with_hdr + PADDING_COMMAND_SIZE) {
  146. /*
  147. * Command would need to wrap, so we need to pad the remainder
  148. * of the CCCB.
  149. */
  150. required_size = sz_with_hdr + remaining;
  151. } else {
  152. required_size = sz_with_hdr;
  153. }
  154. read_offset = READ_ONCE(ctrl->read_offset);
  155. cccb_space = get_ccb_space(pvr_cccb->write_offset, read_offset, pvr_cccb->size);
  156. if (WARN_ON(cccb_space < required_size))
  157. return;
  158. if (required_size != sz_with_hdr) {
  159. /* Add padding command */
  160. struct rogue_fwif_ccb_cmd_header pad_cmd = {
  161. .cmd_type = ROGUE_FWIF_CCB_CMD_TYPE_PADDING,
  162. .cmd_size = remaining - sizeof(pad_cmd),
  163. };
  164. memcpy(&pvr_cccb->cccb[pvr_cccb->write_offset], &pad_cmd, sizeof(pad_cmd));
  165. pvr_cccb->write_offset = 0;
  166. }
  167. memcpy(&pvr_cccb->cccb[pvr_cccb->write_offset], &cmd_header, sizeof(cmd_header));
  168. memcpy(&pvr_cccb->cccb[pvr_cccb->write_offset + sizeof(cmd_header)], cmd_data, cmd_size);
  169. pvr_cccb->write_offset += sz_with_hdr;
  170. }
  171. static void fill_cmd_kick_data(struct pvr_cccb *cccb, u32 ctx_fw_addr,
  172. struct pvr_hwrt_data *hwrt,
  173. struct rogue_fwif_kccb_cmd_kick_data *k)
  174. {
  175. k->context_fw_addr = ctx_fw_addr;
  176. k->client_woff_update = cccb->write_offset;
  177. k->client_wrap_mask_update = cccb->wrap_mask;
  178. if (hwrt) {
  179. u32 cleanup_state_offset = offsetof(struct rogue_fwif_hwrtdata, cleanup_state);
  180. pvr_fw_object_get_fw_addr_offset(hwrt->fw_obj, cleanup_state_offset,
  181. &k->cleanup_ctl_fw_addr[k->num_cleanup_ctl++]);
  182. }
  183. }
  184. /**
  185. * pvr_cccb_send_kccb_kick: Send KCCB kick to trigger command processing
  186. * @pvr_dev: Device pointer.
  187. * @pvr_cccb: Pointer to CCCB to process.
  188. * @cctx_fw_addr: FW virtual address for context owning this Client CCB.
  189. * @hwrt: HWRT data set associated with this kick. May be %NULL.
  190. *
  191. * You must call pvr_kccb_reserve_slot() and wait for the returned fence to
  192. * signal (if this function didn't return NULL) before calling
  193. * pvr_cccb_send_kccb_kick().
  194. */
  195. void
  196. pvr_cccb_send_kccb_kick(struct pvr_device *pvr_dev,
  197. struct pvr_cccb *pvr_cccb, u32 cctx_fw_addr,
  198. struct pvr_hwrt_data *hwrt)
  199. {
  200. struct rogue_fwif_kccb_cmd cmd_kick = {
  201. .cmd_type = ROGUE_FWIF_KCCB_CMD_KICK,
  202. };
  203. fill_cmd_kick_data(pvr_cccb, cctx_fw_addr, hwrt, &cmd_kick.cmd_data.cmd_kick_data);
  204. /* Make sure the writes to the CCCB are flushed before sending the KICK. */
  205. wmb();
  206. pvr_kccb_send_cmd_reserved_powered(pvr_dev, &cmd_kick, NULL);
  207. }
  208. void
  209. pvr_cccb_send_kccb_combined_kick(struct pvr_device *pvr_dev,
  210. struct pvr_cccb *geom_cccb,
  211. struct pvr_cccb *frag_cccb,
  212. u32 geom_ctx_fw_addr,
  213. u32 frag_ctx_fw_addr,
  214. struct pvr_hwrt_data *hwrt,
  215. bool frag_is_pr)
  216. {
  217. struct rogue_fwif_kccb_cmd cmd_kick = {
  218. .cmd_type = ROGUE_FWIF_KCCB_CMD_COMBINED_GEOM_FRAG_KICK,
  219. };
  220. fill_cmd_kick_data(geom_cccb, geom_ctx_fw_addr, hwrt,
  221. &cmd_kick.cmd_data.combined_geom_frag_cmd_kick_data.geom_cmd_kick_data);
  222. /* If this is a partial-render job, we don't attach resources to cleanup-ctl array,
  223. * because the resources are already retained by the geometry job.
  224. */
  225. fill_cmd_kick_data(frag_cccb, frag_ctx_fw_addr, frag_is_pr ? NULL : hwrt,
  226. &cmd_kick.cmd_data.combined_geom_frag_cmd_kick_data.frag_cmd_kick_data);
  227. /* Make sure the writes to the CCCB are flushed before sending the KICK. */
  228. wmb();
  229. pvr_kccb_send_cmd_reserved_powered(pvr_dev, &cmd_kick, NULL);
  230. }