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