1// SPDX-License-Identifier: GPL-2.0 2/* 3 * Copyright (C) 2018-2022 Marvell International Ltd. 4 * 5 * PKI Support. 6 */ 7 8#include <time.h> 9#include <log.h> 10#include <linux/delay.h> 11 12#include <mach/cvmx-regs.h> 13#include <mach/cvmx-csr.h> 14#include <mach/cvmx-bootmem.h> 15#include <mach/octeon-model.h> 16#include <mach/cvmx-fuse.h> 17#include <mach/octeon-feature.h> 18#include <mach/cvmx-qlm.h> 19#include <mach/octeon_qlm.h> 20#include <mach/cvmx-pcie.h> 21#include <mach/cvmx-coremask.h> 22 23#include <mach/cvmx-global-resources.h> 24 25#include <mach/cvmx-pki-defs.h> 26#include <mach/cvmx-pko-defs.h> 27 28#include <mach/cvmx-pki.h> 29#include <mach/cvmx-helper.h> 30#include <mach/cvmx-helper-board.h> 31#include <mach/cvmx-helper-cfg.h> 32 33static s32 cvmx_pki_style_refcnt[CVMX_MAX_NODES][CVMX_PKI_NUM_INTERNAL_STYLE]; 34 35/** 36 * This function allocates/reserves a style from pool of global styles per node. 37 * @param node node to allocate style from. 38 * @param style style to allocate, if -1 it will be allocated 39 * first available style from style resource. If index is positive 40 * number and in range, it will try to allocate specified style. 41 * @return style number on success, 42 * -1 on alloc failure. 43 * -2 on resource already reserved. 44 */ 45int cvmx_pki_style_alloc(int node, int style) 46{ 47 int rs; 48 49 if (cvmx_create_global_resource_range(CVMX_GR_TAG_STYLE(node), 50 CVMX_PKI_NUM_INTERNAL_STYLE)) { 51 printf("ERROR: Failed to create styles global resource\n"); 52 return -1; 53 } 54 if (style >= 0) { 55 /* Reserving specific style, use refcnt for sharing */ 56 rs = cvmx_atomic_fetch_and_add32( 57 &cvmx_pki_style_refcnt[node][style], 1); 58 if (rs > 0) 59 return CVMX_RESOURCE_ALREADY_RESERVED; 60 61 rs = cvmx_reserve_global_resource_range(CVMX_GR_TAG_STYLE(node), 62 style, style, 1); 63 if (rs == -1) { 64 /* This means the style is taken by another app */ 65 printf("ERROR: style %d is reserved by another app\n", 66 style); 67 cvmx_atomic_fetch_and_add32( 68 &cvmx_pki_style_refcnt[node][style], -1); 69 return CVMX_RESOURCE_ALLOC_FAILED; 70 } 71 } else { 72 /* Allocate first available style */ 73 rs = cvmx_allocate_global_resource_range( 74 CVMX_GR_TAG_STYLE(node), style, 1, 1); 75 if (rs < 0) { 76 printf("ERROR: Failed to allocate style, none available\n"); 77 return CVMX_RESOURCE_ALLOC_FAILED; 78 } 79 style = rs; 80 /* Increment refcnt for newly created style */ 81 cvmx_atomic_fetch_and_add32(&cvmx_pki_style_refcnt[node][style], 82 1); 83 } 84 return style; 85} 86 87/** 88 * This function frees a style from pool of global styles per node. 89 * @param node node to free style from. 90 * @param style style to free 91 * @return 0 on success, -1 on failure or 92 * if the style is shared a positive count of remaining users for this style. 93 */ 94int cvmx_pki_style_free(int node, int style) 95{ 96 int rs; 97 98 rs = cvmx_atomic_fetch_and_add32(&cvmx_pki_style_refcnt[node][style], 99 -1); 100 if (rs > 1) 101 return rs - 1; 102 103 if (cvmx_free_global_resource_range_with_base(CVMX_GR_TAG_STYLE(node), 104 style, 1) == -1) { 105 printf("ERROR Failed to release style %d\n", (int)style); 106 return -1; 107 } 108 return 0; 109} 110 111/** 112 * This function allocates/reserves a cluster group from per node 113 cluster group resources. 114 * @param node node to allocate cluster group from. 115 @param cl_grp cluster group to allocate/reserve, if -1 , 116 * allocate any available cluster group. 117 * @return cluster group number 118 * -1 on alloc failure. 119 * -2 on resource already reserved. 120 */ 121int cvmx_pki_cluster_grp_alloc(int node, int cl_grp) 122{ 123 int rs; 124 125 if (node >= CVMX_MAX_NODES) { 126 printf("ERROR: Invalid node number %d\n", node); 127 return -1; 128 } 129 if (cvmx_create_global_resource_range(CVMX_GR_TAG_CLUSTER_GRP(node), 130 CVMX_PKI_NUM_CLUSTER_GROUP)) { 131 printf("ERROR: Failed to create Cluster group global resource\n"); 132 return -1; 133 } 134 if (cl_grp >= 0) { 135 rs = cvmx_reserve_global_resource_range( 136 CVMX_GR_TAG_CLUSTER_GRP(node), 0, cl_grp, 1); 137 if (rs == -1) { 138 debug("INFO: cl_grp %d is already reserved\n", 139 (int)cl_grp); 140 return CVMX_RESOURCE_ALREADY_RESERVED; 141 } 142 } else { 143 rs = cvmx_allocate_global_resource_range( 144 CVMX_GR_TAG_CLUSTER_GRP(node), 0, 1, 1); 145 if (rs == -1) { 146 debug("Warning: Failed to alloc cluster grp\n"); 147 return CVMX_RESOURCE_ALLOC_FAILED; 148 } 149 } 150 cl_grp = rs; 151 return cl_grp; 152} 153 154/** 155 * This function allocates/reserves a pcam entry from node 156 * @param node node to allocate pcam entry from. 157 * @param index index of pacm entry (0-191), if -1 , 158 * allocate any available pcam entry. 159 * @param bank pcam bank where to allocate/reserve pcan entry from 160 * @param cluster_mask mask of clusters from which pcam entry is needed. 161 * @return pcam entry of -1 on failure 162 */ 163int cvmx_pki_pcam_entry_alloc(int node, int index, int bank, u64 cluster_mask) 164{ 165 int rs = 0; 166 unsigned int cluster; 167 168 for (cluster = 0; cluster < CVMX_PKI_NUM_CLUSTER; cluster++) { 169 if ((cluster_mask & (1 << cluster)) == 0) 170 continue; 171 rs = cvmx_create_global_resource_range( 172 CVMX_GR_TAG_PCAM(node, cluster, bank), 173 CVMX_PKI_TOTAL_PCAM_ENTRY); 174 if (rs != 0) { 175 printf("ERROR: Failed to create pki pcam global resource\n"); 176 return -1; 177 } 178 if (index >= 0) 179 rs = cvmx_reserve_global_resource_range( 180 CVMX_GR_TAG_PCAM(node, cluster, bank), cluster, 181 index, 1); 182 else 183 rs = cvmx_allocate_global_resource_range( 184 CVMX_GR_TAG_PCAM(node, cluster, bank), cluster, 185 1, 1); 186 if (rs == -1) { 187 printf("ERROR: PCAM :index %d not available in cluster %d bank %d", 188 (int)index, (int)cluster, bank); 189 return -1; 190 } 191 } /* for cluster */ 192 index = rs; 193 /* implement cluster handle for pass2, for now assume 194 all clusters will have same base index*/ 195 return index; 196} 197 198/** 199 * This function allocates/reserves QPG table entries per node. 200 * @param node node number. 201 * @param base_offset base_offset in qpg table. If -1, first available 202 * qpg base_offset will be allocated. If base_offset is positive 203 * number and in range, it will try to allocate specified base_offset. 204 * @param count number of consecutive qpg entries to allocate. They will be consecutive 205 * from base offset. 206 * @return qpg table base offset number on success 207 * -1 on alloc failure. 208 * -2 on resource already reserved. 209 */ 210int cvmx_pki_qpg_entry_alloc(int node, int base_offset, int count) 211{ 212 int rs; 213 214 if (cvmx_create_global_resource_range(CVMX_GR_TAG_QPG_ENTRY(node), 215 CVMX_PKI_NUM_QPG_ENTRY)) { 216 printf("ERROR: Failed to create qpg_entry global resource\n"); 217 return -1; 218 } 219 if (base_offset >= 0) { 220 rs = cvmx_reserve_global_resource_range( 221 CVMX_GR_TAG_QPG_ENTRY(node), base_offset, base_offset, 222 count); 223 if (rs == -1) { 224 debug("INFO: qpg entry %d is already reserved\n", 225 (int)base_offset); 226 return CVMX_RESOURCE_ALREADY_RESERVED; 227 } 228 } else { 229 rs = cvmx_allocate_global_resource_range( 230 CVMX_GR_TAG_QPG_ENTRY(node), base_offset, count, 1); 231 if (rs == -1) { 232 printf("ERROR: Failed to allocate qpg entry\n"); 233 return CVMX_RESOURCE_ALLOC_FAILED; 234 } 235 } 236 base_offset = rs; 237 return base_offset; 238} 239 240/** 241 * This function frees QPG table entries per node. 242 * @param node node number. 243 * @param base_offset base_offset in qpg table. If -1, first available 244 * qpg base_offset will be allocated. If base_offset is positive 245 * number and in range, it will try to allocate specified base_offset. 246 * @param count number of consecutive qpg entries to allocate. They will be consecutive 247 * from base offset. 248 * @return qpg table base offset number on success, -1 on failure. 249 */ 250int cvmx_pki_qpg_entry_free(int node, int base_offset, int count) 251{ 252 if (cvmx_free_global_resource_range_with_base( 253 CVMX_GR_TAG_QPG_ENTRY(node), base_offset, count) == -1) { 254 printf("ERROR Failed to release qpg offset %d", 255 (int)base_offset); 256 return -1; 257 } 258 return 0; 259} 260 261int cvmx_pki_mtag_idx_alloc(int node, int idx) 262{ 263 if (cvmx_create_global_resource_range(CVMX_GR_TAG_MTAG_IDX(node), 264 CVMX_PKI_NUM_MTAG_IDX)) { 265 printf("ERROR: Failed to create MTAG-IDX global resource\n"); 266 return -1; 267 } 268 if (idx >= 0) { 269 idx = cvmx_reserve_global_resource_range( 270 CVMX_GR_TAG_MTAG_IDX(node), idx, idx, 1); 271 if (idx == -1) { 272 debug("INFO: MTAG index %d is already reserved\n", 273 (int)idx); 274 return CVMX_RESOURCE_ALREADY_RESERVED; 275 } 276 } else { 277 idx = cvmx_allocate_global_resource_range( 278 CVMX_GR_TAG_MTAG_IDX(node), idx, 1, 1); 279 if (idx == -1) { 280 printf("ERROR: Failed to allocate MTAG index\n"); 281 return CVMX_RESOURCE_ALLOC_FAILED; 282 } 283 } 284 return idx; 285} 286