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-agl-defs.h> 24#include <mach/cvmx-bgxx-defs.h> 25#include <mach/cvmx-ciu-defs.h> 26#include <mach/cvmx-gmxx-defs.h> 27#include <mach/cvmx-gserx-defs.h> 28#include <mach/cvmx-ilk-defs.h> 29#include <mach/cvmx-ipd-defs.h> 30#include <mach/cvmx-pcsx-defs.h> 31#include <mach/cvmx-pcsxx-defs.h> 32#include <mach/cvmx-pki-defs.h> 33#include <mach/cvmx-pko-defs.h> 34#include <mach/cvmx-xcv-defs.h> 35 36#include <mach/cvmx-hwpko.h> 37#include <mach/cvmx-ilk.h> 38#include <mach/cvmx-pki.h> 39#include <mach/cvmx-pki-cluster.h> 40#include <mach/cvmx-pki-resources.h> 41 42#include <mach/cvmx-helper.h> 43#include <mach/cvmx-helper-board.h> 44#include <mach/cvmx-helper-cfg.h> 45 46/** 47 * This function enables PKI 48 * 49 * @param node Node to enable PKI. 50 */ 51void cvmx_pki_enable(int node) 52{ 53 cvmx_pki_sft_rst_t sft_rst; 54 cvmx_pki_buf_ctl_t buf_ctl; 55 56 sft_rst.u64 = csr_rd_node(node, CVMX_PKI_SFT_RST); 57 while (sft_rst.s.busy != 0) 58 sft_rst.u64 = csr_rd_node(node, CVMX_PKI_SFT_RST); 59 60 buf_ctl.u64 = csr_rd_node(node, CVMX_PKI_BUF_CTL); 61 if (buf_ctl.s.pki_en) 62 debug("Warning: Enabling PKI when PKI already enabled.\n"); 63 64 buf_ctl.s.pki_en = 1; 65 csr_wr_node(node, CVMX_PKI_BUF_CTL, buf_ctl.u64); 66} 67 68/** 69 * This function sets the clusters in PKI. 70 * 71 * @param node Node to set clusters. 72 */ 73int cvmx_pki_setup_clusters(int node) 74{ 75 int i; 76 77 for (i = 0; i < cvmx_pki_cluster_code_length; i++) 78 csr_wr_node(node, CVMX_PKI_IMEMX(i), 79 cvmx_pki_cluster_code_default[i]); 80 81 return 0; 82} 83 84/** 85 * This function reads global configuration of PKI block. 86 * 87 * @param node Node number. 88 * @param gbl_cfg Pointer to struct to read global configuration. 89 */ 90void cvmx_pki_read_global_config(int node, 91 struct cvmx_pki_global_config *gbl_cfg) 92{ 93 cvmx_pki_stat_ctl_t stat_ctl; 94 cvmx_pki_icgx_cfg_t icg_cfg; 95 cvmx_pki_gbl_pen_t gbl_pen; 96 cvmx_pki_tag_secret_t tag_secret; 97 cvmx_pki_frm_len_chkx_t frm_len_chk; 98 cvmx_pki_buf_ctl_t buf_ctl; 99 unsigned int cl_grp; 100 int id; 101 102 stat_ctl.u64 = csr_rd_node(node, CVMX_PKI_STAT_CTL); 103 gbl_cfg->stat_mode = stat_ctl.s.mode; 104 105 for (cl_grp = 0; cl_grp < CVMX_PKI_NUM_CLUSTER_GROUP; cl_grp++) { 106 icg_cfg.u64 = csr_rd_node(node, CVMX_PKI_ICGX_CFG(cl_grp)); 107 gbl_cfg->cluster_mask[cl_grp] = icg_cfg.s.clusters; 108 } 109 gbl_pen.u64 = csr_rd_node(node, CVMX_PKI_GBL_PEN); 110 gbl_cfg->gbl_pen.virt_pen = gbl_pen.s.virt_pen; 111 gbl_cfg->gbl_pen.clg_pen = gbl_pen.s.clg_pen; 112 gbl_cfg->gbl_pen.cl2_pen = gbl_pen.s.cl2_pen; 113 gbl_cfg->gbl_pen.l4_pen = gbl_pen.s.l4_pen; 114 gbl_cfg->gbl_pen.il3_pen = gbl_pen.s.il3_pen; 115 gbl_cfg->gbl_pen.l3_pen = gbl_pen.s.l3_pen; 116 gbl_cfg->gbl_pen.mpls_pen = gbl_pen.s.mpls_pen; 117 gbl_cfg->gbl_pen.fulc_pen = gbl_pen.s.fulc_pen; 118 gbl_cfg->gbl_pen.dsa_pen = gbl_pen.s.dsa_pen; 119 gbl_cfg->gbl_pen.hg_pen = gbl_pen.s.hg_pen; 120 121 tag_secret.u64 = csr_rd_node(node, CVMX_PKI_TAG_SECRET); 122 gbl_cfg->tag_secret.dst6 = tag_secret.s.dst6; 123 gbl_cfg->tag_secret.src6 = tag_secret.s.src6; 124 gbl_cfg->tag_secret.dst = tag_secret.s.dst; 125 gbl_cfg->tag_secret.src = tag_secret.s.src; 126 127 for (id = 0; id < CVMX_PKI_NUM_FRAME_CHECK; id++) { 128 frm_len_chk.u64 = csr_rd_node(node, CVMX_PKI_FRM_LEN_CHKX(id)); 129 gbl_cfg->frm_len[id].maxlen = frm_len_chk.s.maxlen; 130 gbl_cfg->frm_len[id].minlen = frm_len_chk.s.minlen; 131 } 132 buf_ctl.u64 = csr_rd_node(node, CVMX_PKI_BUF_CTL); 133 gbl_cfg->fpa_wait = buf_ctl.s.fpa_wait; 134} 135 136/** 137 * This function writes max and min frame lengths to hardware which can be used 138 * to check the size of frame arrived.There are 2 possible combination which are 139 * indicated by id field. 140 * 141 * @param node Node number. 142 * @param id Choose which frame len register to write to 143 * @param len_chk Struct containing byte count for max-sized/min-sized frame check. 144 */ 145static void cvmx_pki_write_frame_len(int node, int id, 146 struct cvmx_pki_frame_len len_chk) 147{ 148 cvmx_pki_frm_len_chkx_t frm_len_chk; 149 150 frm_len_chk.u64 = csr_rd_node(node, CVMX_PKI_FRM_LEN_CHKX(id)); 151 frm_len_chk.s.maxlen = len_chk.maxlen; 152 frm_len_chk.s.minlen = len_chk.minlen; 153 csr_wr_node(node, CVMX_PKI_FRM_LEN_CHKX(id), frm_len_chk.u64); 154} 155 156/** 157 * This function writes global configuration of PKI into hw. 158 * 159 * @param node Node number. 160 * @param gbl_cfg Pointer to struct to global configuration. 161 */ 162void cvmx_pki_write_global_config(int node, 163 struct cvmx_pki_global_config *gbl_cfg) 164{ 165 cvmx_pki_stat_ctl_t stat_ctl; 166 cvmx_pki_buf_ctl_t buf_ctl; 167 unsigned int cl_grp; 168 169 for (cl_grp = 0; cl_grp < CVMX_PKI_NUM_CLUSTER_GROUP; cl_grp++) 170 cvmx_pki_attach_cluster_to_group(node, cl_grp, 171 gbl_cfg->cluster_mask[cl_grp]); 172 173 stat_ctl.u64 = 0; 174 stat_ctl.s.mode = gbl_cfg->stat_mode; 175 csr_wr_node(node, CVMX_PKI_STAT_CTL, stat_ctl.u64); 176 177 buf_ctl.u64 = csr_rd_node(node, CVMX_PKI_BUF_CTL); 178 buf_ctl.s.fpa_wait = gbl_cfg->fpa_wait; 179 csr_wr_node(node, CVMX_PKI_BUF_CTL, buf_ctl.u64); 180 181 cvmx_pki_write_global_parse(node, gbl_cfg->gbl_pen); 182 cvmx_pki_write_tag_secret(node, gbl_cfg->tag_secret); 183 cvmx_pki_write_frame_len(node, 0, gbl_cfg->frm_len[0]); 184 cvmx_pki_write_frame_len(node, 1, gbl_cfg->frm_len[1]); 185} 186 187/** 188 * This function reads per pkind parameters in hardware which defines how 189 * the incoming packet is processed. 190 * 191 * @param node Node number. 192 * @param pkind PKI supports a large number of incoming interfaces and packets 193 * arriving on different interfaces or channels may want to be processed 194 * differently. PKI uses the pkind to determine how the incoming packet 195 * is processed. 196 * @param pkind_cfg Pointer to struct conatining pkind configuration read 197 * from the hardware. 198 */ 199int cvmx_pki_read_pkind_config(int node, int pkind, 200 struct cvmx_pki_pkind_config *pkind_cfg) 201{ 202 int cluster = 0; 203 u64 cl_mask; 204 cvmx_pki_pkindx_icgsel_t icgsel; 205 cvmx_pki_clx_pkindx_style_t pstyle; 206 cvmx_pki_icgx_cfg_t icg_cfg; 207 cvmx_pki_clx_pkindx_cfg_t pcfg; 208 cvmx_pki_clx_pkindx_skip_t skip; 209 cvmx_pki_clx_pkindx_l2_custom_t l2cust; 210 cvmx_pki_clx_pkindx_lg_custom_t lgcust; 211 212 icgsel.u64 = csr_rd_node(node, CVMX_PKI_PKINDX_ICGSEL(pkind)); 213 icg_cfg.u64 = csr_rd_node(node, CVMX_PKI_ICGX_CFG(icgsel.s.icg)); 214 pkind_cfg->cluster_grp = (uint8_t)icgsel.s.icg; 215 cl_mask = (uint64_t)icg_cfg.s.clusters; 216 cluster = __builtin_ffsll(cl_mask) - 1; 217 218 pstyle.u64 = 219 csr_rd_node(node, CVMX_PKI_CLX_PKINDX_STYLE(pkind, cluster)); 220 pkind_cfg->initial_parse_mode = pstyle.s.pm; 221 pkind_cfg->initial_style = pstyle.s.style; 222 223 pcfg.u64 = csr_rd_node(node, CVMX_PKI_CLX_PKINDX_CFG(pkind, cluster)); 224 pkind_cfg->fcs_pres = pcfg.s.fcs_pres; 225 pkind_cfg->parse_en.inst_hdr = pcfg.s.inst_hdr; 226 pkind_cfg->parse_en.mpls_en = pcfg.s.mpls_en; 227 pkind_cfg->parse_en.lg_custom = pcfg.s.lg_custom; 228 pkind_cfg->parse_en.fulc_en = pcfg.s.fulc_en; 229 pkind_cfg->parse_en.dsa_en = pcfg.s.dsa_en; 230 pkind_cfg->parse_en.hg2_en = pcfg.s.hg2_en; 231 pkind_cfg->parse_en.hg_en = pcfg.s.hg_en; 232 233 skip.u64 = csr_rd_node(node, CVMX_PKI_CLX_PKINDX_SKIP(pkind, cluster)); 234 pkind_cfg->fcs_skip = skip.s.fcs_skip; 235 pkind_cfg->inst_skip = skip.s.inst_skip; 236 237 l2cust.u64 = csr_rd_node(node, 238 CVMX_PKI_CLX_PKINDX_L2_CUSTOM(pkind, cluster)); 239 pkind_cfg->l2_scan_offset = l2cust.s.offset; 240 241 lgcust.u64 = csr_rd_node(node, 242 CVMX_PKI_CLX_PKINDX_LG_CUSTOM(pkind, cluster)); 243 pkind_cfg->lg_scan_offset = lgcust.s.offset; 244 return 0; 245} 246 247/** 248 * This function writes per pkind parameters in hardware which defines how 249 * the incoming packet is processed. 250 * 251 * @param node Node number. 252 * @param pkind PKI supports a large number of incoming interfaces and packets 253 * arriving on different interfaces or channels may want to be processed 254 * differently. PKI uses the pkind to determine how the incoming 255 * packet is processed. 256 * @param pkind_cfg Pointer to struct conatining pkind configuration need 257 * to be written in the hardware. 258 */ 259int cvmx_pki_write_pkind_config(int node, int pkind, 260 struct cvmx_pki_pkind_config *pkind_cfg) 261{ 262 unsigned int cluster = 0; 263 u64 cluster_mask; 264 cvmx_pki_pkindx_icgsel_t icgsel; 265 cvmx_pki_clx_pkindx_style_t pstyle; 266 cvmx_pki_icgx_cfg_t icg_cfg; 267 cvmx_pki_clx_pkindx_cfg_t pcfg; 268 cvmx_pki_clx_pkindx_skip_t skip; 269 cvmx_pki_clx_pkindx_l2_custom_t l2cust; 270 cvmx_pki_clx_pkindx_lg_custom_t lgcust; 271 272 if (pkind >= CVMX_PKI_NUM_PKIND || 273 pkind_cfg->cluster_grp >= CVMX_PKI_NUM_CLUSTER_GROUP || 274 pkind_cfg->initial_style >= CVMX_PKI_NUM_FINAL_STYLE) { 275 debug("ERROR: Configuring PKIND pkind = %d cluster_group = %d style = %d\n", 276 pkind, pkind_cfg->cluster_grp, pkind_cfg->initial_style); 277 return -1; 278 } 279 icgsel.u64 = csr_rd_node(node, CVMX_PKI_PKINDX_ICGSEL(pkind)); 280 icgsel.s.icg = pkind_cfg->cluster_grp; 281 csr_wr_node(node, CVMX_PKI_PKINDX_ICGSEL(pkind), icgsel.u64); 282 283 icg_cfg.u64 = 284 csr_rd_node(node, CVMX_PKI_ICGX_CFG(pkind_cfg->cluster_grp)); 285 cluster_mask = (uint64_t)icg_cfg.s.clusters; 286 while (cluster < CVMX_PKI_NUM_CLUSTER) { 287 if (cluster_mask & (0x01L << cluster)) { 288 pstyle.u64 = csr_rd_node( 289 node, 290 CVMX_PKI_CLX_PKINDX_STYLE(pkind, cluster)); 291 pstyle.s.pm = pkind_cfg->initial_parse_mode; 292 pstyle.s.style = pkind_cfg->initial_style; 293 csr_wr_node(node, 294 CVMX_PKI_CLX_PKINDX_STYLE(pkind, cluster), 295 pstyle.u64); 296 297 pcfg.u64 = csr_rd_node( 298 node, CVMX_PKI_CLX_PKINDX_CFG(pkind, cluster)); 299 pcfg.s.fcs_pres = pkind_cfg->fcs_pres; 300 pcfg.s.inst_hdr = pkind_cfg->parse_en.inst_hdr; 301 pcfg.s.mpls_en = pkind_cfg->parse_en.mpls_en; 302 pcfg.s.lg_custom = pkind_cfg->parse_en.lg_custom; 303 pcfg.s.fulc_en = pkind_cfg->parse_en.fulc_en; 304 pcfg.s.dsa_en = pkind_cfg->parse_en.dsa_en; 305 pcfg.s.hg2_en = pkind_cfg->parse_en.hg2_en; 306 pcfg.s.hg_en = pkind_cfg->parse_en.hg_en; 307 csr_wr_node(node, 308 CVMX_PKI_CLX_PKINDX_CFG(pkind, cluster), 309 pcfg.u64); 310 311 skip.u64 = csr_rd_node( 312 node, CVMX_PKI_CLX_PKINDX_SKIP(pkind, cluster)); 313 skip.s.fcs_skip = pkind_cfg->fcs_skip; 314 skip.s.inst_skip = pkind_cfg->inst_skip; 315 csr_wr_node(node, 316 CVMX_PKI_CLX_PKINDX_SKIP(pkind, cluster), 317 skip.u64); 318 319 l2cust.u64 = csr_rd_node( 320 node, 321 CVMX_PKI_CLX_PKINDX_L2_CUSTOM(pkind, cluster)); 322 l2cust.s.offset = pkind_cfg->l2_scan_offset; 323 csr_wr_node(node, 324 CVMX_PKI_CLX_PKINDX_L2_CUSTOM(pkind, 325 cluster), 326 l2cust.u64); 327 328 lgcust.u64 = csr_rd_node( 329 node, 330 CVMX_PKI_CLX_PKINDX_LG_CUSTOM(pkind, cluster)); 331 lgcust.s.offset = pkind_cfg->lg_scan_offset; 332 csr_wr_node(node, 333 CVMX_PKI_CLX_PKINDX_LG_CUSTOM(pkind, 334 cluster), 335 lgcust.u64); 336 } 337 cluster++; 338 } 339 return 0; 340} 341 342/** 343 * This function reads parameters associated with tag configuration in hardware. 344 * Only first cluster in the group is used. 345 * 346 * @param node Node number. 347 * @param style Style to configure tag for. 348 * @param cluster_mask Mask of clusters to configure the style for. 349 * @param tag_cfg Pointer to tag configuration struct. 350 */ 351void cvmx_pki_read_tag_config(int node, int style, uint64_t cluster_mask, 352 struct cvmx_pki_style_tag_cfg *tag_cfg) 353{ 354 int mask, tag_idx, index; 355 cvmx_pki_clx_stylex_cfg2_t style_cfg2; 356 cvmx_pki_clx_stylex_alg_t style_alg; 357 cvmx_pki_stylex_tag_sel_t tag_sel; 358 cvmx_pki_tag_incx_ctl_t tag_ctl; 359 cvmx_pki_tag_incx_mask_t tag_mask; 360 int cluster = __builtin_ffsll(cluster_mask) - 1; 361 362 style_cfg2.u64 = 363 csr_rd_node(node, CVMX_PKI_CLX_STYLEX_CFG2(style, cluster)); 364 style_alg.u64 = 365 csr_rd_node(node, CVMX_PKI_CLX_STYLEX_ALG(style, cluster)); 366 367 /* 7-Tuple Tag: */ 368 tag_cfg->tag_fields.layer_g_src = style_cfg2.s.tag_src_lg; 369 tag_cfg->tag_fields.layer_f_src = style_cfg2.s.tag_src_lf; 370 tag_cfg->tag_fields.layer_e_src = style_cfg2.s.tag_src_le; 371 tag_cfg->tag_fields.layer_d_src = style_cfg2.s.tag_src_ld; 372 tag_cfg->tag_fields.layer_c_src = style_cfg2.s.tag_src_lc; 373 tag_cfg->tag_fields.layer_b_src = style_cfg2.s.tag_src_lb; 374 tag_cfg->tag_fields.layer_g_dst = style_cfg2.s.tag_dst_lg; 375 tag_cfg->tag_fields.layer_f_dst = style_cfg2.s.tag_dst_lf; 376 tag_cfg->tag_fields.layer_e_dst = style_cfg2.s.tag_dst_le; 377 tag_cfg->tag_fields.layer_d_dst = style_cfg2.s.tag_dst_ld; 378 tag_cfg->tag_fields.layer_c_dst = style_cfg2.s.tag_dst_lc; 379 tag_cfg->tag_fields.layer_b_dst = style_cfg2.s.tag_dst_lb; 380 tag_cfg->tag_fields.tag_vni = style_alg.s.tag_vni; 381 tag_cfg->tag_fields.tag_gtp = style_alg.s.tag_gtp; 382 tag_cfg->tag_fields.tag_spi = style_alg.s.tag_spi; 383 tag_cfg->tag_fields.tag_sync = style_alg.s.tag_syn; 384 tag_cfg->tag_fields.ip_prot_nexthdr = style_alg.s.tag_pctl; 385 tag_cfg->tag_fields.second_vlan = style_alg.s.tag_vs1; 386 tag_cfg->tag_fields.first_vlan = style_alg.s.tag_vs0; 387 tag_cfg->tag_fields.mpls_label = style_alg.s.tag_mpls0; 388 tag_cfg->tag_fields.input_port = style_alg.s.tag_prt; 389 390 /* Custom-Mask Tag: */ 391 tag_sel.u64 = csr_rd_node(node, CVMX_PKI_STYLEX_TAG_SEL(style)); 392 for (mask = 0; mask < 4; mask++) { 393 tag_cfg->mask_tag[mask].enable = 394 (style_cfg2.s.tag_inc & (1 << mask)) != 0; 395 switch (mask) { 396 case 0: 397 tag_idx = tag_sel.s.tag_idx0; 398 break; 399 case 1: 400 tag_idx = tag_sel.s.tag_idx1; 401 break; 402 case 2: 403 tag_idx = tag_sel.s.tag_idx2; 404 break; 405 case 3: 406 tag_idx = tag_sel.s.tag_idx3; 407 break; 408 } 409 index = tag_idx * 4 + mask; 410 tag_mask.u64 = csr_rd_node(node, CVMX_PKI_TAG_INCX_MASK(index)); 411 tag_cfg->mask_tag[mask].val = tag_mask.s.en; 412 tag_ctl.u64 = csr_rd_node(node, CVMX_PKI_TAG_INCX_CTL(index)); 413 tag_cfg->mask_tag[mask].base = tag_ctl.s.ptr_sel; 414 tag_cfg->mask_tag[mask].offset = tag_ctl.s.offset; 415 } 416} 417 418/** 419 * This function writes/configures parameters associated with tag configuration in 420 * hardware. In Custom-Mask Tagging, all four masks use the same base index 421 * to access Tag Control and Tag Mask registers. 422 * 423 * @param node Node number. 424 * @param style Style to configure tag for. 425 * @param cluster_mask Mask of clusters to configure the style for. 426 * @param tag_cfg Pointer to taf configuration struct. 427 */ 428void cvmx_pki_write_tag_config(int node, int style, uint64_t cluster_mask, 429 struct cvmx_pki_style_tag_cfg *tag_cfg) 430{ 431 int mask, index, tag_idx, mtag_en = 0; 432 unsigned int cluster = 0; 433 cvmx_pki_clx_stylex_cfg2_t scfg2; 434 cvmx_pki_clx_stylex_alg_t style_alg; 435 cvmx_pki_tag_incx_ctl_t tag_ctl; 436 cvmx_pki_tag_incx_mask_t tag_mask; 437 cvmx_pki_stylex_tag_sel_t tag_sel; 438 439 while (cluster < CVMX_PKI_NUM_CLUSTER) { 440 if (cluster_mask & (0x01L << cluster)) { 441 /* 7-Tuple Tag: */ 442 scfg2.u64 = csr_rd_node( 443 node, CVMX_PKI_CLX_STYLEX_CFG2(style, cluster)); 444 scfg2.s.tag_src_lg = tag_cfg->tag_fields.layer_g_src; 445 scfg2.s.tag_src_lf = tag_cfg->tag_fields.layer_f_src; 446 scfg2.s.tag_src_le = tag_cfg->tag_fields.layer_e_src; 447 scfg2.s.tag_src_ld = tag_cfg->tag_fields.layer_d_src; 448 scfg2.s.tag_src_lc = tag_cfg->tag_fields.layer_c_src; 449 scfg2.s.tag_src_lb = tag_cfg->tag_fields.layer_b_src; 450 scfg2.s.tag_dst_lg = tag_cfg->tag_fields.layer_g_dst; 451 scfg2.s.tag_dst_lf = tag_cfg->tag_fields.layer_f_dst; 452 scfg2.s.tag_dst_le = tag_cfg->tag_fields.layer_e_dst; 453 scfg2.s.tag_dst_ld = tag_cfg->tag_fields.layer_d_dst; 454 scfg2.s.tag_dst_lc = tag_cfg->tag_fields.layer_c_dst; 455 scfg2.s.tag_dst_lb = tag_cfg->tag_fields.layer_b_dst; 456 csr_wr_node(node, 457 CVMX_PKI_CLX_STYLEX_CFG2(style, cluster), 458 scfg2.u64); 459 460 style_alg.u64 = csr_rd_node( 461 node, CVMX_PKI_CLX_STYLEX_ALG(style, cluster)); 462 style_alg.s.tag_vni = tag_cfg->tag_fields.tag_vni; 463 style_alg.s.tag_gtp = tag_cfg->tag_fields.tag_gtp; 464 style_alg.s.tag_spi = tag_cfg->tag_fields.tag_spi; 465 style_alg.s.tag_syn = tag_cfg->tag_fields.tag_sync; 466 style_alg.s.tag_pctl = 467 tag_cfg->tag_fields.ip_prot_nexthdr; 468 style_alg.s.tag_vs1 = tag_cfg->tag_fields.second_vlan; 469 style_alg.s.tag_vs0 = tag_cfg->tag_fields.first_vlan; 470 style_alg.s.tag_mpls0 = tag_cfg->tag_fields.mpls_label; 471 style_alg.s.tag_prt = tag_cfg->tag_fields.input_port; 472 csr_wr_node(node, 473 CVMX_PKI_CLX_STYLEX_ALG(style, cluster), 474 style_alg.u64); 475 476 /* Custom-Mask Tag (Part 1): */ 477 for (mask = 0; mask < 4; mask++) { 478 if (tag_cfg->mask_tag[mask].enable) 479 mtag_en++; 480 } 481 if (mtag_en) { 482 scfg2.u64 = csr_rd_node( 483 node, CVMX_PKI_CLX_STYLEX_CFG2( 484 style, cluster)); 485 scfg2.s.tag_inc = 0; 486 for (mask = 0; mask < 4; mask++) { 487 if (tag_cfg->mask_tag[mask].enable) 488 scfg2.s.tag_inc |= 1 << mask; 489 } 490 csr_wr_node(node, 491 CVMX_PKI_CLX_STYLEX_CFG2(style, 492 cluster), 493 scfg2.u64); 494 } 495 } 496 cluster++; 497 } 498 /* Custom-Mask Tag (Part 2): */ 499 if (mtag_en) { 500 tag_idx = cvmx_pki_mtag_idx_alloc(node, -1); 501 if (tag_idx < 0) 502 return; 503 504 tag_sel.u64 = csr_rd_node(node, CVMX_PKI_STYLEX_TAG_SEL(style)); 505 for (mask = 0; mask < 4; mask++) { 506 if (tag_cfg->mask_tag[mask].enable) { 507 switch (mask) { 508 case 0: 509 tag_sel.s.tag_idx0 = tag_idx; 510 break; 511 case 1: 512 tag_sel.s.tag_idx1 = tag_idx; 513 break; 514 case 2: 515 tag_sel.s.tag_idx2 = tag_idx; 516 break; 517 case 3: 518 tag_sel.s.tag_idx3 = tag_idx; 519 break; 520 } 521 index = tag_idx * 4 + mask; 522 tag_mask.u64 = csr_rd_node( 523 node, CVMX_PKI_TAG_INCX_MASK(index)); 524 tag_mask.s.en = tag_cfg->mask_tag[mask].val; 525 csr_wr_node(node, CVMX_PKI_TAG_INCX_MASK(index), 526 tag_mask.u64); 527 528 tag_ctl.u64 = csr_rd_node( 529 node, CVMX_PKI_TAG_INCX_CTL(index)); 530 tag_ctl.s.ptr_sel = 531 tag_cfg->mask_tag[mask].base; 532 tag_ctl.s.offset = 533 tag_cfg->mask_tag[mask].offset; 534 csr_wr_node(node, CVMX_PKI_TAG_INCX_CTL(index), 535 tag_ctl.u64); 536 } 537 } 538 csr_wr_node(node, CVMX_PKI_STYLEX_TAG_SEL(style), tag_sel.u64); 539 } 540} 541 542/** 543 * This function reads parameters associated with style in hardware. 544 * 545 * @param node Node number. 546 * @param style Style to read from. 547 * @param cluster_mask Mask of clusters style belongs to. 548 * @param style_cfg Pointer to style config struct. 549 */ 550void cvmx_pki_read_style_config(int node, int style, uint64_t cluster_mask, 551 struct cvmx_pki_style_config *style_cfg) 552{ 553 cvmx_pki_clx_stylex_cfg_t scfg; 554 cvmx_pki_clx_stylex_cfg2_t scfg2; 555 cvmx_pki_clx_stylex_alg_t style_alg; 556 cvmx_pki_stylex_buf_t style_buf; 557 int cluster = __builtin_ffsll(cluster_mask) - 1; 558 559 scfg.u64 = csr_rd_node(node, CVMX_PKI_CLX_STYLEX_CFG(style, cluster)); 560 scfg2.u64 = csr_rd_node(node, CVMX_PKI_CLX_STYLEX_CFG2(style, cluster)); 561 style_alg.u64 = 562 csr_rd_node(node, CVMX_PKI_CLX_STYLEX_ALG(style, cluster)); 563 style_buf.u64 = csr_rd_node(node, CVMX_PKI_STYLEX_BUF(style)); 564 565 style_cfg->parm_cfg.ip6_udp_opt = scfg.s.ip6_udp_opt; 566 style_cfg->parm_cfg.lenerr_en = scfg.s.lenerr_en; 567 style_cfg->parm_cfg.lenerr_eqpad = scfg.s.lenerr_eqpad; 568 style_cfg->parm_cfg.maxerr_en = scfg.s.maxerr_en; 569 style_cfg->parm_cfg.minerr_en = scfg.s.minerr_en; 570 style_cfg->parm_cfg.fcs_chk = scfg.s.fcs_chk; 571 style_cfg->parm_cfg.fcs_strip = scfg.s.fcs_strip; 572 style_cfg->parm_cfg.minmax_sel = scfg.s.minmax_sel; 573 style_cfg->parm_cfg.qpg_base = scfg.s.qpg_base; 574 style_cfg->parm_cfg.qpg_dis_padd = scfg.s.qpg_dis_padd; 575 style_cfg->parm_cfg.qpg_dis_aura = scfg.s.qpg_dis_aura; 576 style_cfg->parm_cfg.qpg_dis_grp = scfg.s.qpg_dis_grp; 577 style_cfg->parm_cfg.qpg_dis_grptag = scfg.s.qpg_dis_grptag; 578 style_cfg->parm_cfg.rawdrp = scfg.s.rawdrp; 579 style_cfg->parm_cfg.force_drop = scfg.s.drop; 580 style_cfg->parm_cfg.nodrop = scfg.s.nodrop; 581 582 style_cfg->parm_cfg.len_lg = scfg2.s.len_lg; 583 style_cfg->parm_cfg.len_lf = scfg2.s.len_lf; 584 style_cfg->parm_cfg.len_le = scfg2.s.len_le; 585 style_cfg->parm_cfg.len_ld = scfg2.s.len_ld; 586 style_cfg->parm_cfg.len_lc = scfg2.s.len_lc; 587 style_cfg->parm_cfg.len_lb = scfg2.s.len_lb; 588 style_cfg->parm_cfg.csum_lg = scfg2.s.csum_lg; 589 style_cfg->parm_cfg.csum_lf = scfg2.s.csum_lf; 590 style_cfg->parm_cfg.csum_le = scfg2.s.csum_le; 591 style_cfg->parm_cfg.csum_ld = scfg2.s.csum_ld; 592 style_cfg->parm_cfg.csum_lc = scfg2.s.csum_lc; 593 style_cfg->parm_cfg.csum_lb = scfg2.s.csum_lb; 594 595 style_cfg->parm_cfg.qpg_qos = style_alg.s.qpg_qos; 596 style_cfg->parm_cfg.tag_type = style_alg.s.tt; 597 style_cfg->parm_cfg.apad_nip = style_alg.s.apad_nip; 598 style_cfg->parm_cfg.qpg_port_sh = style_alg.s.qpg_port_sh; 599 style_cfg->parm_cfg.qpg_port_msb = style_alg.s.qpg_port_msb; 600 style_cfg->parm_cfg.wqe_vs = style_alg.s.wqe_vs; 601 602 style_cfg->parm_cfg.pkt_lend = style_buf.s.pkt_lend; 603 style_cfg->parm_cfg.wqe_hsz = style_buf.s.wqe_hsz; 604 style_cfg->parm_cfg.wqe_skip = style_buf.s.wqe_skip * 128; 605 style_cfg->parm_cfg.first_skip = style_buf.s.first_skip * 8; 606 style_cfg->parm_cfg.later_skip = style_buf.s.later_skip * 8; 607 style_cfg->parm_cfg.cache_mode = style_buf.s.opc_mode; 608 style_cfg->parm_cfg.mbuff_size = style_buf.s.mb_size * 8; 609 style_cfg->parm_cfg.dis_wq_dat = style_buf.s.dis_wq_dat; 610 611 cvmx_pki_read_tag_config(node, style, cluster_mask, 612 &style_cfg->tag_cfg); 613} 614 615/** 616 * This function writes/configures parameters associated with style in hardware. 617 * 618 * @param node Node number. 619 * @param style Style to configure. 620 * @param cluster_mask Mask of clusters to configure the style for. 621 * @param style_cfg Pointer to style config struct. 622 */ 623void cvmx_pki_write_style_config(int node, uint64_t style, u64 cluster_mask, 624 struct cvmx_pki_style_config *style_cfg) 625{ 626 cvmx_pki_clx_stylex_cfg_t scfg; 627 cvmx_pki_clx_stylex_cfg2_t scfg2; 628 cvmx_pki_clx_stylex_alg_t style_alg; 629 cvmx_pki_stylex_buf_t style_buf; 630 unsigned int cluster = 0; 631 632 while (cluster < CVMX_PKI_NUM_CLUSTER) { 633 if (cluster_mask & (0x01L << cluster)) { 634 scfg.u64 = csr_rd_node( 635 node, CVMX_PKI_CLX_STYLEX_CFG(style, cluster)); 636 scfg.s.ip6_udp_opt = style_cfg->parm_cfg.ip6_udp_opt; 637 scfg.s.lenerr_en = style_cfg->parm_cfg.lenerr_en; 638 scfg.s.lenerr_eqpad = style_cfg->parm_cfg.lenerr_eqpad; 639 scfg.s.maxerr_en = style_cfg->parm_cfg.maxerr_en; 640 scfg.s.minerr_en = style_cfg->parm_cfg.minerr_en; 641 scfg.s.fcs_chk = style_cfg->parm_cfg.fcs_chk; 642 scfg.s.fcs_strip = style_cfg->parm_cfg.fcs_strip; 643 scfg.s.minmax_sel = style_cfg->parm_cfg.minmax_sel; 644 scfg.s.qpg_base = style_cfg->parm_cfg.qpg_base; 645 scfg.s.qpg_dis_padd = style_cfg->parm_cfg.qpg_dis_padd; 646 scfg.s.qpg_dis_aura = style_cfg->parm_cfg.qpg_dis_aura; 647 scfg.s.qpg_dis_grp = style_cfg->parm_cfg.qpg_dis_grp; 648 scfg.s.qpg_dis_grptag = 649 style_cfg->parm_cfg.qpg_dis_grptag; 650 scfg.s.rawdrp = style_cfg->parm_cfg.rawdrp; 651 scfg.s.drop = style_cfg->parm_cfg.force_drop; 652 scfg.s.nodrop = style_cfg->parm_cfg.nodrop; 653 csr_wr_node(node, 654 CVMX_PKI_CLX_STYLEX_CFG(style, cluster), 655 scfg.u64); 656 657 scfg2.u64 = csr_rd_node( 658 node, CVMX_PKI_CLX_STYLEX_CFG2(style, cluster)); 659 scfg2.s.len_lg = style_cfg->parm_cfg.len_lg; 660 scfg2.s.len_lf = style_cfg->parm_cfg.len_lf; 661 scfg2.s.len_le = style_cfg->parm_cfg.len_le; 662 scfg2.s.len_ld = style_cfg->parm_cfg.len_ld; 663 scfg2.s.len_lc = style_cfg->parm_cfg.len_lc; 664 scfg2.s.len_lb = style_cfg->parm_cfg.len_lb; 665 scfg2.s.csum_lg = style_cfg->parm_cfg.csum_lg; 666 scfg2.s.csum_lf = style_cfg->parm_cfg.csum_lf; 667 scfg2.s.csum_le = style_cfg->parm_cfg.csum_le; 668 scfg2.s.csum_ld = style_cfg->parm_cfg.csum_ld; 669 scfg2.s.csum_lc = style_cfg->parm_cfg.csum_lc; 670 scfg2.s.csum_lb = style_cfg->parm_cfg.csum_lb; 671 csr_wr_node(node, 672 CVMX_PKI_CLX_STYLEX_CFG2(style, cluster), 673 scfg2.u64); 674 675 style_alg.u64 = csr_rd_node( 676 node, CVMX_PKI_CLX_STYLEX_ALG(style, cluster)); 677 style_alg.s.qpg_qos = style_cfg->parm_cfg.qpg_qos; 678 style_alg.s.tt = style_cfg->parm_cfg.tag_type; 679 style_alg.s.apad_nip = style_cfg->parm_cfg.apad_nip; 680 style_alg.s.qpg_port_sh = 681 style_cfg->parm_cfg.qpg_port_sh; 682 style_alg.s.qpg_port_msb = 683 style_cfg->parm_cfg.qpg_port_msb; 684 style_alg.s.wqe_vs = style_cfg->parm_cfg.wqe_vs; 685 csr_wr_node(node, 686 CVMX_PKI_CLX_STYLEX_ALG(style, cluster), 687 style_alg.u64); 688 } 689 cluster++; 690 } 691 style_buf.u64 = csr_rd_node(node, CVMX_PKI_STYLEX_BUF(style)); 692 style_buf.s.pkt_lend = style_cfg->parm_cfg.pkt_lend; 693 style_buf.s.wqe_hsz = style_cfg->parm_cfg.wqe_hsz; 694 style_buf.s.wqe_skip = (style_cfg->parm_cfg.wqe_skip) / 128; 695 style_buf.s.first_skip = (style_cfg->parm_cfg.first_skip) / 8; 696 style_buf.s.later_skip = style_cfg->parm_cfg.later_skip / 8; 697 style_buf.s.opc_mode = style_cfg->parm_cfg.cache_mode; 698 style_buf.s.mb_size = (style_cfg->parm_cfg.mbuff_size) / 8; 699 style_buf.s.dis_wq_dat = style_cfg->parm_cfg.dis_wq_dat; 700 csr_wr_node(node, CVMX_PKI_STYLEX_BUF(style), style_buf.u64); 701 702 cvmx_pki_write_tag_config(node, style, cluster_mask, 703 &style_cfg->tag_cfg); 704} 705 706/** 707 * This function reads qpg entry at specified offset from qpg table. 708 * 709 * @param node Node number. 710 * @param offset Offset in qpg table to read from. 711 * @param qpg_cfg Pointer to structure containing qpg values. 712 */ 713int cvmx_pki_read_qpg_entry(int node, int offset, 714 struct cvmx_pki_qpg_config *qpg_cfg) 715{ 716 cvmx_pki_qpg_tblx_t qpg_tbl; 717 718 if (offset >= CVMX_PKI_NUM_QPG_ENTRY) { 719 debug("ERROR: qpg offset %d is >= 2048\n", offset); 720 return -1; 721 } 722 qpg_tbl.u64 = csr_rd_node(node, CVMX_PKI_QPG_TBLX(offset)); 723 qpg_cfg->aura_num = qpg_tbl.s.laura; 724 qpg_cfg->port_add = qpg_tbl.s.padd; 725 qpg_cfg->grp_ok = qpg_tbl.s.grp_ok; 726 qpg_cfg->grp_bad = qpg_tbl.s.grp_bad; 727 qpg_cfg->grptag_ok = qpg_tbl.s.grptag_ok; 728 qpg_cfg->grptag_bad = qpg_tbl.s.grptag_bad; 729 return 0; 730} 731 732/** 733 * This function writes qpg entry at specified offset in qpg table. 734 * 735 * @param node Node number. 736 * @param offset Offset in qpg table to read from. 737 * @param qpg_cfg Pointer to structure containing qpg values. 738 */ 739void cvmx_pki_write_qpg_entry(int node, int offset, 740 struct cvmx_pki_qpg_config *qpg_cfg) 741{ 742 cvmx_pki_qpg_tblx_t qpg_tbl; 743 744 qpg_tbl.u64 = csr_rd_node(node, CVMX_PKI_QPG_TBLX(offset)); 745 qpg_tbl.s.padd = qpg_cfg->port_add; 746 qpg_tbl.s.laura = qpg_cfg->aura_num; 747 qpg_tbl.s.grp_ok = qpg_cfg->grp_ok; 748 qpg_tbl.s.grp_bad = qpg_cfg->grp_bad; 749 qpg_tbl.s.grptag_ok = qpg_cfg->grptag_ok; 750 qpg_tbl.s.grptag_bad = qpg_cfg->grptag_bad; 751 csr_wr_node(node, CVMX_PKI_QPG_TBLX(offset), qpg_tbl.u64); 752} 753 754/** 755 * This function writes pcam entry at given offset in pcam table in hardware 756 * 757 * @param node Node number. 758 * @param index Offset in pcam table. 759 * @param cluster_mask Mask of clusters in which to write pcam entry. 760 * @param input Input keys to pcam match passed as struct. 761 * @param action PCAM match action passed as struct. 762 */ 763int cvmx_pki_pcam_write_entry(int node, int index, uint64_t cluster_mask, 764 struct cvmx_pki_pcam_input input, 765 struct cvmx_pki_pcam_action action) 766{ 767 int bank; 768 unsigned int cluster = 0; 769 cvmx_pki_clx_pcamx_termx_t term; 770 cvmx_pki_clx_pcamx_matchx_t match; 771 cvmx_pki_clx_pcamx_actionx_t act; 772 773 if (index >= CVMX_PKI_TOTAL_PCAM_ENTRY) { 774 debug("\nERROR: Invalid pcam entry %d\n", index); 775 return -1; 776 } 777 bank = (int)(input.field & 0x01); 778 while (cluster < CVMX_PKI_NUM_CLUSTER) { 779 if (cluster_mask & (0x01L << cluster)) { 780 term.u64 = csr_rd_node( 781 node, 782 CVMX_PKI_CLX_PCAMX_TERMX(cluster, bank, index)); 783 term.s.valid = 0; 784 csr_wr_node(node, 785 CVMX_PKI_CLX_PCAMX_TERMX(cluster, bank, 786 index), 787 term.u64); 788 match.u64 = csr_rd_node( 789 node, CVMX_PKI_CLX_PCAMX_MATCHX(cluster, bank, 790 index)); 791 match.s.data1 = input.data & input.data_mask; 792 match.s.data0 = (~input.data) & input.data_mask; 793 csr_wr_node(node, 794 CVMX_PKI_CLX_PCAMX_MATCHX(cluster, bank, 795 index), 796 match.u64); 797 798 act.u64 = csr_rd_node( 799 node, CVMX_PKI_CLX_PCAMX_ACTIONX(cluster, bank, 800 index)); 801 act.s.pmc = action.parse_mode_chg; 802 act.s.style_add = action.style_add; 803 act.s.pf = action.parse_flag_set; 804 act.s.setty = action.layer_type_set; 805 act.s.advance = action.pointer_advance; 806 csr_wr_node(node, 807 CVMX_PKI_CLX_PCAMX_ACTIONX(cluster, bank, 808 index), 809 act.u64); 810 811 term.u64 = csr_rd_node( 812 node, 813 CVMX_PKI_CLX_PCAMX_TERMX(cluster, bank, index)); 814 term.s.term1 = input.field & input.field_mask; 815 term.s.term0 = (~input.field) & input.field_mask; 816 term.s.style1 = input.style & input.style_mask; 817 term.s.style0 = (~input.style) & input.style_mask; 818 term.s.valid = 1; 819 csr_wr_node(node, 820 CVMX_PKI_CLX_PCAMX_TERMX(cluster, bank, 821 index), 822 term.u64); 823 } 824 cluster++; 825 } 826 return 0; 827} 828 829/** 830 * Enables/Disables fcs check and fcs stripping on the pkind. 831 * 832 * @param node Node number 833 * @param pknd PKIND to apply settings on. 834 * @param fcs_chk Enable/disable fcs check. 835 * 1 = enable fcs error check. 836 * 0 = disable fcs error check. 837 * @param fcs_strip Strip L2 FCS bytes from packet, decrease WQE[LEN] by 4 bytes 838 * 1 = strip L2 FCS. 839 * 0 = Do not strip L2 FCS. 840 */ 841void cvmx_pki_endis_fcs_check(int node, int pknd, bool fcs_chk, bool fcs_strip) 842{ 843 int style; 844 unsigned int cluster; 845 cvmx_pki_clx_pkindx_style_t pstyle; 846 cvmx_pki_clx_stylex_cfg_t style_cfg; 847 848 /* Valudate PKIND # */ 849 if (pknd >= CVMX_PKI_NUM_PKIND) { 850 printf("%s: PKIND %d out of range\n", __func__, pknd); 851 return; 852 } 853 854 for (cluster = 0; cluster < CVMX_PKI_NUM_CLUSTER; cluster++) { 855 pstyle.u64 = csr_rd_node( 856 node, CVMX_PKI_CLX_PKINDX_STYLE(pknd, cluster)); 857 style = pstyle.s.style; 858 /* Validate STYLE # */ 859 if (style >= CVMX_PKI_NUM_INTERNAL_STYLE) 860 continue; 861 style_cfg.u64 = csr_rd_node( 862 node, CVMX_PKI_CLX_STYLEX_CFG(style, cluster)); 863 style_cfg.s.fcs_chk = fcs_chk; 864 style_cfg.s.fcs_strip = fcs_strip; 865 csr_wr_node(node, CVMX_PKI_CLX_STYLEX_CFG(style, cluster), 866 style_cfg.u64); 867 } 868} 869 870/** 871 * Enables/Disables l2 length error check and max & min frame length checks 872 * 873 * @param node Node number 874 * @param pknd PKIND to disable error for. 875 * @param l2len_err L2 length error check enable. 876 * @param maxframe_err Max frame error check enable. 877 * @param minframe_err Min frame error check enable. 878 * 1 = Enabel err checks 879 * 0 = Disable error checks 880 */ 881void cvmx_pki_endis_l2_errs(int node, int pknd, bool l2len_err, 882 bool maxframe_err, bool minframe_err) 883{ 884 int style; 885 unsigned int cluster; 886 cvmx_pki_clx_pkindx_style_t pstyle; 887 cvmx_pki_clx_stylex_cfg_t style_cfg; 888 889 /* Valudate PKIND # */ 890 if (pknd >= CVMX_PKI_NUM_PKIND) { 891 printf("%s: PKIND %d out of range\n", __func__, pknd); 892 return; 893 } 894 895 for (cluster = 0; cluster < CVMX_PKI_NUM_CLUSTER; cluster++) { 896 pstyle.u64 = csr_rd_node( 897 node, CVMX_PKI_CLX_PKINDX_STYLE(pknd, cluster)); 898 style = pstyle.s.style; 899 /* Validate STYLE # */ 900 if (style >= CVMX_PKI_NUM_INTERNAL_STYLE) 901 continue; 902 style_cfg.u64 = csr_rd_node( 903 node, CVMX_PKI_CLX_STYLEX_CFG(style, cluster)); 904 style_cfg.s.lenerr_en = l2len_err; 905 style_cfg.s.maxerr_en = maxframe_err; 906 style_cfg.s.minerr_en = minframe_err; 907 csr_wr_node(node, CVMX_PKI_CLX_STYLEX_CFG(style, cluster), 908 style_cfg.u64); 909 } 910} 911