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 }