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

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