1 /*
2 * Copyright (c) 2021-2023 Huawei Device 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_test.h"
10 #include "device_resource_if.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 "osal_time.h"
16
17 #define HDF_LOG_TAG pcie_test_c
18
19 #define USER_LEM_MAX 8192
20 #define DMA_ALIGN_SIZE 256
21 #define DMA_TEST_LEN 256
22 #define PCIE_TEST_DISABLE_ADDR 0xB7
23 #define PCIE_TEST_UPPER_ADDR 0x28
24 #define PCIE_TEST_CMD_ADDR 0x04
25
26 struct PcieTestFunc {
27 int cmd;
28 int32_t (*func)(struct PcieTester *tester);
29 };
30
PcieTestGetConfig(struct PcieTestConfig * config)31 static int32_t PcieTestGetConfig(struct PcieTestConfig *config)
32 {
33 int32_t ret;
34 struct HdfSBuf *reply = NULL;
35 struct HdfIoService *service = NULL;
36
37 service = HdfIoServiceBind("PCIE_TEST");
38 if (service == NULL || service->dispatcher == NULL || service->dispatcher->Dispatch == NULL) {
39 HDF_LOGE("PcieTestGetConfig: bind service fail!");
40 return HDF_ERR_NOT_SUPPORT;
41 }
42
43 reply = HdfSbufObtainDefaultSize();
44 if (reply == NULL) {
45 HDF_LOGE("PcieTestGetConfig: fail to obtain reply!");
46 HdfIoServiceRecycle(service);
47 return HDF_ERR_MALLOC_FAIL;
48 }
49
50 ret = service->dispatcher->Dispatch(&service->object, 0, NULL, reply);
51 if (ret != HDF_SUCCESS) {
52 HDF_LOGE("PcieTestGetConfig: remote dispatch fail!");
53 HdfSbufRecycle(reply);
54 HdfIoServiceRecycle(service);
55 return ret;
56 }
57
58 if (!HdfSbufReadUint32(reply, &config->busNum)) {
59 HDF_LOGE("PcieTestGetConfig: read busNum fail!");
60 HdfSbufRecycle(reply);
61 HdfIoServiceRecycle(service);
62 return HDF_ERR_IO;
63 }
64 HdfSbufRecycle(reply);
65 HdfIoServiceRecycle(service);
66 return ret;
67 }
68
PcieTesterGet(void)69 static DevHandle PcieTesterGet(void)
70 {
71 int32_t ret;
72 static struct PcieTester tester = {0};
73
74 ret = PcieTestGetConfig(&tester.config);
75 if (ret != HDF_SUCCESS) {
76 HDF_LOGE("PcieTesterGet: read config fail, ret: %d!", ret);
77 return NULL;
78 }
79 tester.handle = PcieOpen(tester.config.busNum);
80 if (tester.handle == NULL) {
81 HDF_LOGE("PcieTesterGet: open pcie %u fail!", tester.config.busNum);
82 return NULL;
83 }
84
85 return &tester;
86 }
87
PcieTesterPut(struct PcieTester * tester)88 static void PcieTesterPut(struct PcieTester *tester)
89 {
90 if (tester == NULL) {
91 HDF_LOGE("PcieTesterPut: tester is null!");
92 return;
93 }
94 PcieClose(tester->handle);
95 tester->handle = NULL;
96 }
97
TestPcieReadAndWrite(struct PcieTester * tester)98 static int32_t TestPcieReadAndWrite(struct PcieTester *tester)
99 {
100 int32_t ret;
101 uint8_t disable;
102 uint32_t upper;
103 uint16_t cmd;
104
105 ret = PcieRead(tester->handle, PCIE_CONFIG, PCIE_TEST_DISABLE_ADDR, &disable, sizeof(disable));
106 if (ret != HDF_SUCCESS) {
107 HDF_LOGE("TestPcieReadAndWrite: PcieRead fail, ret = %d!", ret);
108 return ret;
109 }
110 HDF_LOGD("TestPcieReadAndWrite: disable is %d!", disable);
111 ret = PcieWrite(tester->handle, PCIE_CONFIG, PCIE_TEST_DISABLE_ADDR, &disable, sizeof(disable));
112 if (ret != HDF_SUCCESS) {
113 HDF_LOGE("TestPcieReadAndWrite: PcieWrite fail, ret = %d!", ret);
114 return ret;
115 }
116
117 ret = PcieRead(tester->handle, PCIE_CONFIG, PCIE_TEST_UPPER_ADDR, (uint8_t *)&upper, sizeof(upper));
118 if (ret != HDF_SUCCESS) {
119 HDF_LOGE("TestPcieReadAndWrite: PcieRead fail, ret = %d!", ret);
120 return ret;
121 }
122 HDF_LOGD("TestPcieReadAndWrite: upper is 0x%x!", upper);
123 ret = PcieWrite(tester->handle, PCIE_CONFIG, PCIE_TEST_UPPER_ADDR, (uint8_t *)&upper, sizeof(upper));
124 if (ret != HDF_SUCCESS) {
125 HDF_LOGE("TestPcieReadAndWrite: PcieWrite fail, ret = %d!", ret);
126 return ret;
127 }
128
129 ret = PcieRead(tester->handle, PCIE_CONFIG, PCIE_TEST_CMD_ADDR, (uint8_t *)&cmd, sizeof(cmd));
130 if (ret != HDF_SUCCESS) {
131 HDF_LOGE("TestPcieReadAndWrite: PcieRead fail, ret = %d!", ret);
132 return ret;
133 }
134 HDF_LOGD("TestPcieReadAndWrite: cmd is 0x%x!", cmd);
135 ret = PcieWrite(tester->handle, PCIE_CONFIG, PCIE_TEST_CMD_ADDR, (uint8_t *)&cmd, sizeof(cmd));
136 if (ret != HDF_SUCCESS) {
137 HDF_LOGE("TestPcieReadAndWrite: PcieWrite fail, ret = %d!", ret);
138 }
139 return ret;
140 }
141
TestPcieDmaCb(DevHandle handle)142 int32_t TestPcieDmaCb(DevHandle handle)
143 {
144 (void)handle;
145 HDF_LOGI("TestPcieDmaCb: trigger!");
146 return HDF_SUCCESS;
147 }
148
TestPcieDmaMapAndUnmap(struct PcieTester * tester)149 static int32_t TestPcieDmaMapAndUnmap(struct PcieTester *tester)
150 {
151 int32_t ret;
152 uintptr_t buf = 0;
153
154 if (tester->handle == NULL) {
155 HDF_LOGE("TestPcieDmaMapAndUnmap: invalid tester!");
156 return HDF_ERR_INVALID_PARAM;
157 }
158 buf = (uintptr_t)OsalMemAllocAlign(DMA_ALIGN_SIZE, DMA_TEST_LEN);
159 if (buf == 0) {
160 HDF_LOGE("TestPcieDmaMapAndUnmap: malloc fail!");
161 return HDF_ERR_MALLOC_FAIL;
162 }
163 /* dma to device */
164 ret = PcieDmaMap(tester->handle, TestPcieDmaCb, buf, DMA_TEST_LEN, PCIE_DMA_TO_DEVICE);
165 if (ret != HDF_SUCCESS) {
166 HDF_LOGE("TestPcieDmaMapAndUnmap: fail, ret = %d!", ret);
167 OsalMemFree((void *)buf);
168 return ret;
169 }
170 PcieDmaUnmap(tester->handle, buf, DMA_TEST_LEN, PCIE_DMA_TO_DEVICE);
171
172 /* device to dma */
173 ret = PcieDmaMap(tester->handle, TestPcieDmaCb, buf, DMA_TEST_LEN, PCIE_DMA_FROM_DEVICE);
174 if (ret != HDF_SUCCESS) {
175 HDF_LOGE("TestPcieDmaMapAndUnmap: fail, ret = %d!", ret);
176 OsalMemFree((void *)buf);
177 return ret;
178 }
179 PcieDmaUnmap(tester->handle, buf, DMA_TEST_LEN, PCIE_DMA_FROM_DEVICE);
180 OsalMemFree((void *)buf);
181
182 return HDF_SUCCESS;
183 }
184
TestPcieIrqCb(DevHandle handle)185 int32_t TestPcieIrqCb(DevHandle handle)
186 {
187 (void)handle;
188 HDF_LOGI("TestPcieIrqCb: trigger!");
189 return HDF_SUCCESS;
190 }
191
TestPcieRegAndUnregIrq(struct PcieTester * tester)192 static int32_t TestPcieRegAndUnregIrq(struct PcieTester *tester)
193 {
194 int32_t ret;
195 ret = PcieRegisterIrq(tester->handle, TestPcieIrqCb);
196 if (ret != HDF_SUCCESS) {
197 HDF_LOGE("TestPcieRegAndUnregIrq: register irq fail!");
198 return ret;
199 }
200
201 PcieUnregisterIrq(tester->handle);
202 return HDF_SUCCESS;
203 }
204
205 static struct PcieTestFunc g_entry[] = {
206 { PCIE_READ_AND_WRITE_01, TestPcieReadAndWrite },
207 { PCIE_DMA_MAP_AND_UNMAP_01, TestPcieDmaMapAndUnmap },
208 { PCIE_REG_AND_UNREG_IRQ_01, TestPcieRegAndUnregIrq },
209 };
210
PcieTestExecute(int cmd)211 int32_t PcieTestExecute(int cmd)
212 {
213 uint32_t i;
214 int32_t ret = HDF_ERR_NOT_SUPPORT;
215 struct PcieTester *tester = NULL;
216
217 if (cmd > PCIE_TEST_MAX) {
218 HDF_LOGE("PcieTestExecute: invalid cmd: %d!", cmd);
219 return ret;
220 }
221
222 tester = PcieTesterGet();
223 if (tester == NULL) {
224 HDF_LOGE("PcieTestExecute: get tester fail!");
225 return HDF_ERR_INVALID_OBJECT;
226 }
227
228 for (i = 0; i < sizeof(g_entry) / sizeof(g_entry[0]); i++) {
229 if (g_entry[i].cmd == cmd && g_entry[i].func != NULL) {
230 ret = g_entry[i].func(tester);
231 break;
232 }
233 }
234
235 HDF_LOGI("[PcieTestExecute][======cmd:%d====ret:%d======]", cmd, ret);
236 PcieTesterPut(tester);
237 return ret;
238 }
239