1 // 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 13 int 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 */ 55 static 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 68 int 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 102 static const struct protocol_ops protocol_ops_v1 = { 103 .get_info = protocol_v1_get_info, 104 }; 105 106 static const struct protocol_ops protocol_ops_v2 = { 107 .get_info = protocol_v2_get_info, 108 }; 109 110 static const struct protocol_ops *protocol_ops_map[] = { 111 [0] = NULL, 112 [1] = &protocol_ops_v1, 113 [2] = &protocol_ops_v2, 114 }; 115 116 int 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 131 int 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 139 void protocol_free(struct mbox_context *context) 140 { 141 return; 142 } 143