1 /*
2 * Copyright (c) 2023 Shenzhen Kaihong Digital Industry Development Co., Ltd.
3 *
4 * HDF is dual licensed: you can use it either under the terms of
5 * the GPL, or the BSD license, at your option.
6 * See the LICENSE file in the root of this repository for complete details.
7 */
8
9 #include "pcie_bus_test.h"
10 #include <securec.h>
11 #include "hdf_base.h"
12 #include "hdf_io_service_if.h"
13 #include "hdf_log.h"
14 #include "osal_mem.h"
15 #include "pcie_if.h"
16 #define USER_LEM_MAX 8192
17 #define DMA_ALIGN_SIZE 256
18 #define DMA_TEST_LEN 256
19 #define PCIE_TEST_DISABLE_ADDR 0xB7
20 #define PCIE_TEST_UPPER_ADDR 0x28
21 #define PCIE_TEST_CMD_ADDR 0x04
22
23 struct PcieBusTestFunc {
24 int32_t cmd;
25 int32_t (*func)(struct PcieBusTester *tester);
26 };
27
TestPcieBusGetInfo(struct PcieBusTester * tester)28 static int32_t TestPcieBusGetInfo(struct PcieBusTester *tester)
29 {
30 int32_t ret;
31 struct BusConfig config;
32 if (tester == NULL) {
33 HDF_LOGE("%s: tester is null.", __func__);
34 return HDF_ERR_INVALID_OBJECT;
35 }
36 ret = tester->busDev.ops.getBusInfo(&tester->busDev, &config);
37 if (ret != HDF_SUCCESS) {
38 HDF_LOGE("%s: getBusInfo failed ret = %d.", __func__, ret);
39 return ret;
40 }
41 return HDF_SUCCESS;
42 }
43
TestPcieBusDataReadWrite(struct PcieBusTester * tester)44 static int32_t TestPcieBusDataReadWrite(struct PcieBusTester *tester)
45 {
46 uint8_t disable;
47 uint32_t upper;
48 uint16_t cmd;
49 int32_t ret;
50 if (tester == NULL) {
51 HDF_LOGE("%s: tester is null.", __func__);
52 return HDF_ERR_INVALID_OBJECT;
53 }
54
55 ret = tester->busDev.ops.readData(&tester->busDev, PCIE_TEST_DISABLE_ADDR, sizeof(disable), &disable);
56 if (ret != HDF_SUCCESS) {
57 HDF_LOGE("%s: disable read failed ret = %d.", __func__, ret);
58 return ret;
59 }
60 HDF_LOGD("%s: disable is %d", __func__, disable);
61
62 ret = tester->busDev.ops.writeData(&tester->busDev, PCIE_TEST_DISABLE_ADDR, sizeof(disable), &disable);
63 if (ret != HDF_SUCCESS) {
64 HDF_LOGE("%s: disable write failed ret = %d.", __func__, ret);
65 return ret;
66 }
67
68 ret = tester->busDev.ops.readData(&tester->busDev, PCIE_TEST_UPPER_ADDR, sizeof(upper), (uint8_t *)&upper);
69 if (ret != HDF_SUCCESS) {
70 HDF_LOGE("%s: upper read failed ret = %d.", __func__, ret);
71 return ret;
72 }
73 HDF_LOGD("%s: upper is %d", __func__, upper);
74
75 ret = tester->busDev.ops.writeData(&tester->busDev, PCIE_TEST_UPPER_ADDR, sizeof(upper), (uint8_t *)&upper);
76 if (ret != HDF_SUCCESS) {
77 HDF_LOGE("%s: upper write failed ret = %d.", __func__, ret);
78 return ret;
79 }
80
81 ret = tester->busDev.ops.readData(&tester->busDev, PCIE_TEST_CMD_ADDR, sizeof(cmd), (uint8_t *)&cmd);
82 if (ret != HDF_SUCCESS) {
83 HDF_LOGE("%s: cmd read failed ret = %d.", __func__, ret);
84 return ret;
85 }
86 HDF_LOGD("%s: cmd is %d", __func__, disable);
87
88 ret = tester->busDev.ops.writeData(&tester->busDev, PCIE_TEST_CMD_ADDR, sizeof(cmd), (uint8_t *)&cmd);
89 if (ret != HDF_SUCCESS) {
90 HDF_LOGE("%s: cmd write failed ret = %d.", __func__, ret);
91 return ret;
92 }
93 return HDF_SUCCESS;
94 }
95
TestPcieBusBulkReadWrite(struct PcieBusTester * tester)96 static int32_t TestPcieBusBulkReadWrite(struct PcieBusTester *tester)
97 {
98 uint32_t data;
99 int32_t ret;
100 if (tester == NULL) {
101 HDF_LOGE("%s: tester is null.", __func__);
102 return HDF_ERR_INVALID_OBJECT;
103 }
104 ret = tester->busDev.ops.bulkRead(&tester->busDev, PCIE_TEST_UPPER_ADDR, sizeof(data), (uint8_t *)&data,
105 sizeof(data));
106 if (ret != HDF_SUCCESS) {
107 HDF_LOGE("%s: readFunc0 failed ret = %d.", __func__, ret);
108 return ret;
109 }
110 ret = tester->busDev.ops.bulkWrite(&tester->busDev, PCIE_TEST_UPPER_ADDR, sizeof(data), (uint8_t *)&data,
111 sizeof(data));
112 if (ret != HDF_SUCCESS) {
113 HDF_LOGE("%s: writeFunc0 failed ret = %d.", __func__, ret);
114 return ret;
115 }
116 return HDF_SUCCESS;
117 }
118
TestPcieBusFunc0ReadWrite(struct PcieBusTester * tester)119 static int32_t TestPcieBusFunc0ReadWrite(struct PcieBusTester *tester)
120 {
121 uint32_t data;
122 int32_t ret;
123 if (tester == NULL) {
124 HDF_LOGE("%s: tester is null.", __func__);
125 return HDF_ERR_INVALID_OBJECT;
126 }
127 ret = tester->busDev.ops.readFunc0(&tester->busDev, PCIE_TEST_UPPER_ADDR, sizeof(data), (uint8_t *)&data);
128 if (ret != HDF_SUCCESS) {
129 HDF_LOGE("%s: readFunc0 failed ret = %d.", __func__, ret);
130 return ret;
131 }
132 ret = tester->busDev.ops.writeFunc0(&tester->busDev, PCIE_TEST_UPPER_ADDR, sizeof(data), (uint8_t *)&data);
133 if (ret != HDF_SUCCESS) {
134 HDF_LOGE("%s: writeFunc0 failed ret = %d.", __func__, ret);
135 return ret;
136 }
137 return HDF_SUCCESS;
138 }
139
PcieBusIrqHandler(void * arg)140 static void PcieBusIrqHandler(void *arg)
141 {
142 HDF_LOGD("%s: data is %{public}p", __func__, arg);
143 }
144
TestPcieBusIrqClaimRelease(struct PcieBusTester * tester)145 static int32_t TestPcieBusIrqClaimRelease(struct PcieBusTester *tester)
146 {
147 int32_t ret;
148 if (tester == NULL) {
149 HDF_LOGE("%s: tester is null.", __func__);
150 return HDF_ERR_INVALID_OBJECT;
151 }
152 ret = tester->busDev.ops.claimIrq(&tester->busDev, PcieBusIrqHandler, NULL);
153 if (ret != HDF_SUCCESS) {
154 HDF_LOGE("%s: claimIrq failed ret = %d.", __func__, ret);
155 return ret;
156 }
157
158 ret = tester->busDev.ops.releaseIrq(&tester->busDev);
159 if (ret != HDF_SUCCESS) {
160 HDF_LOGE("%s: releaseIrq failed ret = %d.", __func__, ret);
161 return ret;
162 }
163 return HDF_SUCCESS;
164 }
165
TestPcieBusDisalbeReset(struct PcieBusTester * tester)166 static int32_t TestPcieBusDisalbeReset(struct PcieBusTester *tester)
167 {
168 int32_t ret;
169 if (tester == NULL) {
170 HDF_LOGE("%s: tester is null.", __func__);
171 return HDF_ERR_INVALID_OBJECT;
172 }
173 ret = tester->busDev.ops.disableBus(&tester->busDev);
174 if (ret != HDF_SUCCESS) {
175 HDF_LOGE("%s: disableBus failed ret = %d.", __func__, ret);
176 return ret;
177 }
178 ret = tester->busDev.ops.reset(&tester->busDev);
179 if (ret != HDF_SUCCESS) {
180 HDF_LOGE("%s: disableBus failed ret = %d.", __func__, ret);
181 return ret;
182 }
183 return HDF_SUCCESS;
184 }
185
TestPcieBusHostClaimRelease(struct PcieBusTester * tester)186 static int32_t TestPcieBusHostClaimRelease(struct PcieBusTester *tester)
187 {
188 if (tester == NULL) {
189 HDF_LOGE("%s: tester is null.", __func__);
190 return HDF_ERR_INVALID_OBJECT;
191 }
192 tester->busDev.ops.claimHost(&tester->busDev);
193 tester->busDev.ops.releaseHost(&tester->busDev);
194 return HDF_SUCCESS;
195 }
196
TestPcieBusIoReadWrite(struct PcieBusTester * tester)197 static int32_t TestPcieBusIoReadWrite(struct PcieBusTester *tester)
198 {
199 uint32_t upper;
200 int32_t ret;
201 if (tester == NULL) {
202 HDF_LOGE("%s: tester is null.", __func__);
203 return HDF_ERR_INVALID_OBJECT;
204 }
205 ret = tester->busDev.ops.ioRead(&tester->busDev, PCIE_TEST_UPPER_ADDR, sizeof(upper), (uint8_t *)&upper);
206 if (ret != HDF_SUCCESS) {
207 HDF_LOGE("%s: upper read failed ret = %d.", __func__, ret);
208 return ret;
209 }
210 HDF_LOGD("%s: upper is %d", __func__, upper);
211
212 ret = tester->busDev.ops.ioWrite(&tester->busDev, PCIE_TEST_UPPER_ADDR, sizeof(upper), (uint8_t *)&upper);
213 if (ret != HDF_SUCCESS) {
214 HDF_LOGE("%s: upper write failed ret = %d.", __func__, ret);
215 return ret;
216 }
217 return HDF_SUCCESS;
218 }
219
PcieBusMapHandler(void * arg)220 static int32_t PcieBusMapHandler(void *arg)
221 {
222 HDF_LOGD("%s: data is %{public}p", __func__, arg);
223 return HDF_SUCCESS;
224 }
225
TestPcieBusDmaMapUnMap(struct PcieBusTester * tester)226 static int32_t TestPcieBusDmaMapUnMap(struct PcieBusTester *tester)
227 {
228 int32_t ret;
229 uintptr_t buf = 0;
230 if (tester == NULL) {
231 HDF_LOGE("%s: tester is null.", __func__);
232 return HDF_ERR_INVALID_OBJECT;
233 }
234 buf = (uintptr_t)OsalMemAllocAlign(DMA_ALIGN_SIZE, DMA_TEST_LEN);
235 if (buf == 0) {
236 HDF_LOGE("%s: malloc fail", __func__);
237 return HDF_ERR_MALLOC_FAIL;
238 }
239 // dma to device
240 ret = tester->busDev.ops.dmaMap(&tester->busDev, PcieBusMapHandler, buf, DMA_TEST_LEN, PCIE_DMA_TO_DEVICE);
241 if (ret != HDF_SUCCESS) {
242 HDF_LOGE("%s: failed ret = %d", __func__, ret);
243 OsalMemFree((void *)buf);
244 return ret;
245 }
246
247 ret = tester->busDev.ops.dmaUnmap(&tester->busDev, buf, DMA_TEST_LEN, PCIE_DMA_TO_DEVICE);
248 if (ret != HDF_SUCCESS) {
249 HDF_LOGE("%s: failed ret = %d", __func__, ret);
250 OsalMemFree((void *)buf);
251 return ret;
252 }
253
254 /* device to dma */
255 ret = tester->busDev.ops.dmaMap(&tester->busDev, PcieBusMapHandler, buf, DMA_TEST_LEN, PCIE_DMA_FROM_DEVICE);
256 if (ret != HDF_SUCCESS) {
257 HDF_LOGE("%s: failed ret = %d", __func__, ret);
258 OsalMemFree((void *)buf);
259 return ret;
260 }
261 ret = tester->busDev.ops.dmaUnmap(&tester->busDev, buf, DMA_TEST_LEN, PCIE_DMA_FROM_DEVICE);
262 OsalMemFree((void *)buf);
263 return HDF_SUCCESS;
264 }
265
266 static struct PcieBusTestFunc g_entry[] = {
267 {CMD_TEST_PCIE_BUS_GET_INFO, TestPcieBusGetInfo},
268 {CMD_TEST_PCIE_BUS_READ_WRITE_DATA, TestPcieBusDataReadWrite},
269 {CMD_TEST_PCIE_BUS_READ_WRITE_BULK, TestPcieBusBulkReadWrite},
270 {CMD_TEST_PCIE_BUS_READ_WRITE_FUNC0, TestPcieBusFunc0ReadWrite},
271 {CMD_TEST_PCIE_BUS_CLAIM_RELEASE_IRQ, TestPcieBusIrqClaimRelease},
272 {CMD_TEST_PCIE_BUS_DISABLE_RESET_BUS, TestPcieBusDisalbeReset},
273 {CMD_TEST_PCIE_BUS_CLAIM_RELEASE_HOST, TestPcieBusHostClaimRelease},
274 {CMD_TEST_PCIE_BUS_READ_WRITE_IO, TestPcieBusIoReadWrite},
275 {CMD_TEST_PCIE_BUS_MAP_UNMAP_DMA, TestPcieBusDmaMapUnMap},
276 };
277
PcieBusTesterGetConfig(struct PcieBusTestConfig * config)278 static int32_t PcieBusTesterGetConfig(struct PcieBusTestConfig *config)
279 {
280 int32_t ret;
281 struct HdfSBuf *reply = NULL;
282 struct HdfIoService *service = NULL;
283 const void *buf = NULL;
284 uint32_t len;
285
286 service = HdfIoServiceBind("PCIE_BUS_TEST");
287 if ((service == NULL) || (service->dispatcher == NULL) || (service->dispatcher->Dispatch == NULL)) {
288 HDF_LOGE("%s: HdfIoServiceBind failed\n", __func__);
289 return HDF_ERR_NOT_SUPPORT;
290 }
291
292 reply = HdfSbufObtain(sizeof(*config) + sizeof(uint32_t));
293 if (reply == NULL) {
294 HDF_LOGE("%s: failed to obtain reply", __func__);
295 HdfIoServiceRecycle(service);
296 return HDF_ERR_MALLOC_FAIL;
297 }
298
299 ret = service->dispatcher->Dispatch(&service->object, 0, NULL, reply);
300 if (ret != HDF_SUCCESS) {
301 HDF_LOGE("%s: remote dispatch failed", __func__);
302 HdfIoServiceRecycle(service);
303 HdfSbufRecycle(reply);
304 return ret;
305 }
306
307 if (!HdfSbufReadBuffer(reply, &buf, &len)) {
308 HDF_LOGE("%s: read buf failed", __func__);
309 HdfIoServiceRecycle(service);
310 HdfSbufRecycle(reply);
311 return HDF_ERR_IO;
312 }
313
314 if (len != sizeof(*config)) {
315 HDF_LOGE("%s: config size:%zu, read size:%u", __func__, sizeof(*config), len);
316 HdfIoServiceRecycle(service);
317 HdfSbufRecycle(reply);
318 return HDF_ERR_IO;
319 }
320
321 if (memcpy_s(config, sizeof(*config), buf, sizeof(*config)) != EOK) {
322 HDF_LOGE("%s: memcpy buf failed", __func__);
323 HdfIoServiceRecycle(service);
324 HdfSbufRecycle(reply);
325 return HDF_ERR_IO;
326 }
327
328 HdfIoServiceRecycle(service);
329 HdfSbufRecycle(reply);
330 return HDF_SUCCESS;
331 }
332
PcieBusTesterGet(void)333 static struct PcieBusTester *PcieBusTesterGet(void)
334 {
335 static struct PcieBusTester tester = {0};
336 struct HdfConfigWlanBus busConfig = {0};
337 int32_t ret = PcieBusTesterGetConfig(&tester.config);
338 if (ret != HDF_SUCCESS) {
339 HDF_LOGE("%s: read config failed:%d", __func__, ret);
340 return NULL;
341 }
342 HdfWlanConfigBusAbs(tester.config.busNum);
343 busConfig.busIdx = tester.config.busNum;
344 // busConfig.blockSize
345 HdfWlanBusAbsInit(&tester.busDev, &busConfig);
346 return &tester;
347 }
348
PcieBusTesterPut(struct PcieBusTester * tester)349 static void PcieBusTesterPut(struct PcieBusTester *tester)
350 {
351 if (tester == NULL) {
352 HDF_LOGE("%s:tester or service is null", __func__);
353 return;
354 }
355 tester->busDev.ops.deInit(&tester->busDev);
356 }
357
PcieBusTestExecute(int32_t cmd)358 int32_t PcieBusTestExecute(int32_t cmd)
359 {
360 uint32_t i;
361 int32_t ret = HDF_ERR_NOT_SUPPORT;
362 struct PcieBusTester *tester = NULL;
363
364 if (cmd > CMD_TEST_PCIE_MAX) {
365 HDF_LOGE("%s: invalid cmd:%d", __func__, cmd);
366 return ret;
367 }
368
369 tester = PcieBusTesterGet();
370 if (tester == NULL) {
371 HDF_LOGE("%s: get tester failed", __func__);
372 return HDF_ERR_INVALID_OBJECT;
373 }
374
375 for (i = 0; i < sizeof(g_entry) / sizeof(g_entry[0]); i++) {
376 if (g_entry[i].cmd == cmd && g_entry[i].func != NULL) {
377 ret = g_entry[i].func(tester);
378 break;
379 }
380 }
381 PcieBusTesterPut(tester);
382 HDF_LOGI("[%s][======cmd:%d====ret:%d======]", __func__, cmd, ret);
383 return ret;
384 }