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
51 })51 })
52#define NUM_EVENTS 12852#define NUM_EVENTS 128
53#define NUM_DELAYS 1053#define NUM_DELAYS 10
54#define fifo_at(base, offset) ((base) + (offset) * get_dbc_req_elem_size())
54 55
55static unsigned int wait_exec_default_timeout_ms = 5000; /* 5 sec default */56static unsigned int wait_exec_default_timeout_ms = 5000; /* 5 sec default */
56module_param(wait_exec_default_timeout_ms, uint, 0600);57module_param(wait_exec_default_timeout_ms, uint, 0600);
@@ -1058,6 +1059,16 @@ unlock_usr_srcu: · 1001 unmodified lines
1058 return ret;1059 return ret;
1059}1060}
1060 1061
1062static 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
1061static inline int copy_exec_reqs(struct qaic_device *qdev, struct bo_slice *slice, u32 dbc_id,1072static inline int copy_exec_reqs(struct qaic_device *qdev, struct bo_slice *slice, u32 dbc_id,
1062 u32 head, u32 *ptail)1073 u32 head, u32 *ptail)
1063{1074{
@@ -1066,27 +1077,20 @@ static inline int copy_exec_reqs(struct qaic_device *qdev, struct bo_slice *slic · 2 unmodified lines
1066 u32 tail = *ptail;1077 u32 tail = *ptail;
1067 u32 avail;1078 u32 avail;
1068 1079
1069 avail = head - tail;1080 avail = fifo_space_avail(head, tail, dbc->nelem);
1070 if (head <= tail)
1071 avail += dbc->nelem;
1072
1073 --avail;
1074
1075 if (avail < slice->nents)1081 if (avail < slice->nents)
1076 return -EAGAIN;1082 return -EAGAIN;
1077 1083
1078 if (tail + slice->nents > dbc->nelem) {1084 if (tail + slice->nents > dbc->nelem) {
1079 avail = dbc->nelem - tail;1085 avail = dbc->nelem - tail;
1080 avail = min_t(u32, avail, slice->nents);1086 avail = min_t(u32, avail, slice->nents);
1081 memcpy(dbc->req_q_base + tail * get_dbc_req_elem_size(), reqs,1087 memcpy(fifo_at(dbc->req_q_base, tail), reqs, sizeof(*reqs) * avail);
1082 sizeof(*reqs) * avail);
1083 reqs += avail;1088 reqs += avail;
1084 avail = slice->nents - avail;1089 avail = slice->nents - avail;
1085 if (avail)1090 if (avail)
1086 memcpy(dbc->req_q_base, reqs, sizeof(*reqs) * avail);1091 memcpy(dbc->req_q_base, reqs, sizeof(*reqs) * avail);
1087 } else {1092 } else {
1088 memcpy(dbc->req_q_base + tail * get_dbc_req_elem_size(), reqs,1093 memcpy(fifo_at(dbc->req_q_base, tail), reqs, sizeof(*reqs) * slice->nents);
1089 sizeof(*reqs) * slice->nents);
1090 }1094 }
1091 1095
1092 *ptail = (tail + slice->nents) % dbc->nelem;1096 *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
1094 return 0;1098 return 0;
1095}1099}
1096 1100
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 */
1102static inline int copy_partial_exec_reqs(struct qaic_device *qdev, struct bo_slice *slice,1101static 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)
1104{1104{
1105 struct dma_bridge_chan *dbc = &qdev->dbc[dbc_id];
1106 struct dbc_req *reqs = slice->reqs;1105 struct dbc_req *reqs = slice->reqs;
1107 struct dbc_req *last_req;1106 struct dbc_req *last_req;
1108 u32 tail = *ptail;1107 u32 tail = *ptail;
1109 u64 total_bytes;
1110 u64 last_bytes;1108 u64 last_bytes;
1111 u32 first_n;1109 u32 first_n;
1112 u32 avail;1110 u32 avail;
1113 int ret;
1114 int i;
1115
1116 avail = head - tail;
1117 if (head <= tail)
1118 avail += dbc->nelem;
1119 1111
1120 --avail;1112 avail = fifo_space_avail(head, tail, dbc->nelem);
1121 1113
1122 total_bytes = 0;1114 /*
1123 for (i = 0; i < slice->nents; i++) {1115 * After this for loop is complete, first_n represents the index
1124 total_bytes += le32_to_cpu(reqs[i].len);1116 * of the last DMA request of this slice that needs to be
1125 if (total_bytes >= resize)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
1126 break;1125 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;
1137 1126
1138 if (avail < (first_n + 1))1127 if (avail < (first_n + 1))
1139 return -EAGAIN;1128 return -EAGAIN;
@@ -1142,22 +1131,21 @@ static inline int copy_partial_exec_reqs(struct qaic_device *qdev, struct bo_sli · 2 unmodified lines
1142 if (tail + first_n > dbc->nelem) {1131 if (tail + first_n > dbc->nelem) {
1143 avail = dbc->nelem - tail;1132 avail = dbc->nelem - tail;
1144 avail = min_t(u32, avail, first_n);1133 avail = min_t(u32, avail, first_n);
1145 memcpy(dbc->req_q_base + tail * get_dbc_req_elem_size(), reqs,1134 memcpy(fifo_at(dbc->req_q_base, tail), reqs, sizeof(*reqs) * avail);
1146 sizeof(*reqs) * avail);
1147 last_req = reqs + avail;1135 last_req = reqs + avail;
1148 avail = first_n - avail;1136 avail = first_n - avail;
1149 if (avail)1137 if (avail)
1150 memcpy(dbc->req_q_base, last_req, sizeof(*reqs) * avail);1138 memcpy(dbc->req_q_base, last_req, sizeof(*reqs) * avail);
1151 } else {1139 } else {
1152 memcpy(dbc->req_q_base + tail * get_dbc_req_elem_size(), reqs,1140 memcpy(fifo_at(dbc->req_q_base, tail), reqs, sizeof(*reqs) * first_n);
1153 sizeof(*reqs) * first_n);
1154 }1141 }
1155 }1142 }
1156 1143
1157 /* Copy over the last entry. Here we need to adjust len to the left over1144 /*
1145 * Copy over the last entry. Here we need to adjust len to the left over
1158 * size, and set src and dst to the entry it is copied to.1146 * size, and set src and dst to the entry it is copied to.
1159 */1147 */
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);
1161 memcpy(last_req, reqs + slice->nents - 1, sizeof(*reqs));1149 memcpy(last_req, reqs + slice->nents - 1, sizeof(*reqs));
1162 1150
1163 /*1151 /*
@@ -1168,6 +1156,9 @@ static inline int copy_partial_exec_reqs(struct qaic_device *qdev, struct bo_sli · 4 unmodified lines
1168 last_req->len = cpu_to_le32((u32)last_bytes);1156 last_req->len = cpu_to_le32((u32)last_bytes);
1169 last_req->src_addr = reqs[first_n].src_addr;1157 last_req->src_addr = reqs[first_n].src_addr;
1170 last_req->dest_addr = reqs[first_n].dest_addr;1158 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;
1171 1162
1172 *ptail = (tail + first_n + 1) % dbc->nelem;1163 *ptail = (tail + first_n + 1) % dbc->nelem;
1173 1164
@@ -1227,26 +1218,17 @@ static int send_bo_list_to_device(struct qaic_device *qdev, struct drm_file *fil · 53 unmodified lines
1227 bo->req_id = dbc->next_req_id++;1218 bo->req_id = dbc->next_req_id++;
1228 1219
1229 list_for_each_entry(slice, &bo->slices, slice) {1220 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
1237 for (j = 0; j < slice->nents; j++)1221 for (j = 0; j < slice->nents; j++)
1238 slice->reqs[j].req_id = cpu_to_le16(bo->req_id);1222 slice->reqs[j].req_id = cpu_to_le16(bo->req_id);
1239 1223
1240 /*1224 if (is_partial && (!pexec[i].resize || pexec[i].resize <= slice->offset))
1241 * If it is a partial execute ioctl call then check if1225 /* Configure the slice for no DMA transfer */
1242 * resize has cut this slice short then do a partial copy1226 ret = copy_partial_exec_reqs(qdev, slice, 0, dbc, head, tail);
1243 * else do complete copy1227 else if (is_partial && pexec[i].resize < slice->offset + slice->size)
1244 */1228 /* Configure the slice to be partially DMA transferred */
1245 if (is_partial && pexec[i].resize &&
1246 pexec[i].resize < slice->offset + slice->size)
1247 ret = copy_partial_exec_reqs(qdev, slice,1229 ret = copy_partial_exec_reqs(qdev, slice,
1248 pexec[i].resize - slice->offset,1230 pexec[i].resize - slice->offset, dbc,
1249 dbc->id, head, tail);1231 head, tail);
1250 else1232 else
1251 ret = copy_exec_reqs(qdev, slice, dbc->id, head, tail);1233 ret = copy_exec_reqs(qdev, slice, dbc->id, head, tail);
1252 if (ret) {1234 if (ret) {
include/uapi/drm/qaic_accel.h+3−2
@@ -287,8 +287,9 @@ struct qaic_execute_entry { · 286 unmodified lines
287 * struct qaic_partial_execute_entry - Defines a BO to resize and submit.287 * struct qaic_partial_execute_entry - Defines a BO to resize and submit.
288 * @handle: In. GEM handle of the BO to commit to the device.288 * @handle: In. GEM handle of the BO to commit to the device.
289 * @dir: In. Direction of data. 1 = to device, 2 = from device.289 * @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 is290 * @resize: In. New size of the BO. Must be <= the original BO size.
291 * short for no resize.291 * @resize as 0 would be interpreted as no DMA transfer is
292 * involved.
292 */293 */
293struct qaic_partial_execute_entry {294struct qaic_partial_execute_entry {
294 __u32 handle;295 __u32 handle;