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

tdm_ap_chk.c (51665B)


      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  * $All Rights Reserved.$
      7  *
      8  * TDM chip self-check operations
      9  */
     10 #ifdef _TDM_STANDALONE
     11 	#include <tdm_top.h>
     12 #else
     13 	#include <soc/tdm/core/tdm_top.h>
     14 #endif
     15 
     16 
     17 /**
     18 @name: tdm_ap_chk_ethernet
     19 @param: int, enum[], int[][], int[]
     20 
     21 Returns BOOL_TRUE or BOOL_FALSE depending on if pipe of the given port has traffic entirely Ethernet.
     22  */
     23 int tdm_ap_chk_ethernet(tdm_mod_t *_tdm)
     24 {
     25 	int result, chk[2];
     26 	chk[0] = BOOL_FALSE; chk[1] = BOOL_FALSE;
     27 	
     28 	/* PIPE_X */
     29 	if(_tdm->_core_data.vars_pkg.pipe == AP_PIPE_X_ID){
     30 		_tdm->_core_data.vars_pkg.port = 1;
     31 		chk[0] = tdm_ap_check_ethernet(_tdm);
     32 		_tdm->_core_data.vars_pkg.port = 37;
     33 		chk[1] = tdm_ap_check_ethernet(_tdm);
     34 	}
     35 	result = (chk[0] && chk[1]) ? (BOOL_TRUE) : (BOOL_FALSE);
     36 	return result;
     37 	
     38 }
     39 
     40 
     41 /**
     42 @name: tdm_ap_chk_struc
     43 @param:
     44 
     45 Checks length, overflow, and symmetry (determinism between IDB and MMU tables)
     46  */
     47 int tdm_ap_chk_struc(tdm_mod_t *_tdm)
     48 {
     49 	int result, max_len, tbl_len=0, freq;
     50 	
     51 	result = PASS;
     52 	freq   = _tdm->_chip_data.soc_pkg.clk_freq;
     53 		
     54 	/* Ethernet */
     55 	if ( tdm_ap_chk_ethernet(_tdm) ) {
     56 		switch (freq) {
     57       /*AP*/
     58 			case 933: max_len=233; break;
     59 			case 840: max_len=212; break;
     60 			case 793: 
     61                         case 794: 
     62                         case 795: 
     63                         case 796: 
     64                         case 797: 
     65                           max_len=402; break;
     66 			case 575: max_len=145; break;
     67 			case 510: max_len=129; break;
     68 			case 435: max_len=110; break;
     69 
     70 			default:
     71 				TDM_ERROR0("TDM structure check received unrecognized frequency\n");
     72 				return UNDEF;
     73 				break;
     74 		}
     75 	}
     76 	/* Highgig */
     77 	else {
     78 		switch (freq) {
     79       /*AP*/
     80 			case 933: max_len=233; break;
     81 			case 840: max_len=212; break;
     82 			case 793: 
     83                         case 794:
     84                         case 795: 
     85                         case 796: 
     86                         case 797: 
     87                           max_len=402; break;
     88 			case 575: max_len=145; break;
     89 			case 510: max_len=129; break;
     90 			case 435: max_len=110; break;
     91 			default:
     92 				TDM_ERROR0("TDM structure check received unrecognized frequency\n");
     93 				return UNDEF;
     94 				break;
     95 		}	
     96 	}
     97 	
     98 	/* Actual calender length */
     99 	switch (_tdm->_core_data.vars_pkg.pipe){
    100 		case AP_PIPE_X_ID: tbl_len= _tdm->_chip_data.cal_2.cal_len; break;
    101 		default:
    102 			TDM_ERROR0("TDM structure check received unrecognized pipe ID\n");
    103 			return UNDEF;
    104 			break;
    105 	}
    106 	
    107 	if (tbl_len>max_len){
    108 		result=FAIL; 
    109 		TDM_ERROR3("TDM pipe %0d TDM length %0d slots, spec %0d slots\n",_tdm->_core_data.vars_pkg.pipe,tbl_len,max_len);
    110 	}
    111 	return result;
    112 }
    113 
    114 
    115 /**
    116 @name: tdm_ap_chk_tsc
    117 @param:
    118 
    119 Verifies TSC transcription of all ports indexed in bcm configuration
    120  */
    121 int tdm_ap_chk_tsc(tdm_mod_t *_tdm)
    122 {
    123 	int i, j, k, result=PASS, result_i, num_lanes; 
    124 	int **port_pmap, num_pm_lanes, num_ext_ports;
    125 	enum port_speed_e *port_speeds;
    126 	enum port_state_e *port_states;
    127 	
    128 	port_states  = _tdm->_chip_data.soc_pkg.state;
    129 	port_speeds  = _tdm->_chip_data.soc_pkg.speed;
    130 	port_pmap    = _tdm->_chip_data.soc_pkg.pmap;
    131 	num_pm_lanes = _tdm->_chip_data.soc_pkg.pmap_num_lanes;
    132 	num_ext_ports= _tdm->_chip_data.soc_pkg.num_ext_ports;
    133 	/*num_phy_pm   = _tdm->_chip_data.soc_pkg.pm_num_phy_modules;*/
    134 	
    135 	for (i=1; i<(num_ext_ports-57); i++){
    136 		/* check if port is active */
    137 		if (  port_states[i-1]==PORT_STATE__LINERATE    || 
    138 			  port_states[i-1]==PORT_STATE__OVERSUB     ||
    139 			  port_states[i-1]==PORT_STATE__LINERATE_HG ||
    140 			  port_states[i-1]==PORT_STATE__OVERSUB_HG  ){
    141 			result_i = PASS;
    142 			/* Check tsc numbering */
    143 			_tdm->_core_data.vars_pkg.port = i;
    144 			  if(tdm_ap_which_tsc(_tdm)==num_ext_ports){
    145 			  	TDM_ERROR1("TDM TSC check failed to transcribe port %0d\n",i);
    146 			  	result_i = FAIL;
    147 			  }
    148 			  /* Check legal lane configs to see if port speed can fit (AP) */
    149 			  else{
    150 			  	num_lanes=0;
    151 			  	if ( (i ==17 || i==53) && port_speeds[i]>=SPEED_100G){
    152 			  	  	for (k=0; k<3; k++){
    153 			  	  		for(j=0; j<num_pm_lanes; j++){
    154 			  	  			if(port_pmap[(i-1+k)/num_pm_lanes][j]==i){++num_lanes;}
    155 			  	  		}
    156 			  	  	}
    157             }
    158 			  	else{
    159 			  		for(j=0; j<num_pm_lanes; j++){
    160 			  			if(port_pmap[(i-1)/num_pm_lanes][j]==i){++num_lanes;}
    161 			  		}
    162 			  	}
    163 			  	
    164 			  	switch (port_speeds[i]) {
    165 			  		case SPEED_1G: 
    166 			  		case SPEED_2p5G:
    167 			  		case SPEED_10G: 
    168 			  		case SPEED_10G_DUAL:
    169 			  		case SPEED_10G_XAUI:
    170 			  		case SPEED_25G:
    171 			  			if (num_lanes!=1 && num_lanes !=4) {result_i = FAIL;} 
    172 			  			break;
    173 			  		case SPEED_20G:
    174               if((i>= 29 && i<= 35) || (i>= 65 && i<= 71)) {
    175 			  			if (num_lanes!=1) {result_i = FAIL;} 
    176 			  			break;
    177               }
    178               else { if (num_lanes!=2) {result_i = FAIL;}
    179               break;
    180               }
    181 			  		case SPEED_50G:
    182 			  			if (num_lanes!=2) {result_i = FAIL;} 
    183 			  			break;
    184 			  		case SPEED_40G: 
    185 			  		case SPEED_42G:
    186               if((i>= 29 && i<= 35) || (i>= 65 && i<= 71)) {
    187 			  			if (num_lanes!=2) {result_i = FAIL;} 
    188 			  			break;
    189               }
    190               else { if (num_lanes!=4) {result_i = FAIL;}
    191               break;
    192               }
    193 			  		case SPEED_100G:
    194               if( i==17 || i==53){ 
    195 			  			if (num_lanes<10) {result_i = FAIL;}
    196 			  			break;
    197               }
    198               else { if (num_lanes!=4) {result_i = FAIL;}
    199               break;
    200               }
    201 			  		case SPEED_120G:
    202 			  			if (num_lanes<12) {result_i = FAIL;}
    203 			  			break;
    204 			  		default:
    205 			  			result_i = UNDEF;
    206 			  			break;			
    207 			  	}
    208 			  	if (result_i==FAIL) {
    209 			  		TDM_ERROR2("TDM TSC check found illegal TSC config for port %0d speed %0dG\n",i,(port_speeds[i]/1000));
    210 			  		result = FAIL;
    211 			  	}
    212 			  	else if (result_i==UNDEF){
    213 			  		TDM_ERROR2("TDM TSC check found unrecognized speed %0dG for port %0d\n",(port_speeds[i]/1000),i);
    214 			  		result = FAIL;
    215 			  	}
    216 			  }
    217 	  }
    218   }
    219 	
    220 	return result;
    221 }
    222 
    223 
    224 /**
    225 @name: tdm_ap_chk_min
    226 @param:
    227 
    228 Checks min spacing in TDM (TSC sister port spacing)
    229  */
    230 int tdm_ap_chk_min(tdm_mod_t *_tdm)
    231 {
    232 	int i, j, result=PASS, cal_len, *cal_main; 
    233 	const char *table;
    234 	unsigned short mmu_mtbl[1024];
    235 	
    236 
    237 	/* check pipe ID */
    238 	switch (_tdm->_core_data.vars_pkg.pipe) {
    239 		/*
    240 		case 0: table = "IDB Pipe 0"; break;
    241 		case 1: table = "IDB Pipe 1"; break;		
    242 		case 2: table = "IDB Pipe 2"; break;		
    243 		case 3: table = "IDB Pipe 3"; break; */
    244 		case 2: table = "MMU Pipe 0"; 
    245 				cal_main=_tdm->_chip_data.cal_2.cal_main; 
    246 				cal_len=_tdm->_chip_data.cal_2.cal_len; 
    247 				break;
    248 
    249 		default:
    250 			result = UNDEF;
    251 			TDM_ERROR1("Min spacing check failed, unrecognized PIPE ID %0d\n",_tdm->_core_data.vars_pkg.pipe);
    252 			break;
    253 	}
    254 	if (result!=PASS){	return result;}
    255 	
    256 	/* Mirror the tables to make loopback easier to navigate */
    257 	for (i=0; i<cal_len; i++) {
    258 		mmu_mtbl[i]        = cal_main[i]; 
    259 		mmu_mtbl[i+cal_len]= cal_main[i];
    260 	}
    261 	/* Check Min same port spacing for each active port */
    262 	for (i=0; i<cal_len; i++){
    263  		AP_TOKEN_CHECK(mmu_mtbl[i]) {
    264       for (j=1; j<VBS_MIN_SPACING; j++) {
    265     	  if(mmu_mtbl[i+j] == mmu_mtbl[i]) {
    266 						result = FAIL;
    267 						TDM_ERROR4("%s MIN same port spacing violation port %0d, (#%03d | #%03d)\n",table,mmu_mtbl[i],i,(i+j));
    268 				}
    269       }
    270     }
    271   }
    272 
    273   /*Nak , no sister port spacing requirement in AP */
    274 /*	for (i=1; i<cal_len; i++){
    275 		AP_TOKEN_CHECK(mmu_mtbl[i]) {
    276 			tsc0 = tdm_ap_legacy_which_tsc(mmu_mtbl[i],tsc);
    277 			for (j=1; j<VBS_MIN_SPACING; j++) {
    278 				AP_TOKEN_CHECK(mmu_mtbl[i+j]) {
    279 					tsc1 = tdm_ap_legacy_which_tsc(mmu_mtbl[i+j],tsc);
    280 					if (tsc0==tsc1){
    281 						result = FAIL;
    282 						TDM_ERROR8("%s MIN spacing violation port %0d, (#%03d | #%03d), TSC: [%0d, %0d, %0d, %0d]\n",table,mmu_mtbl[i],i,(i+j),
    283 							tsc[tdm_ap_legacy_which_tsc(mmu_mtbl[i+j],tsc)][0],
    284 							tsc[tdm_ap_legacy_which_tsc(mmu_mtbl[i+j],tsc)][1],
    285 							tsc[tdm_ap_legacy_which_tsc(mmu_mtbl[i+j],tsc)][2],
    286 							tsc[tdm_ap_legacy_which_tsc(mmu_mtbl[i+j],tsc)][3]);
    287 					}
    288 				}
    289 			}
    290 		}
    291 	}*/
    292 	/* Check Min same port spacing for each CPU and LPBK port */
    293 	for (i=0; i<cal_len; i++){
    294     if(mmu_mtbl[i] == AP_CPU_PORT) {
    295       for (j=1; j<LLS_MIN_SPACING; j++) {
    296     	  if(mmu_mtbl[i+j] == AP_CPU_PORT ) {
    297 						result = FAIL;
    298 						TDM_ERROR4("%s MIN same port spacing violation for CPU port %0d, (#%03d | #%03d)\n",table,mmu_mtbl[i],i,(i+j));
    299 				}
    300       }
    301     }
    302   }
    303 	for (i=0; i<cal_len; i++){
    304     if(mmu_mtbl[i] == AP_LOOPBACK_PORT) {
    305       for (j=1; j<LLS_MIN_SPACING; j++) {
    306     	  if(mmu_mtbl[i+j] == AP_LOOPBACK_PORT ) {
    307 						result = FAIL;
    308 						TDM_ERROR4("%s MIN same port spacing violation for LOOPBACK port %0d, (#%03d | #%03d)\n",table,mmu_mtbl[i],i,(i+j));
    309 				}
    310       }
    311     }
    312   }	
    313 	return result;
    314 }
    315 
    316 
    317 /**
    318 @name: tdm_ap_chk_sub_lr
    319 @param:
    320 
    321 Checks that all line rate nodes were extracted from solution matrix
    322  */
    323 int tdm_ap_chk_sub_lr( tdm_mod_t *_tdm)
    324 {
    325 	int i, j, idx_0, idx_1, result=PASS, result_i, port_spd_M, port_spd_G, found_nodes,
    326 	    *cal_main, cal_len, pipe_id, clk_freq;
    327 	const char *table;
    328 	enum port_speed_e *port_speeds;
    329 	enum port_state_e *port_states;
    330 	
    331 	pipe_id    = _tdm->_core_data.vars_pkg.pipe;
    332 	clk_freq   = _tdm->_chip_data.soc_pkg.clk_freq;
    333 	port_speeds= _tdm->_chip_data.soc_pkg.speed;
    334 	port_states= _tdm->_chip_data.soc_pkg.state;
    335 	
    336 	/* check pipe ID */
    337 	switch (pipe_id) {
    338 		/*
    339 		case 0: table = "IDB Pipe 0"; break;
    340 		case 1: table = "IDB Pipe 1"; break;		
    341 		case 2: table = "IDB Pipe 2"; break;		
    342 		case 3: table = "IDB Pipe 3"; break; */
    343 		case 2: table    = "MMU Pipe 0"; 
    344 				cal_main = _tdm->_chip_data.cal_2.cal_main; 
    345 				cal_len  = _tdm->_chip_data.cal_2.cal_len;
    346 				idx_0    = 1;
    347 				idx_1    = 72;
    348 				break;
    349 		default: 
    350 			result = UNDEF;
    351 			TDM_ERROR1("Linerate subscription check failed, unrecognized PIPE ID %0d\n",pipe_id);
    352 			break;
    353 	}
    354 	if (result!=PASS){return result;}
    355 	
    356 	/* Check frequency */
    357 	if (clk_freq>933) {
    358 		TDM_ERROR2("Linerate subscription check failed in %s, unrecognized chip frequency %d\n",table,clk_freq );
    359 		return UNDEF;
    360 	}
    361 	/* Check linerate port speed */
    362 	for (i=idx_0; i<=idx_1; i++) {
    363 		if (port_states[i-1]==PORT_STATE__LINERATE   || 
    364 			port_states[i-1]==PORT_STATE__LINERATE_HG){
    365 			result_i = PASS;
    366 			
    367 			/* Check speed type */
    368 			port_spd_M = port_speeds[i];
    369 			port_spd_G = port_spd_M/1000;
    370 			switch (port_spd_G){
    371 				case 1:
    372 				case 2:
    373 				case 10:
    374 				case 20: case 21:
    375 				case 25:
    376 				case 40: case 42:
    377 				case 50:
    378 				case 100: 
    379 				case 120:
    380 					break;
    381 				default:
    382 					result_i = UNDEF;
    383 					TDM_ERROR3("Linerate subscription check failed in %s, unrecognized speed %0d (Gbps) for port %0d\n",table,port_spd_G,i);
    384 					break;
    385 			}
    386 			
    387 			/* Check port rate */
    388 			found_nodes=0;
    389 			for (j=0; j<cal_len; j++) {
    390 				if (cal_main[j]==i) {
    391 					found_nodes++;
    392 				}
    393 			}
    394 			if(found_nodes==0){
    395 				TDM_ERROR3("Linerate subscription check failed in %s, port %0d is enabled but not scheduled in calender, %0d slots\n", table, i,found_nodes);
    396 				result_i = FAIL;
    397 			}
    398 			else if ( found_nodes < ((port_spd_M*10)/1000/(BW_QUANTA)) ) {
    399 				TDM_ERROR5("Linerate subscription failed in %s, %0dG vector for port %0d expected %0d nodes (found %0d)\n",table,port_spd_G,i,((port_spd_M*10)/1000/(BW_QUANTA)),found_nodes);
    400 				result_i = FAIL;
    401 			}
    402 			
    403 			result = (result==FAIL) ? (result): (result_i);
    404 		}	
    405 	}
    406 	
    407 	return result;
    408 }
    409 
    410 
    411 /**
    412 @name: tdm_ap_chk_sub_os
    413 @param:
    414 
    415 Checks that the oversub node is sorted into oversub speed groups
    416  */
    417 int tdm_ap_chk_sub_os(tdm_mod_t *_tdm)
    418 {
    419 	int i, j, k, idx_0, idx_1, result=PASS, result_i, group_idx, slot_idx, is_found,
    420 	    **cal_grp, cal_grp_num, cal_grp_len,pipe_id, port_spd_M;
    421 	const char *table;
    422 	enum port_speed_e *port_speeds;
    423 	enum port_state_e *port_states;
    424 	
    425 	port_speeds= _tdm->_chip_data.soc_pkg.speed;
    426 	port_states= _tdm->_chip_data.soc_pkg.state;
    427 	pipe_id    = _tdm->_core_data.vars_pkg.pipe;
    428 	
    429 	/* check pipe id */
    430 	switch (pipe_id) {
    431 		/*
    432 		case 0: table = "IDB Pipe 0"; break;
    433 		case 1: table = "IDB Pipe 1"; break;		
    434 		case 2: table = "IDB Pipe 2"; break;		
    435 		case 3: table = "IDB Pipe 3"; break; */
    436 		case 2: table = "MMU Pipe 0"; 
    437 				cal_grp     = _tdm->_chip_data.cal_2.cal_grp; 
    438 				cal_grp_num = _tdm->_chip_data.cal_2.grp_num; 
    439 				cal_grp_len = _tdm->_chip_data.cal_2.grp_len;
    440 				idx_0       = 1;
    441 				idx_1       = 72;
    442 				break;
    443 		default:
    444 			result = UNDEF;
    445 			TDM_ERROR1("Oversub subscription check failed, unrecognized PIPE ID %0d\n",pipe_id);
    446 			break;
    447 	}
    448 	if (result!=PASS){return result;}
    449 	
    450 	
    451 	for (i=idx_0; i<=idx_1; i++){
    452 		if (port_states[i-1]==PORT_STATE__OVERSUB   ||
    453 			port_states[i-1]==PORT_STATE__OVERSUB_HG){
    454 			result_i   = PASS;
    455 			port_spd_M = port_speeds[i];
    456 			/* determine ovsb speed group */
    457 			group_idx  = 0;
    458 			slot_idx   = 0;
    459 			is_found   = BOOL_FALSE;
    460 			for (j=0; j<cal_grp_num ; j++) {
    461 				for (k=0; k<cal_grp_len; k++){
    462 					if((cal_grp[j][k]) == i){
    463 						is_found  = BOOL_TRUE;
    464 						group_idx = j;
    465 						slot_idx  = k;
    466 						break;
    467 					}
    468 				}
    469 			}
    470 			/* check port speed with the corresponding speed group */
    471 			if (is_found == BOOL_FALSE) {
    472 				TDM_ERROR1("Oversub subscription check failed, could not find passed port %0d in any oversub speed group\n",i);
    473 				result_i = FAIL;
    474 			}
    475 			else if (port_spd_M>=SPEED_10G && (port_spd_M>(port_speeds[cal_grp[group_idx][0]]+1010) || port_spd_M<(port_speeds[cal_grp[group_idx][0]]-1010))) {
    476 				TDM_ERROR6("Oversub subscription check failed in %s, OVSB group %0d slot #%0d port %0d speed %0dG mismatches %0dG group assginment\n",table,group_idx,slot_idx,i,(port_spd_M/1000),port_speeds[cal_grp[group_idx][0]]/1000);
    477 				result_i = FAIL;
    478 			}
    479 			result = (result==FAIL) ? (result): (result_i);
    480 		}
    481 	}
    482 	
    483 	return result;
    484 }
    485 
    486 
    487 /**
    488 @name: tdm_ap_chk_sub_mgmt
    489 @param:
    490 
    491 Checks that CPU bandwidth is satisfied
    492  */
    493 int tdm_ap_chk_sub_cpu( tdm_mod_t *_tdm)
    494 {
    495 	int i, k, result=PASS, cpu_slots_required,  
    496 	    *cal_main, cal_len, clk_freq; 
    497 	
    498 	clk_freq   = _tdm->_chip_data.soc_pkg.clk_freq;
    499 	cal_main   = _tdm->_chip_data.cal_2.cal_main; 
    500 	cal_len    = _tdm->_chip_data.cal_2.cal_len; 
    501 	
    502 	/* determine number of CPU slots  */
    503 	cpu_slots_required = 2;
    504 	if (clk_freq==793 || clk_freq==794 || clk_freq == 795 || clk_freq == 796 || clk_freq == 797) {
    505 		cpu_slots_required=4;
    506 	}
    507 	/* calculate number of actual CPU slots */
    508 	k=0;
    509 	for (i=0; i<cal_len; i++){
    510 		if(cal_main[i] == AP_CPU_PORT){
    511 			k++;
    512 		}
    513 	}
    514 	
    515 	if (k<cpu_slots_required) {
    516 		result = FAIL;
    517 		TDM_ERROR2("Subscription check failed in MMU pipe , CPU port bandwidth is insufficient in this configuration - %0d slots of %0d required\n",k,cpu_slots_required);
    518 	}
    519 	
    520 	return result;
    521 }
    522 
    523 
    524 /**
    525 @name: tdm_ap_chk_sub_lpbk
    526 @param:
    527 
    528 Checks that LOOPBACK bandwidth is satisfied
    529  */
    530 int tdm_ap_chk_sub_lpbk( tdm_mod_t *_tdm)
    531 {
    532 	int i, k, result=PASS, lb_slots_required,
    533 	    *cal_main, cal_len, clk_freq;
    534 	
    535 	clk_freq   = _tdm->_chip_data.soc_pkg.clk_freq;
    536 	cal_main   = _tdm->_chip_data.cal_2.cal_main; 
    537 	cal_len    = _tdm->_chip_data.cal_2.cal_len; 
    538 	
    539 	/* determine number of loopback slots  */
    540 	lb_slots_required = 2;
    541 	if (clk_freq==793 || clk_freq==794 || clk_freq == 795 || clk_freq == 796 || clk_freq == 797) {
    542 			lb_slots_required=4;
    543 	}
    544 	else if (clk_freq==575 || clk_freq==510) {
    545 			lb_slots_required=2;
    546 	}
    547 	else if (clk_freq==435){
    548 		lb_slots_required=3;
    549 	}
    550 	/* calculate number of actual loopback slots */
    551 	k=0;
    552 	for (i=0; i<cal_len; i++) {
    553 		if (cal_main[i]==AP_LOOPBACK_PORT) {
    554 			k++;
    555 		}
    556 	}
    557 	if (k<lb_slots_required) {
    558 		result = FAIL;
    559 		TDM_ERROR2("Subscription check failed in MMU pipe , loopback port bandwidth is insufficient in this configuration - %0d slots of %0d required\n",k,lb_slots_required);
    560 	}
    561 	
    562 	return result;
    563 }
    564 
    565 
    566 /**
    567 @name: tdm_ap_chk_sub_lpbk
    568 @param:
    569 
    570 Checks that AGNOSTIC ACCESSORY bandwidth is satisfied
    571  */
    572 int tdm_ap_chk_sub_acc( tdm_mod_t *_tdm)
    573 {
    574 	int i, k, result=PASS, ac_slots_required,
    575 	    *x_cal_main, x_cal_len, clk_freq;
    576 	
    577 	clk_freq   = _tdm->_chip_data.soc_pkg.clk_freq;
    578 	x_cal_main = _tdm->_chip_data.cal_2.cal_main; 
    579 	x_cal_len  = _tdm->_chip_data.cal_2.cal_len;
    580 
    581 	/* check pipe X */
    582 		ac_slots_required=9;
    583 
    584     if (clk_freq==793 || clk_freq==794  || clk_freq == 795 || clk_freq == 796 || clk_freq == 797){
    585 		ac_slots_required=18;
    586 	  }
    587 		else if (clk_freq==575 || clk_freq==510) {
    588 			ac_slots_required=9;
    589 		}
    590 	  else if (clk_freq==435){
    591 		ac_slots_required=10;
    592 	  }
    593 
    594 		k=0;
    595 		for (i=0; i<x_cal_len; i++) {
    596 			if (x_cal_main[i]==AP_CPU_PORT      ||
    597 				x_cal_main[i]==AP_LOOPBACK_PORT ||
    598 				x_cal_main[i]==AP_AUX_TOKEN    ||
    599 				x_cal_main[i]==AP_SBUS_TOKEN    ||
    600 				x_cal_main[i]==AP_IDL1_TOKEN    ||
    601 				x_cal_main[i]==AP_IDL2_TOKEN    ){
    602 				k++;
    603 			}
    604 		}
    605 		
    606 		if (k<ac_slots_required) {
    607 			result = FAIL;
    608 			TDM_ERROR2("Subscription check failed in MMU pipe X, accessory bandwidth is insufficient in this configuration - %0d slots of %0d required\n",k,ac_slots_required);
    609 		}
    610 	
    611 	return result;
    612 }
    613 
    614 /**
    615 @name: tdm_ap_chk_subscription
    616 @param:
    617 
    618 Check subscription status per port 
    619  */
    620 int tdm_ap_chk_subscription(tdm_mod_t *_tdm)
    621 {
    622 	int rst, result=PASS;
    623 	
    624 	/* 1. Check CPU port */
    625 	if (FAIL==tdm_ap_chk_sub_cpu(_tdm)){
    626 		result = FAIL;
    627 	}
    628 	/* 2. Check Loopback port */
    629 	if (FAIL==tdm_ap_chk_sub_lpbk(_tdm)){
    630 		result = FAIL;
    631 	}
    632 	/* 3. Check Agnostic accessory slots (must be equal to 8 or 10 in TD2/TD2+) */
    633 	if (FAIL==tdm_ap_chk_sub_acc(_tdm)){
    634 		result = FAIL;
    635 	}
    636 	
    637 	/* 4. Check linerate ports */
    638 	_tdm->_core_data.vars_pkg.pipe = AP_XPIPE_CAL_ID;
    639 	rst  = tdm_ap_chk_sub_lr(_tdm);
    640 	if(PASS!=rst){
    641 		result = (result==FAIL) ? (result): (rst);
    642 	}
    643 	
    644 
    645 	/* 5. Check oversub ports */
    646 	_tdm->_core_data.vars_pkg.pipe = AP_XPIPE_CAL_ID;
    647 	rst  = tdm_ap_chk_sub_os(_tdm);
    648 	if(PASS!=rst){
    649 		result = (result==FAIL) ? (result): (rst);
    650 	}
    651 	
    652 	return result;
    653 }
    654 
    655 /**
    656 @name: tdm_ap_chk_os_jitter
    657 @param:
    658 
    659 Checks distribution of oversub tokens to maximize performance of oversub scheduler
    660  */
    661 int tdm_ap_chk_os_jitter(tdm_mod_t *_tdm)
    662 {	
    663 	int i, result=PASS, *cal_main, cal_len, os_range_thresh, os_clump_ave, os_clump_size, os_cnt_idx, lr_cnt_idx, group_size,	clump_cnt=0, lr_bw=0, os_bw=0;
    664 	int ratio_opt, ratio_ave=0, ratio_sum1=0, ratio_sum2=0, ratio_var=0, ratio_i, ratio_floor, ratio_ceil;
    665 	int dist_opt, dist_floor, dist_ceil, dist_i, dist_sum1=0, dist_sum2=0, dist_ave=0, dist_var=0;
    666 	const char *table;
    667 	
    668 	switch (_tdm->_core_data.vars_pkg.pipe) {
    669 		/*
    670 		case 0: table = "IDB Pipe 0"; break;
    671 		case 1: table = "IDB Pipe 1"; break;		
    672 		case 2: table = "IDB Pipe 2"; break;		
    673 		case 3: table = "IDB Pipe 3"; break; */
    674 		case 2: table = "MMU Pipe 0"; 
    675 				cal_main=_tdm->_chip_data.cal_2.cal_main; 
    676 				cal_len=_tdm->_chip_data.cal_2.cal_len; 
    677 				break;
    678 		default: 
    679 			TDM_ERROR1("Oversub jitter check failed, unrecognized PIPE ID %0d\n",_tdm->_core_data.vars_pkg.pipe);
    680 			result = UNDEF; 
    681 			break;
    682 	}
    683 	if (result!=PASS) {return result;}
    684 	
    685 	for (i=0; i<cal_len; i++) {
    686 		if (cal_main[i]==AP_OVSB_TOKEN) {
    687 			os_bw+=BW_QUANTA;
    688 		}
    689 		else {
    690 			lr_bw+=BW_QUANTA;
    691 		}
    692       TDM_PRINT3("os bw=%d lr bw=%d Ap_token=%d \n",  os_bw, lr_bw, AP_OVSB_TOKEN );
    693 	}
    694 	if (lr_bw==0 || os_bw==0) {
    695 		TDM_PRINT1("TDM: Not applicable in - %s\n",table);
    696 		TDM_SML_BAR
    697 		return result;
    698 	}
    699 	
    700 	TDM_PRINT1("TDM: Analyzing oversub - %s\n",table);
    701 	dist_opt    =  (100*((os_bw+lr_bw)/BW_QUANTA)/(os_bw/BW_QUANTA));
    702 	ratio_opt   = dist_opt;
    703 	os_clump_ave= (100*(os_bw/BW_QUANTA))/((lr_bw/BW_QUANTA)+1);
    704 	
    705 	if ((os_bw/10)>=200) {
    706 		os_range_thresh = 100*OS_RANGE_BW_HI;
    707 	}
    708 	else if ( ((os_bw/10)<200) && ((os_bw/10)>=100) ) {
    709 		os_range_thresh = 100*OS_RANGE_BW_MD;
    710 	}
    711 	else {
    712 		os_range_thresh = 100*JITTER_THRESH_MH;
    713 	}
    714 	ratio_floor = ((10000/(dist_opt+os_range_thresh)));
    715 	ratio_ceil  = ((10000/(dist_opt-os_range_thresh)));
    716 	dist_floor  = ((dist_opt-os_range_thresh)>0)? (dist_opt-os_range_thresh): (100);
    717 	dist_ceil   = dist_opt+os_range_thresh;
    718 	
    719 	TDM_PRINT4("TDM:%12s|%12s|%12s|%12s\n","Ratio","Optimal", "Floor","Ceiling");
    720 	TDM_PRINT4("TDM:%12s|%12d|%12d|%12d\n"," ",ratio_opt,ratio_floor,ratio_ceil);
    721 	
    722 	for (i=1; i<cal_len; i++) {
    723 		if (cal_main[i]==AP_OVSB_TOKEN) {
    724 			os_clump_size=100; os_cnt_idx=i; lr_cnt_idx=i;
    725 			while (os_cnt_idx<cal_len && cal_main[++os_cnt_idx]==AP_OVSB_TOKEN) {os_clump_size += 100;}
    726 			group_size=os_clump_size;
    727 			while(lr_cnt_idx>0 && cal_main[--lr_cnt_idx]!=AP_OVSB_TOKEN) {group_size += 100;}
    728 			
    729 			ratio_i = (100*os_clump_size/(group_size));
    730 			dist_i  = (100*group_size)/(os_clump_size);
    731 			
    732 			TDM_PRINT4("\t\t[%3d]\t|\tSlots = %2d\t|\tSlice size = %2d\t|\tGrant ratio = %0d\n",i,os_clump_size,group_size,ratio_i);
    733 			if ( (ratio_i<ratio_floor) || (ratio_i>ratio_ceil) ) {
    734 				TDM_PRINT2("\t\tGrant ratio suboptimal range is [%0d, %0d]\n",ratio_floor,ratio_ceil);
    735 			}
    736 			ratio_sum1+=ratio_i;
    737 			ratio_sum2+=((ratio_i-ratio_opt)*(ratio_i-ratio_opt))/100;
    738 			dist_sum1 += dist_i;
    739 			dist_sum2 += ((dist_i-dist_opt)*(dist_i-dist_opt))/100;
    740 			clump_cnt++;
    741 			
    742 			if (os_clump_size>(os_clump_ave+os_range_thresh)) {
    743 				TDM_PRINT3("\t\tOversub slice suboptimal, size %0d index %0d, limit %0d\n",os_clump_size,i,(os_clump_ave+os_range_thresh));
    744 			}
    745 			while (cal_main[i+1]==AP_OVSB_TOKEN) {i++;}
    746 		}
    747 	}
    748 	if(clump_cnt!=0){
    749 		ratio_ave = (ratio_sum1)/clump_cnt;
    750 		ratio_var = tdm_sqrt(ratio_sum2/clump_cnt);
    751 		dist_ave  = dist_sum1/clump_cnt;
    752 		dist_var  = tdm_sqrt(dist_sum2/clump_cnt);
    753 	
    754 		if ( (ratio_ave<ratio_floor) || (ratio_ave>ratio_ceil) || (dist_var>os_range_thresh) ) {
    755 			result = FAIL;
    756 		}
    757 		if ( (dist_ave<dist_floor) || (dist_ave>dist_ceil) || (dist_var>os_range_thresh) ) {
    758 			result = FAIL;
    759 		}
    760 	}
    761 	
    762 	TDM_SML_BAR
    763 	TDM_PRINT1("TDM:\tTracked %0d oversub slices in calendar\n",clump_cnt);
    764 	TDM_PRINT2("TDM:\t\t\tRatio    - Optimal Range  = [%0d, %0d]\n",ratio_floor, ratio_ceil);
    765 	TDM_PRINT1("TDM:\t\t\tRatio    - Optimal Value  = %0d\n",ratio_opt);
    766 	TDM_PRINT1("TDM:\t\t\tRatio    - Grant Average  = %0d\n",ratio_ave);
    767 	TDM_PRINT1("TDM:\t\t\tRatio    - Grant Variance = %0d\n",ratio_var);
    768 	TDM_PRINT0("\n");
    769 	TDM_PRINT2("TDM:\t\t\tDistance - Optimal Range    = [%0d, %0d]\n",dist_floor, dist_ceil);
    770 	TDM_PRINT1("TDM:\t\t\tDistance - Optimal Value    = %0d\n",dist_opt);
    771 	TDM_PRINT1("TDM:\t\t\tDistance - Jitter Tolerance = %0d slots\n",os_range_thresh);
    772 	TDM_PRINT1("TDM:\t\t\tDistance - Grant Average    = %0d\n",dist_ave);
    773 	TDM_PRINT1("TDM:\t\t\tDistance - Grant Variance   = %0d\n",dist_var);
    774 	TDM_SML_BAR
    775 	
    776 	return result;
    777 }
    778 
    779 
    780 /**
    781 @name: tdm_ap_chk_lr_jitter
    782 @param:
    783 
    784 Checks jitter of line rate ports
    785  */
    786 int tdm_ap_chk_lr_jitter(tdm_mod_t *_tdm, int fail[16])
    787 {
    788 	int i, j, num=1, avg=0, rate=0, ports_done[AP_NUM_EXT_PORTS], done_idx=0, exists, jitter, is_spd_valid;
    789 	int *cal_main, cal_len, pipe_id, clk_freq, result=PASS, distance, port_spd_G, port_phyID, mirror_tbl[1024], tracker[AP_LR_VBS_LEN];
    790 	const char *table;
    791 	enum port_speed_e *port_speeds;
    792 	
    793 	fail[6] = PASS;
    794 	fail[5] = (fail[5]==UNDEF || fail[5]==PASS) ? (PASS) : (fail[5]);
    795 	
    796 	clk_freq   = _tdm->_chip_data.soc_pkg.clk_freq;
    797 	port_speeds= _tdm->_chip_data.soc_pkg.speed;
    798 	pipe_id    = _tdm->_core_data.vars_pkg.pipe;
    799 	
    800 	for (i=0; i<(AP_NUM_EXT_PORTS-56); i++) {ports_done[i]=AP_NUM_EXT_PORTS;}
    801 	
    802 	switch (pipe_id) {
    803 		/*
    804 		case 0: table = "IDB Pipe 0"; break;
    805 		case 1: table = "IDB Pipe 1"; break;		
    806 		case 2: table = "IDB Pipe 2"; break;		
    807 		case 3: table = "IDB Pipe 3"; break; */
    808 		case 2: table = "MMU Pipe 0"; 
    809 				cal_main=_tdm->_chip_data.cal_2.cal_main; 
    810 				cal_len=_tdm->_chip_data.cal_2.cal_len; 
    811 				break;
    812 		default:
    813 			fail[5] = (fail[5]==FAIL || fail[5]==UNDEF) ? (fail[5]):(UNDEF);
    814 			fail[6] = (fail[6]==FAIL || fail[6]==UNDEF) ? (fail[6]):(UNDEF);
    815 			TDM_ERROR1("Line-rate jitter check failed, unrecognized PIPE ID %0d\n",pipe_id);
    816 			result = UNDEF; 
    817 			break;
    818 	}
    819 	if (result!=PASS) {return result;}
    820 	
    821 	/* Construct "tracker" based on a mirror table of cal_main */
    822 	for (i=0; i<cal_len; i++) {mirror_tbl[i] = cal_main[i]; mirror_tbl[i+cal_len] = cal_main[i];}
    823 	for (i=0; i<cal_len; i++) {tracker[i] = 0;}
    824 	for (i=0; i<cal_len; i++) {
    825 		AP_TOKEN_CHECK(mirror_tbl[i]){
    826 			distance=0;
    827 			for (j=1; j<cal_len; j++) {
    828 				distance++;
    829 				if (mirror_tbl[i+j]==mirror_tbl[i]) {tracker[i]=distance; break;}
    830 			}
    831 		}
    832 	}
    833 	
    834 	/* Check Line-rate ports */
    835 	for (i=0; i<cal_len; i++) {
    836 		if (tracker[i]==0) {continue;}
    837 			port_phyID = cal_main[i];
    838 			
    839 			exists=BOOL_FALSE;
    840 			for (j=0; j<done_idx; j++) {
    841 				if (ports_done[j]==port_phyID) {
    842 					exists=BOOL_TRUE;
    843 					break;
    844 				}
    845 			}
    846 			if (exists==BOOL_FALSE) {
    847 				ports_done[done_idx++]=port_phyID;
    848 				
    849 				/* Set jitter threshold */
    850 				port_spd_G   = port_speeds[port_phyID]/1000;
    851 				is_spd_valid = BOOL_TRUE;
    852 				switch(port_spd_G) {
    853 					case 1: case 2:
    854 						jitter = cal_len;
    855 						break;
    856 					case 10:
    857 						jitter = 21; /* Jitter range from SW TDM Generation Spec for Apache */
    858 						break;
    859 					case 20: case 21: case 25:
    860 						jitter = JITTER_THRESH_MH;
    861 						break;
    862 					case 40:case 42:case 50:
    863 						jitter = 5;
    864 						break;
    865 					case 100: case 120:
    866 						jitter = 2;
    867 						break;
    868 					default:
    869 						fail[5] = (fail[5]==FAIL || fail[5]==UNDEF) ? (fail[5]):(UNDEF);
    870 						fail[6] = (fail[6]==FAIL || fail[6]==UNDEF) ? (fail[6]):(UNDEF);
    871 						TDM_ERROR3("Line-rate jitter check failed in %s, unrecognized port speed %0d at port %0d\n",table,port_spd_G,port_phyID);
    872 						is_spd_valid = BOOL_FALSE;
    873 						break;
    874 				}
    875 				
    876 				/* Check linerate port jitter */
    877 				if(is_spd_valid==BOOL_TRUE){
    878 					/* Calculate grant speed */
    879 					num=0;
    880 					for (j=0; j<cal_len; j++) {
    881 						if (cal_main[j]==port_phyID) {
    882 							++num;
    883 						}
    884 					}
    885 					avg  = (cal_len/num);
    886 					rate = (((PKT_SIZE+PKT_PREAMBLE+PKT_IPG)*800)/(2*avg*(100000/clk_freq)));
    887 					/* Check grant speed with expected speed */
    888 					if (rate < port_spd_G) {
    889 						/* 
    890 						fail[6] = (fail[6]==FAIL || fail[6]==UNDEF) ? (fail[6]):(FAIL);
    891 						TDM_PRINT4("TDM: _____WARNING: Line-rate jitter checker in %s, port %0d projected rate %0dG to operate under line rate %0dG\n",table,port_phyID,rate,port_spd_G); */
    892 						fail[6] = FAIL;
    893 						TDM_ERROR4("Line-rate jitter checker in %s, port %0d projected rate %0dG to operate under line rate %0dG\n",table,port_phyID,rate,port_spd_G);
    894 					}
    895 					/* Check jitters for all slots allocated to the same port. */
    896 					for (j=0; j<cal_len; j++){
    897 						if (cal_main[j]==port_phyID) {
    898 							if (tracker[j] > (avg+1+jitter) ) {
    899 								/* fail[5] = (fail[5]==FAIL || fail[5]==UNDEF) ? (fail[5]):(FAIL);
    900 								TDM_PRINT6("TDM: _____WARNING: Line-rate jitter checker in %s, excess jitter, %0dG port %0d index %0d past threshold %0d with %0d\n",table,port_spd_G,port_phyID,j,(avg+1+jitter),tracker[j]); */
    901 								fail[5] = FAIL;
    902 								TDM_ERROR6("Line-rate jitter checker in %s, excess jitter, %0dG port %0d index %0d past threshold %0d with %0d\n",table,port_spd_G,port_phyID,j,(avg+1+jitter),tracker[j]);
    903 							}
    904 						}
    905 					}
    906 				}
    907 			}
    908 	  }
    909 
    910 	return ((fail[5]==PASS && fail[6]==PASS) ? (PASS) : (FAIL));
    911 }
    912 
    913 /**
    914 @name: tdm_ap_chk_lls
    915 @param:
    916 
    917 Checks linked list scheduler
    918  */
    919 int tdm_ap_chk_lls(tdm_mod_t *_tdm)
    920 {
    921 	int i, j, k, port_phyID, result=PASS, *cal_main, cal_len, pipe_id, clk_freq, min_spacing, line_rate=BOOL_TRUE;
    922 	const char *table;
    923 	enum port_speed_e *port_speeds;
    924 	
    925 	port_speeds= _tdm->_chip_data.soc_pkg.speed;
    926   clk_freq   = _tdm->_chip_data.soc_pkg.clk_freq;
    927 	pipe_id    = _tdm->_core_data.vars_pkg.pipe;
    928 	
    929 	switch (pipe_id) {
    930 		case 2: table = "MMU Pipe 0"; 
    931 				cal_main=_tdm->_chip_data.cal_2.cal_main; 
    932 				cal_len=_tdm->_chip_data.cal_2.cal_len; 
    933 				break;
    934 		default: 
    935 			TDM_ERROR1("LLS check failed, unrecognized PIPE ID %0d\n",pipe_id);
    936 			result = UNDEF; 
    937 			break;
    938 	}
    939 	if (result!=PASS) {return result;}
    940 
    941 	for (i=0; i<cal_len; i++) {
    942 		if(cal_main[i] == AP_OVSB_TOKEN){
    943     line_rate= BOOL_FALSE;
    944     break;
    945     }
    946   }
    947  if(line_rate) {
    948 	for (i=0; i<cal_len; i++) {
    949 		port_phyID = cal_main[i];
    950 		AP_TOKEN_CHECK(port_phyID){
    951 	  	switch (clk_freq) {
    952 	  		case 933: 
    953           min_spacing=LLS_MIN_SPACING; break;
    954 	  		case 793: 
    955                         case 794:
    956                         case 795:
    957                         case 796:
    958                         case 797:
    959           if (port_speeds[port_phyID]<SPEED_42G) {min_spacing=(LLS_MIN_SPACING-2);}
    960           else if (port_speeds[port_phyID]>=SPEED_100G) {min_spacing=(LLS_MIN_SPACING-6);}
    961           else if (port_speeds[port_phyID]==SPEED_50G) {min_spacing=(LLS_MIN_SPACING-4);}
    962           else {min_spacing=LLS_MIN_SPACING;}
    963         break;
    964 	  		case 575: 
    965           min_spacing=(LLS_MIN_SPACING-4); break;
    966 	  		case 435: 
    967           min_spacing=(LLS_MIN_SPACING-6); break;
    968 	  		default: 
    969           min_spacing=LLS_MIN_SPACING; break;
    970 	  	}
    971 			for (j=1; j<min_spacing; j++) {
    972 				k = ( (i+j)<cal_len) ? (i+j) : (i+j-cal_len) ;
    973 				if (cal_main[k]==port_phyID) {
    974 					result=FAIL; 
    975 					TDM_ERROR4("LLS check failed in %s, port %0d between [%0d,%0d] violates LLS min spacing requirement\n",table, port_phyID,i,k);
    976 					break;
    977 				}
    978 			}
    979 		}
    980 	}
    981    
    982 	for (i=0; i<cal_len; i++){
    983  		AP_TOKEN_CHECK(cal_main[i]) {
    984 				k = ( (i+6)<cal_len) ? (i+6) : (i+6-cal_len) ;
    985     	  if(cal_main[k] == cal_main[i]) {
    986 						result = FAIL;
    987 						TDM_ERROR4("%s LLS 1:6 same port spacing violation port %0d, (#%03d | #%03d)\n",table,cal_main[i],i,k);
    988 				}
    989 				k = ( (i+8)<cal_len) ? (i+8) : (i+8-cal_len) ;
    990     	  if(cal_main[k] == cal_main[i]) {
    991 						result = FAIL;
    992 						TDM_ERROR4("%s LLS 1:8 same port spacing violation port %0d, (#%03d | #%03d)\n",table,cal_main[i],i,k);
    993 				}
    994       }
    995     }
    996   }
    997 	return result;
    998 }
    999 
   1000 /**
   1001 @name: tdm_ap_chk_ovs_space
   1002 @param:
   1003 
   1004 Checks that no port is back to back in the OVS table
   1005  */
   1006 int tdm_ap_chk_ovs_space( tdm_mod_t *_tdm)
   1007 {
   1008 	int i, result=PASS, cal0_len, cal1_len,
   1009 	    *ovs_cal0, *ovs_cal1;
   1010 
   1011 
   1012 	ovs_cal0 = _tdm->_chip_data.cal_0.cal_grp[0];
   1013   ovs_cal1 = _tdm->_chip_data.cal_1.cal_grp[0];
   1014 
   1015   for(i =0; i<AP_OS_LLS_GRP_LEN; i++) {
   1016     if(ovs_cal0[i] == AP_NUM_EXT_PORTS) break;
   1017    }
   1018   cal0_len = i;
   1019 
   1020   for(i =0; i<AP_OS_LLS_GRP_LEN; i++) {
   1021     if(ovs_cal1[i] == AP_NUM_EXT_PORTS) break;
   1022    }
   1023   cal1_len = i;
   1024   
   1025    if (cal0_len >40 || cal1_len >40) { result=FAIL; TDM_ERROR0("OVS table overscheduled\n"); }
   1026 
   1027 		if(ovs_cal0[0] == ovs_cal0[cal0_len-1]){
   1028 		 result = FAIL;
   1029      TDM_ERROR1("SPACING VOILATION:Found back to back ports in OVS TDM TBL0:port %0d\n",ovs_cal0[i]);
   1030 	  }
   1031    	if(ovs_cal1[0] == ovs_cal1[cal1_len-1]){
   1032 		 result = FAIL;
   1033      TDM_ERROR1("SPACING VOILATION:Found back to back ports in OVS TDM TBL1:port %0d\n",ovs_cal1[i]);
   1034 	  }
   1035 	
   1036 	for (i=0; i<cal0_len; i++){
   1037     AP_TOKEN_CHECK(ovs_cal0[i]) {
   1038 		 if(ovs_cal0[i] == ovs_cal0[i+1]){
   1039 		  result = FAIL;
   1040       TDM_ERROR1("SPACING VOILATION:Found back to back ports in OVS TDM TBL0:port %0d\n",ovs_cal0[i]);
   1041 	   }
   1042     }
   1043   }
   1044 	for (i=0; i<cal1_len; i++){
   1045     AP_TOKEN_CHECK(ovs_cal1[i]) {
   1046    	 if(ovs_cal1[i] == ovs_cal1[i+1]){
   1047 		  result = FAIL;
   1048       TDM_ERROR1("SPACING VOILATION:Found back to back ports in OVS TDM TBL1:port %0d\n",ovs_cal1[i]);
   1049 	   }
   1050     }
   1051 	}
   1052 	
   1053 	return result;
   1054 }
   1055 
   1056 /**
   1057 @name: tdm_ap_chk_pgw_min
   1058 @param:
   1059 
   1060 Checks min spacing in  the PGW table
   1061  */
   1062 int tdm_ap_chk_pgw_min( tdm_mod_t *_tdm)
   1063 {
   1064 	int i, result=PASS, pgw0_len, pgw1_len,
   1065 	    *pgw_cal0, *pgw_cal1;
   1066 
   1067 
   1068 	pgw_cal0 = _tdm->_chip_data.cal_0.cal_main;
   1069   pgw_cal1 = _tdm->_chip_data.cal_1.cal_main;
   1070 
   1071   for(i =0; i<AP_LR_LLS_LEN; i++) {
   1072     if(pgw_cal0[i] == AP_NUM_EXT_PORTS) break;
   1073    }
   1074   pgw0_len = i;
   1075 
   1076   for(i =0; i<AP_LR_LLS_LEN; i++) {
   1077     if(pgw_cal1[i] == AP_NUM_EXT_PORTS) break;
   1078    }
   1079   pgw1_len = i;
   1080   
   1081 
   1082 	if(pgw_cal0[0] == pgw_cal0[pgw0_len-1]){
   1083      AP_TOKEN_CHECK(pgw_cal0[i]) {
   1084 		 result = FAIL;
   1085      TDM_ERROR1("1 SPACING VOILATION:Found back to back ports in PGW TDM TBL0:port %0d\n",pgw_cal0[i]);
   1086 	   }
   1087    }
   1088    if(pgw_cal1[0] == pgw_cal1[pgw1_len-1]){
   1089      AP_TOKEN_CHECK(pgw_cal0[i]) {
   1090 		 result = FAIL;
   1091      TDM_ERROR1("2 SPACING VOILATION:Found back to back ports in PGW TDM TBL1:port %0d\n",pgw_cal1[i]);
   1092 	   }
   1093    }
   1094 	
   1095 	for (i=0; i<pgw0_len; i++){
   1096     AP_TOKEN_CHECK(pgw_cal0[i]) {
   1097 		 if(pgw_cal0[i] == pgw_cal0[i+1]){
   1098 		  result = FAIL;
   1099       TDM_ERROR1("3 SPACING VOILATION:Found back to back ports in PGW TDM TBL0:port %0d\n",pgw_cal0[i]);
   1100 	   }
   1101     }
   1102   }
   1103 	for (i=0; i<pgw1_len; i++){
   1104     AP_TOKEN_CHECK(pgw_cal1[i]) {
   1105    	 if(pgw_cal1[i] == pgw_cal1[i+1]){
   1106 		  result = FAIL;
   1107       TDM_ERROR1("SPACING VOILATION:Found back to back ports in PGW TDM TBL1:port %0d\n",pgw_cal1[i]);
   1108 	   }
   1109     }
   1110 	}
   1111 	
   1112 	return result;
   1113 }
   1114 
   1115 /**
   1116 @name: tdm_ap_chk_chip_specific
   1117 @param:
   1118 
   1119 Checks chip specific 
   1120  */
   1121 void tdm_ap_chk_chip_specific(tdm_mod_t *_tdm, int fail[16])
   1122 {
   1123 	int i,j,k, clk, core_bw, accessories, port_spd, port_state, port_phyID, phy_idx_s, phy_idx_e, msub_x0, msub_x1, pgw_x0_len, pgw_x1_len, t1, t2,t3,t4,t5;
   1124 	int s1, s1xcnt=0, s1xavg=0, s2, s2xcnt=0, s2xavg=0, s3, s3xcnt=0, s3xavg=0, /*s5=4,*/ s5xcnt=0, s5xavg=0, s4=5, s4xcnt=0, s4xavg=0;
   1125 	int pgw_tbl_len, *pgw_tbl_ptr, **ovsb_tbl_ptr, wc_principle, **wc_checker, pgw_mtbl[AP_LR_LLS_LEN*2], pgw_tracker[AP_NUM_EXT_PORTS];
   1126 	const char *str_pgw_tbl_x0, *str_pgw_tbl_x1,*str_ovs_tbl_x0,*str_ovs_tbl_x1;
   1127 	char *str_pgw_ptr, *str_ovs_ptr;
   1128 	
   1129 	/* Initialize */
   1130 	str_pgw_tbl_x0 = "PGW table x0";
   1131 	str_pgw_tbl_x1 = "PGW table x1";
   1132 	str_ovs_tbl_x0 = "PGW OVSB table x0";
   1133 	str_ovs_tbl_x1 = "PGW OVSB table x1";
   1134 	
   1135 	pgw_x0_len=0; pgw_x1_len=0; 
   1136 	clk = _tdm->_chip_data.soc_pkg.clk_freq;
   1137 		
   1138 	for (i=0; i<AP_LR_LLS_LEN; i++) {
   1139 		if (_tdm->_chip_data.cal_0.cal_main[i]!=AP_NUM_EXT_PORTS) pgw_x0_len++;
   1140 		if (_tdm->_chip_data.cal_1.cal_main[i]!=AP_NUM_EXT_PORTS) pgw_x1_len++;
   1141 	}
   1142 	
   1143 	switch(clk) {
   1144     case 840: core_bw=511; accessories=9; break; 
   1145     case 793: 
   1146     case 794: 
   1147     case 795:
   1148     case 796:
   1149     case 797:
   1150       core_bw=480; accessories=18; break; 
   1151     case 575: core_bw=340; accessories=9; break; 
   1152     case 510: core_bw=300; accessories=13; break; 
   1153     case 435: core_bw=260; accessories=10; break; 
   1154 		default: 			core_bw=567; accessories=9 ; break; 
   1155 	}
   1156 	TDM_PRINT3("TDM: _____VERBOSE: (clk - %0d) (core bw - %0d) (mmu acc - %0d)\n", clk, core_bw, accessories);
   1157 	s4=(((495*((clk/76))))/1000); /*100G*/
   1158 	TDM_PRINT1("TDM: _____VERBOSE: calculated 100G MMU spacing as %0d\n", s4);
   1159 	s3=(((12*((clk/76))))/10); /*40G*/
   1160 	TDM_PRINT1("TDM: _____VERBOSE: calculated 40G MMU spacing as %0d\n", s3);
   1161 	s2=(((24*((clk/76))))/10); /*20G*/
   1162 	TDM_PRINT1("TDM: _____VERBOSE: calculated 20G MMU spacing as %0d\n", s2);
   1163 	s1=(((495*((clk/76))))/100); /*10G*/
   1164 	TDM_PRINT1("TDM: _____VERBOSE: calculated 10G MMU spacing as %0d\n", s1);	
   1165 	
   1166 	/* [7] Check length (overflow and symmetry) */
   1167 	if (fail[7]==2) {
   1168 		msub_x0=0; msub_x1=0; 
   1169 		
   1170 		for (i=1; i<(AP_NUM_EXT_PORTS-57); i++) {
   1171 			if((_tdm->_chip_data.soc_pkg.state[i-1]== PORT_STATE__LINERATE || _tdm->_chip_data.soc_pkg.state[i-1]== PORT_STATE__LINERATE_HG) && 
   1172 			   _tdm->_chip_data.soc_pkg.state[i]  != PORT_STATE__COMBINE  &&
   1173 			   _tdm->_chip_data.soc_pkg.speed[i]  <  SPEED_10G){
   1174 				if     (i>=1  && i<=36 ){msub_x0++;}
   1175 				else if(i>=37 && i<=72 ){msub_x1++;}
   1176 			}
   1177 		}
   1178 
   1179 		TDM_PRINT1("TDM: _____VERBOSE: length of pgw table x0 is %0d\n", pgw_x0_len);
   1180 		TDM_PRINT1("TDM: _____VERBOSE: length of pgw table x1 is %0d\n", pgw_x1_len);
   1181 		
   1182 		if (msub_x0==0 && msub_x1==0) { 
   1183 			switch (core_bw) {
   1184 				case 567:
   1185 					if (pgw_x0_len>56 || pgw_x1_len>56)  {fail[7]=1; TDM_ERROR0("PGW table overscheduled\n");}
   1186 					if (pgw_x0_len!=pgw_x1_len) {TDM_PRINT0(" PGW table asymmetry on symmetrically subscribed core bw\n");}
   1187 					break;
   1188 				case 511: case 480:
   1189 					if (pgw_x0_len>48 || pgw_x1_len>48 ) {fail[7]=1; TDM_ERROR0("PGW table overscheduled\n");}
   1190 					if (pgw_x0_len!=pgw_x1_len ) {TDM_PRINT0(" PGW table asymmetry on symmetrically subscribed core bw\n");}
   1191 					break;
   1192 				case 340:
   1193 					if (pgw_x0_len>34 || pgw_x1_len>34 ) {fail[7]=1; TDM_ERROR0("PGW table overscheduled\n");}
   1194 					if (pgw_x0_len!=pgw_x1_len ) {TDM_PRINT0(" PGW table asymmetry on symmetrically subscribed core bw\n");}
   1195 					break;
   1196 				case 260:
   1197 					if (pgw_x0_len>26 || pgw_x1_len>24 ) {fail[7]=1; TDM_ERROR0("PGW table overscheduled\n");}
   1198 					break;
   1199 				default: break;
   1200 			}
   1201 		}
   1202 		
   1203 		fail[7]= (fail[7]==2) ? (PASS) : (FAIL);
   1204 	}
   1205 	
   1206 	/* [8] [9] Check pgw table TSC transcription and TSC proximity */
   1207 	if (fail[8]==2 && fail[9]==2) {
   1208 		/* Length and loopback passes are implicitly combined */
   1209 		wc_checker = _tdm->_chip_data.soc_pkg.pmap;
   1210 		for (k=0; k<2; k++){
   1211 			/* select pgw table */
   1212 			switch(k){
   1213 				/* pgw_tdm_tbl_x0 */
   1214 				case 0:  pgw_tbl_ptr = _tdm->_chip_data.cal_0.cal_main; 
   1215 						 pgw_tbl_len = pgw_x0_len; 
   1216 						 str_pgw_ptr = (char *) str_pgw_tbl_x0;
   1217 						 break;
   1218 				/* pgw_tdm_tbl_x1 */
   1219 				default: pgw_tbl_ptr = _tdm->_chip_data.cal_1.cal_main; 
   1220 						 pgw_tbl_len = pgw_x1_len; 
   1221 						 str_pgw_ptr = (char *) str_pgw_tbl_x1;
   1222 						 break;
   1223 			}
   1224 			
   1225 			/* check transcription and TSC violations */
   1226 			for (i=0; i<pgw_tbl_len; i++) {
   1227 				port_phyID = pgw_tbl_ptr[i];
   1228 				AP_TOKEN_CHECK(port_phyID){
   1229 					if(port_phyID>0 && port_phyID<(AP_NUM_EXT_PORTS-57)){
   1230 						wc_principle = -1;
   1231 						for (j=0; j<AP_NUM_PHY_PM; j++) {
   1232 							if (wc_checker[j][0] == port_phyID || wc_checker[j][1] == port_phyID || wc_checker[j][2] == port_phyID || wc_checker[j][3] == port_phyID){
   1233 								wc_principle = j;
   1234 								break;
   1235 							}
   1236             }
   1237 						if (wc_principle == -1) {
   1238 							fail[8] = 1; 
   1239 							TDM_ERROR2("TSC transcription corruption %s port %0d\n", str_pgw_ptr, port_phyID);
   1240 						}
   1241 						else if ((pgw_tbl_len>8) && (i<pgw_tbl_len-1) && /*proximity check to be done for pgw calendar between index 0 & 47 */ 
   1242 								 (pgw_tbl_ptr[i+1]==wc_checker[wc_principle][0]  || 
   1243 								  pgw_tbl_ptr[i+1]==wc_checker[wc_principle][1]  || 
   1244 								  pgw_tbl_ptr[i+1]==wc_checker[wc_principle][2]  || 
   1245 								  pgw_tbl_ptr[i+1]==wc_checker[wc_principle][3]) ){
   1246 								fail[9]=2; /* proximity check disabled for Apache as sister port spacing is 0 for Apache. */
   1247 								TDM_ERROR4("TSC proximity violation in %s between index %0d & +1 pgw_tbl_ptr %0d %0d\n", str_pgw_ptr, i,  pgw_tbl_ptr[i], pgw_tbl_ptr[i+1]);
   1248                                 TDM_PRINT4("\nwc_checker 0=%0d 1=%0d 2=%0d 3=%0d",wc_checker[wc_principle][0] , wc_checker[wc_principle][1], wc_checker[wc_principle][2], wc_checker[wc_principle][3]    );
   1249 						}
   1250 					}
   1251 				}
   1252 			}
   1253 		}
   1254 		fail[8]= (fail[8]==2) ? (PASS) : (FAIL);
   1255 		fail[9]= (fail[9]==2) ? (PASS) : (FAIL);
   1256 	}
   1257 	
   1258 	/* [10] Check pgw table spacing*/
   1259 	if (fail[10]==2) {
   1260 		for (k=0; k<2; k++){
   1261 			/* select pgw table */
   1262 			switch(k){
   1263 				/* pgw_tdm_tbl_x0 */
   1264 				case 0:  pgw_tbl_ptr = _tdm->_chip_data.cal_0.cal_main; 
   1265 						 pgw_tbl_len = pgw_x0_len; 
   1266 						 phy_idx_s   = 1;
   1267 						 phy_idx_e   = 36;
   1268 						 str_pgw_ptr = (char *) str_pgw_tbl_x0;
   1269 						 break;
   1270 				/* pgw_tdm_tbl_x1 */
   1271 				default: pgw_tbl_ptr = _tdm->_chip_data.cal_1.cal_main; 
   1272 						 pgw_tbl_len = pgw_x1_len; 
   1273 						 phy_idx_s   = 37;
   1274 						 phy_idx_e   = 72;
   1275 						 str_pgw_ptr = (char *) str_pgw_tbl_x1;
   1276 						 break;
   1277 			}
   1278 			t1 = (pgw_tbl_len/2);/*10G*/
   1279 			t2 = (pgw_tbl_len/4);/*20G*/
   1280 			t3 = (pgw_tbl_len/8);/*40G*/
   1281 			t4 = (pgw_tbl_len/20);/*100G*/
   1282 			t5 = (pgw_tbl_len/10);/*50G*/
   1283 			TDM_PRINT3("TDM: _____VERBOSE: %s calculated 10G PGW spacing %0d pgw_tbl_len %0d\n",str_pgw_ptr, t1, pgw_tbl_len);
   1284 			TDM_PRINT2("TDM: _____VERBOSE: %s calculated 20G PGW spacing %0d\n",str_pgw_ptr, t2);
   1285 			TDM_PRINT2("TDM: _____VERBOSE: %s calculated 40G PGW spacing %0d\n",str_pgw_ptr, t3);
   1286 			TDM_PRINT2("TDM: _____VERBOSE: %s calculated 100G PGW spacing %0d\n",str_pgw_ptr, t4);
   1287 			TDM_PRINT2("TDM: _____VERBOSE: %s calculated 50G PGW spacing %0d\n",str_pgw_ptr, t5);
   1288 			
   1289 			/* set tracker */
   1290 			for (i=0; i<(AP_NUM_EXT_PORTS-56); i++) {pgw_tracker[i]=0;}
   1291 			for (i=0; i<pgw_tbl_len; i++) { pgw_mtbl[i]=pgw_tbl_ptr[i]; pgw_mtbl[i+pgw_tbl_len]=pgw_tbl_ptr[i];}
   1292 			for (i=0; i<pgw_tbl_len; i++) {
   1293 				port_phyID = pgw_tbl_ptr[i];
   1294 				AP_TOKEN_CHECK(port_phyID){
   1295 					if(port_phyID>0 && port_phyID<(AP_NUM_EXT_PORTS-57)){
   1296 						pgw_tracker[port_phyID] = 1;
   1297 						for (j=1; j<=pgw_tbl_len; j++) {
   1298 							if (pgw_mtbl[i+j]!=pgw_mtbl[i]) {pgw_tracker[port_phyID]++; }
   1299 							else {break;}
   1300 						}
   1301 					}
   1302 				}
   1303 			}
   1304 			
   1305 			/* check pgw spacing */
   1306 			for (i=phy_idx_s; i<phy_idx_e; i++){
   1307 				if(pgw_tracker[i]!=0){
   1308 					switch (_tdm->_chip_data.soc_pkg.speed[i]) {
   1309 						case SPEED_10G:
   1310 							if (pgw_tracker[i] != t1) {
   1311 								/*fail[10]=1;*/ 
   1312 								TDM_PRINT3(" %s, 10G port spacing deviation from average port %0d (%0d)\n", str_pgw_ptr, i,pgw_tracker[i]);
   1313 							}
   1314 							break;
   1315 						case SPEED_21G:
   1316 						case SPEED_20G:
   1317 						case SPEED_21G_DUAL:
   1318 							if (pgw_tracker[i] != t2) {
   1319 								/*fail[10]=1;*/ 
   1320 								TDM_PRINT3(" %s, 20G port spacing deviation from average port %0d (%0d)\n", str_pgw_ptr, i,pgw_tracker[i]);
   1321 							}
   1322 							break;
   1323 						case SPEED_42G:
   1324 						case SPEED_40G:
   1325 							if (pgw_tracker[i] != t3) {
   1326 								/*fail[10]=1;*/ 
   1327 								TDM_PRINT3(" %s, 40G port spacing deviation from average port %0d (%0d)\n", str_pgw_ptr, i,pgw_tracker[i]);
   1328 							}
   1329 							break;
   1330 						case SPEED_50G:
   1331 							if (pgw_tracker[i] != t5) {
   1332 								/*fail[10]=1;*/ 
   1333 								TDM_PRINT3(" %s, 50G port spacing deviation from average port %0d (%0d)\n", str_pgw_ptr, i,pgw_tracker[i]);
   1334 							}
   1335 							break;
   1336 						case SPEED_120G:
   1337 						case SPEED_100G:
   1338 							if (pgw_tracker[i] != t4) {
   1339 								/*fail[10]=1;*/ 
   1340 								/*TDM_WARN3(" %s, 100G/120G port spacing deviation from average port %0d (%0d)\n", str_pgw_ptr, i,pgw_tracker[i]);*/
   1341 							}
   1342 							break;
   1343 						default:
   1344 							/* 10G/1G spacing is implicitly checked by both the TSC spacing and the spacing of all other speeds */ 
   1345 							break;
   1346 					}
   1347 				}
   1348 			}
   1349 		}
   1350 		fail[10]= (fail[10]==2) ? (PASS) : (FAIL);
   1351 	}
   1352 	
   1353 	/* [11] */
   1354 	if (fail[11]==2) {
   1355 		
   1356 		s1xavg = (s1xcnt==0) ? 0 : ((s1xavg*100)/s1xcnt);
   1357 		s2xavg = (s2xcnt==0) ? 0 : ((s2xavg*100)/s2xcnt);
   1358 		s3xavg = (s3xcnt==0) ? 0 : ((s3xavg*100)/s3xcnt);
   1359 		s4xavg = (s4xcnt==0) ? 0 : ((s4xavg*100)/s4xcnt);
   1360 		s5xavg = (s5xcnt==0) ? 0 : ((s5xavg*100)/s5xcnt);
   1361 
   1362 		if (s1xavg>0) if ( (s1xavg > (s1*101) || s1xavg < (s1*99)) ) {/*fail[11]=1;*/ TDM_PRINT1("10G line rate not within 1 percent tolerance in x pipe, (s1xavg = %0d)\n", s1xavg);}
   1363 		if (s2xavg>0) if ( (s2xavg > (s1*101) || s2xavg < (s1*99)) ) {/*fail[11]=1;*/ TDM_PRINT1("20G line rate not within 1 percent tolerance in x pipe, (s2xavg = %0d)\n", s2xavg);}
   1364 		if (s3xavg>0) if ( (s3xavg > (s1*101) || s3xavg < (s1*99)) ) {/*fail[11]=1;*/ TDM_PRINT1("40G line rate not within 1 percent tolerance in x pipe, (s3xavg = %0d)\n", s3xavg);}
   1365 		if (s4xavg>0) if ( (s4xavg > (s1*101) || s4xavg < (s1*99)) ) {/*fail[11]=1;*/ TDM_PRINT1("100G line rate not within 1 percent tolerance in x pipe, (s4xavg = %0d)\n", s4xavg);}
   1366 		if (s5xavg>0) if ( (s5xavg > (s1*101) || s5xavg < (s1*99)) ) {/*fail[11]=1;*/ TDM_PRINT1("120G line rate not within 1 percent tolerance in x pipe, (s5xavg = %0d)\n", s5xavg);}
   1367 		fail[11]= (fail[11]==2) ? (PASS) : (FAIL);
   1368 	}
   1369 	
   1370 	/* [12] Check 100G/120G port numbering */
   1371 	if (fail[12]==2) {
   1372 		for (i=1; i<(AP_NUM_EXT_PORTS-57); i++) {
   1373 			if (_tdm->_chip_data.soc_pkg.speed[i]==SPEED_100G || _tdm->_chip_data.soc_pkg.speed[i]==SPEED_120G) {
   1374 				if (i!=17 && i!=29 && i!=33 && i!=53 && i!=65 && i!=69) {
   1375 					fail[12]=1; 
   1376 					TDM_ERROR1("port number %0d is a 100G/120G port that is improperly subscribed\n",i);
   1377 				}
   1378 			}
   1379 		}
   1380 		fail[12]= (fail[12]==2) ? (PASS) : (FAIL);
   1381 	}
   1382 	
   1383 	/* [13] Check port subscription */
   1384 	if (fail[13]==2) {
   1385 		for(i=1; i<(AP_NUM_EXT_PORTS-57); i++){
   1386 			/* pgw_x_0 */
   1387 			if(i<=36) {
   1388 				pgw_tbl_ptr  = _tdm->_chip_data.cal_0.cal_main;
   1389 				ovsb_tbl_ptr = _tdm->_chip_data.cal_0.cal_grp;
   1390 				str_pgw_ptr  = (char *) str_pgw_tbl_x0;
   1391 				str_ovs_ptr  = (char *) str_ovs_tbl_x0;
   1392 			}
   1393 			/* pgw_x_1 */
   1394 			else {
   1395 				pgw_tbl_ptr  = _tdm->_chip_data.cal_1.cal_main;
   1396 				ovsb_tbl_ptr = _tdm->_chip_data.cal_1.cal_grp;
   1397 				str_pgw_ptr  = (char *) str_pgw_tbl_x1;
   1398 				str_ovs_ptr  = (char *) str_ovs_tbl_x1;
   1399 			}
   1400 			
   1401 				k=0;
   1402 				port_spd  = _tdm->_chip_data.soc_pkg.speed[i];
   1403 				port_state= _tdm->_chip_data.soc_pkg.state[i-1];
   1404 				/* line-rate ports */
   1405 				if (port_state==PORT_STATE__LINERATE   || 
   1406 				    port_state==PORT_STATE__LINERATE_HG){
   1407 					switch (port_spd) {
   1408 						case SPEED_1G:
   1409 						case SPEED_2p5G:
   1410 							for (j=0; j<64; j++) {if (pgw_tbl_ptr[j]==i) {k++;}}
   1411 							if (k!=1) {fail[13]=1; TDM_ERROR3("port %0d subscription error in %s (k=%0d)\n",i, str_pgw_ptr, k);}
   1412 							break;
   1413 						case SPEED_10G:
   1414 						case SPEED_10G_XAUI:
   1415 							for (j=0; j<64; j++) {if (pgw_tbl_ptr[j]==i) {k++;}}
   1416 							if (k!=2 && k!=8 && k!=20) {fail[13]=1; TDM_ERROR3("port %0d subscription error in %s (k=%0d)\n",i,str_pgw_ptr,k);}
   1417 							break;
   1418 						case SPEED_21G:
   1419 						case SPEED_20G:
   1420 						case SPEED_21G_DUAL:
   1421 							for (j=0; j<64; j++) {if (pgw_tbl_ptr[j]==i) {k++;}}
   1422 							if (k!=4) {fail[13]=1; TDM_ERROR3("port %0d subscription error in %s (k=%0d)\n",i,str_pgw_ptr,k);}
   1423 							break;
   1424 						case SPEED_25G:
   1425 							for (j=0; j<64; j++) {if (pgw_tbl_ptr[j]==i) {k++;}}
   1426 							if (k!=5) {fail[13]=1; TDM_ERROR3("port %0d subscription error in %s (k=%0d)\n",i,str_pgw_ptr,k);}
   1427 							break;
   1428 						case SPEED_42G_HG2:
   1429 						case SPEED_42G:
   1430 						case SPEED_40G:
   1431 							for (j=0; j<64; j++) {if (pgw_tbl_ptr[j]==i) {k++;}}
   1432 							if (k!=8) {fail[13]=1; TDM_ERROR3("port %0d subscription error in %s (k=%0d)\n",i,str_pgw_ptr,k);}
   1433 							break;
   1434 						case SPEED_50G:
   1435 							for (j=0; j<64; j++) {if (pgw_tbl_ptr[j]==i) {k++;}}
   1436 							if (k!=10) {fail[13]=1; TDM_ERROR3("port %0d subscription error in %s (k=%0d)\n",i,str_pgw_ptr,k);}
   1437 							break;
   1438 						case SPEED_120G:
   1439 							for (j=0; j<64; j++) {if (pgw_tbl_ptr[j]==i) {k++;}}
   1440 							if (k!=24) {fail[13]=1; TDM_ERROR3("port %0d subscription error in %s (k=%0d)\n",i,str_pgw_ptr,k);}
   1441 							break;
   1442 						case SPEED_100G:
   1443 							for (j=0; j<64; j++) {if (pgw_tbl_ptr[j]==i) {k++;}}
   1444 							if (k!=24 && k!=20) {fail[13]=1; TDM_ERROR3("port %0d subscription error in %s (k=%0d)\n",i,str_pgw_ptr,k);}
   1445 							break;
   1446 						default:
   1447 							break;
   1448 					}
   1449 				}
   1450 				/* oversub ports */
   1451 				else if (port_state==PORT_STATE__OVERSUB   ||
   1452 				         port_state==PORT_STATE__OVERSUB_HG){
   1453 					switch (port_spd) {
   1454 						case SPEED_1G:
   1455 						case SPEED_2p5G:
   1456 							for (j=0; j<40; j++) {if (ovsb_tbl_ptr[0][j]==i) {k++;}}
   1457 							if (k!=1) {fail[13]=1; TDM_ERROR3("port %0d subscription error in %s (k=%0d)\n",i,str_ovs_ptr,k);}
   1458 							break;
   1459 						case SPEED_10G:
   1460 						case SPEED_10G_XAUI:
   1461 							for (j=0; j<40; j++) {if (ovsb_tbl_ptr[0][j]==i) {k++;}}
   1462 							if (k!=1 && k!=4 && k!=10) {fail[13]=1; TDM_ERROR3("port %0d subscription error in %s (k=%0d)\n",i,str_ovs_ptr,k);}
   1463 							break;
   1464 						case SPEED_21G:
   1465 						case SPEED_20G:
   1466 						case SPEED_21G_DUAL:
   1467 							for (j=0; j<40; j++) {if (ovsb_tbl_ptr[0][j]==i) {k++;}}
   1468 							if (k!=2) {fail[13]=1; TDM_ERROR3("port %0d subscription error in %s (k=%0d)\n",i,str_ovs_ptr,k);}
   1469 							break;
   1470 						case SPEED_25G:
   1471 							for (j=0; j<40; j++) {if (ovsb_tbl_ptr[0][j]==i) {k++;}}
   1472 							if (k!=3 && k!=1) {fail[13]=1; TDM_ERROR3("port %0d subscription error in %s (k=%0d)\n",i,str_ovs_ptr,k);}
   1473               break;
   1474 						case SPEED_42G_HG2:
   1475 						case SPEED_42G:
   1476 						case SPEED_40G:
   1477 							for (j=0; j<40; j++) {if (ovsb_tbl_ptr[0][j]==i) {k++;}}
   1478 							if (k!=4 && k!=2) {fail[13]=1; TDM_ERROR3("port %0d subscription error in %s (k=%0d)\n",i,str_ovs_ptr,k);}
   1479 							break;
   1480 						case SPEED_50G:
   1481 							for (j=0; j<40; j++) {if (ovsb_tbl_ptr[0][j]==i) {k++;}}
   1482 							if (k!=5 && k!=2) {fail[13]=1; TDM_ERROR3("port %0d subscription error in %s (k=%0d)\n",i,str_ovs_ptr,k);}
   1483               break;
   1484 						case SPEED_100G:
   1485 							for (j=0; j<40; j++) {if (ovsb_tbl_ptr[0][j]==i) {k++;}}
   1486 							if (k!=10 && k!=8 && k!=4 && k!=12) {fail[13]=1; TDM_ERROR3("port %0d subscription error in %s (k=%0d)\n",i,str_ovs_ptr,k);}
   1487 							break;
   1488 						default:
   1489 							break;
   1490 					}
   1491 				}
   1492 		}
   1493 		fail[13]= (fail[13]==2) ? (PASS) : (FAIL);
   1494 	}
   1495 }
   1496 
   1497 
   1498 /**
   1499 @name: tdm_ap_chk
   1500 @param: 
   1501  */
   1502 int
   1503 tdm_ap_chk( tdm_mod_t *_tdm)
   1504 {	
   1505 	int i, result, mmu_x_len, fail[16];
   1506 
   1507 	for (i=0; i<16; i++) {
   1508 		fail[i] = 2;
   1509 	}
   1510 
   1511 	mmu_x_len= _tdm->_chip_data.cal_2.cal_len;
   1512 	for (i=(_tdm->_chip_data.cal_2.cal_len-1); i>0; i--){
   1513 		if(_tdm->_chip_data.cal_2.cal_main[i]==AP_NUM_EXT_PORTS){
   1514 			mmu_x_len--;
   1515 		}
   1516 		else{
   1517 			break;
   1518 		}
   1519 	}
   1520 
   1521 	_tdm->_chip_data.cal_2.cal_len = mmu_x_len;
   1522 	
   1523 	/**********************************/
   1524 	TDM_BIG_BAR
   1525 	TDM_PRINT0("TDM: TDM Self Check\n\n");
   1526 	
   1527 	/* [0] Check MMU table length (overflow and symmetry) */
   1528 	if (fail[0]==2) {
   1529 		TDM_PRINT0("TDM: [0] Checking length (overflow and symmetry)\n"); TDM_SML_BAR
   1530 		/* Pipe X */
   1531 		_tdm->_core_data.vars_pkg.pipe = AP_PIPE_X_ID;
   1532 		result  = tdm_ap_chk_struc(_tdm);
   1533 		fail[0] = (fail[0]==FAIL || fail[0]==UNDEF) ? (fail[0]):(result);
   1534 	}
   1535 	
   1536 	/* [1] Check TSC transcription in MMU tables */
   1537 	if (fail[1]==2) {
   1538 		TDM_PRINT0("\nTDM: [1] Checking TSC transcription\n"); TDM_SML_BAR
   1539 		fail[1] = tdm_ap_chk_tsc(_tdm);
   1540 	}
   1541 	
   1542 	/* [2] Check sister port spacing in MMU tables */
   1543 	if (fail[2]==2) {
   1544 		TDM_PRINT0("\nTDM: [2] Checking min spacing\n"); TDM_SML_BAR
   1545 		/* X Pipe */
   1546 		_tdm->_core_data.vars_pkg.pipe = AP_XPIPE_CAL_ID;
   1547 		result  = tdm_ap_chk_min(_tdm);
   1548 		fail[2] = (fail[2]==FAIL || fail[2]==UNDEF) ? (fail[2]):(result);
   1549 	}
   1550 	
   1551 	/* [3] Check (CPU/loopback/regular) port subscription and accessory slot allocation. */
   1552 	if (fail[3]==2) {
   1553 		TDM_PRINT0("\nTDM: [3] Checking per port subscription stats\n"); TDM_SML_BAR
   1554 		fail[3] = tdm_ap_chk_subscription(_tdm);
   1555 	}
   1556 	
   1557 	/* [4] Check Oversub jitter */
   1558 	if (fail[4]==2) {
   1559 		TDM_PRINT0("\nTDM: [4] Checking Oversub jitter\n"); TDM_SML_BAR
   1560 		/* X Pipe */
   1561 		_tdm->_core_data.vars_pkg.pipe = AP_XPIPE_CAL_ID;
   1562 		result  = tdm_ap_chk_os_jitter(_tdm);
   1563 		fail[4] = (fail[4]==FAIL || fail[4]==UNDEF) ? (fail[4]):(result);
   1564         TDM_PRINT2("result = %d fail[4] = %d\n", result, fail[4]);
   1565 	}
   1566 	
   1567 	/* [5] [6] Check Linerate jitter */
   1568 	if (fail[5]==2 || fail[6]==2) {
   1569 		TDM_PRINT0("\nTDM: [5] [6] Checking line rate jitter\n"); TDM_SML_BAR
   1570 		/* X Pipe */
   1571 		_tdm->_core_data.vars_pkg.pipe = AP_XPIPE_CAL_ID;
   1572 		tdm_ap_chk_lr_jitter(_tdm, fail);
   1573 	}
   1574 	
   1575 	/* [14] Check LLS min spacing requiement */
   1576 /*#ifdef _LLS_SCHEDULER*/
   1577 	if (fail[14]==2 && _tdm->_chip_data.soc_pkg.clk_freq>=435) {
   1578 		TDM_PRINT0("\nTDM: [14] Checking LLS min spacing requirement\n"); TDM_SML_BAR
   1579 		/* X Pipe */
   1580 		_tdm->_core_data.vars_pkg.pipe = AP_XPIPE_CAL_ID;
   1581 		result = tdm_ap_chk_lls(_tdm);
   1582 		fail[14] = (fail[14]==FAIL || fail[14]==UNDEF) ? (fail[14]):(result);
   1583 	}
   1584 /*#endif*/
   1585 
   1586 	/* [15] Check back to back ports in PGW/OVS TDM table */
   1587 	if (fail[15]==2) {
   1588 		TDM_PRINT0("\nTDM: [15] Checking min spacing in PGW/OVS table\n"); TDM_SML_BAR
   1589 		fail[15] = tdm_ap_chk_pgw_min(_tdm) || tdm_ap_chk_ovs_space(_tdm);	
   1590 	}
   1591 
   1592 	/* [7] [8] [9] [10] [11] [12] [13] Check chip specific constraints */
   1593 	if (fail[7]==2 || fail[8]==2 || fail[9]==2 || fail[10]==2 || fail[11]==2 || fail[12]==2 || fail[13]==2){
   1594 		TDM_PRINT0("\nTDM: --- Chip specific checkers [7] [8] [9] [10] [11] [12] [13]\n"); TDM_SML_BAR
   1595 		tdm_ap_chk_chip_specific( _tdm, fail );
   1596 	}
   1597 	
   1598 	/* Summarize check results */
   1599 	TDM_PRINT0("\n");
   1600 	TDM_SML_BAR
   1601 	if (fail[15]==FAIL ||
   1602 		fail[14]==FAIL ||
   1603 		fail[13]==FAIL ||
   1604 		fail[12]==FAIL ||
   1605 		fail[11]==FAIL ||
   1606 		/*fail[10]==FAIL ||*/
   1607 		fail[9]==FAIL ||
   1608 		fail[8]==FAIL ||
   1609 		fail[7]==FAIL ||
   1610 		fail[6]==FAIL ||
   1611 		/*fail[5]==FAIL ||*/
   1612 		fail[4]==FAIL ||
   1613 		fail[3]==FAIL ||
   1614 		fail[2]==FAIL ||
   1615 		fail[1]==FAIL ||
   1616 		fail[0]==FAIL ){
   1617 		TDM_ERROR0("Apache TDM Self Check: *** FAILED ***\n");
   1618 		TDM_SML_BAR
   1619 		TDM_ERROR0("TDM: Fail vector: [");
   1620 		for (i=0; i<16; i++) {
   1621 			TDM_ERROR1(" %0d ",fail[i]);
   1622 		}
   1623 		TDM_ERROR0("]\n");
   1624         return FAIL;
   1625 	}
   1626 	else {
   1627 		TDM_PRINT0("Apache TDM Self Check: *** PASSED ***\n");
   1628 	}
   1629 	TDM_SML_BAR
   1630 	TDM_PRINT0("\n");
   1631 	TDM_PRINT0("TDM: TDM Self Check Complete.\n");
   1632 	TDM_BIG_BAR
   1633 
   1634 	return PASS;
   1635 }