blob: 232d737994e4f9529eb080c7212240ece8004268 [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
65 mctp_prdebug("%s: 0x%hhx from %s", __func__, *val, reg ? "status" : "data");
66
Andrew Jefferyd5e3cd72020-05-12 22:10:22 +093067 if (reg == MCTP_ASTLPC_KCS_REG_DATA) {
68 uint8_t flag = mmio->bmc ? KCS_STATUS_IBF : KCS_STATUS_OBF;
69 (*mmio->kcs)[MCTP_ASTLPC_KCS_REG_STATUS] &= ~flag;
70 }
Andrew Jeffery0247c732020-02-06 11:48:52 +103071
72 return 0;
73}
74
Andrew Jeffery53ea1472020-05-23 21:06:24 +093075static int mctp_astlpc_mmio_kcs_write(void *data,
76 enum mctp_binding_astlpc_kcs_reg reg,
77 uint8_t val)
Andrew Jeffery0247c732020-02-06 11:48:52 +103078{
79 struct mctp_binding_astlpc_mmio *mmio = binding_to_mmio(data);
Andrew Jefferyd5e3cd72020-05-12 22:10:22 +093080 uint8_t *regp;
Andrew Jeffery0247c732020-02-06 11:48:52 +103081
Andrew Jefferyd5e3cd72020-05-12 22:10:22 +093082 assert(reg == MCTP_ASTLPC_KCS_REG_DATA ||
83 reg == MCTP_ASTLPC_KCS_REG_STATUS);
Andrew Jeffery0247c732020-02-06 11:48:52 +103084
Andrew Jefferyd5e3cd72020-05-12 22:10:22 +093085 if (reg == MCTP_ASTLPC_KCS_REG_DATA) {
86 uint8_t flag = mmio->bmc ? KCS_STATUS_OBF : KCS_STATUS_IBF;
87 (*mmio->kcs)[MCTP_ASTLPC_KCS_REG_STATUS] |= flag;
88 }
89
90 regp = &(*mmio->kcs)[reg];
Andrew Jeffery0247c732020-02-06 11:48:52 +103091 if (reg == MCTP_ASTLPC_KCS_REG_STATUS)
Andrew Jefferyd5e3cd72020-05-12 22:10:22 +093092 *regp = (val & ~0xbU) | (val & *regp & 1);
Andrew Jeffery0247c732020-02-06 11:48:52 +103093 else
Andrew Jefferyd5e3cd72020-05-12 22:10:22 +093094 *regp = val;
Andrew Jeffery0247c732020-02-06 11:48:52 +103095
96 mctp_prdebug("%s: 0x%hhx to %s", __func__, val, reg ? "status" : "data");
97
98 return 0;
99}
Andrew Jeffery06b2cd82020-03-17 23:12:27 +1030100int mctp_astlpc_mmio_lpc_read(void *data, void *buf, long offset, size_t len)
Andrew Jeffery0247c732020-02-06 11:48:52 +1030101{
102 struct mctp_binding_astlpc_mmio *mmio = binding_to_mmio(data);
103
Andrew Jeffery1dbf0212020-05-12 13:53:50 +0930104 mctp_prdebug("%s: %zu bytes from 0x%lx", __func__, len, offset);
105
Andrew Jeffery06b2cd82020-03-17 23:12:27 +1030106 assert(offset >= 0L);
Andrew Jeffery0247c732020-02-06 11:48:52 +1030107 assert(offset + len < mmio->lpc_size);
108
109 memcpy(buf, mmio->lpc + offset, len);
110
Andrew Jeffery0247c732020-02-06 11:48:52 +1030111 return 0;
112}
113
Andrew Jeffery06b2cd82020-03-17 23:12:27 +1030114int mctp_astlpc_mmio_lpc_write(void *data, void *buf, long offset, size_t len)
Andrew Jeffery0247c732020-02-06 11:48:52 +1030115{
116 struct mctp_binding_astlpc_mmio *mmio = binding_to_mmio(data);
117
Andrew Jeffery1dbf0212020-05-12 13:53:50 +0930118 mctp_prdebug("%s: %zu bytes to 0x%lx", __func__, len, offset);
119
Andrew Jeffery06b2cd82020-03-17 23:12:27 +1030120 assert(offset >= 0L);
Andrew Jeffery0247c732020-02-06 11:48:52 +1030121 assert(offset + len < mmio->lpc_size);
122
123 memcpy(mmio->lpc + offset, buf, len);
124
Andrew Jeffery0247c732020-02-06 11:48:52 +1030125 return 0;
126}
127
Andrew Jefferyb93b6112020-06-05 14:13:44 +0930128#define __unused __attribute__((unused))
129
130static void rx_message(uint8_t eid __unused, void *data __unused, void *msg,
131 size_t len)
Andrew Jeffery0247c732020-02-06 11:48:52 +1030132{
Andrew Jeffery5a7c2db2020-05-22 20:13:42 +0930133 struct astlpc_test *test = data;
Andrew Jeffery0247c732020-02-06 11:48:52 +1030134
Andrew Jeffery5a7c2db2020-05-22 20:13:42 +0930135 mctp_prdebug("MCTP message received: msg: %p, len %zd", msg, len);
Andrew Jeffery0247c732020-02-06 11:48:52 +1030136
Andrew Jeffery5a7c2db2020-05-22 20:13:42 +0930137 assert(len > 0);
138 assert(msg);
139 assert(test);
140 assert(test->msg);
141 assert(!memcmp(test->msg, msg, len));
142
143 test->count++;
Andrew Jeffery0247c732020-02-06 11:48:52 +1030144}
145
Andrew Jeffery53ea1472020-05-23 21:06:24 +0930146static const struct mctp_binding_astlpc_ops mctp_binding_astlpc_mmio_ops = {
Andrew Jeffery0247c732020-02-06 11:48:52 +1030147 .kcs_read = mctp_astlpc_mmio_kcs_read,
148 .kcs_write = mctp_astlpc_mmio_kcs_write,
149 .lpc_read = mctp_astlpc_mmio_lpc_read,
150 .lpc_write = mctp_astlpc_mmio_lpc_write,
151};
152
Andrew Jefferyd5e3cd72020-05-12 22:10:22 +0930153static void endpoint_init(struct astlpc_endpoint *ep, mctp_eid_t eid,
154 uint8_t mode, uint8_t (*kcs)[2], void *lpc_mem,
155 size_t lpc_size)
156{
157 /*
158 * Configure the direction of the KCS interface so we know whether to
159 * set or clear IBF or OBF on writes or reads.
160 */
161 ep->mmio.bmc = (mode == MCTP_BINDING_ASTLPC_MODE_BMC);
162
163 ep->mctp = mctp_init();
164 assert(ep->mctp);
165
Andrew Jefferyd5e3cd72020-05-12 22:10:22 +0930166 /* Inject KCS registers */
167 ep->mmio.kcs = kcs;
168
169 /* Inject the heap allocation as the LPC mapping */
170 ep->mmio.lpc_size = lpc_size;
171 ep->mmio.lpc = lpc_mem;
172
173 /* Initialise the binding */
Andrew Jeffery129ef932020-05-22 16:24:19 +0930174 ep->astlpc = mctp_astlpc_init(mode, MCTP_BTU, lpc_mem,
Andrew Jefferyd5e3cd72020-05-12 22:10:22 +0930175 &mctp_binding_astlpc_mmio_ops, &ep->mmio);
176
177 mctp_register_bus(ep->mctp, &ep->astlpc->binding, eid);
178}
179
180static void endpoint_destroy(struct astlpc_endpoint *ep)
181{
182 mctp_astlpc_destroy(ep->astlpc);
183 mctp_destroy(ep->mctp);
184}
185
Andrew Jefferycb5d55c2020-05-22 13:26:27 +0930186static void network_init(struct astlpc_test *ctx)
187{
188 const size_t lpc_size = 1 * 1024 * 1024;
189
190 ctx->lpc_mem = calloc(1, lpc_size);
191 assert(ctx->lpc_mem);
192
193 /* BMC initialisation */
194 endpoint_init(&ctx->bmc, 8, MCTP_BINDING_ASTLPC_MODE_BMC, &ctx->kcs,
195 ctx->lpc_mem, lpc_size);
196
197 /* Host initialisation */
198 endpoint_init(&ctx->host, 9, MCTP_BINDING_ASTLPC_MODE_HOST, &ctx->kcs,
199 ctx->lpc_mem, lpc_size);
200
201 /* BMC processes host channel init request, alerts host */
202 mctp_astlpc_poll(ctx->bmc.astlpc);
203 assert(ctx->kcs[KCS_REG_STATUS] & KCS_STATUS_CHANNEL_ACTIVE);
204 assert(ctx->kcs[KCS_REG_DATA] == 0xff);
205
206 /* Host dequeues channel init result */
207 mctp_astlpc_poll(ctx->host.astlpc);
208}
209
210static void network_destroy(struct astlpc_test *ctx)
211{
212 endpoint_destroy(&ctx->bmc);
213 endpoint_destroy(&ctx->host);
214 free(ctx->lpc_mem);
215}
216
Andrew Jeffery129ef932020-05-22 16:24:19 +0930217static void astlpc_assert_tx_packet(struct astlpc_endpoint *src,
218 const void *expected, size_t len)
219{
220 const size_t tx_body = src->astlpc->layout.tx.offset + 4 + 4;
221 const void *test = ((char *)src->astlpc->lpc_map) + tx_body;
222 assert(!memcmp(test, expected, len));
223}
224
Andrew Jefferye756de82020-05-22 12:30:58 +0930225static void astlpc_test_packetised_message_bmc_to_host(void)
Andrew Jefferyd5e3cd72020-05-12 22:10:22 +0930226{
Andrew Jefferycb5d55c2020-05-22 13:26:27 +0930227 struct astlpc_test ctx = { 0 };
Andrew Jefferyd5e3cd72020-05-12 22:10:22 +0930228 uint8_t msg[2 * MCTP_BTU];
Andrew Jeffery0247c732020-02-06 11:48:52 +1030229 int rc;
230
Andrew Jefferyd5e3cd72020-05-12 22:10:22 +0930231 /* Test harness initialisation */
232
Andrew Jeffery5a7c2db2020-05-22 20:13:42 +0930233 network_init(&ctx);
234
Andrew Jeffery0247c732020-02-06 11:48:52 +1030235 memset(&msg[0], 0x5a, MCTP_BTU);
236 memset(&msg[MCTP_BTU], 0xa5, MCTP_BTU);
237
Andrew Jeffery5a7c2db2020-05-22 20:13:42 +0930238 ctx.msg = &msg[0];
239 ctx.count = 0;
240 mctp_set_rx_all(ctx.host.mctp, rx_message, &ctx);
Andrew Jeffery0247c732020-02-06 11:48:52 +1030241
242 /* BMC sends a message */
Andrew Jefferycb5d55c2020-05-22 13:26:27 +0930243 rc = mctp_message_tx(ctx.bmc.mctp, 9, msg, sizeof(msg));
Andrew Jeffery0247c732020-02-06 11:48:52 +1030244 assert(rc == 0);
Andrew Jefferycb5d55c2020-05-22 13:26:27 +0930245 assert(ctx.kcs[MCTP_ASTLPC_KCS_REG_STATUS] & KCS_STATUS_OBF);
246 assert(ctx.kcs[MCTP_ASTLPC_KCS_REG_DATA] == 0x01);
Andrew Jeffery0247c732020-02-06 11:48:52 +1030247
Andrew Jeffery129ef932020-05-22 16:24:19 +0930248 astlpc_assert_tx_packet(&ctx.bmc, &msg[0], MCTP_BTU);
Andrew Jefferyd5e3cd72020-05-12 22:10:22 +0930249
Andrew Jeffery129ef932020-05-22 16:24:19 +0930250 /* Host receives the first packet */
Andrew Jefferycb5d55c2020-05-22 13:26:27 +0930251 mctp_astlpc_poll(ctx.host.astlpc);
Andrew Jeffery0247c732020-02-06 11:48:52 +1030252
253 /* Host returns Rx area ownership to BMC */
Andrew Jefferycb5d55c2020-05-22 13:26:27 +0930254 assert(!(ctx.kcs[MCTP_ASTLPC_KCS_REG_STATUS] & KCS_STATUS_OBF));
255 assert(ctx.kcs[MCTP_ASTLPC_KCS_REG_DATA] == 0x02);
256 assert(ctx.kcs[MCTP_ASTLPC_KCS_REG_STATUS] & KCS_STATUS_IBF);
Andrew Jeffery0247c732020-02-06 11:48:52 +1030257
258 /* BMC dequeues ownership hand-over and sends the queued packet */
Andrew Jefferycb5d55c2020-05-22 13:26:27 +0930259 rc = mctp_astlpc_poll(ctx.bmc.astlpc);
Andrew Jeffery0247c732020-02-06 11:48:52 +1030260 assert(rc == 0);
261
Andrew Jeffery129ef932020-05-22 16:24:19 +0930262 /* Host receives the next packet */
Andrew Jefferycb5d55c2020-05-22 13:26:27 +0930263 assert(ctx.kcs[MCTP_ASTLPC_KCS_REG_STATUS] & KCS_STATUS_OBF);
264 assert(ctx.kcs[MCTP_ASTLPC_KCS_REG_DATA] == 0x01);
Andrew Jeffery0247c732020-02-06 11:48:52 +1030265
Andrew Jeffery129ef932020-05-22 16:24:19 +0930266 astlpc_assert_tx_packet(&ctx.bmc, &msg[MCTP_BTU], MCTP_BTU);
Andrew Jeffery0247c732020-02-06 11:48:52 +1030267
Andrew Jeffery5a7c2db2020-05-22 20:13:42 +0930268 /* Host receives final packet */
269 mctp_astlpc_poll(ctx.host.astlpc);
270 assert(ctx.count == 1);
271
Andrew Jefferycb5d55c2020-05-22 13:26:27 +0930272 network_destroy(&ctx);
Andrew Jefferye756de82020-05-22 12:30:58 +0930273}
274
Andrew Jefferyf1a21312020-05-22 12:48:21 +0930275static void astlpc_test_simple_init(void)
276{
277 struct astlpc_endpoint bmc, host;
278 uint8_t kcs[2] = { 0 };
279 size_t lpc_size;
280 void *lpc_mem;
281
282 /* Test harness initialisation */
283 lpc_size = 1 * 1024 * 1024;
284 lpc_mem = calloc(1, lpc_size);
285 assert(lpc_mem);
286
287 /* Bus owner (BMC) initialisation */
288 endpoint_init(&bmc, 8, MCTP_BINDING_ASTLPC_MODE_BMC, &kcs, lpc_mem,
289 lpc_size);
290
291 /* Verify the BMC binding was initialised */
292 assert(kcs[MCTP_ASTLPC_KCS_REG_STATUS] & KCS_STATUS_BMC_READY);
293
294 /* Device (Host) initialisation */
295 endpoint_init(&host, 9, MCTP_BINDING_ASTLPC_MODE_HOST, &kcs, lpc_mem,
296 lpc_size);
297
298 /* Host sends channel init command */
299 assert(kcs[MCTP_ASTLPC_KCS_REG_STATUS] & KCS_STATUS_IBF);
300 assert(kcs[MCTP_ASTLPC_KCS_REG_DATA] == 0x00);
301
302 /* BMC receives host channel init request */
303 mctp_astlpc_poll(bmc.astlpc);
304
305 /* BMC sends init response */
306 assert(kcs[MCTP_ASTLPC_KCS_REG_STATUS] & KCS_STATUS_OBF);
307 assert(kcs[MCTP_ASTLPC_KCS_REG_STATUS] & KCS_STATUS_CHANNEL_ACTIVE);
308 assert(kcs[MCTP_ASTLPC_KCS_REG_DATA] == 0xff);
309
310 /* Host dequeues data */
311 mctp_astlpc_poll(host.astlpc);
312
313 endpoint_destroy(&bmc);
314 endpoint_destroy(&host);
315 free(lpc_mem);
316}
317
Andrew Jefferye756de82020-05-22 12:30:58 +0930318int main(void)
319{
320 mctp_set_log_stdio(MCTP_LOG_DEBUG);
321
Andrew Jefferyf1a21312020-05-22 12:48:21 +0930322 astlpc_test_simple_init();
Andrew Jefferye756de82020-05-22 12:30:58 +0930323 astlpc_test_packetised_message_bmc_to_host();
Andrew Jeffery11b7e922020-03-10 23:37:09 +1030324
Andrew Jeffery0247c732020-02-06 11:48:52 +1030325 return 0;
326}