History

accel/qaic: Support for 0 resize slice execution in BO

Add support to partially execute a slice which is resized to zero. Executing a zero size slice in a BO should mean that there is no DMA transfers involved but you should still configure doorbell and semaphores. For example consider a BO of size 18K and it is sliced into 3 6K slices and user calls partial execute ioctl with resize as 10K. slice 0 - size is 6k and offset is 0, so resize of 10K will not cut short this slice hence we send the entire slice for execution. slice 1 - size is 6k and offset is 6k, so resize of 10K will cut short this slice and only the first 4k should be DMA along with configuring doorbell and semaphores. slice 2 - size is 6k and offset is 12k, so resize of 10k will cut short this slice and no DMA transfer would be involved but we should would configure doorbell and semaphores. This change begs to change the behavior of 0 resize. Currently, 0 resize partial execute ioctl behaves exactly like execute ioctl i.e. no resize. After this patch all the slice in BO should behave exactly like slice 2 in above example. Refactor copy_partial_exec_reqs() to make it more readable and less complex.

Pranjal Ramajor Asha Kanojiya committed 3 years ago

Commit 3b511271 parent 44793c62 files · +46 −63Browse files

Unified · Split

2 files
  1. drivers/accel/qaic/qaic_data.c +43 −61
  2. include/uapi/drm/qaic_accel.h +3 −2
drivers/accel/qaic/qaic_data.c+43−61
@@ -51,6 +51,7 @@ · 50 unmodified lines
5151 })
5252 #define NUM_EVENTS 128
5353 #define NUM_DELAYS 10
54+#define fifo_at(base, offset) ((base) + (offset) * get_dbc_req_elem_size())
5455
5556 static unsigned int wait_exec_default_timeout_ms = 5000; /* 5 sec default */
5657 module_param(wait_exec_default_timeout_ms, uint, 0600);
@@ -1058,6 +1059,16 @@ unlock_usr_srcu: · 1001 unmodified lines
10581059 return ret;
10591060 }
10601061
1062+static inline u32 fifo_space_avail(u32 head, u32 tail, u32 q_size)
1063+{
1064+ u32 avail = head - tail - 1;
1065+
1066+ if (head <= tail)
1067+ avail += q_size;
1068+
1069+ return avail;
1070+}
1071+
10611072 static inline int copy_exec_reqs(struct qaic_device *qdev, struct bo_slice *slice, u32 dbc_id,
10621073 u32 head, u32 *ptail)
10631074 {
@@ -1066,27 +1077,20 @@ static inline int copy_exec_reqs(struct qaic_device *qdev, struct bo_slice *slic · 2 unmodified lines
10661077 u32 tail = *ptail;
10671078 u32 avail;
10681079
1069− avail = head - tail;
1070− if (head <= tail)
1071− avail += dbc->nelem;
1072−
1073− --avail;
1074−
1080+ avail = fifo_space_avail(head, tail, dbc->nelem);
10751081 if (avail < slice->nents)
10761082 return -EAGAIN;
10771083
10781084 if (tail + slice->nents > dbc->nelem) {
10791085 avail = dbc->nelem - tail;
10801086 avail = min_t(u32, avail, slice->nents);
1081− memcpy(dbc->req_q_base + tail * get_dbc_req_elem_size(), reqs,
1082− sizeof(*reqs) * avail);
1087+ memcpy(fifo_at(dbc->req_q_base, tail), reqs, sizeof(*reqs) * avail);
10831088 reqs += avail;
10841089 avail = slice->nents - avail;
10851090 if (avail)
10861091 memcpy(dbc->req_q_base, reqs, sizeof(*reqs) * avail);
10871092 } else {
1088− memcpy(dbc->req_q_base + tail * get_dbc_req_elem_size(), reqs,
1089− sizeof(*reqs) * slice->nents);
1093+ memcpy(fifo_at(dbc->req_q_base, tail), reqs, sizeof(*reqs) * slice->nents);
10901094 }
10911095
10921096 *ptail = (tail + slice->nents) % dbc->nelem;
@@ -1094,46 +1098,31 @@ static inline int copy_exec_reqs(struct qaic_device *qdev, struct bo_slice *slic · 1 unmodified line
10941098 return 0;
10951099 }
10961100
1097−/*
1098− * Based on the value of resize we may only need to transmit first_n
1099− * entries and the last entry, with last_bytes to send from the last entry.
1100− * Note that first_n could be 0.
1101− */
11021101 static inline int copy_partial_exec_reqs(struct qaic_device *qdev, struct bo_slice *slice,
1103− u64 resize, u32 dbc_id, u32 head, u32 *ptail)
1102+ u64 resize, struct dma_bridge_chan *dbc, u32 head,
1103+ u32 *ptail)
11041104 {
1105− struct dma_bridge_chan *dbc = &qdev->dbc[dbc_id];
11061105 struct dbc_req *reqs = slice->reqs;
11071106 struct dbc_req *last_req;
11081107 u32 tail = *ptail;
1109− u64 total_bytes;
11101108 u64 last_bytes;
11111109 u32 first_n;
11121110 u32 avail;
1113− int ret;
1114− int i;
1115−
1116− avail = head - tail;
1117− if (head <= tail)
1118− avail += dbc->nelem;
11191111
1120− --avail;
1112+ avail = fifo_space_avail(head, tail, dbc->nelem);
11211113
1122− total_bytes = 0;
1123− for (i = 0; i < slice->nents; i++) {
1124− total_bytes += le32_to_cpu(reqs[i].len);
1125− if (total_bytes >= resize)
1114+ /*
1115+ * After this for loop is complete, first_n represents the index
1116+ * of the last DMA request of this slice that needs to be
1117+ * transferred after resizing and last_bytes represents DMA size
1118+ * of that request.
1119+ */
1120+ last_bytes = resize;
1121+ for (first_n = 0; first_n < slice->nents; first_n++)
1122+ if (last_bytes > le32_to_cpu(reqs[first_n].len))
1123+ last_bytes -= le32_to_cpu(reqs[first_n].len);
1124+ else
11261125 break;
1127− }
1128−
1129− if (total_bytes < resize) {
1130− /* User space should have used the full buffer path. */
1131− ret = -EINVAL;
1132− return ret;
1133− }
1134−
1135− first_n = i;
1136− last_bytes = i ? resize + le32_to_cpu(reqs[i].len) - total_bytes : resize;
11371126
11381127 if (avail < (first_n + 1))
11391128 return -EAGAIN;
@@ -1142,22 +1131,21 @@ static inline int copy_partial_exec_reqs(struct qaic_device *qdev, struct bo_sli · 2 unmodified lines
11421131 if (tail + first_n > dbc->nelem) {
11431132 avail = dbc->nelem - tail;
11441133 avail = min_t(u32, avail, first_n);
1145− memcpy(dbc->req_q_base + tail * get_dbc_req_elem_size(), reqs,
1146− sizeof(*reqs) * avail);
1134+ memcpy(fifo_at(dbc->req_q_base, tail), reqs, sizeof(*reqs) * avail);
11471135 last_req = reqs + avail;
11481136 avail = first_n - avail;
11491137 if (avail)
11501138 memcpy(dbc->req_q_base, last_req, sizeof(*reqs) * avail);
11511139 } else {
1152− memcpy(dbc->req_q_base + tail * get_dbc_req_elem_size(), reqs,
1153− sizeof(*reqs) * first_n);
1140+ memcpy(fifo_at(dbc->req_q_base, tail), reqs, sizeof(*reqs) * first_n);
11541141 }
11551142 }
11561143
1157− /* Copy over the last entry. Here we need to adjust len to the left over
1144+ /*
1145+ * Copy over the last entry. Here we need to adjust len to the left over
11581146 * size, and set src and dst to the entry it is copied to.
11591147 */
1160− last_req = dbc->req_q_base + (tail + first_n) % dbc->nelem * get_dbc_req_elem_size();
1148+ last_req = fifo_at(dbc->req_q_base, (tail + first_n) % dbc->nelem);
11611149 memcpy(last_req, reqs + slice->nents - 1, sizeof(*reqs));
11621150
11631151 /*
@@ -1168,6 +1156,9 @@ static inline int copy_partial_exec_reqs(struct qaic_device *qdev, struct bo_sli · 4 unmodified lines
11681156 last_req->len = cpu_to_le32((u32)last_bytes);
11691157 last_req->src_addr = reqs[first_n].src_addr;
11701158 last_req->dest_addr = reqs[first_n].dest_addr;
1159+ if (!last_bytes)
1160+ /* Disable DMA transfer */
1161+ last_req->cmd = GENMASK(7, 2) & reqs[first_n].cmd;
11711162
11721163 *ptail = (tail + first_n + 1) % dbc->nelem;
11731164
@@ -1227,26 +1218,17 @@ static int send_bo_list_to_device(struct qaic_device *qdev, struct drm_file *fil · 53 unmodified lines
12271218 bo->req_id = dbc->next_req_id++;
12281219
12291220 list_for_each_entry(slice, &bo->slices, slice) {
1230− /*
1231− * If this slice does not fall under the given
1232− * resize then skip this slice and continue the loop
1233− */
1234− if (is_partial && pexec[i].resize && pexec[i].resize <= slice->offset)
1235− continue;
1236−
12371221 for (j = 0; j < slice->nents; j++)
12381222 slice->reqs[j].req_id = cpu_to_le16(bo->req_id);
12391223
1240− /*
1241− * If it is a partial execute ioctl call then check if
1242− * resize has cut this slice short then do a partial copy
1243− * else do complete copy
1244− */
1245− if (is_partial && pexec[i].resize &&
1246− pexec[i].resize < slice->offset + slice->size)
1224+ if (is_partial && (!pexec[i].resize || pexec[i].resize <= slice->offset))
1225+ /* Configure the slice for no DMA transfer */
1226+ ret = copy_partial_exec_reqs(qdev, slice, 0, dbc, head, tail);
1227+ else if (is_partial && pexec[i].resize < slice->offset + slice->size)
1228+ /* Configure the slice to be partially DMA transferred */
12471229 ret = copy_partial_exec_reqs(qdev, slice,
1248− pexec[i].resize - slice->offset,
1249− dbc->id, head, tail);
1230+ pexec[i].resize - slice->offset, dbc,
1231+ head, tail);
12501232 else
12511233 ret = copy_exec_reqs(qdev, slice, dbc->id, head, tail);
12521234 if (ret) {
include/uapi/drm/qaic_accel.h+3−2
@@ -287,8 +287,9 @@ struct qaic_execute_entry { · 286 unmodified lines
287287 * struct qaic_partial_execute_entry - Defines a BO to resize and submit.
288288 * @handle: In. GEM handle of the BO to commit to the device.
289289 * @dir: In. Direction of data. 1 = to device, 2 = from device.
290− * @resize: In. New size of the BO. Must be <= the original BO size. 0 is
291− * short for no resize.
290+ * @resize: In. New size of the BO. Must be <= the original BO size.
291+ * @resize as 0 would be interpreted as no DMA transfer is
292+ * involved.
292293 */
293294 struct qaic_partial_execute_entry {
294295 __u32 handle;