blob: b0e9e23db75f662c8a82c1650082224f47f8dee4 [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
8#include "mbox.h"
9#include "lpc.h"
10#include "transport_mbox.h" /* TODO: Remove dependency on transport_mbox.h */
11#include "windows.h"
12
Andrew Jefferyab666a52018-08-07 14:28:09 +093013int protocol_v1_reset(struct mbox_context *context)
14{
15 /* Host requested it -> No BMC Event */
16 windows_reset_all(context, NO_BMC_EVENT);
17 return lpc_reset(context);
18}
19
Andrew Jeffery1e531af2018-08-07 13:32:57 +093020int protocol_v1_get_info(struct mbox_context *context,
21 struct protocol_get_info *io)
22{
23 uint8_t old_version = context->version;
24 int rc;
25
26 /* Bootstrap protocol version. This may involve {up,down}grading */
27 rc = protocol_negotiate_version(context, io->req.api_version);
28 if (rc < 0)
29 return rc;
30
31 /* Do the {up,down}grade if necessary*/
32 if (rc != old_version) {
33 windows_reset_all(context, SET_BMC_EVENT);
34 return context->protocol->get_info(context, io);
35 }
36
37 /* Record the negotiated version for the response */
38 io->resp.api_version = rc;
39
40 /* Now do all required intialisation for v1 */
41 context->block_size_shift = BLOCK_SIZE_SHIFT_V1;
42 MSG_INFO("Block Size: 0x%.8x (shift: %u)\n",
43 1 << context->block_size_shift, context->block_size_shift);
44
45 /* Knowing blocksize we can allocate the window dirty_bytemap */
46 windows_alloc_dirty_bytemap(context);
47
48 io->resp.v1.read_window_size =
49 context->windows.default_size >> context->block_size_shift;
50 io->resp.v1.write_window_size =
51 context->windows.default_size >> context->block_size_shift;
52
53 return lpc_map_memory(context);
54}
55
56/*
57 * get_suggested_timeout() - get the suggested timeout value in seconds
58 * @context: The mbox context pointer
59 *
60 * Return: Suggested timeout in seconds
61 */
62static uint16_t get_suggested_timeout(struct mbox_context *context)
63{
64 struct window_context *window = windows_find_largest(context);
65 uint32_t max_size_mb = window ? (window->size >> 20) : 0;
66 uint16_t ret;
67
68 ret = align_up(max_size_mb * FLASH_ACCESS_MS_PER_MB, 1000) / 1000;
69
70 MSG_DBG("Suggested Timeout: %us, max window size: %uMB, for %dms/MB\n",
71 ret, max_size_mb, FLASH_ACCESS_MS_PER_MB);
72 return ret;
73}
74
75int protocol_v2_get_info(struct mbox_context *context,
76 struct protocol_get_info *io)
77{
78 uint8_t old_version = context->version;
79 int rc;
80
81 /* Bootstrap protocol version. This may involve {up,down}grading */
82 rc = protocol_negotiate_version(context, io->req.api_version);
83 if (rc < 0)
84 return rc;
85
86 /* Do the {up,down}grade if necessary*/
87 if (rc != old_version) {
88 windows_reset_all(context, SET_BMC_EVENT);
89 return context->protocol->get_info(context, io);
90 }
91
92 /* Record the negotiated version for the response */
93 io->resp.api_version = rc;
94
95 /* Now do all required intialisation for v2 */
96 context->block_size_shift = log_2(context->mtd_info.erasesize);
97 MSG_INFO("Block Size: 0x%.8x (shift: %u)\n",
98 1 << context->block_size_shift, context->block_size_shift);
99
100 /* Knowing blocksize we can allocate the window dirty_bytemap */
101 windows_alloc_dirty_bytemap(context);
102
103 io->resp.v2.block_size_shift = context->block_size_shift;
104 io->resp.v2.timeout = get_suggested_timeout(context);
105
106 return lpc_map_memory(context);
107}
108
109static const struct protocol_ops protocol_ops_v1 = {
Andrew Jefferyab666a52018-08-07 14:28:09 +0930110 .reset = protocol_v1_reset,
Andrew Jeffery1e531af2018-08-07 13:32:57 +0930111 .get_info = protocol_v1_get_info,
112};
113
114static const struct protocol_ops protocol_ops_v2 = {
Andrew Jefferyab666a52018-08-07 14:28:09 +0930115 .reset = protocol_v1_reset,
Andrew Jeffery1e531af2018-08-07 13:32:57 +0930116 .get_info = protocol_v2_get_info,
117};
118
119static const struct protocol_ops *protocol_ops_map[] = {
120 [0] = NULL,
121 [1] = &protocol_ops_v1,
122 [2] = &protocol_ops_v2,
123};
124
125int protocol_negotiate_version(struct mbox_context *context,
126 uint8_t requested)
127{
128 /* Check we support the version requested */
129 if (requested < API_MIN_VERSION)
130 return -EINVAL;
131
132 context->version = (requested > API_MAX_VERSION) ?
133 API_MAX_VERSION : requested;
134
135 context->protocol = protocol_ops_map[context->version];
136
137 return context->version;
138}
139
140int protocol_init(struct mbox_context *context)
141{
142 context->version = API_MAX_VERSION;
143 context->protocol = protocol_ops_map[context->version];
144
145 return 0;
146}
147
148void protocol_free(struct mbox_context *context)
149{
150 return;
151}