openbcm

Git mirror of https://github.com/Broadcom-Network-Switching-Software/OpenBCM
git clone git://git.finwo.net/mirror/broadcom/openbcm
Log | Files | Refs | README

brd_e2e.c (14355B)


      1 /*
      2  * 
      3  * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file.
      4  * 
      5  * Copyright 2007-2019 Broadcom Inc. All rights reserved.
      6  *
      7  * File:        brd_e2e.c
      8  * Purpose:	XGS Board End-to-end flow control programming
      9  *		Supports boards with up to 4 BCM5695 devices, and
     10  *              dual BCM56504 board only.
     11  *		Other XGS1 and XGS2 devices are not end-to-end capable.
     12  */
     13 
     14 #include <soc/drv.h>
     15 #include <soc/higig.h>
     16 
     17 #include <bcm/error.h>
     18 #include <bcm/stack.h>
     19 #include <bcm/link.h>
     20 #include <bcm/port.h>
     21 #include <bcm/trunk.h>
     22 
     23 #include <appl/cputrans/next_hop.h>
     24 #include <appl/stktask/topo_brd.h>
     25 
     26 #define	E2E_CAPABLE(_u)	(SOC_IS_FB_FX_HX(_u))
     27 
     28 #ifndef E2E_MAXUNIT
     29 #define	E2E_MAXUNIT	4
     30 #endif
     31 
     32 #define	E2E_ETHERTYPE	0x8874
     33 #define	E2E_OPCODE_HOL	0xbc01
     34 #define	E2E_OPCODE_IBP	0xbc02
     35 
     36 #ifndef E2E_PKT_DEFRATE
     37 #define	E2E_PKT_DEFRATE		0x100
     38 #endif
     39 
     40 #ifndef E2E_CELL_DEFLIMIT
     41 #define	E2E_CELL_DEFLIMIT	73	/* cells for a jumbo + 1 */
     42 #endif
     43 
     44 #ifndef E2E_PKT_DEFLIMIT
     45 #define	E2E_PKT_DEFLIMIT	0x7ff	/* no limit */
     46 #endif
     47 
     48 #define	E2E_CELL_NOLIMIT	0x1fff
     49 
     50 #define	E2E_PKT_NOLIMIT		0x7ff
     51 
     52 
     53 #ifdef BCM_XGS3_SWITCH_SUPPORT
     54 
     55 #ifndef E2E_MAXUNIT_FB
     56 #define E2E_MAXUNIT_FB          2
     57 #endif
     58 
     59 #ifndef E2E_FB_PKT_LIMIT
     60 #define E2E_FB_PKT_LIMIT        0x90
     61 #endif
     62 
     63 #ifndef E2E_FB_CELL_LIMIT
     64 #define E2E_FB_CELL_LIMIT       0x180
     65 #endif
     66 
     67 #ifndef E2E_CELL_DISCARD_LIMIT
     68 #define E2E_CELL_DISCARD_LIMIT  0x300
     69 #endif
     70 
     71 #ifndef E2E_PKTCELL_RESET_LIMIT
     72 #define E2E_PKTCELL_RESET_LIMIT 0x1
     73 #endif
     74 
     75 #ifndef E2E_MAXTIMER_DEFSEL
     76 #define E2E_MAXTIMER_DEFSEL     0xb
     77 #endif
     78 
     79 #ifndef E2E_MINTIMER_DEFSEL
     80 #define E2E_MINTIMER_DEFSEL     0x3
     81 #endif
     82 
     83 #endif /* BCM_XGS3_SWITCH)SUPPORT */
     84 
     85 STATIC int	_bcm_e2e_pkt_rate = E2E_PKT_DEFRATE;
     86 STATIC int	_bcm_e2e_cell_limit = E2E_CELL_DEFLIMIT;
     87 STATIC int	_bcm_e2e_pkt_limit = E2E_PKT_DEFLIMIT;
     88 
     89 int
     90 bcm_board_e2e_config_set(int pkt_rate, int cell_limit, int pkt_limit)
     91 {
     92     _bcm_e2e_pkt_rate = pkt_rate < 0 ? E2E_PKT_DEFRATE : pkt_rate;
     93     _bcm_e2e_cell_limit = cell_limit < 0 ? E2E_CELL_DEFLIMIT : cell_limit;
     94     _bcm_e2e_pkt_limit = pkt_limit < 0 ? E2E_PKT_DEFLIMIT : pkt_limit;
     95     return BCM_E_NONE;
     96 }
     97 
     98 int
     99 bcm_board_e2e_config_get(int *pkt_rate, int *cell_limit, int *pkt_limit)
    100 {
    101     if (pkt_rate != NULL) {
    102 	*pkt_rate = _bcm_e2e_pkt_rate;
    103     }
    104     if (cell_limit != NULL) {
    105 	*cell_limit = _bcm_e2e_cell_limit;
    106     }
    107     if (pkt_limit != NULL) {
    108 	*pkt_limit = _bcm_e2e_pkt_limit;
    109     }
    110     return BCM_E_NONE;
    111 }
    112 
    113 #ifdef BCM_FIREBOLT_SUPPORT
    114 STATIC int
    115 _bcm_board_e2e_fbx_unit(int unit,
    116                          int lmod,
    117                          int cos,
    118                          int vlan,
    119                          bcm_mac_t mac,
    120                          int *rmod,
    121                          int **rpstate)
    122 {
    123     uint32                val = 0;
    124     bcm_port_t            port;
    125     int	                  cell_limit, pkt_limit;
    126     uint32                val0, val1, val2, val3;
    127     soc_higig_hdr_t       hg;
    128     uint32                hgwords[3];
    129     bcm_trunk_t           tid;
    130     bcm_trunk_info_t      ta_info;
    131     int                   member_count;
    132     bcm_trunk_member_t    member_array[BCM_TRUNK_FABRIC_MAX_PORTCNT];
    133     bcm_port_t            local_port;
    134     bcm_trunk_chip_info_t ti;
    135     int                   idx, trunk_found = 0;
    136 
    137     if (rmod[0] < 0) {
    138         return BCM_E_PARAM; /* or BCM_E_UNAVAIL ?? */
    139     }
    140 
    141     BCM_IF_ERROR_RETURN
    142         (bcm_stk_modport_get(unit, rmod[0], &port));
    143 
    144     sal_memset(&ti, 0, sizeof(bcm_trunk_chip_info_t));
    145     BCM_IF_ERROR_RETURN(bcm_trunk_chip_info_get(unit, &ti));
    146 
    147     /*
    148      * Check for fabric trunk membership, and enable 
    149      * E2E IBP on all trunk members
    150      */
    151     for (tid = ti.trunk_fabric_id_min; 
    152          tid <= ti.trunk_fabric_id_max; tid++) {
    153          sal_memset(&ta_info, 0, sizeof(bcm_trunk_info_t));
    154          if (bcm_trunk_get(unit, tid, &ta_info, BCM_TRUNK_FABRIC_MAX_PORTCNT,
    155                      member_array, &member_count) >= 0) {
    156              for (idx = 0; idx < member_count; idx++) {
    157                  BCM_IF_ERROR_RETURN(bcm_port_local_get(unit,
    158                              member_array[idx].gport, &local_port));
    159                  if (local_port == port) {
    160                      trunk_found = 1;
    161                      break;
    162                  }
    163              }
    164          }
    165 
    166          if (trunk_found) {
    167              break;
    168          }
    169     }
    170 
    171     /*
    172      * If fabric trunk not found for some reason, populate 
    173      * the single HG port for IBP programming
    174      */
    175     if (!trunk_found) {
    176         member_count = 1;
    177         bcm_trunk_member_t_init(&member_array[0]);
    178         member_array[0].gport = BCM_GPORT_DEVPORT(unit, port);
    179     }
    180 
    181     SOC_IF_ERROR_RETURN(READ_E2ECONFIGr(unit, &val));
    182 
    183     /*
    184      * set remote module id
    185      */
    186     soc_reg_field_set(unit, E2ECONFIGr, &val,
    187                       REMOTE_SRCMODIDf, rmod[0]);
    188 
    189     /*
    190      * Turn on e2e IBP only (no HOL)
    191      */
    192     soc_reg_field_set(unit, E2ECONFIGr, &val, E2E_IBP_ENf, 1);
    193     soc_reg_field_set(unit, E2ECONFIGr, &val, E2E_HOL_ENf, 1);
    194     soc_reg_field_set(unit, E2ECONFIGr, &val, E2E_MAXTIMER_SELf,
    195                       E2E_MAXTIMER_DEFSEL);
    196     soc_reg_field_set(unit, E2ECONFIGr, &val, E2E_MINTIMER_SELf,
    197                       E2E_MINTIMER_DEFSEL);
    198     SOC_IF_ERROR_RETURN(WRITE_E2ECONFIGr(unit, val));
    199 
    200     /* define packet higig header */
    201     sal_memset(&hg, 0, sizeof(hg));
    202     soc_higig_field_set(unit, &hg, HG_start, SOC_HIGIG_START);
    203     soc_higig_field_set(unit, &hg, HG_hgi, SOC_HIGIG_HGI);
    204     soc_higig_field_set(unit, &hg, HG_vlan_id, vlan);
    205     soc_higig_field_set(unit, &hg, HG_src_mod, lmod);
    206     soc_higig_field_set(unit, &hg, HG_opcode, SOC_HIGIG_OP_UC);
    207     soc_higig_field_set(unit, &hg, HG_src_port, port);
    208     soc_higig_field_set(unit, &hg, HG_dst_port, port);
    209     soc_higig_field_set(unit, &hg, HG_cos, cos);
    210     sal_memcpy(hgwords, &hg, sizeof(hgwords));
    211 
    212     /* define packet data header (da, sa, len/type, opcode) */
    213     val0 = (mac[0] << 24) | (mac[1] << 16) | (mac[2] << 8) | mac[3];
    214     val1 = (mac[4] << 24) | (mac[5] << 16) | (mac[0] << 8) | mac[1];
    215     val2 = (mac[2] << 24) | (mac[3] << 16) | (mac[4] << 8) | mac[5];
    216     val3 = (E2E_ETHERTYPE << 16) | E2E_OPCODE_IBP;
    217 
    218     for (idx = 0; idx < member_count; idx++) {
    219 
    220          BCM_IF_ERROR_RETURN
    221              (bcm_port_local_get(unit, member_array[idx].gport, &port));
    222          if (!IS_HG_PORT(unit, port)) {
    223              continue;
    224          }
    225 
    226          val = 0;
    227          SOC_IF_ERROR_RETURN(READ_E2ECONFIGr(unit, &val));
    228          switch(port) {
    229          case 24:
    230            soc_reg_field_set(unit, E2ECONFIGr, &val, XPORT24_SEND_E2E_IBPf, 1);
    231            break;
    232     
    233          case 25:
    234            soc_reg_field_set(unit, E2ECONFIGr, &val, XPORT25_SEND_E2E_IBPf, 1);
    235            break;
    236 
    237          case 26:
    238            soc_reg_field_set(unit, E2ECONFIGr, &val, XPORT26_SEND_E2E_IBPf, 1);
    239            break;
    240 
    241          case 27:
    242            soc_reg_field_set(unit, E2ECONFIGr, &val, XPORT27_SEND_E2E_IBPf, 1);
    243            break;
    244 
    245          default:
    246            break;
    247          }
    248          SOC_IF_ERROR_RETURN(WRITE_E2ECONFIGr(unit, val));
    249 
    250          SOC_IF_ERROR_RETURN(WRITE_XIBP_MH0r(unit, port, hgwords[0]));
    251          SOC_IF_ERROR_RETURN(WRITE_XIBP_MH1r(unit, port, hgwords[1]));
    252          SOC_IF_ERROR_RETURN(WRITE_XIBP_MH2r(unit, port, hgwords[2]));
    253 
    254          SOC_IF_ERROR_RETURN(WRITE_XIBP_D0r(unit, port, val0));
    255          SOC_IF_ERROR_RETURN(WRITE_XIBP_D1r(unit, port, val1));
    256          SOC_IF_ERROR_RETURN(WRITE_XIBP_D2r(unit, port, val2));
    257          SOC_IF_ERROR_RETURN(WRITE_XIBP_D3r(unit, port, val3));
    258 
    259          val = 0;
    260          SOC_IF_ERROR_RETURN(READ_IE2E_CONTROLr(unit, port, &val));
    261          soc_reg_field_set(unit, IE2E_CONTROLr, &val, IBP_ENABLEf, 1);
    262          SOC_IF_ERROR_RETURN(WRITE_IE2E_CONTROLr(unit, port, val));
    263 
    264          val = 0;
    265          SOC_IF_ERROR_RETURN(READ_XPORT_CONFIGr(unit, port, &val));
    266          soc_reg_field_set(unit, XPORT_CONFIGr, &val, E2E_IBP_ENf, 1);
    267          SOC_IF_ERROR_RETURN(WRITE_XPORT_CONFIGr(unit, port, val));
    268 
    269          /*
    270           * Setup pkt and cell limits for ibp
    271           */
    272          cell_limit = E2E_FB_CELL_LIMIT;
    273          pkt_limit = E2E_FB_PKT_LIMIT;
    274 
    275          val = 0;
    276          soc_reg_field_set(unit, E2EIBPCELLSETLIMITr, &val, CELLSETLIMITf,
    277                            cell_limit);
    278          soc_reg_field_set(unit, E2EIBPCELLSETLIMITr, &val, RESETLIMITSELf,
    279                            E2E_PKTCELL_RESET_LIMIT);
    280          SOC_IF_ERROR_RETURN(WRITE_E2EIBPCELLSETLIMITr(unit, port, val));
    281 
    282          val = 0;
    283          soc_reg_field_set(unit, E2EIBPPKTSETLIMITr, &val, PKTSETLIMITf,
    284                            pkt_limit);
    285          soc_reg_field_set(unit, E2EIBPPKTSETLIMITr, &val, RESETLIMITSELf,
    286                            E2E_PKTCELL_RESET_LIMIT);
    287          SOC_IF_ERROR_RETURN(WRITE_E2EIBPPKTSETLIMITr(unit, port, val));
    288 
    289          SOC_IF_ERROR_RETURN
    290             (WRITE_E2EIBPDISCARDSETLIMITr(unit, port, 
    291                                           E2E_CELL_DISCARD_LIMIT));
    292     }
    293 
    294     /*
    295      * define packet recognition criteria for IBP
    296      */
    297     val = (mac[0] << 8) | mac[1];
    298     SOC_IF_ERROR_RETURN(WRITE_E2E_IBP_RX_DA_MSr(unit, val));
    299     val = (mac[2] << 24) | (mac[3] << 16) | (mac[4] << 8) | mac[5];
    300     SOC_IF_ERROR_RETURN(WRITE_E2E_IBP_RX_DA_LSr(unit, val));
    301     SOC_IF_ERROR_RETURN(WRITE_E2E_IBP_RX_LENGTH_TYPEr(unit, E2E_ETHERTYPE));
    302     SOC_IF_ERROR_RETURN(WRITE_E2E_IBP_RX_OPCODEr(unit, E2E_OPCODE_IBP));
    303        
    304     return BCM_E_NONE; 
    305 }
    306 #endif /* BCM_FIREBOLT_SUPPORT */
    307 
    308 STATIC int
    309 _bcm_board_e2e_unit(int unit,
    310 		    int lmod,
    311 		    int cos,
    312 		    int vlan,
    313 		    bcm_mac_t mac,
    314 		    int *rmod,
    315 		    int **rpstate)
    316 {
    317    int rv = BCM_E_NONE;
    318 
    319 #ifdef BCM_FIREBOLT_SUPPORT
    320    if (SOC_IS_FIREBOLT(unit)) {
    321        rv = _bcm_board_e2e_fbx_unit(unit, lmod, cos, vlan, mac,
    322                                     rmod, rpstate);
    323    }
    324 #endif
    325 
    326    return rv;
    327 }
    328 
    329 
    330 int
    331 bcm_board_e2e_set(void)
    332 {
    333     int		unit, neunits, i, cos, vlan;
    334     int		eunits[E2E_MAXUNIT];
    335     int		emods[E2E_MAXUNIT];
    336     bcm_mac_t	mac;
    337     int		lmod, nr, j, max_e2e_units;
    338     int		pstate[E2E_MAXUNIT][SOC_MAX_NUM_PORTS];
    339     int		rmod[E2E_MAXUNIT-1], *rpstate[E2E_MAXUNIT-1];
    340     bcm_port_t	port;
    341     int		pause_tx, pause_rx, link_up;
    342 
    343     /* find e2e capable units */
    344     neunits = 0;
    345     max_e2e_units = E2E_MAXUNIT;
    346 
    347 #ifdef BCM_XGS3_SWITCH_SUPPORT
    348     for (unit = 0; unit < soc_ndev; unit++) {
    349          if (SOC_IS_FB_FX_HX(SOC_NDEV_IDX2DEV(unit))) {
    350              neunits++;
    351              if (max_e2e_units != E2E_MAXUNIT_FB) {
    352 	         max_e2e_units = E2E_MAXUNIT_FB;
    353              }
    354          }
    355     }
    356 
    357     if (max_e2e_units == E2E_MAXUNIT_FB) {
    358         /*
    359 	 * We've established there is a FB in the system;
    360          * Allow E2E in a stacked system with only 2 FBs
    361          */
    362         if (neunits != max_e2e_units) {
    363             return BCM_E_UNAVAIL;
    364         }
    365     }
    366 #endif
    367 
    368     neunits = 0;
    369     for (unit = 0; unit < soc_ndev; unit++) {
    370         if (E2E_CAPABLE(SOC_NDEV_IDX2DEV(unit))) {
    371             eunits[neunits] = SOC_NDEV_IDX2DEV(unit);
    372             BCM_IF_ERROR_RETURN(bcm_stk_modid_get(SOC_NDEV_IDX2DEV(unit), &emods[neunits]));
    373             neunits += 1;
    374             if (neunits == max_e2e_units) {
    375                 break;
    376             }
    377         }
    378     }
    379 
    380     if (neunits < 2) {		/* need at least two devices */
    381 	return BCM_E_NONE;
    382     }
    383 
    384     /* use nexthop cos, vlan, mac for E2E packets */
    385     if (next_hop_cos_get(&cos) < 0) {
    386 	cos = 0;
    387     }
    388 
    389     if (next_hop_vlan_get(&vlan) < 0) {
    390 	vlan = 1;
    391     }
    392     (void)nh_tx_local_mac_get(&mac);
    393 
    394     /* get link/pause state */
    395     sal_memset(pstate, 0, sizeof(pstate));
    396     for (i = 0; i < neunits; i++) {
    397 	unit = eunits[i];
    398 	PBMP_E_ITER(unit, port) {
    399 	    if (bcm_port_pause_get(unit, port, &pause_tx, &pause_rx) < 0) {
    400 		continue;
    401 	    }
    402 	    if (!pause_tx) {
    403 		continue;
    404 	    }
    405 	    if (bcm_port_link_status_get(unit, port, &link_up) < 0) {
    406 		continue;
    407 	    }
    408 	    if (!link_up) {
    409 		continue;
    410 	    }
    411 	    pstate[i][port] = 1;
    412 	}
    413     }
    414 
    415     /* setup each unit for e2e */
    416     for (i = 0; i < neunits; i++) {
    417 	unit = eunits[i];
    418 	lmod = emods[i];
    419 	rmod[0] = rmod[1] = rmod[2] = -1;
    420 	nr = 0;
    421 	for (j = 0; j < neunits; j++) {
    422 	    if (j == i) {
    423 		continue;
    424 	    }
    425 	    rmod[nr] = emods[j];
    426 	    rpstate[nr] = &pstate[j][0];
    427 	    nr += 1;
    428 	}
    429 	BCM_IF_ERROR_RETURN
    430 	    (_bcm_board_e2e_unit(unit, lmod, cos, vlan, mac,
    431 				 rmod, rpstate));
    432     }
    433 
    434     return BCM_E_NONE;
    435 }
    436 
    437 /*
    438  * E2E IBP programming for dual FB LMs
    439  */
    440 int
    441 _bcm_board_dual_xgs3_e2e_set(int unit0, bcm_module_t modid0,
    442                              int unit1, bcm_module_t modid1)
    443 {
    444 #ifdef BCM_FIREBOLT_SUPPORT
    445     int		unit,  i, cos, vlan;
    446     bcm_mac_t	mac;
    447     int		lmod, nr, j;
    448     int		pstate[E2E_MAXUNIT_FB][SOC_MAX_NUM_PORTS];
    449     int		rmod[E2E_MAXUNIT_FB], *rpstate[E2E_MAXUNIT_FB];
    450     bcm_port_t	port;
    451     int		pause_tx, pause_rx, link_up;
    452     xgs3devinfo_t dev[E2E_MAXUNIT_FB];
    453     
    454     dev[0].unit = unit0;
    455     dev[0].modid = modid0;
    456     dev[1].unit = unit1;
    457     dev[1].modid = modid1;
    458 
    459     /* use nexthop cos, vlan, mac for E2E packets */
    460     if (next_hop_cos_get(&cos) < 0) {
    461 	cos = 0;
    462     }
    463 
    464     if (next_hop_vlan_get(&vlan) < 0) {
    465 	vlan = 1;
    466     }
    467     (void)nh_tx_local_mac_get(&mac);
    468 
    469     /* get link/pause state */
    470     sal_memset(pstate, 0, sizeof(pstate));
    471     for (i = 0; i < E2E_MAXUNIT_FB; i++) {
    472          unit = dev[i].unit;
    473          PBMP_E_ITER(unit, port) {
    474             if (bcm_port_pause_get(unit, port, &pause_tx, &pause_rx) < 0) {
    475                 continue;
    476             }
    477             if (!pause_tx) {
    478                 continue;
    479             }
    480             if (bcm_port_link_status_get(unit, port, &link_up) < 0) {
    481                 continue;
    482             } 
    483             if (!link_up) {
    484                 continue;
    485             }
    486             pstate[i][port] = 1;
    487          }
    488     }
    489 
    490     /* setup each unit for e2e */
    491     for (i = 0; i < E2E_MAXUNIT_FB; i++) {
    492 	unit = dev[i].unit;
    493 	lmod = dev[i].modid;
    494 	rmod[0] = rmod[1] = -1;
    495 	nr = 0;
    496 	for (j = 0; j < E2E_MAXUNIT_FB; j++) {
    497 	    if (j == i) {
    498 		continue;
    499 	    }
    500 	    rmod[nr] = dev[j].modid;
    501 	    rpstate[nr] = &pstate[j][0];
    502 	    nr += 1;
    503 	}
    504 
    505 	BCM_IF_ERROR_RETURN
    506 	   (_bcm_board_e2e_fbx_unit(unit, lmod, cos, vlan, mac,
    507 				    rmod, rpstate));
    508     }
    509 #endif /* BCM_FIREBOLT_SUPPORT */
    510 
    511     return BCM_E_NONE;
    512 }
    513 
    514