sbusdma_stress_test.c (29347B)
1 2 3 /* 4 * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file. 5 * 6 * Copyright 2007-2019 Broadcom Inc. All rights reserved. 7 */ 8 9 10 #include <shared/bsl.h> 11 #include <appl/diag/system.h> 12 #include <appl/diag/parse.h> 13 #include <soc/defs.h> 14 #include <soc/iproc.h> 15 #include <soc/cmicx.h> 16 #include <soc/sbusdma.h> 17 #include <soc/l2x.h> 18 #include <soc/mem.h> 19 #include <bcm/error.h> 20 #include <bcm/link.h> 21 22 #if defined(BCM_ESW_SUPPORT) && defined(BCM_SBUSDMA_SUPPORT) \ 23 && (defined(BCM_CMICM_SUPPORT) || defined(BCM_CMICX_SUPPORT)) 24 typedef struct sbusdma_params_s { 25 int unit; 26 sal_thread_t tid; 27 int type; 28 int write_secs; 29 int read_secs; 30 int test_time; 31 int status1; 32 int status2; 33 int rd_channel; 34 int wr_channel; 35 soc_mem_t mem; 36 uint32 flags; 37 } sbusdma_params_t; 38 39 typedef struct sbusdma_desc_s { 40 uint32 control; 41 uint32 request; 42 uint32 count; 43 uint32 opcode; 44 uint32 sbus_base; 45 uint32 hostmem_phy_base_lo; 46 uint32 hostmem_phy_base_hi; 47 uint32 reserved; 48 } sbusdma_desc_t; 49 50 #define SBUSDMA_CH_MAX_NUM (3 * SOC_SBUSDMA_CH_PER_CMC) 51 52 #define SBUSDMA_WRITE_RUN (1 << 0) 53 #define SBUSDMA_READ_RUN (1 << 1) 54 55 #define SBUSDMA_STATUS_INVALID 0 56 #define SBUSDMA_STATUS_SUCCESS 1 57 #define SBUSDMA_STATUS_FAILURE 2 58 #define SBUSDMA_STATUS_RUNNING 3 59 60 #define SBUSDMA_TYPE_READ 0 61 #define SBUSDMA_TYPE_WRITE 1 62 63 #define HOST_ADDR_HI_CMICX(_paddr) (PTR_HI_TO_INT(_paddr)) 64 #define HOST_ADDR_LO_CMICX(_paddr) (PTR_TO_INT(_paddr)) 65 66 static void 67 cmicx_continuous_dma_write(void *void_param) 68 { 69 struct sbusdma_params_s *const params = 70 (struct sbusdma_params_s *) void_param; 71 const int JUMP_OFFSET = 29; 72 const int REMAINING_OFFSET = 24; 73 const int DESCRIPTOR_COUNT = 33; /* Many to allow for prefetching */ 74 75 int endian; 76 int entries; 77 int entry_bytes; 78 int entry_width; 79 int idx; 80 int tmp; 81 sbusdma_desc_t *dma_desc; 82 soc_mem_info_t *minfo; 83 uint32 *mdata1; 84 uint32 *mdata2; 85 uint32 rval; 86 uint8 *ptr1; 87 uint8 *ptr2; 88 soc_timeout_t to; 89 int desc_num; 90 int desc_remaining; 91 int ch, cmc; 92 params->status1 = SBUSDMA_STATUS_RUNNING; 93 94 cmc = 1; 95 ch = params->wr_channel; 96 97 /* Sanity checks */ 98 if (!SOC_MEM_IS_VALID(params->unit, params->mem)) { 99 #if !defined(SOC_NO_NAMES) 100 cli_out("This device does not have the %s memory used by this test\n", 101 soc_mem_name[params->mem]); 102 #else 103 cli_out("This device does not have the memory used by this test\n"); 104 #endif 105 params->status1 = SBUSDMA_STATUS_FAILURE; 106 return; 107 } 108 109 if (!SOC_REG_IS_VALID(params->unit, CMIC_CMC1_SBUSDMA_CH1_CONTROLr)) { 110 cli_out 111 ("This device does not support the SBUS descriptor chaining used by this test\n"); 112 params->status1 = SBUSDMA_STATUS_FAILURE; 113 return; 114 } 115 116 /* Allocate memory for the SBUS DMA descriptors and the table data */ 117 dma_desc = 118 soc_cm_salloc(params->unit, DESCRIPTOR_COUNT * sizeof(sbusdma_desc_t), 119 "sbus_dma_descriptors"); 120 if (!dma_desc) { 121 cli_out("Could not allocate memory for SBUS DMA descriptors\n"); 122 params->status1 = SBUSDMA_STATUS_FAILURE; 123 return; 124 } 125 sal_memset(dma_desc, 0, DESCRIPTOR_COUNT * sizeof(sbusdma_desc_t)); 126 127 minfo = &SOC_MEM_INFO(params->unit, params->mem); 128 entries = minfo->index_max - minfo->index_min + 1; /* Compute mem size */ 129 entry_width = ((minfo->bytes + 3) / 4) * 4; 130 entry_bytes = entries * entry_width; 131 mdata1 = soc_cm_salloc(params->unit, entry_bytes, "table_data"); 132 if (!mdata1) { 133 cli_out("Could not allocate memory for table data 1\n"); 134 soc_cm_sfree(params->unit, dma_desc); 135 params->status1 = SBUSDMA_STATUS_FAILURE; 136 return; 137 } 138 139 mdata2 = soc_cm_salloc(params->unit, entry_bytes, "table_data"); 140 if (!mdata2) { 141 cli_out("Could not allocate memory for table data 2\n"); 142 soc_cm_sfree(params->unit, dma_desc); 143 soc_cm_sfree(params->unit, mdata1); 144 params->status1 = SBUSDMA_STATUS_FAILURE; 145 return; 146 } 147 148 /* Fill the table data with a pattern */ 149 ptr1 = (uint8 *) mdata1; 150 ptr2 = (uint8 *) mdata2; 151 for (idx = 0; idx < entry_bytes; idx++) { 152 const uint8 val = (0x3 - (idx & 0x3)) | (idx & 0xFC); 153 154 *ptr1++ = val; 155 *ptr2++ = 0xFF - val; 156 } 157 158 /* Form the SBUS DMA descriptors 159 * desc[0]: DMA mdata1 to the table 160 * desc[1]: DMA mdata2 to the table 161 * desc[2]: DMA mdata1 to the table 162 * ... 163 * desc[n-2]: DMA mdata1 to the table 164 * desc[n-1]: DMA mdata2 to the table 165 * desc[n]: Jump back to desc[0] */ 166 soc_endian_get(params->unit, &tmp, &tmp, &endian); 167 168 desc_remaining = DESCRIPTOR_COUNT - 2; /* Used for prefetch, does not include reload descriptor */ 169 if (desc_remaining > 15) { 170 desc_remaining = 15; 171 } 172 173 /* Fully form a single descriptor */ 174 dma_desc[0].control = (desc_remaining << REMAINING_OFFSET); 175 176 rval = 0; 177 soc_reg_field_set(params->unit, CMIC_CMC1_SBUSDMA_CH1_REQUESTr, 178 &rval, WORDSWAP_IN_64BIT_SBUSDATAf, 0); 179 soc_reg_field_set(params->unit, CMIC_CMC1_SBUSDMA_CH1_REQUESTr, 180 &rval, HOSTMEMWR_ENDIANESSf, endian); 181 soc_reg_field_set(params->unit, CMIC_CMC1_SBUSDMA_CH1_REQUESTr, 182 &rval, HOSTMEMRD_ENDIANESSf, endian); 183 soc_reg_field_set(params->unit, CMIC_CMC1_SBUSDMA_CH1_REQUESTr, 184 &rval, REQ_WORDSf, entry_width / 4); 185 soc_reg_field_set(params->unit, CMIC_CMC1_SBUSDMA_CH1_REQUESTr, 186 &rval, REP_WORDSf, 0); 187 soc_reg_field_set(params->unit, CMIC_CMC1_SBUSDMA_CH1_REQUESTr, 188 &rval, PEND_CLOCKSf, 0); 189 dma_desc[0].request = rval; 190 dma_desc[0].count = entries; 191 192 soc_schan_header_cmd_set(params->unit, (schan_header_t *) & dma_desc[0].opcode, 193 WRITE_MEMORY_CMD_MSG, SOC_BLOCK2SCH(params->unit, 194 minfo->minblock), 0, 195 SOC_MEM_ACC_TYPE(params->unit, params->mem), 196 entry_width, 0, 0); 197 198 dma_desc[0].sbus_base = minfo->base + minfo->index_min; 199 200 dma_desc[0].hostmem_phy_base_lo = 201 HOST_ADDR_LO_CMICX(soc_cm_l2p(params->unit, mdata1)); 202 dma_desc[0].hostmem_phy_base_hi = 203 HOST_ADDR_HI_CMICX(soc_cm_l2p(params->unit, mdata1)); 204 if (soc_cm_get_bus_type(params->unit) & SOC_PCI_DEV_TYPE) { 205 dma_desc[0].hostmem_phy_base_hi |= CMIC_PCIE_SO_OFFSET; 206 } 207 /* Copy the fully formed descriptor to the other descriptors and update as necessary */ 208 for (desc_num = 1; desc_num < (DESCRIPTOR_COUNT - 1); desc_num++) { 209 sal_memcpy(&dma_desc[desc_num], &dma_desc[0], sizeof(sbusdma_desc_t)); 210 211 desc_remaining = DESCRIPTOR_COUNT - desc_num - 2; 212 if (desc_remaining > 15) { 213 desc_remaining = 15; 214 } 215 dma_desc[desc_num].control = (desc_remaining << REMAINING_OFFSET); 216 217 if (desc_num % 2) { 218 dma_desc[0].hostmem_phy_base_lo = 219 HOST_ADDR_LO_CMICX(soc_cm_l2p(params->unit, mdata2)); 220 dma_desc[0].hostmem_phy_base_hi = 221 HOST_ADDR_HI_CMICX(soc_cm_l2p(params->unit, mdata2)); 222 if (soc_cm_get_bus_type(params->unit) & SOC_PCI_DEV_TYPE) { 223 dma_desc[0].hostmem_phy_base_hi |= CMIC_PCIE_SO_OFFSET; 224 } 225 } 226 } 227 228 /* Create the reload descriptor */ 229 dma_desc[desc_num].control = 1 << JUMP_OFFSET; 230 dma_desc[desc_num].hostmem_phy_base_lo = 231 HOST_ADDR_LO_CMICX(soc_cm_l2p(params->unit, dma_desc)); 232 dma_desc[desc_num].hostmem_phy_base_hi = 233 HOST_ADDR_HI_CMICX(soc_cm_l2p(params->unit, dma_desc)); 234 if (soc_cm_get_bus_type(params->unit) & SOC_PCI_DEV_TYPE) { 235 dma_desc[desc_num].hostmem_phy_base_hi |= CMIC_PCIE_SO_OFFSET; 236 } 237 #ifdef TEST_DEBUG 238 cli_out("DMA WRITE: cmc: %d: ch: %d\n", cmc, ch); 239 for (desc_num = 0; 240 desc_num < DESCRIPTOR_COUNT; 241 desc_num++) { 242 cli_out("DMA WRITE: desc num:%d, Control: 0x%08x\n", desc_num, *((uint32 *) dma_desc + (desc_num*8))); 243 cli_out("DMA WRITE desc num:%d, Request: 0x%08x\n", desc_num, *((uint32 *) dma_desc + (desc_num*8)+1)); 244 cli_out("DMA WRITE: desc num:%d, Count: 0x%08x\n", desc_num, *((uint32 *) dma_desc + (desc_num*8)+2)); 245 cli_out("DMA WRITE: desc num:%d, Opcode: 0x%08x\n", desc_num, *((uint32 *) dma_desc + (desc_num*8)+3)); 246 cli_out("DMA WRITE: desc num:%d, sbus addr: 0x%08x\n", desc_num, *((uint32 *) dma_desc + (desc_num*8)+4)); 247 cli_out("DMA WRITE: desc num:%d, haddr_low: 0x%08x\n", desc_num, *((uint32 *) dma_desc + (desc_num*8)+5)); 248 cli_out("DMA WRITE: desc num:%d, haddr_hi: 0x%08x\n", desc_num, *((uint32 *) dma_desc + (desc_num*8)+6)); 249 cli_out("DMA WRITE: desc num:%d, Reserved: 0x%08x\n", desc_num, *((uint32 *) dma_desc + (desc_num*8)+7)); 250 cli_out("\n"); 251 } 252 #endif 253 254 /* Configure descriptor mode */ 255 rval = soc_pci_read(params->unit, CMIC_CMCx_SBUSDMA_CHy_CONTROL(cmc,ch)); 256 soc_reg_field_set(params->unit, CMIC_CMC1_SBUSDMA_CH1_CONTROLr, &rval, 257 DESCRIPTOR_ENDIANESSf, endian); 258 soc_reg_field_set(params->unit, CMIC_CMC1_SBUSDMA_CH1_CONTROLr, &rval, 259 DESC_PREFETCH_ENABLEf, 1); 260 soc_reg_field_set(params->unit, CMIC_CMC1_SBUSDMA_CH1_CONTROLr, &rval, MODEf, 1); 261 soc_pci_write(params->unit, CMIC_CMCx_SBUSDMA_CHy_CONTROL(cmc,ch), rval); 262 263 264 /* Set the starting descriptor address */ 265 rval = soc_pci_read(params->unit, CMIC_CMCx_SBUSDMA_CHy_DESCADDR_LO(cmc,ch)); 266 soc_reg_field_set(params->unit, CMIC_CMC1_SBUSDMA_CH1_DESC_START_ADDRESS_LOr, &rval, 267 ADDRESSf, HOST_ADDR_LO_CMICX(soc_cm_l2p(params->unit, dma_desc))); 268 soc_pci_write(params->unit, CMIC_CMCx_SBUSDMA_CHy_DESCADDR_LO(cmc,ch), rval); 269 270 rval = soc_pci_read(params->unit, CMIC_CMCx_SBUSDMA_CHy_DESCADDR_HI(cmc,ch)); 271 soc_reg_field_set(params->unit, CMIC_CMC1_SBUSDMA_CH1_DESC_START_ADDRESS_HIr, &rval, 272 ADDRESSf, HOST_ADDR_HI_CMICX(soc_cm_l2p(params->unit, dma_desc))); 273 if (soc_cm_get_bus_type(params->unit) & SOC_PCI_DEV_TYPE) { 274 rval |= CMIC_PCIE_SO_OFFSET; 275 } 276 soc_pci_write(params->unit, CMIC_CMCx_SBUSDMA_CHy_DESCADDR_HI(cmc,ch), rval); 277 278 /* Start the DMA */ 279 rval = soc_pci_read(params->unit, CMIC_CMCx_SBUSDMA_CHy_CONTROL(cmc,ch)); 280 soc_reg_field_set(params->unit, CMIC_CMC1_SBUSDMA_CH1_CONTROLr, &rval, STARTf, 1); 281 soc_pci_write(params->unit, CMIC_CMCx_SBUSDMA_CHy_CONTROL(cmc,ch), rval); 282 283 284 285 286 cli_out("Continuous Write DMA has been started: Runtime %d seconds\n", 287 params->test_time); 288 cli_out("Use the following to see the values changing in the table:\n"); 289 cli_out(" loop 100 \'d raw nocache NONUCAST_TRUNK_BLOCK_MASK 0 2\'\n"); 290 291 for (params->write_secs = 0; params->write_secs < params->test_time; 292 params->write_secs++) { 293 if ((params->flags & SBUSDMA_WRITE_RUN) == 0) { 294 break; 295 } 296 sal_sleep(1); 297 rval = soc_pci_read(params->unit, CMIC_CMCx_SBUSDMA_CHy_STATUS(cmc,ch)); 298 if (rval & 0x7FE) { 299 /* One of the error bits is set */ 300 cli_out("Error in SBUS DMA STATUS: %08X\n", rval); 301 params->status1 = SBUSDMA_STATUS_FAILURE; 302 break; 303 } 304 } 305 306 if (params->status1 == SBUSDMA_STATUS_RUNNING) { 307 params->status1 = SBUSDMA_STATUS_SUCCESS; 308 } 309 310 cli_out("About to stop the Write DMA: %d seconds run time\n", params->write_secs ); 311 params->flags &= ~SBUSDMA_WRITE_RUN; 312 313 /* Stop the DMA */ 314 rval = soc_pci_read(params->unit, CMIC_CMCx_SBUSDMA_CHy_CONTROL(cmc,ch)); 315 soc_reg_field_set(params->unit, CMIC_CMC1_SBUSDMA_CH1_CONTROLr, &rval, ABORTf, 1); 316 soc_pci_write(params->unit, CMIC_CMCx_SBUSDMA_CHy_CONTROL(cmc,ch), rval); 317 318 soc_timeout_init(&to, 1000000, 0); 319 do { 320 rval = soc_pci_read(params->unit, CMIC_CMCx_SBUSDMA_CHy_STATUS(cmc,ch)); 321 if (soc_reg_field_get(params->unit, CMIC_CMC1_SBUSDMA_CH1_STATUSr, rval, DONEf)) { 322 break; 323 } 324 325 if (soc_timeout_check(&to)) { 326 cli_out("DMA read abort timeout!\n"); 327 params->status1 = SBUSDMA_STATUS_FAILURE; 328 break; 329 } 330 } while (1); 331 332 rval = soc_pci_read(params->unit, CMIC_CMCx_SBUSDMA_CHy_CONTROL(cmc,ch)); 333 soc_reg_field_set(params->unit, CMIC_CMC1_SBUSDMA_CH1_CONTROLr, &rval, STARTf, 0); 334 soc_reg_field_set(params->unit, CMIC_CMC1_SBUSDMA_CH1_CONTROLr, &rval, ABORTf, 0); 335 soc_pci_write(params->unit, CMIC_CMCx_SBUSDMA_CHy_CONTROL(cmc,ch), rval); 336 soc_cm_sfree(params->unit, dma_desc); 337 soc_cm_sfree(params->unit, mdata1); 338 soc_cm_sfree(params->unit, mdata2); 339 340 return; 341 } 342 static void 343 cmicx_continuous_dma_read(void *void_param) 344 { 345 struct sbusdma_params_s *const params = 346 (struct sbusdma_params_s *) void_param; 347 const int JUMP_OFFSET = 29; 348 const int REMAINING_OFFSET = 24; 349 const int DESCRIPTOR_COUNT = 33; /* Many to allow for prefetching */ 350 351 int endian; 352 int entries; 353 int entry_bytes; 354 int entry_width; 355 int tmp; 356 sbusdma_desc_t *dma_desc; 357 soc_mem_info_t *minfo; 358 uint32 check[8]; 359 uint32 *mdata1; 360 uint32 rval; 361 int print_count = 0; 362 soc_timeout_t to; 363 int desc_num; 364 int desc_remaining; 365 int ch, cmc; 366 367 cmc = 0; 368 ch = params->rd_channel; 369 params->status2 = SBUSDMA_STATUS_RUNNING; 370 371 /* Sanity checks */ 372 if (!SOC_MEM_IS_VALID(params->unit, params->mem)) { 373 #if !defined(SOC_NO_NAMES) 374 cli_out("This device does not have the %s memory used by this test\n", 375 soc_mem_name[params->mem]); 376 #else 377 cli_out("This device does not have the memory used by this test\n"); 378 #endif 379 params->status2 = SBUSDMA_STATUS_FAILURE; 380 return; 381 } 382 383 /* Allocate memory for the SBUS DMA descriptors and the table data */ 384 dma_desc = 385 soc_cm_salloc(params->unit, DESCRIPTOR_COUNT * sizeof(sbusdma_desc_t), 386 "sbus_dma_descriptors"); 387 if (!dma_desc) { 388 cli_out("Could not allocate memory for SBUS DMA descriptors\n"); 389 params->status2 = SBUSDMA_STATUS_FAILURE; 390 return; 391 } 392 sal_memset(dma_desc, 0, DESCRIPTOR_COUNT * sizeof(sbusdma_desc_t)); 393 394 minfo = &SOC_MEM_INFO(params->unit, params->mem); 395 entries = minfo->index_max - minfo->index_min + 1; /* Compute mem size */ 396 entry_width = ((minfo->bytes + 3) / 4) * 4; 397 entry_bytes = entries * entry_width; 398 mdata1 = soc_cm_salloc(params->unit, entry_bytes, "table_data"); 399 if (!mdata1) { 400 cli_out("Could not allocate memory for table data 1\n"); 401 soc_cm_sfree(params->unit, dma_desc); 402 params->status2 = SBUSDMA_STATUS_FAILURE; 403 return; 404 } 405 sal_memset(mdata1, 0xA5, entry_bytes); 406 sal_memcpy(check, mdata1, sizeof(check)); 407 408 /* Form the SBUS DMA descriptors 409 * desc[0]: DMA table entry to mdata1 410 * desc[1]: DMA table entry to mdata1 411 * desc[2]: DMA table entry to mdata1 412 * ... 413 * desc[n-2]: DMA table entry to mdata1 414 * desc[n-1]: DMA table entry to mdata1 415 * desc[n]: Jump back to desc[0] */ 416 soc_endian_get(params->unit, &tmp, &tmp, &endian); 417 418 desc_remaining = DESCRIPTOR_COUNT - 2; /* Used for prefetch, does not include reload descriptor */ 419 if (desc_remaining > 15) { 420 desc_remaining = 15; 421 } 422 423 /* Fully form a single descriptor */ 424 dma_desc[0].control = (desc_remaining << REMAINING_OFFSET); 425 426 rval = 0; 427 soc_reg_field_set(params->unit, CMIC_CMC1_SBUSDMA_CH0_REQUESTr, 428 &rval, WORDSWAP_IN_64BIT_SBUSDATAf, 0); 429 soc_reg_field_set(params->unit, CMIC_CMC1_SBUSDMA_CH0_REQUESTr, 430 &rval, HOSTMEMWR_ENDIANESSf, endian); 431 soc_reg_field_set(params->unit, CMIC_CMC1_SBUSDMA_CH0_REQUESTr, 432 &rval, HOSTMEMRD_ENDIANESSf, endian); 433 soc_reg_field_set(params->unit, CMIC_CMC1_SBUSDMA_CH0_REQUESTr, 434 &rval, REQ_WORDSf, 0); 435 soc_reg_field_set(params->unit, CMIC_CMC1_SBUSDMA_CH0_REQUESTr, 436 &rval, REP_WORDSf, entry_width / 4); 437 soc_reg_field_set(params->unit, CMIC_CMC1_SBUSDMA_CH0_REQUESTr, 438 &rval, PEND_CLOCKSf, 0); 439 dma_desc[0].request = rval; 440 dma_desc[0].count = entries; 441 442 soc_schan_header_cmd_set(params->unit, (schan_header_t *) & dma_desc[0].opcode, 443 READ_MEMORY_CMD_MSG, SOC_BLOCK2SCH(params->unit, 444 minfo->minblock), 0, 445 SOC_MEM_ACC_TYPE(params->unit, params->mem), 446 entry_width, 0, 0); 447 448 dma_desc[0].sbus_base = minfo->base + minfo->index_min; 449 450 dma_desc[0].hostmem_phy_base_lo = 451 HOST_ADDR_LO_CMICX(soc_cm_l2p(params->unit, mdata1)); 452 dma_desc[0].hostmem_phy_base_hi = 453 HOST_ADDR_HI_CMICX(soc_cm_l2p(params->unit, mdata1)); 454 if (soc_cm_get_bus_type(params->unit) & SOC_PCI_DEV_TYPE) { 455 dma_desc[0].hostmem_phy_base_hi |= CMIC_PCIE_SO_OFFSET; 456 } 457 458 /* Copy the fully formed descriptor to the other descriptors and update as necessary */ 459 for (desc_num = 1; desc_num < (DESCRIPTOR_COUNT - 1); desc_num++) { 460 sal_memcpy(&dma_desc[desc_num], &dma_desc[0], sizeof(sbusdma_desc_t)); 461 462 desc_remaining = DESCRIPTOR_COUNT - desc_num - 2; 463 if (desc_remaining > 15) { 464 desc_remaining = 15; 465 } 466 dma_desc[desc_num].control = (desc_remaining << REMAINING_OFFSET); 467 } 468 469 /* Create the reload descriptor */ 470 dma_desc[desc_num].control = 1 << JUMP_OFFSET; 471 dma_desc[desc_num].hostmem_phy_base_lo = 472 HOST_ADDR_LO_CMICX(soc_cm_l2p(params->unit, dma_desc)); 473 dma_desc[desc_num].hostmem_phy_base_hi = 474 HOST_ADDR_HI_CMICX(soc_cm_l2p(params->unit, dma_desc)); 475 if (soc_cm_get_bus_type(params->unit) & SOC_PCI_DEV_TYPE) { 476 dma_desc[desc_num].hostmem_phy_base_hi |= CMIC_PCIE_SO_OFFSET; 477 } 478 479 #ifdef TEST_DEBUG 480 cli_out("DMA READ: cmc: %d: ch: %d\n", cmc, ch); 481 for (desc_num = 0; 482 desc_num < DESCRIPTOR_COUNT; 483 desc_num++) { 484 cli_out("DMA READ: desc num:%d, Control: 0x%08x\n", desc_num, *((uint32 *) dma_desc + (desc_num*8))); 485 cli_out("DMA READ desc num:%d, Request: 0x%08x\n", desc_num, *((uint32 *) dma_desc + (desc_num*8)+1)); 486 cli_out("DMA READ: desc num:%d, Count: 0x%08x\n", desc_num, *((uint32 *) dma_desc + (desc_num*8)+2)); 487 cli_out("DMA READ: desc num:%d, Opcode: 0x%08x\n", desc_num, *((uint32 *) dma_desc + (desc_num*8)+3)); 488 cli_out("DMA READ: desc num:%d, sbus addr: 0x%08x\n", desc_num, *((uint32 *) dma_desc + (desc_num*8)+4)); 489 cli_out("DMA READ: desc num:%d, haddr_low: 0x%08x\n", desc_num, *((uint32 *) dma_desc + (desc_num*8)+5)); 490 cli_out("DMA READ: desc num:%d, haddr_hi: 0x%08x\n", desc_num, *((uint32 *) dma_desc + (desc_num*8)+6)); 491 cli_out("DMA READ: desc num:%d, Reserved: 0x%08x\n", desc_num, *((uint32 *) dma_desc + (desc_num*8)+7)); 492 cli_out("\n"); 493 } 494 #endif 495 496 /* Configure descriptor mode */ 497 rval = soc_pci_read(params->unit, CMIC_CMCx_SBUSDMA_CHy_CONTROL(cmc,ch)); 498 soc_reg_field_set(params->unit, CMIC_CMC1_SBUSDMA_CH0_CONTROLr, &rval, 499 DESCRIPTOR_ENDIANESSf, endian); 500 soc_reg_field_set(params->unit, CMIC_CMC1_SBUSDMA_CH0_CONTROLr, &rval, 501 DESC_PREFETCH_ENABLEf, 1); 502 soc_reg_field_set(params->unit, CMIC_CMC1_SBUSDMA_CH0_CONTROLr, &rval, MODEf, 1); 503 soc_pci_write(params->unit, CMIC_CMCx_SBUSDMA_CHy_CONTROL(cmc,ch), rval); 504 505 /* Set the starting descriptor address */ 506 507 rval = soc_pci_read(params->unit, CMIC_CMCx_SBUSDMA_CHy_DESCADDR_LO(cmc,ch)); 508 soc_reg_field_set(params->unit, CMIC_CMC1_SBUSDMA_CH0_DESC_START_ADDRESS_LOr, &rval, 509 ADDRESSf, HOST_ADDR_LO_CMICX(soc_cm_l2p(params->unit, dma_desc))); 510 soc_pci_write(params->unit, CMIC_CMCx_SBUSDMA_CHy_DESCADDR_LO(cmc,ch), rval); 511 512 rval = soc_pci_read(params->unit, CMIC_CMCx_SBUSDMA_CHy_DESCADDR_HI(cmc,ch)); 513 soc_reg_field_set(params->unit, CMIC_CMC1_SBUSDMA_CH0_DESC_START_ADDRESS_HIr, &rval, 514 ADDRESSf, HOST_ADDR_HI_CMICX(soc_cm_l2p(params->unit, dma_desc))); 515 if (soc_cm_get_bus_type(params->unit) & SOC_PCI_DEV_TYPE) { 516 rval |= CMIC_PCIE_SO_OFFSET; 517 } 518 soc_pci_write(params->unit, CMIC_CMCx_SBUSDMA_CHy_DESCADDR_HI(cmc,ch), rval); 519 520 /* Start the DMA */ 521 rval = soc_pci_read(params->unit, CMIC_CMCx_SBUSDMA_CHy_CONTROL(cmc,ch)); 522 (soc_reg32_get(params->unit, CMIC_CMCx_SBUSDMA_CHy_CONTROL(cmc,ch), REG_PORT_ANY, 523 0, &rval)); 524 soc_reg_field_set(params->unit, CMIC_CMC1_SBUSDMA_CH0_CONTROLr, &rval, STARTf, 1); 525 soc_pci_write(params->unit, CMIC_CMCx_SBUSDMA_CHy_CONTROL(cmc,ch), rval); 526 527 cli_out("Continuous Read DMA has been started: Runtime %d seconds\n", 528 params->test_time); 529 530 for (params->read_secs = 0;params->read_secs < params->test_time; 531 params->read_secs++) { 532 if ((params->flags & SBUSDMA_READ_RUN) == 0) { 533 /* Test aborted */ 534 break; 535 } 536 sal_sleep(1); 537 rval = soc_pci_read(params->unit, CMIC_CMCx_SBUSDMA_CHy_STATUS(cmc,ch)); 538 if (rval & 0x7FE) { 539 /* One of the error bits is set */ 540 cli_out("Error in SBUS DMA STATUS: %08X\n", rval); 541 params->status2 = SBUSDMA_STATUS_FAILURE; 542 break; 543 } 544 if (sal_memcmp(mdata1, check, sizeof(check))) { 545 if (print_count++ < 5) { 546 cli_out("DMA Read: %08X %08X %08X %08X %08X %08X %08X %08X\n", 547 mdata1[0], mdata1[1], mdata1[2], mdata1[3], mdata1[4], 548 mdata1[5], mdata1[6], mdata1[7]); 549 } 550 sal_memcpy(check, mdata1, sizeof(check)); 551 } 552 } 553 cli_out("About to stop the Read DMA: %d seconds run time\n", params->read_secs); 554 params->flags &= ~SBUSDMA_READ_RUN; 555 556 /* Stop the DMA */ 557 rval = soc_pci_read(params->unit, CMIC_CMCx_SBUSDMA_CHy_CONTROL(cmc,ch)); 558 soc_reg_field_set(params->unit, CMIC_CMC1_SBUSDMA_CH0_CONTROLr, &rval, ABORTf, 1); 559 soc_pci_write(params->unit, CMIC_CMCx_SBUSDMA_CHy_CONTROL(cmc,ch), rval); 560 561 soc_timeout_init(&to, 1000000, 0); 562 do { 563 rval = soc_pci_read(params->unit, CMIC_CMCx_SBUSDMA_CHy_STATUS(cmc,ch)); 564 if (soc_reg_field_get(params->unit, CMIC_CMC1_SBUSDMA_CH0_STATUSr, rval, DONEf)) { 565 break; 566 } 567 568 if (soc_timeout_check(&to)) { 569 cli_out("DMA read abort timeout!\n"); 570 params->status2 = SBUSDMA_STATUS_FAILURE; 571 break; 572 } 573 } while (1); 574 if (params->status2 != SBUSDMA_STATUS_FAILURE) { 575 params->status2 = SBUSDMA_STATUS_SUCCESS; 576 } 577 578 rval = soc_pci_read(params->unit, CMIC_CMCx_SBUSDMA_CHy_CONTROL(cmc,ch)); 579 soc_reg_field_set(params->unit, CMIC_CMC1_SBUSDMA_CH0_CONTROLr, &rval, STARTf, 0); 580 soc_pci_write(params->unit, CMIC_CMCx_SBUSDMA_CHy_CONTROL(cmc,ch), rval); 581 582 soc_cm_sfree(params->unit, dma_desc); 583 soc_cm_sfree(params->unit, mdata1); 584 585 return; 586 } 587 static const char sbusdma_stress_test_usage[] = 588 "SBUS DMA stress test usage:\n" 589 "RdChanBitmap=<hex> - specify which of the 9 available CMC/channels to read\n" 590 " default is channel 0 for read, multi channels can be assigned to read\n" 591 "WrChanBitmap=<hex> - specify which of the 9 available CMC/channels to write\n" 592 " default is channel 1 for write, multi channels can be assigned to write\n" 593 "Seconds=<int> - specify test time, default is 10 seconds\n"; 594 595 int sb_stress_test(int unit, args_t *a, void *pa) 596 { 597 static sbusdma_params_t sbusdma_params; 598 static int needs_init = 1; 599 int wrchbmp = 0, rdchbmp = 0; 600 parse_table_t pt; 601 const int DEFAULT_TEST_TIME = 60; 602 int index, count; 603 604 int seconds = DEFAULT_TEST_TIME; 605 606 parse_table_init(unit, &pt); 607 parse_table_add(&pt, "WrChanBitmap", PQ_DFL | PQ_INT, 0, &wrchbmp, 0); 608 parse_table_add(&pt, "RdChanBitmap", PQ_DFL | PQ_INT, 0, &rdchbmp, 0); 609 parse_table_add(&pt, "seconds", PQ_DFL | PQ_INT, 0, &seconds, 0); 610 611 if ((parse_arg_eq(a, &pt)) < 0 || (ARG_CNT(a) > 0)) { 612 cli_out("%s", sbusdma_stress_test_usage); 613 cli_out("%s: ERROR: Unknown option: %s\n", ARG_CMD(a), 614 ARG_CUR(a) ? ARG_CUR(a) : "*"); 615 parse_arg_eq_done(&pt); 616 return BCM_E_FAIL; 617 } 618 619 parse_arg_eq_done(&pt); 620 621 622 if (needs_init) { 623 sal_memset(&sbusdma_params, 0, sizeof(sbusdma_params_t)); 624 needs_init = 0; 625 } 626 627 if (wrchbmp & rdchbmp) { 628 cli_out("WrChanBitmap=0x%x and RdChanBitmap=0x%x are conflict\n", wrchbmp, rdchbmp); 629 return BCM_E_FAIL; 630 } else if ((wrchbmp == 0) && (rdchbmp == 0)) { 631 /* Default channel */ 632 rdchbmp = 0x1; 633 wrchbmp = 0x2; 634 } 635 count = 0; 636 for (index = 0; index < SBUSDMA_CH_MAX_NUM; index++) { 637 638 if (wrchbmp & (1 << index)) { 639 const soc_mem_t mem = NONUCAST_TRUNK_BLOCK_MASKm; 640 const int priority = 100; 641 642 char thread_name[64]; 643 644 if (sbusdma_params.status1 == SBUSDMA_STATUS_RUNNING) { 645 cli_out("SBUSDMA Write test in progress\n"); 646 return CMD_OK; 647 } 648 649 sbusdma_params.unit = unit; 650 sbusdma_params.mem = mem; 651 sbusdma_params.flags |= SBUSDMA_WRITE_RUN; 652 sbusdma_params.test_time = seconds; 653 sbusdma_params.wr_channel = index; 654 #if !defined(SOC_NO_NAMES) 655 sal_sprintf(thread_name, "Write SBUSDMA-%s", soc_mem_name[mem]); 656 #else 657 sal_sprintf(thread_name, "Write SBUSDMA-%d", index); 658 #endif 659 /* Start DMA thread. */ 660 sbusdma_params.tid = sal_thread_create(thread_name, 661 SAL_THREAD_STKSZ, 662 priority, 663 cmicx_continuous_dma_write, 664 &sbusdma_params); 665 count++; 666 } else if (rdchbmp & (1<< index)) { 667 const soc_mem_t mem = NONUCAST_TRUNK_BLOCK_MASKm; 668 const int priority = 100; 669 670 char thread_name[64]; 671 672 if (sbusdma_params.status2 == SBUSDMA_STATUS_RUNNING) { 673 cli_out("SBUSDMA Read test in progress\n"); 674 return CMD_OK; 675 } 676 sbusdma_params.unit = unit; 677 sbusdma_params.mem = mem; 678 sbusdma_params.flags |= SBUSDMA_READ_RUN; 679 sbusdma_params.test_time = seconds; 680 sbusdma_params.rd_channel = index; 681 #if !defined(SOC_NO_NAMES) 682 sal_sprintf(thread_name, "Read SBUSDMA-%s", soc_mem_name[mem]); 683 #else 684 sal_sprintf(thread_name, "Read SBUSDMA-%d", index); 685 #endif 686 687 /* Start DMA thread. */ 688 sbusdma_params.tid = sal_thread_create(thread_name, 689 SAL_THREAD_STKSZ, 690 priority, cmicx_continuous_dma_read, 691 &sbusdma_params); 692 count++; 693 } 694 695 #if 0 696 else if (!sal_strcasecmp(subcmd, "stopw")) { 697 sbusdma_params.flags &= ~SBUSDMA_WRITE_RUN; 698 sal_sleep(2); 699 cli_out("Write test status: %s\n", status_strings[sbusdma_params.status]); 700 } else if (!sal_strcasecmp(subcmd, "stopr")) { 701 sbusdma_params.flags &= ~SBUSDMA_READ_RUN; 702 sal_sleep(2); 703 cli_out("Read test status: %s\n", status_strings[sbusdma_params.status]); 704 } else if (!sal_strcasecmp(subcmd, "status")) { 705 if (sbusdma_params.status == SBUSDMA_STATUS_RUNNING) { 706 cli_out("Read DMA in progress: seconds out of %d\n", 707 sbusdma_params.test_time); 708 } else { 709 cli_out("Read DMA last status: %s\n", 710 status_strings[sbusdma_params.status]); 711 } 712 if (sbusdma_params.status == SBUSDMA_STATUS_RUNNING) { 713 cli_out("Write DMA in progress: seconds out of %d\n", 714 sbusdma_params.test_time); 715 } else { 716 cli_out("Write DMA last status: %s\n", 717 status_strings[sbusdma_params.status]); 718 } 719 } else { 720 cli_out("Unknown sub-command\n"); 721 return CMD_USAGE; 722 } 723 #endif 724 } 725 726 if (count == 0) { 727 cli_out("No valid channel assigned\n"); 728 return BCM_E_FAIL; 729 } 730 return CMD_OK; 731 } 732 #endif