blob: 76bc6ea45496d28ea3324ab42d46022fcaa2b9b1 [file] [log] [blame]
Andrew Jeffery1e531af2018-08-07 13:32:57 +09301// SPDX-License-Identifier: Apache-2.0
2// Copyright (C) 2018 IBM Corp.
3#include "config.h"
4
5#include <errno.h>
6#include <stdint.h>
7
Andrew Jeffery5335f092018-08-09 14:56:08 +09308#include "common.h"
Andrew Jefferyc48d0702018-08-09 14:04:27 +09309#include "flash.h"
Andrew Jeffery1e531af2018-08-07 13:32:57 +093010#include "lpc.h"
Andrew Jefferycb935042019-03-15 09:54:33 +103011#include "mboxd.h"
12#include "protocol.h"
Andrew Jeffery1e531af2018-08-07 13:32:57 +093013#include "windows.h"
14
Andrew Jeffery26558db2018-08-10 00:22:38 +093015#define BLOCK_SIZE_SHIFT_V1 12 /* 4K */
16
Andrew Jeffery0453aa42018-08-21 08:25:46 +093017static inline uint8_t protocol_get_bmc_event_mask(struct mbox_context *context)
18{
19 if (context->version == API_VERSION_1) {
20 return BMC_EVENT_V1_MASK;
21 }
22
23 return BMC_EVENT_V2_MASK;
24}
25
Andrew Jeffery5335f092018-08-09 14:56:08 +093026/*
Andrew Jefferyfe0c9e82018-11-01 14:02:17 +103027 * protocol_events_put() - Push the full set/cleared state of BMC events on the
28 * provided transport
29 * @context: The mbox context pointer
30 * @ops: The operations struct for the transport of interest
31 *
32 * Return: 0 on success otherwise negative error code
33 */
34int protocol_events_put(struct mbox_context *context,
35 const struct transport_ops *ops)
36{
37 const uint8_t mask = protocol_get_bmc_event_mask(context);
38
39 return ops->put_events(context, mask);
40}
41
42/*
43 * protocol_events_set() - Update the set BMC events on the active transport
Andrew Jeffery5335f092018-08-09 14:56:08 +093044 * @context: The mbox context pointer
45 * @bmc_event: The bits to set
Andrew Jeffery5335f092018-08-09 14:56:08 +093046 *
47 * Return: 0 on success otherwise negative error code
48 */
Andrew Jeffery2ebfd202018-08-20 11:46:28 +093049int protocol_events_set(struct mbox_context *context, uint8_t bmc_event)
Andrew Jeffery5335f092018-08-09 14:56:08 +093050{
Andrew Jeffery0453aa42018-08-21 08:25:46 +093051 const uint8_t mask = protocol_get_bmc_event_mask(context);
Andrew Jeffery5335f092018-08-09 14:56:08 +093052
Andrew Jeffery0453aa42018-08-21 08:25:46 +093053 /*
54 * Store the raw value, as we may up- or down- grade the protocol
55 * version and subsequently need to flush the appropriate set. Instead
56 * we pass the masked value through to the transport
57 */
58 context->bmc_events |= bmc_event;
Andrew Jeffery5335f092018-08-09 14:56:08 +093059
Andrew Jefferyf62601b2018-11-01 13:44:25 +103060 return context->transport->set_events(context, bmc_event, mask);
Andrew Jeffery5335f092018-08-09 14:56:08 +093061}
62
63/*
Andrew Jefferyfe0c9e82018-11-01 14:02:17 +103064 * protocol_events_clear() - Update the cleared BMC events on the active
65 * transport
Andrew Jeffery5335f092018-08-09 14:56:08 +093066 * @context: The mbox context pointer
67 * @bmc_event: The bits to clear
Andrew Jeffery5335f092018-08-09 14:56:08 +093068 *
69 * Return: 0 on success otherwise negative error code
70 */
Andrew Jeffery2ebfd202018-08-20 11:46:28 +093071int protocol_events_clear(struct mbox_context *context, uint8_t bmc_event)
Andrew Jeffery5335f092018-08-09 14:56:08 +093072{
Andrew Jeffery0453aa42018-08-21 08:25:46 +093073 const uint8_t mask = protocol_get_bmc_event_mask(context);
74
75 context->bmc_events &= ~bmc_event;
76
Andrew Jefferyf62601b2018-11-01 13:44:25 +103077 return context->transport->clear_events(context, bmc_event, mask);
Andrew Jeffery5335f092018-08-09 14:56:08 +093078}
79
Andrew Jefferycb935042019-03-15 09:54:33 +103080static int protocol_v1_reset(struct mbox_context *context)
Andrew Jefferyab666a52018-08-07 14:28:09 +093081{
82 /* Host requested it -> No BMC Event */
Andrew Jeffery2ebfd202018-08-20 11:46:28 +093083 windows_reset_all(context);
Andrew Jefferyab666a52018-08-07 14:28:09 +093084 return lpc_reset(context);
85}
86
Andrew Jefferycb935042019-03-15 09:54:33 +103087static int protocol_negotiate_version(struct mbox_context *context,
88 uint8_t requested);
89
90static int protocol_v1_get_info(struct mbox_context *context,
91 struct protocol_get_info *io)
Andrew Jeffery1e531af2018-08-07 13:32:57 +093092{
93 uint8_t old_version = context->version;
94 int rc;
95
96 /* Bootstrap protocol version. This may involve {up,down}grading */
97 rc = protocol_negotiate_version(context, io->req.api_version);
98 if (rc < 0)
99 return rc;
100
101 /* Do the {up,down}grade if necessary*/
102 if (rc != old_version) {
Andrew Jeffery2ebfd202018-08-20 11:46:28 +0930103 /* Doing version negotiation, don't alert host to reset */
104 windows_reset_all(context);
Andrew Jeffery1e531af2018-08-07 13:32:57 +0930105 return context->protocol->get_info(context, io);
106 }
107
108 /* Record the negotiated version for the response */
109 io->resp.api_version = rc;
110
111 /* Now do all required intialisation for v1 */
112 context->block_size_shift = BLOCK_SIZE_SHIFT_V1;
113 MSG_INFO("Block Size: 0x%.8x (shift: %u)\n",
114 1 << context->block_size_shift, context->block_size_shift);
115
116 /* Knowing blocksize we can allocate the window dirty_bytemap */
117 windows_alloc_dirty_bytemap(context);
118
119 io->resp.v1.read_window_size =
120 context->windows.default_size >> context->block_size_shift;
121 io->resp.v1.write_window_size =
122 context->windows.default_size >> context->block_size_shift;
123
124 return lpc_map_memory(context);
125}
126
Andrew Jefferycb935042019-03-15 09:54:33 +1030127static int protocol_v1_get_flash_info(struct mbox_context *context,
Andrew Jeffery91a87452018-08-07 14:54:14 +0930128 struct protocol_get_flash_info *io)
129{
130 io->resp.v1.flash_size = context->flash_size;
131 io->resp.v1.erase_size = context->mtd_info.erasesize;
132
133 return 0;
134}
135
Andrew Jeffery1e531af2018-08-07 13:32:57 +0930136/*
Andrew Jeffery22fa5002018-08-07 15:22:50 +0930137 * get_lpc_addr_shifted() - Get lpc address of the current window
138 * @context: The mbox context pointer
139 *
140 * Return: The lpc address to access that offset shifted by block size
141 */
142static inline uint16_t get_lpc_addr_shifted(struct mbox_context *context)
143{
144 uint32_t lpc_addr, mem_offset;
145
146 /* Offset of the current window in the reserved memory region */
147 mem_offset = context->current->mem - context->mem;
148 /* Total LPC Address */
149 lpc_addr = context->lpc_base + mem_offset;
150
151 MSG_DBG("LPC address of current window: 0x%.8x\n", lpc_addr);
152
153 return lpc_addr >> context->block_size_shift;
154}
155
Andrew Jefferycb935042019-03-15 09:54:33 +1030156static int protocol_v1_create_window(struct mbox_context *context,
157 struct protocol_create_window *io)
Andrew Jeffery22fa5002018-08-07 15:22:50 +0930158{
Andrew Jeffery22fa5002018-08-07 15:22:50 +0930159 uint32_t offset = io->req.offset << context->block_size_shift;
Andrew Jefferycb935042019-03-15 09:54:33 +1030160 uint32_t size = io->req.size << context->block_size_shift;
161 int rc;
162
163 rc = flash_validate(context, offset, size, io->req.ro);
164 if (rc < 0) {
165 /* Backend does not allow window to be created. */
166 return rc;
167 }
Andrew Jeffery22fa5002018-08-07 15:22:50 +0930168
169 /* Close the current window if there is one */
170 if (context->current) {
Andrew Jefferyf21c81c2018-08-09 13:57:46 +0930171 /* There is an implicit flush if it was a write window
172 *
173 * protocol_v2_create_window() calls
174 * protocol_v1_create_window(), so use indirect call to
175 * write_flush() to make sure we pick the right one.
176 */
Andrew Jeffery22fa5002018-08-07 15:22:50 +0930177 if (context->current_is_write) {
Andrew Jefferyf21c81c2018-08-09 13:57:46 +0930178 rc = context->protocol->flush(context, NULL);
Andrew Jeffery22fa5002018-08-07 15:22:50 +0930179 if (rc < 0) {
180 MSG_ERR("Couldn't Flush Write Window\n");
181 return rc;
182 }
183 }
Andrew Jeffery2ebfd202018-08-20 11:46:28 +0930184 windows_close_current(context, FLAGS_NONE);
Andrew Jeffery22fa5002018-08-07 15:22:50 +0930185 }
186
187 /* Offset the host has requested */
188 MSG_INFO("Host requested flash @ 0x%.8x\n", offset);
189 /* Check if we have an existing window */
190 context->current = windows_search(context, offset,
191 context->version == API_VERSION_1);
192
193 if (!context->current) { /* No existing window */
194 MSG_DBG("No existing window which maps that flash offset\n");
195 rc = windows_create_map(context, &context->current,
196 offset,
197 context->version == API_VERSION_1);
198 if (rc < 0) { /* Unable to map offset */
199 MSG_ERR("Couldn't create window mapping for offset 0x%.8x\n",
Andrew Jeffery4bcec8e2018-08-07 15:33:41 +0930200 offset);
Andrew Jeffery22fa5002018-08-07 15:22:50 +0930201 return rc;
202 }
203 }
204
Andrew Jeffery4bcec8e2018-08-07 15:33:41 +0930205 context->current_is_write = !io->req.ro;
206
Andrew Jeffery22fa5002018-08-07 15:22:50 +0930207 MSG_INFO("Window @ %p for size 0x%.8x maps flash offset 0x%.8x\n",
208 context->current->mem, context->current->size,
209 context->current->flash_offset);
210
211 io->resp.lpc_address = get_lpc_addr_shifted(context);
212
213 return 0;
214}
215
Andrew Jefferycb935042019-03-15 09:54:33 +1030216static int protocol_v1_mark_dirty(struct mbox_context *context,
217 struct protocol_mark_dirty *io)
Andrew Jefferya336e432018-08-07 16:00:40 +0930218{
219 uint32_t offset = io->req.v1.offset;
220 uint32_t size = io->req.v1.size;
221 uint32_t off;
222
223 if (!(context->current && context->current_is_write)) {
224 MSG_ERR("Tried to call mark dirty without open write window\n");
225 return -EPERM;
226 }
227
228 /* For V1 offset given relative to flash - we want the window */
229 off = offset - ((context->current->flash_offset) >>
230 context->block_size_shift);
231 if (off > offset) { /* Underflow - before current window */
232 MSG_ERR("Tried to mark dirty before start of window\n");
233 MSG_ERR("requested offset: 0x%x window start: 0x%x\n",
234 offset << context->block_size_shift,
235 context->current->flash_offset);
236 return -EINVAL;
237 }
238 offset = off;
239 /*
240 * We only track dirty at the block level.
241 * For protocol V1 we can get away with just marking the whole
242 * block dirty.
243 */
244 size = align_up(size, 1 << context->block_size_shift);
245 size >>= context->block_size_shift;
246
247 MSG_INFO("Dirty window @ 0x%.8x for 0x%.8x\n",
248 offset << context->block_size_shift,
249 size << context->block_size_shift);
250
251 return window_set_bytemap(context, context->current, offset, size,
252 WINDOW_DIRTY);
253}
254
Andrew Jeffery9b920cf2018-08-07 22:49:19 +0930255static int generic_flush(struct mbox_context *context)
256{
257 int rc, i, offset, count;
258 uint8_t prev;
259
260 offset = 0;
261 count = 0;
262 prev = WINDOW_CLEAN;
263
264 MSG_INFO("Flush window @ %p for size 0x%.8x which maps flash @ 0x%.8x\n",
265 context->current->mem, context->current->size,
266 context->current->flash_offset);
267
268 /*
269 * We look for streaks of the same type and keep a count, when the type
270 * (dirty/erased) changes we perform the required action on the backing
271 * store and update the current streak-type
272 */
273 for (i = 0; i < (context->current->size >> context->block_size_shift);
274 i++) {
275 uint8_t cur = context->current->dirty_bmap[i];
276 if (cur != WINDOW_CLEAN) {
277 if (cur == prev) { /* Same as previous block, incrmnt */
278 count++;
279 } else if (prev == WINDOW_CLEAN) { /* Start of run */
280 offset = i;
281 count++;
282 } else { /* Change in streak type */
283 rc = window_flush(context, offset, count,
284 prev);
285 if (rc < 0) {
286 return rc;
287 }
288 offset = i;
289 count = 1;
290 }
291 } else {
292 if (prev != WINDOW_CLEAN) { /* End of a streak */
293 rc = window_flush(context, offset, count,
294 prev);
295 if (rc < 0) {
296 return rc;
297 }
298 offset = 0;
299 count = 0;
300 }
301 }
302 prev = cur;
303 }
304
305 if (prev != WINDOW_CLEAN) { /* Still the last streak to write */
306 rc = window_flush(context, offset, count, prev);
307 if (rc < 0) {
308 return rc;
309 }
310 }
311
312 /* Clear the dirty bytemap since we have written back all changes */
313 return window_set_bytemap(context, context->current, 0,
314 context->current->size >>
315 context->block_size_shift,
316 WINDOW_CLEAN);
317}
318
Andrew Jefferycb935042019-03-15 09:54:33 +1030319static int protocol_v1_flush(struct mbox_context *context,
320 struct protocol_flush *io)
Andrew Jeffery9b920cf2018-08-07 22:49:19 +0930321{
322 int rc;
323
324 if (!(context->current && context->current_is_write)) {
325 MSG_ERR("Tried to call flush without open write window\n");
326 return -EPERM;
327 }
328
329 /*
330 * For V1 the Flush command acts much the same as the dirty command
331 * except with a flush as well. Only do this on an actual flush
332 * command not when we call flush because we've implicitly closed a
333 * window because we might not have the required args in req.
334 */
Andrew Jeffery093eda52018-08-07 23:10:43 +0930335 if (io) {
336 struct protocol_mark_dirty *mdio = (void *)io;
337 rc = protocol_v1_mark_dirty(context, mdio);
338 if (rc < 0) {
339 return rc;
340 }
Andrew Jeffery9b920cf2018-08-07 22:49:19 +0930341 }
342
343 return generic_flush(context);
344}
345
Andrew Jefferycb935042019-03-15 09:54:33 +1030346static int protocol_v1_close(struct mbox_context *context,
347 struct protocol_close *io)
Andrew Jeffery093eda52018-08-07 23:10:43 +0930348{
349 int rc;
350
351 /* Close the current window if there is one */
352 if (!context->current) {
353 return 0;
354 }
355
356 /* There is an implicit flush if it was a write window */
357 if (context->current_is_write) {
358 rc = protocol_v1_flush(context, NULL);
359 if (rc < 0) {
360 MSG_ERR("Couldn't Flush Write Window\n");
361 return rc;
362 }
363 }
364
365 /* Host asked for it -> Don't set the BMC Event */
Andrew Jeffery2ebfd202018-08-20 11:46:28 +0930366 windows_close_current(context, io->req.flags);
Andrew Jeffery093eda52018-08-07 23:10:43 +0930367
368 return 0;
369}
370
Andrew Jefferycb935042019-03-15 09:54:33 +1030371static int protocol_v1_ack(struct mbox_context *context,
372 struct protocol_ack *io)
Andrew Jefferyc5c83042018-08-07 23:22:05 +0930373{
Andrew Jeffery2ebfd202018-08-20 11:46:28 +0930374 return protocol_events_clear(context,
375 (io->req.flags & BMC_EVENT_ACK_MASK));
Andrew Jefferyc5c83042018-08-07 23:22:05 +0930376}
377
Andrew Jeffery22fa5002018-08-07 15:22:50 +0930378/*
Andrew Jeffery1e531af2018-08-07 13:32:57 +0930379 * get_suggested_timeout() - get the suggested timeout value in seconds
380 * @context: The mbox context pointer
381 *
382 * Return: Suggested timeout in seconds
383 */
384static uint16_t get_suggested_timeout(struct mbox_context *context)
385{
386 struct window_context *window = windows_find_largest(context);
387 uint32_t max_size_mb = window ? (window->size >> 20) : 0;
388 uint16_t ret;
389
390 ret = align_up(max_size_mb * FLASH_ACCESS_MS_PER_MB, 1000) / 1000;
391
392 MSG_DBG("Suggested Timeout: %us, max window size: %uMB, for %dms/MB\n",
393 ret, max_size_mb, FLASH_ACCESS_MS_PER_MB);
394 return ret;
395}
396
Andrew Jefferycb935042019-03-15 09:54:33 +1030397static int protocol_v2_get_info(struct mbox_context *context,
398 struct protocol_get_info *io)
Andrew Jeffery1e531af2018-08-07 13:32:57 +0930399{
400 uint8_t old_version = context->version;
401 int rc;
402
403 /* Bootstrap protocol version. This may involve {up,down}grading */
404 rc = protocol_negotiate_version(context, io->req.api_version);
405 if (rc < 0)
406 return rc;
407
408 /* Do the {up,down}grade if necessary*/
409 if (rc != old_version) {
Andrew Jeffery2ebfd202018-08-20 11:46:28 +0930410 /* Doing version negotiation, don't alert host to reset */
411 windows_reset_all(context);
Andrew Jeffery1e531af2018-08-07 13:32:57 +0930412 return context->protocol->get_info(context, io);
413 }
414
415 /* Record the negotiated version for the response */
416 io->resp.api_version = rc;
417
418 /* Now do all required intialisation for v2 */
419 context->block_size_shift = log_2(context->mtd_info.erasesize);
420 MSG_INFO("Block Size: 0x%.8x (shift: %u)\n",
421 1 << context->block_size_shift, context->block_size_shift);
422
423 /* Knowing blocksize we can allocate the window dirty_bytemap */
424 windows_alloc_dirty_bytemap(context);
425
426 io->resp.v2.block_size_shift = context->block_size_shift;
427 io->resp.v2.timeout = get_suggested_timeout(context);
428
429 return lpc_map_memory(context);
430}
431
Andrew Jefferycb935042019-03-15 09:54:33 +1030432static int protocol_v2_get_flash_info(struct mbox_context *context,
433 struct protocol_get_flash_info *io)
Andrew Jeffery91a87452018-08-07 14:54:14 +0930434{
435 io->resp.v2.flash_size =
436 context->flash_size >> context->block_size_shift;
437 io->resp.v2.erase_size =
438 context->mtd_info.erasesize >> context->block_size_shift;
439
440 return 0;
441}
442
Andrew Jefferycb935042019-03-15 09:54:33 +1030443static int protocol_v2_create_window(struct mbox_context *context,
444 struct protocol_create_window *io)
Andrew Jeffery22fa5002018-08-07 15:22:50 +0930445{
446 int rc;
447
Andrew Jeffery4bcec8e2018-08-07 15:33:41 +0930448 rc = protocol_v1_create_window(context, io);
Andrew Jeffery22fa5002018-08-07 15:22:50 +0930449 if (rc < 0)
450 return rc;
451
452 io->resp.size = context->current->size >> context->block_size_shift;
453 io->resp.offset = context->current->flash_offset >>
454 context->block_size_shift;
455
456 return 0;
457}
458
Andrew Jefferycb935042019-03-15 09:54:33 +1030459static int protocol_v2_mark_dirty(struct mbox_context *context,
460 struct protocol_mark_dirty *io)
Andrew Jefferya336e432018-08-07 16:00:40 +0930461{
462 if (!(context->current && context->current_is_write)) {
463 MSG_ERR("Tried to call mark dirty without open write window\n");
464 return -EPERM;
465 }
466
467 MSG_INFO("Dirty window @ 0x%.8x for 0x%.8x\n",
468 io->req.v2.offset << context->block_size_shift,
469 io->req.v2.size << context->block_size_shift);
470
471 return window_set_bytemap(context, context->current, io->req.v2.offset,
472 io->req.v2.size, WINDOW_DIRTY);
473}
474
Andrew Jefferycb935042019-03-15 09:54:33 +1030475static int protocol_v2_erase(struct mbox_context *context,
476 struct protocol_erase *io)
Andrew Jeffery62a3daa2018-08-07 22:30:32 +0930477{
478 size_t start, len;
479 int rc;
480
481 if (!(context->current && context->current_is_write)) {
482 MSG_ERR("Tried to call erase without open write window\n");
483 return -EPERM;
484 }
485
486 MSG_INFO("Erase window @ 0x%.8x for 0x%.8x\n",
487 io->req.offset << context->block_size_shift,
488 io->req.size << context->block_size_shift);
489
490 rc = window_set_bytemap(context, context->current, io->req.offset,
491 io->req.size, WINDOW_ERASED);
492 if (rc < 0) {
493 return rc;
494 }
495
496 /* Write 0xFF to mem -> This ensures consistency between flash & ram */
497 start = io->req.offset << context->block_size_shift;
498 len = io->req.size << context->block_size_shift;
499 memset(context->current->mem + start, 0xFF, len);
500
501 return 0;
502}
503
Andrew Jefferycb935042019-03-15 09:54:33 +1030504static int protocol_v2_flush(struct mbox_context *context,
505 struct protocol_flush *io)
Andrew Jeffery9b920cf2018-08-07 22:49:19 +0930506{
507 if (!(context->current && context->current_is_write)) {
508 MSG_ERR("Tried to call flush without open write window\n");
509 return -EPERM;
510 }
511
512 return generic_flush(context);
513}
514
Andrew Jefferycb935042019-03-15 09:54:33 +1030515static int protocol_v2_close(struct mbox_context *context,
516 struct protocol_close *io)
Andrew Jeffery093eda52018-08-07 23:10:43 +0930517{
518 int rc;
519
520 /* Close the current window if there is one */
521 if (!context->current) {
522 return 0;
523 }
524
525 /* There is an implicit flush if it was a write window */
526 if (context->current_is_write) {
527 rc = protocol_v2_flush(context, NULL);
528 if (rc < 0) {
529 MSG_ERR("Couldn't Flush Write Window\n");
530 return rc;
531 }
532 }
533
534 /* Host asked for it -> Don't set the BMC Event */
Andrew Jeffery2ebfd202018-08-20 11:46:28 +0930535 windows_close_current(context, io->req.flags);
Andrew Jeffery093eda52018-08-07 23:10:43 +0930536
537 return 0;
538}
539
Andrew Jefferycb935042019-03-15 09:54:33 +1030540static const struct protocol_ops protocol_ops_v1 = {
541 .reset = protocol_v1_reset,
542 .get_info = protocol_v1_get_info,
543 .get_flash_info = protocol_v1_get_flash_info,
544 .create_window = protocol_v1_create_window,
545 .mark_dirty = protocol_v1_mark_dirty,
546 .erase = NULL,
547 .flush = protocol_v1_flush,
548 .close = protocol_v1_close,
549 .ack = protocol_v1_ack,
550};
551
552static const struct protocol_ops protocol_ops_v2 = {
553 .reset = protocol_v1_reset,
554 .get_info = protocol_v2_get_info,
555 .get_flash_info = protocol_v2_get_flash_info,
556 .create_window = protocol_v2_create_window,
557 .mark_dirty = protocol_v2_mark_dirty,
558 .erase = protocol_v2_erase,
559 .flush = protocol_v2_flush,
560 .close = protocol_v2_close,
561 .ack = protocol_v1_ack,
562};
563
564static const struct protocol_ops *protocol_ops_map[] = {
565 [0] = NULL,
566 [1] = &protocol_ops_v1,
567 [2] = &protocol_ops_v2,
568};
569
570static int protocol_negotiate_version(struct mbox_context *context,
571 uint8_t requested)
572{
573 /* Check we support the version requested */
574 if (requested < API_MIN_VERSION)
575 return -EINVAL;
576
577 context->version = (requested > API_MAX_VERSION) ?
578 API_MAX_VERSION : requested;
579
580 context->protocol = protocol_ops_map[context->version];
581
582 return context->version;
583}
584
Andrew Jeffery1e531af2018-08-07 13:32:57 +0930585int protocol_init(struct mbox_context *context)
586{
Andrew Jefferyc7d19472018-08-08 11:43:08 +0930587 protocol_negotiate_version(context, API_MAX_VERSION);
Andrew Jeffery1e531af2018-08-07 13:32:57 +0930588
589 return 0;
590}
591
592void protocol_free(struct mbox_context *context)
593{
594 return;
595}
Andrew Jefferyf69760d2019-03-14 16:54:13 +1030596
597/* Don't do any state manipulation, just perform the reset */
598int __protocol_reset(struct mbox_context *context)
599{
600 windows_reset_all(context);
601
602 return lpc_reset(context);
603}
604
605/* Prevent the host from performing actions whilst reset takes place */
606int protocol_reset(struct mbox_context *context)
607{
608 int rc;
609
610 rc = protocol_events_clear(context, BMC_EVENT_DAEMON_READY);
611 if (rc < 0) {
612 MSG_ERR("Failed to clear daemon ready state, reset failed\n");
613 return rc;
614 }
615
616 rc = __protocol_reset(context);
617 if (rc < 0) {
618 MSG_ERR("Failed to reset protocol, daemon remains not ready\n");
619 return rc;
620 }
621
622 rc = protocol_events_set(context,
623 BMC_EVENT_DAEMON_READY | BMC_EVENT_PROTOCOL_RESET);
624 if (rc < 0) {
625 MSG_ERR("Failed to set daemon ready state, daemon remains not ready\n");
626 return rc;
627 }
628
629 return 0;
630}