blob: 2a115c5a4f920bd3074ffb56d5125f299964250e [file] [log] [blame]
Andrew Jeffery0247c732020-02-06 11:48:52 +10301/* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */
2
Andrew Jeffery2cda40f2020-02-28 15:26:20 +10303#ifdef HAVE_CONFIG_H
Andrew Jeffery0247c732020-02-06 11:48:52 +10304#include "config.h"
Andrew Jeffery2cda40f2020-02-28 15:26:20 +10305#endif
6
Andrew Jefferydf5f6b92020-05-12 21:39:06 +09307#include "astlpc.c"
8
9#ifdef pr_fmt
10#undef pr_fmt
11#define pr_fmt(x) "test: " x
12#endif
13
Andrew Jeffery0247c732020-02-06 11:48:52 +103014#include "libmctp-astlpc.h"
15#include "libmctp-log.h"
Przemyslaw Czarnowskiff25d7e2020-03-26 11:39:37 +010016#include "container_of.h"
Andrew Jeffery0247c732020-02-06 11:48:52 +103017
18#ifdef NDEBUG
19#undef NDEBUG
20#endif
21
Andrew Jeffery0247c732020-02-06 11:48:52 +103022#include <assert.h>
23#include <stdint.h>
24#include <stdio.h>
25#include <stdlib.h>
26#include <string.h>
27
Andrew Jeffery0247c732020-02-06 11:48:52 +103028struct mctp_binding_astlpc_mmio {
29 struct mctp_binding_astlpc astlpc;
Andrew Jefferyd5e3cd72020-05-12 22:10:22 +093030 bool bmc;
Andrew Jeffery0247c732020-02-06 11:48:52 +103031
Andrew Jefferyd5e3cd72020-05-12 22:10:22 +093032 uint8_t (*kcs)[2];
Andrew Jeffery0247c732020-02-06 11:48:52 +103033
34 size_t lpc_size;
35 uint8_t *lpc;
36};
37
Andrew Jeffery5a7c2db2020-05-22 20:13:42 +093038struct astlpc_endpoint {
39 struct mctp_binding_astlpc_mmio mmio;
40 struct mctp_binding_astlpc *astlpc;
41 struct mctp *mctp;
42};
43
44struct astlpc_test {
45 struct astlpc_endpoint bmc;
46 struct astlpc_endpoint host;
47 uint8_t kcs[2];
48 uint8_t *lpc_mem;
49
50 void *msg;
51 uint8_t count;
52};
53
54#define binding_to_mmio(b) \
Andrew Jeffery0247c732020-02-06 11:48:52 +103055 container_of(b, struct mctp_binding_astlpc_mmio, astlpc)
56
Andrew Jeffery53ea1472020-05-23 21:06:24 +093057static int mctp_astlpc_mmio_kcs_read(void *data,
58 enum mctp_binding_astlpc_kcs_reg reg,
59 uint8_t *val)
Andrew Jeffery0247c732020-02-06 11:48:52 +103060{
61 struct mctp_binding_astlpc_mmio *mmio = binding_to_mmio(data);
62
Andrew Jefferyd5e3cd72020-05-12 22:10:22 +093063 *val = (*mmio->kcs)[reg];
Andrew Jeffery0247c732020-02-06 11:48:52 +103064
Andrew Jefferyd3c0bf02020-05-28 15:28:40 +093065 mctp_prdebug("%s: 0x%hhx from %s", __func__, *val,
66 reg ? "status" : "data");
Andrew Jeffery0247c732020-02-06 11:48:52 +103067
Andrew Jefferyd5e3cd72020-05-12 22:10:22 +093068 if (reg == MCTP_ASTLPC_KCS_REG_DATA) {
69 uint8_t flag = mmio->bmc ? KCS_STATUS_IBF : KCS_STATUS_OBF;
70 (*mmio->kcs)[MCTP_ASTLPC_KCS_REG_STATUS] &= ~flag;
71 }
Andrew Jeffery0247c732020-02-06 11:48:52 +103072
73 return 0;
74}
75
Andrew Jeffery53ea1472020-05-23 21:06:24 +093076static int mctp_astlpc_mmio_kcs_write(void *data,
77 enum mctp_binding_astlpc_kcs_reg reg,
78 uint8_t val)
Andrew Jeffery0247c732020-02-06 11:48:52 +103079{
80 struct mctp_binding_astlpc_mmio *mmio = binding_to_mmio(data);
Andrew Jefferyd5e3cd72020-05-12 22:10:22 +093081 uint8_t *regp;
Andrew Jeffery0247c732020-02-06 11:48:52 +103082
Andrew Jefferyd5e3cd72020-05-12 22:10:22 +093083 assert(reg == MCTP_ASTLPC_KCS_REG_DATA ||
84 reg == MCTP_ASTLPC_KCS_REG_STATUS);
Andrew Jeffery0247c732020-02-06 11:48:52 +103085
Andrew Jefferyd5e3cd72020-05-12 22:10:22 +093086 if (reg == MCTP_ASTLPC_KCS_REG_DATA) {
87 uint8_t flag = mmio->bmc ? KCS_STATUS_OBF : KCS_STATUS_IBF;
88 (*mmio->kcs)[MCTP_ASTLPC_KCS_REG_STATUS] |= flag;
89 }
90
91 regp = &(*mmio->kcs)[reg];
Andrew Jeffery0247c732020-02-06 11:48:52 +103092 if (reg == MCTP_ASTLPC_KCS_REG_STATUS)
Andrew Jefferyd5e3cd72020-05-12 22:10:22 +093093 *regp = (val & ~0xbU) | (val & *regp & 1);
Andrew Jeffery0247c732020-02-06 11:48:52 +103094 else
Andrew Jefferyd5e3cd72020-05-12 22:10:22 +093095 *regp = val;
Andrew Jeffery0247c732020-02-06 11:48:52 +103096
Andrew Jefferyd3c0bf02020-05-28 15:28:40 +093097 mctp_prdebug("%s: 0x%hhx to %s", __func__, val,
98 reg ? "status" : "data");
Andrew Jeffery0247c732020-02-06 11:48:52 +103099
100 return 0;
101}
Andrew Jeffery06b2cd82020-03-17 23:12:27 +1030102int mctp_astlpc_mmio_lpc_read(void *data, void *buf, long offset, size_t len)
Andrew Jeffery0247c732020-02-06 11:48:52 +1030103{
104 struct mctp_binding_astlpc_mmio *mmio = binding_to_mmio(data);
105
Andrew Jeffery1dbf0212020-05-12 13:53:50 +0930106 mctp_prdebug("%s: %zu bytes from 0x%lx", __func__, len, offset);
107
Andrew Jeffery06b2cd82020-03-17 23:12:27 +1030108 assert(offset >= 0L);
Andrew Jeffery0247c732020-02-06 11:48:52 +1030109 assert(offset + len < mmio->lpc_size);
110
111 memcpy(buf, mmio->lpc + offset, len);
112
Andrew Jeffery0247c732020-02-06 11:48:52 +1030113 return 0;
114}
115
Andrew Jeffery06b2cd82020-03-17 23:12:27 +1030116int mctp_astlpc_mmio_lpc_write(void *data, void *buf, long offset, size_t len)
Andrew Jeffery0247c732020-02-06 11:48:52 +1030117{
118 struct mctp_binding_astlpc_mmio *mmio = binding_to_mmio(data);
119
Andrew Jeffery1dbf0212020-05-12 13:53:50 +0930120 mctp_prdebug("%s: %zu bytes to 0x%lx", __func__, len, offset);
121
Andrew Jeffery06b2cd82020-03-17 23:12:27 +1030122 assert(offset >= 0L);
Andrew Jeffery0247c732020-02-06 11:48:52 +1030123 assert(offset + len < mmio->lpc_size);
124
125 memcpy(mmio->lpc + offset, buf, len);
126
Andrew Jeffery0247c732020-02-06 11:48:52 +1030127 return 0;
128}
129
Andrew Jefferyb93b6112020-06-05 14:13:44 +0930130#define __unused __attribute__((unused))
131
132static void rx_message(uint8_t eid __unused, void *data __unused, void *msg,
133 size_t len)
Andrew Jeffery0247c732020-02-06 11:48:52 +1030134{
Andrew Jeffery5a7c2db2020-05-22 20:13:42 +0930135 struct astlpc_test *test = data;
Andrew Jeffery0247c732020-02-06 11:48:52 +1030136
Andrew Jeffery5a7c2db2020-05-22 20:13:42 +0930137 mctp_prdebug("MCTP message received: msg: %p, len %zd", msg, len);
Andrew Jeffery0247c732020-02-06 11:48:52 +1030138
Andrew Jeffery5a7c2db2020-05-22 20:13:42 +0930139 assert(len > 0);
140 assert(msg);
141 assert(test);
142 assert(test->msg);
143 assert(!memcmp(test->msg, msg, len));
144
145 test->count++;
Andrew Jeffery0247c732020-02-06 11:48:52 +1030146}
147
Andrew Jeffery53ea1472020-05-23 21:06:24 +0930148static const struct mctp_binding_astlpc_ops mctp_binding_astlpc_mmio_ops = {
Andrew Jeffery0247c732020-02-06 11:48:52 +1030149 .kcs_read = mctp_astlpc_mmio_kcs_read,
150 .kcs_write = mctp_astlpc_mmio_kcs_write,
151 .lpc_read = mctp_astlpc_mmio_lpc_read,
152 .lpc_write = mctp_astlpc_mmio_lpc_write,
153};
154
Andrew Jefferyd5e3cd72020-05-12 22:10:22 +0930155static void endpoint_init(struct astlpc_endpoint *ep, mctp_eid_t eid,
156 uint8_t mode, uint8_t (*kcs)[2], void *lpc_mem,
157 size_t lpc_size)
158{
159 /*
160 * Configure the direction of the KCS interface so we know whether to
161 * set or clear IBF or OBF on writes or reads.
162 */
163 ep->mmio.bmc = (mode == MCTP_BINDING_ASTLPC_MODE_BMC);
164
165 ep->mctp = mctp_init();
166 assert(ep->mctp);
167
Andrew Jefferyd5e3cd72020-05-12 22:10:22 +0930168 /* Inject KCS registers */
169 ep->mmio.kcs = kcs;
170
171 /* Inject the heap allocation as the LPC mapping */
172 ep->mmio.lpc_size = lpc_size;
173 ep->mmio.lpc = lpc_mem;
174
175 /* Initialise the binding */
Andrew Jeffery129ef932020-05-22 16:24:19 +0930176 ep->astlpc = mctp_astlpc_init(mode, MCTP_BTU, lpc_mem,
Andrew Jefferyd5e3cd72020-05-12 22:10:22 +0930177 &mctp_binding_astlpc_mmio_ops, &ep->mmio);
178
179 mctp_register_bus(ep->mctp, &ep->astlpc->binding, eid);
180}
181
182static void endpoint_destroy(struct astlpc_endpoint *ep)
183{
184 mctp_astlpc_destroy(ep->astlpc);
185 mctp_destroy(ep->mctp);
186}
187
Andrew Jefferycb5d55c2020-05-22 13:26:27 +0930188static void network_init(struct astlpc_test *ctx)
189{
190 const size_t lpc_size = 1 * 1024 * 1024;
191
192 ctx->lpc_mem = calloc(1, lpc_size);
193 assert(ctx->lpc_mem);
194
195 /* BMC initialisation */
196 endpoint_init(&ctx->bmc, 8, MCTP_BINDING_ASTLPC_MODE_BMC, &ctx->kcs,
197 ctx->lpc_mem, lpc_size);
198
199 /* Host initialisation */
200 endpoint_init(&ctx->host, 9, MCTP_BINDING_ASTLPC_MODE_HOST, &ctx->kcs,
201 ctx->lpc_mem, lpc_size);
202
203 /* BMC processes host channel init request, alerts host */
204 mctp_astlpc_poll(ctx->bmc.astlpc);
205 assert(ctx->kcs[KCS_REG_STATUS] & KCS_STATUS_CHANNEL_ACTIVE);
206 assert(ctx->kcs[KCS_REG_DATA] == 0xff);
207
208 /* Host dequeues channel init result */
209 mctp_astlpc_poll(ctx->host.astlpc);
210}
211
212static void network_destroy(struct astlpc_test *ctx)
213{
214 endpoint_destroy(&ctx->bmc);
215 endpoint_destroy(&ctx->host);
216 free(ctx->lpc_mem);
217}
218
Andrew Jeffery129ef932020-05-22 16:24:19 +0930219static void astlpc_assert_tx_packet(struct astlpc_endpoint *src,
220 const void *expected, size_t len)
221{
222 const size_t tx_body = src->astlpc->layout.tx.offset + 4 + 4;
223 const void *test = ((char *)src->astlpc->lpc_map) + tx_body;
224 assert(!memcmp(test, expected, len));
225}
226
Andrew Jefferye756de82020-05-22 12:30:58 +0930227static void astlpc_test_packetised_message_bmc_to_host(void)
Andrew Jefferyd5e3cd72020-05-12 22:10:22 +0930228{
Andrew Jefferycb5d55c2020-05-22 13:26:27 +0930229 struct astlpc_test ctx = { 0 };
Andrew Jefferyd5e3cd72020-05-12 22:10:22 +0930230 uint8_t msg[2 * MCTP_BTU];
Andrew Jeffery0247c732020-02-06 11:48:52 +1030231 int rc;
232
Andrew Jefferyd5e3cd72020-05-12 22:10:22 +0930233 /* Test harness initialisation */
234
Andrew Jeffery5a7c2db2020-05-22 20:13:42 +0930235 network_init(&ctx);
236
Andrew Jeffery0247c732020-02-06 11:48:52 +1030237 memset(&msg[0], 0x5a, MCTP_BTU);
238 memset(&msg[MCTP_BTU], 0xa5, MCTP_BTU);
239
Andrew Jeffery5a7c2db2020-05-22 20:13:42 +0930240 ctx.msg = &msg[0];
241 ctx.count = 0;
242 mctp_set_rx_all(ctx.host.mctp, rx_message, &ctx);
Andrew Jeffery0247c732020-02-06 11:48:52 +1030243
244 /* BMC sends a message */
Andrew Jefferycb5d55c2020-05-22 13:26:27 +0930245 rc = mctp_message_tx(ctx.bmc.mctp, 9, msg, sizeof(msg));
Andrew Jeffery0247c732020-02-06 11:48:52 +1030246 assert(rc == 0);
Andrew Jefferycb5d55c2020-05-22 13:26:27 +0930247 assert(ctx.kcs[MCTP_ASTLPC_KCS_REG_STATUS] & KCS_STATUS_OBF);
248 assert(ctx.kcs[MCTP_ASTLPC_KCS_REG_DATA] == 0x01);
Andrew Jeffery0247c732020-02-06 11:48:52 +1030249
Andrew Jeffery129ef932020-05-22 16:24:19 +0930250 astlpc_assert_tx_packet(&ctx.bmc, &msg[0], MCTP_BTU);
Andrew Jefferyd5e3cd72020-05-12 22:10:22 +0930251
Andrew Jeffery129ef932020-05-22 16:24:19 +0930252 /* Host receives the first packet */
Andrew Jefferycb5d55c2020-05-22 13:26:27 +0930253 mctp_astlpc_poll(ctx.host.astlpc);
Andrew Jeffery0247c732020-02-06 11:48:52 +1030254
255 /* Host returns Rx area ownership to BMC */
Andrew Jefferycb5d55c2020-05-22 13:26:27 +0930256 assert(!(ctx.kcs[MCTP_ASTLPC_KCS_REG_STATUS] & KCS_STATUS_OBF));
257 assert(ctx.kcs[MCTP_ASTLPC_KCS_REG_DATA] == 0x02);
258 assert(ctx.kcs[MCTP_ASTLPC_KCS_REG_STATUS] & KCS_STATUS_IBF);
Andrew Jeffery0247c732020-02-06 11:48:52 +1030259
260 /* BMC dequeues ownership hand-over and sends the queued packet */
Andrew Jefferycb5d55c2020-05-22 13:26:27 +0930261 rc = mctp_astlpc_poll(ctx.bmc.astlpc);
Andrew Jeffery0247c732020-02-06 11:48:52 +1030262 assert(rc == 0);
263
Andrew Jeffery129ef932020-05-22 16:24:19 +0930264 /* Host receives the next packet */
Andrew Jefferycb5d55c2020-05-22 13:26:27 +0930265 assert(ctx.kcs[MCTP_ASTLPC_KCS_REG_STATUS] & KCS_STATUS_OBF);
266 assert(ctx.kcs[MCTP_ASTLPC_KCS_REG_DATA] == 0x01);
Andrew Jeffery0247c732020-02-06 11:48:52 +1030267
Andrew Jeffery129ef932020-05-22 16:24:19 +0930268 astlpc_assert_tx_packet(&ctx.bmc, &msg[MCTP_BTU], MCTP_BTU);
Andrew Jeffery0247c732020-02-06 11:48:52 +1030269
Andrew Jeffery5a7c2db2020-05-22 20:13:42 +0930270 /* Host receives final packet */
271 mctp_astlpc_poll(ctx.host.astlpc);
272 assert(ctx.count == 1);
273
Andrew Jefferycb5d55c2020-05-22 13:26:27 +0930274 network_destroy(&ctx);
Andrew Jefferye756de82020-05-22 12:30:58 +0930275}
276
Andrew Jefferyf1a21312020-05-22 12:48:21 +0930277static void astlpc_test_simple_init(void)
278{
279 struct astlpc_endpoint bmc, host;
280 uint8_t kcs[2] = { 0 };
281 size_t lpc_size;
282 void *lpc_mem;
283
284 /* Test harness initialisation */
285 lpc_size = 1 * 1024 * 1024;
286 lpc_mem = calloc(1, lpc_size);
287 assert(lpc_mem);
288
289 /* Bus owner (BMC) initialisation */
290 endpoint_init(&bmc, 8, MCTP_BINDING_ASTLPC_MODE_BMC, &kcs, lpc_mem,
291 lpc_size);
292
293 /* Verify the BMC binding was initialised */
294 assert(kcs[MCTP_ASTLPC_KCS_REG_STATUS] & KCS_STATUS_BMC_READY);
295
296 /* Device (Host) initialisation */
297 endpoint_init(&host, 9, MCTP_BINDING_ASTLPC_MODE_HOST, &kcs, lpc_mem,
298 lpc_size);
299
300 /* Host sends channel init command */
301 assert(kcs[MCTP_ASTLPC_KCS_REG_STATUS] & KCS_STATUS_IBF);
302 assert(kcs[MCTP_ASTLPC_KCS_REG_DATA] == 0x00);
303
304 /* BMC receives host channel init request */
305 mctp_astlpc_poll(bmc.astlpc);
306
307 /* BMC sends init response */
308 assert(kcs[MCTP_ASTLPC_KCS_REG_STATUS] & KCS_STATUS_OBF);
309 assert(kcs[MCTP_ASTLPC_KCS_REG_STATUS] & KCS_STATUS_CHANNEL_ACTIVE);
310 assert(kcs[MCTP_ASTLPC_KCS_REG_DATA] == 0xff);
311
312 /* Host dequeues data */
313 mctp_astlpc_poll(host.astlpc);
314
315 endpoint_destroy(&bmc);
316 endpoint_destroy(&host);
317 free(lpc_mem);
318}
319
Andrew Jefferye756de82020-05-22 12:30:58 +0930320int main(void)
321{
322 mctp_set_log_stdio(MCTP_LOG_DEBUG);
323
Andrew Jefferyf1a21312020-05-22 12:48:21 +0930324 astlpc_test_simple_init();
Andrew Jefferye756de82020-05-22 12:30:58 +0930325 astlpc_test_packetised_message_bmc_to_host();
Andrew Jeffery11b7e922020-03-10 23:37:09 +1030326
Andrew Jeffery0247c732020-02-06 11:48:52 +1030327 return 0;
328}