1*29e2dbd4SRam Kishore Vegesna /* 2*29e2dbd4SRam Kishore Vegesna * Copyright (c) 2021 Broadcom. All rights reserved. 3*29e2dbd4SRam Kishore Vegesna * The term "Broadcom" refers to Broadcom Limited and/or its subsidiaries. 4*29e2dbd4SRam Kishore Vegesna * 5*29e2dbd4SRam Kishore Vegesna * Redistribution and use in source and binary forms, with or without 6*29e2dbd4SRam Kishore Vegesna * modification, are permitted provided that the following conditions are met: 7*29e2dbd4SRam Kishore Vegesna * 8*29e2dbd4SRam Kishore Vegesna * 1. Redistributions of source code must retain the above copyright notice, 9*29e2dbd4SRam Kishore Vegesna * this list of conditions and the following disclaimer. 10*29e2dbd4SRam Kishore Vegesna * 11*29e2dbd4SRam Kishore Vegesna * 2. Redistributions in binary form must reproduce the above copyright notice, 12*29e2dbd4SRam Kishore Vegesna * this list of conditions and the following disclaimer in the documentation 13*29e2dbd4SRam Kishore Vegesna * and/or other materials provided with the distribution. 14*29e2dbd4SRam Kishore Vegesna * 15*29e2dbd4SRam Kishore Vegesna * 3. Neither the name of the copyright holder nor the names of its contributors 16*29e2dbd4SRam Kishore Vegesna * may be used to endorse or promote products derived from this software 17*29e2dbd4SRam Kishore Vegesna * without specific prior written permission. 18*29e2dbd4SRam Kishore Vegesna * 19*29e2dbd4SRam Kishore Vegesna * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20*29e2dbd4SRam Kishore Vegesna * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21*29e2dbd4SRam Kishore Vegesna * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22*29e2dbd4SRam Kishore Vegesna * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 23*29e2dbd4SRam Kishore Vegesna * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24*29e2dbd4SRam Kishore Vegesna * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25*29e2dbd4SRam Kishore Vegesna * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26*29e2dbd4SRam Kishore Vegesna * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27*29e2dbd4SRam Kishore Vegesna * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28*29e2dbd4SRam Kishore Vegesna * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29*29e2dbd4SRam Kishore Vegesna * POSSIBILITY OF SUCH DAMAGE. 30*29e2dbd4SRam Kishore Vegesna * 31*29e2dbd4SRam Kishore Vegesna */ 32*29e2dbd4SRam Kishore Vegesna 33*29e2dbd4SRam Kishore Vegesna #include "ocs.h" 34*29e2dbd4SRam Kishore Vegesna #include "ocs_gendump.h" 35*29e2dbd4SRam Kishore Vegesna 36*29e2dbd4SRam Kishore Vegesna /* Reset all the functions associated with a bus/dev */ 37*29e2dbd4SRam Kishore Vegesna static int 38*29e2dbd4SRam Kishore Vegesna ocs_gen_dump_reset(uint8_t bus, uint8_t dev) 39*29e2dbd4SRam Kishore Vegesna { 40*29e2dbd4SRam Kishore Vegesna uint32_t index = 0; 41*29e2dbd4SRam Kishore Vegesna ocs_t *ocs; 42*29e2dbd4SRam Kishore Vegesna int rc = 0; 43*29e2dbd4SRam Kishore Vegesna 44*29e2dbd4SRam Kishore Vegesna while ((ocs = ocs_get_instance(index++)) != NULL) { 45*29e2dbd4SRam Kishore Vegesna uint8_t ocs_bus, ocs_dev, ocs_func; 46*29e2dbd4SRam Kishore Vegesna ocs_domain_t *domain; 47*29e2dbd4SRam Kishore Vegesna 48*29e2dbd4SRam Kishore Vegesna ocs_get_bus_dev_func(ocs, &ocs_bus, &ocs_dev, &ocs_func); 49*29e2dbd4SRam Kishore Vegesna 50*29e2dbd4SRam Kishore Vegesna if (!(ocs_bus == bus && ocs_dev == dev)) 51*29e2dbd4SRam Kishore Vegesna continue; 52*29e2dbd4SRam Kishore Vegesna 53*29e2dbd4SRam Kishore Vegesna if (ocs_hw_reset(&ocs->hw, OCS_HW_RESET_FUNCTION)) { 54*29e2dbd4SRam Kishore Vegesna ocs_log_test(ocs, "failed to reset port\n"); 55*29e2dbd4SRam Kishore Vegesna rc = -1; 56*29e2dbd4SRam Kishore Vegesna continue; 57*29e2dbd4SRam Kishore Vegesna } 58*29e2dbd4SRam Kishore Vegesna 59*29e2dbd4SRam Kishore Vegesna ocs_log_debug(ocs, "successfully reset port\n"); 60*29e2dbd4SRam Kishore Vegesna while ((domain = ocs_list_get_head(&ocs->domain_list)) != NULL) { 61*29e2dbd4SRam Kishore Vegesna ocs_log_debug(ocs, "free domain %p\n", domain); 62*29e2dbd4SRam Kishore Vegesna ocs_domain_force_free(domain); 63*29e2dbd4SRam Kishore Vegesna } 64*29e2dbd4SRam Kishore Vegesna /* now initialize hw so user can read the dump in */ 65*29e2dbd4SRam Kishore Vegesna if (ocs_hw_init(&ocs->hw)) { 66*29e2dbd4SRam Kishore Vegesna ocs_log_err(ocs, "failed to initialize hw\n"); 67*29e2dbd4SRam Kishore Vegesna rc = -1; 68*29e2dbd4SRam Kishore Vegesna } else { 69*29e2dbd4SRam Kishore Vegesna ocs_log_debug(ocs, "successfully initialized hw\n"); 70*29e2dbd4SRam Kishore Vegesna } 71*29e2dbd4SRam Kishore Vegesna } 72*29e2dbd4SRam Kishore Vegesna return rc; 73*29e2dbd4SRam Kishore Vegesna } 74*29e2dbd4SRam Kishore Vegesna 75*29e2dbd4SRam Kishore Vegesna int 76*29e2dbd4SRam Kishore Vegesna ocs_gen_dump(ocs_t *ocs) 77*29e2dbd4SRam Kishore Vegesna { 78*29e2dbd4SRam Kishore Vegesna uint32_t reset_required; 79*29e2dbd4SRam Kishore Vegesna uint32_t dump_ready; 80*29e2dbd4SRam Kishore Vegesna uint32_t ms_waited; 81*29e2dbd4SRam Kishore Vegesna uint8_t bus, dev, func; 82*29e2dbd4SRam Kishore Vegesna int rc = 0; 83*29e2dbd4SRam Kishore Vegesna int index = 0, port_index = 0; 84*29e2dbd4SRam Kishore Vegesna ocs_t *nxt_ocs; 85*29e2dbd4SRam Kishore Vegesna uint8_t nxt_bus, nxt_dev, nxt_func; 86*29e2dbd4SRam Kishore Vegesna uint8_t prev_port_state[OCS_MAX_HBA_PORTS] = {0,}; 87*29e2dbd4SRam Kishore Vegesna ocs_xport_stats_t link_status; 88*29e2dbd4SRam Kishore Vegesna 89*29e2dbd4SRam Kishore Vegesna ocs_get_bus_dev_func(ocs, &bus, &dev, &func); 90*29e2dbd4SRam Kishore Vegesna 91*29e2dbd4SRam Kishore Vegesna /* Drop link on all ports belongs to this HBA*/ 92*29e2dbd4SRam Kishore Vegesna while ((nxt_ocs = ocs_get_instance(index++)) != NULL) { 93*29e2dbd4SRam Kishore Vegesna ocs_get_bus_dev_func(nxt_ocs, &nxt_bus, &nxt_dev, &nxt_func); 94*29e2dbd4SRam Kishore Vegesna 95*29e2dbd4SRam Kishore Vegesna if (!(bus == nxt_bus && dev == nxt_dev)) 96*29e2dbd4SRam Kishore Vegesna continue; 97*29e2dbd4SRam Kishore Vegesna 98*29e2dbd4SRam Kishore Vegesna if ((port_index >= OCS_MAX_HBA_PORTS)) 99*29e2dbd4SRam Kishore Vegesna continue; 100*29e2dbd4SRam Kishore Vegesna 101*29e2dbd4SRam Kishore Vegesna /* Check current link status and save for future use */ 102*29e2dbd4SRam Kishore Vegesna if (ocs_xport_status(nxt_ocs->xport, OCS_XPORT_PORT_STATUS, 103*29e2dbd4SRam Kishore Vegesna &link_status) == 0) { 104*29e2dbd4SRam Kishore Vegesna if (link_status.value == OCS_XPORT_PORT_ONLINE) { 105*29e2dbd4SRam Kishore Vegesna prev_port_state[port_index] = 1; 106*29e2dbd4SRam Kishore Vegesna ocs_xport_control(nxt_ocs->xport, 107*29e2dbd4SRam Kishore Vegesna OCS_XPORT_PORT_OFFLINE); 108*29e2dbd4SRam Kishore Vegesna } else { 109*29e2dbd4SRam Kishore Vegesna prev_port_state[port_index] = 0; 110*29e2dbd4SRam Kishore Vegesna } 111*29e2dbd4SRam Kishore Vegesna } 112*29e2dbd4SRam Kishore Vegesna port_index++; 113*29e2dbd4SRam Kishore Vegesna } 114*29e2dbd4SRam Kishore Vegesna 115*29e2dbd4SRam Kishore Vegesna /* Wait until all ports have quiesced */ 116*29e2dbd4SRam Kishore Vegesna for (index = 0; (nxt_ocs = ocs_get_instance(index++)) != NULL; ) { 117*29e2dbd4SRam Kishore Vegesna ms_waited = 0; 118*29e2dbd4SRam Kishore Vegesna for (;;) { 119*29e2dbd4SRam Kishore Vegesna ocs_xport_stats_t status; 120*29e2dbd4SRam Kishore Vegesna 121*29e2dbd4SRam Kishore Vegesna ocs_xport_status(nxt_ocs->xport, OCS_XPORT_IS_QUIESCED, 122*29e2dbd4SRam Kishore Vegesna &status); 123*29e2dbd4SRam Kishore Vegesna if (status.value) { 124*29e2dbd4SRam Kishore Vegesna ocs_log_debug(nxt_ocs, "port quiesced\n"); 125*29e2dbd4SRam Kishore Vegesna break; 126*29e2dbd4SRam Kishore Vegesna } 127*29e2dbd4SRam Kishore Vegesna 128*29e2dbd4SRam Kishore Vegesna ocs_msleep(10); 129*29e2dbd4SRam Kishore Vegesna ms_waited += 10; 130*29e2dbd4SRam Kishore Vegesna if (ms_waited > 60000) { 131*29e2dbd4SRam Kishore Vegesna ocs_log_test(nxt_ocs, 132*29e2dbd4SRam Kishore Vegesna "timed out waiting for port to quiesce\n"); 133*29e2dbd4SRam Kishore Vegesna break; 134*29e2dbd4SRam Kishore Vegesna } 135*29e2dbd4SRam Kishore Vegesna } 136*29e2dbd4SRam Kishore Vegesna } 137*29e2dbd4SRam Kishore Vegesna 138*29e2dbd4SRam Kishore Vegesna /* Initiate dump */ 139*29e2dbd4SRam Kishore Vegesna if (ocs_hw_raise_ue(&ocs->hw, 1) == OCS_HW_RTN_SUCCESS) { 140*29e2dbd4SRam Kishore Vegesna 141*29e2dbd4SRam Kishore Vegesna /* Wait for dump to complete */ 142*29e2dbd4SRam Kishore Vegesna ocs_log_debug(ocs, "Dump requested, wait for completion.\n"); 143*29e2dbd4SRam Kishore Vegesna 144*29e2dbd4SRam Kishore Vegesna dump_ready = 0; 145*29e2dbd4SRam Kishore Vegesna ms_waited = 0; 146*29e2dbd4SRam Kishore Vegesna while ((!dump_ready) && (ms_waited < 30000)) { 147*29e2dbd4SRam Kishore Vegesna ocs_hw_get(&ocs->hw, OCS_HW_DUMP_READY, &dump_ready); 148*29e2dbd4SRam Kishore Vegesna ocs_udelay(10000); 149*29e2dbd4SRam Kishore Vegesna ms_waited += 10; 150*29e2dbd4SRam Kishore Vegesna } 151*29e2dbd4SRam Kishore Vegesna 152*29e2dbd4SRam Kishore Vegesna if (!dump_ready) { 153*29e2dbd4SRam Kishore Vegesna ocs_log_test(ocs, "Failed to see dump after 30 secs\n"); 154*29e2dbd4SRam Kishore Vegesna rc = -1; 155*29e2dbd4SRam Kishore Vegesna } else { 156*29e2dbd4SRam Kishore Vegesna ocs_log_debug(ocs, "sucessfully generated dump\n"); 157*29e2dbd4SRam Kishore Vegesna } 158*29e2dbd4SRam Kishore Vegesna 159*29e2dbd4SRam Kishore Vegesna /* now reset port */ 160*29e2dbd4SRam Kishore Vegesna ocs_hw_get(&ocs->hw, OCS_HW_RESET_REQUIRED, &reset_required); 161*29e2dbd4SRam Kishore Vegesna ocs_log_debug(ocs, "reset required=%d\n", reset_required); 162*29e2dbd4SRam Kishore Vegesna if (reset_required) { 163*29e2dbd4SRam Kishore Vegesna if (ocs_gen_dump_reset(bus, dev) == 0) { 164*29e2dbd4SRam Kishore Vegesna ocs_log_debug(ocs, "all devices reset\n"); 165*29e2dbd4SRam Kishore Vegesna } else { 166*29e2dbd4SRam Kishore Vegesna ocs_log_test(ocs, "all devices NOT reset\n"); 167*29e2dbd4SRam Kishore Vegesna } 168*29e2dbd4SRam Kishore Vegesna } 169*29e2dbd4SRam Kishore Vegesna } else { 170*29e2dbd4SRam Kishore Vegesna ocs_log_test(ocs, "dump request to hw failed\n"); 171*29e2dbd4SRam Kishore Vegesna rc = -1; 172*29e2dbd4SRam Kishore Vegesna } 173*29e2dbd4SRam Kishore Vegesna 174*29e2dbd4SRam Kishore Vegesna index = port_index = 0; 175*29e2dbd4SRam Kishore Vegesna nxt_ocs = NULL; 176*29e2dbd4SRam Kishore Vegesna /* Bring links on each HBA port to previous state*/ 177*29e2dbd4SRam Kishore Vegesna while ((nxt_ocs = ocs_get_instance(index++)) != NULL) { 178*29e2dbd4SRam Kishore Vegesna ocs_get_bus_dev_func(nxt_ocs, &nxt_bus, &nxt_dev, &nxt_func); 179*29e2dbd4SRam Kishore Vegesna if (port_index > OCS_MAX_HBA_PORTS) { 180*29e2dbd4SRam Kishore Vegesna ocs_log_err(NULL, "port index(%d) out of boundary\n", 181*29e2dbd4SRam Kishore Vegesna port_index); 182*29e2dbd4SRam Kishore Vegesna rc = -1; 183*29e2dbd4SRam Kishore Vegesna break; 184*29e2dbd4SRam Kishore Vegesna } 185*29e2dbd4SRam Kishore Vegesna if ((bus == nxt_bus) && (dev == nxt_dev) && 186*29e2dbd4SRam Kishore Vegesna prev_port_state[port_index++]) { 187*29e2dbd4SRam Kishore Vegesna ocs_xport_control(nxt_ocs->xport, OCS_XPORT_PORT_ONLINE); 188*29e2dbd4SRam Kishore Vegesna } 189*29e2dbd4SRam Kishore Vegesna } 190*29e2dbd4SRam Kishore Vegesna 191*29e2dbd4SRam Kishore Vegesna return rc; 192*29e2dbd4SRam Kishore Vegesna } 193*29e2dbd4SRam Kishore Vegesna 194*29e2dbd4SRam Kishore Vegesna int 195*29e2dbd4SRam Kishore Vegesna ocs_fdb_dump(ocs_t *ocs) 196*29e2dbd4SRam Kishore Vegesna { 197*29e2dbd4SRam Kishore Vegesna uint32_t dump_ready; 198*29e2dbd4SRam Kishore Vegesna uint32_t ms_waited; 199*29e2dbd4SRam Kishore Vegesna int rc = 0; 200*29e2dbd4SRam Kishore Vegesna 201*29e2dbd4SRam Kishore Vegesna #define FDB 2 202*29e2dbd4SRam Kishore Vegesna 203*29e2dbd4SRam Kishore Vegesna /* Initiate dump */ 204*29e2dbd4SRam Kishore Vegesna if (ocs_hw_raise_ue(&ocs->hw, FDB) == OCS_HW_RTN_SUCCESS) { 205*29e2dbd4SRam Kishore Vegesna 206*29e2dbd4SRam Kishore Vegesna /* Wait for dump to complete */ 207*29e2dbd4SRam Kishore Vegesna ocs_log_debug(ocs, "Dump requested, wait for completion.\n"); 208*29e2dbd4SRam Kishore Vegesna 209*29e2dbd4SRam Kishore Vegesna dump_ready = 0; 210*29e2dbd4SRam Kishore Vegesna ms_waited = 0; 211*29e2dbd4SRam Kishore Vegesna while ((!(dump_ready == FDB)) && (ms_waited < 10000)) { 212*29e2dbd4SRam Kishore Vegesna ocs_hw_get(&ocs->hw, OCS_HW_DUMP_READY, &dump_ready); 213*29e2dbd4SRam Kishore Vegesna ocs_udelay(10000); 214*29e2dbd4SRam Kishore Vegesna ms_waited += 10; 215*29e2dbd4SRam Kishore Vegesna } 216*29e2dbd4SRam Kishore Vegesna 217*29e2dbd4SRam Kishore Vegesna if (!dump_ready) { 218*29e2dbd4SRam Kishore Vegesna ocs_log_err(ocs, "Failed to see dump after 10 secs\n"); 219*29e2dbd4SRam Kishore Vegesna return -1; 220*29e2dbd4SRam Kishore Vegesna } 221*29e2dbd4SRam Kishore Vegesna 222*29e2dbd4SRam Kishore Vegesna ocs_log_debug(ocs, "sucessfully generated dump\n"); 223*29e2dbd4SRam Kishore Vegesna 224*29e2dbd4SRam Kishore Vegesna } else { 225*29e2dbd4SRam Kishore Vegesna ocs_log_err(ocs, "dump request to hw failed\n"); 226*29e2dbd4SRam Kishore Vegesna rc = -1; 227*29e2dbd4SRam Kishore Vegesna } 228*29e2dbd4SRam Kishore Vegesna 229*29e2dbd4SRam Kishore Vegesna return rc; 230*29e2dbd4SRam Kishore Vegesna } 231*29e2dbd4SRam Kishore Vegesna 232*29e2dbd4SRam Kishore Vegesna /** 233*29e2dbd4SRam Kishore Vegesna * @brief Create a Lancer dump into a memory buffer 234*29e2dbd4SRam Kishore Vegesna * @par Description 235*29e2dbd4SRam Kishore Vegesna * This function creates a DMA buffer to hold a Lancer dump, 236*29e2dbd4SRam Kishore Vegesna * sets the dump location to point to that buffer, then calls 237*29e2dbd4SRam Kishore Vegesna * ocs_gen_dump to cause a dump to be transfered to the buffer. 238*29e2dbd4SRam Kishore Vegesna * After the dump is complete it copies the dump to the provided 239*29e2dbd4SRam Kishore Vegesna * user space buffer. 240*29e2dbd4SRam Kishore Vegesna * 241*29e2dbd4SRam Kishore Vegesna * @param ocs Pointer to ocs structure 242*29e2dbd4SRam Kishore Vegesna * @param buf User space buffer in which to store the dump 243*29e2dbd4SRam Kishore Vegesna * @param buflen Length of the user buffer in bytes 244*29e2dbd4SRam Kishore Vegesna * 245*29e2dbd4SRam Kishore Vegesna * @return Returns 0 on success, non-zero on error. 246*29e2dbd4SRam Kishore Vegesna */ 247*29e2dbd4SRam Kishore Vegesna int 248*29e2dbd4SRam Kishore Vegesna ocs_dump_to_host(ocs_t *ocs, void *buf, uint32_t buflen) 249*29e2dbd4SRam Kishore Vegesna { 250*29e2dbd4SRam Kishore Vegesna int rc; 251*29e2dbd4SRam Kishore Vegesna uint32_t i, num_buffers; 252*29e2dbd4SRam Kishore Vegesna ocs_dma_t *dump_buffers; 253*29e2dbd4SRam Kishore Vegesna uint32_t rem_bytes, offset; 254*29e2dbd4SRam Kishore Vegesna 255*29e2dbd4SRam Kishore Vegesna if (buflen == 0) { 256*29e2dbd4SRam Kishore Vegesna ocs_log_test(ocs, "zero buffer length is invalid\n"); 257*29e2dbd4SRam Kishore Vegesna return -1; 258*29e2dbd4SRam Kishore Vegesna } 259*29e2dbd4SRam Kishore Vegesna 260*29e2dbd4SRam Kishore Vegesna num_buffers = ((buflen + OCS_MAX_DMA_ALLOC - 1) / OCS_MAX_DMA_ALLOC); 261*29e2dbd4SRam Kishore Vegesna 262*29e2dbd4SRam Kishore Vegesna dump_buffers = ocs_malloc(ocs, sizeof(ocs_dma_t) * num_buffers, 263*29e2dbd4SRam Kishore Vegesna OCS_M_ZERO | OCS_M_NOWAIT); 264*29e2dbd4SRam Kishore Vegesna if (dump_buffers == NULL) { 265*29e2dbd4SRam Kishore Vegesna ocs_log_err(ocs, "Failed to dump buffers\n"); 266*29e2dbd4SRam Kishore Vegesna return -1; 267*29e2dbd4SRam Kishore Vegesna } 268*29e2dbd4SRam Kishore Vegesna 269*29e2dbd4SRam Kishore Vegesna /* Allocate a DMA buffers to hold the dump */ 270*29e2dbd4SRam Kishore Vegesna rem_bytes = buflen; 271*29e2dbd4SRam Kishore Vegesna for (i = 0; i < num_buffers; i++) { 272*29e2dbd4SRam Kishore Vegesna uint32_t num_bytes = MIN(rem_bytes, OCS_MAX_DMA_ALLOC); 273*29e2dbd4SRam Kishore Vegesna 274*29e2dbd4SRam Kishore Vegesna rc = ocs_dma_alloc(ocs, &dump_buffers[i], num_bytes, 275*29e2dbd4SRam Kishore Vegesna OCS_MIN_DMA_ALIGNMENT); 276*29e2dbd4SRam Kishore Vegesna if (rc) { 277*29e2dbd4SRam Kishore Vegesna ocs_log_err(ocs, "Failed to allocate dump buffer\n"); 278*29e2dbd4SRam Kishore Vegesna 279*29e2dbd4SRam Kishore Vegesna /* Free any previously allocated buffers */ 280*29e2dbd4SRam Kishore Vegesna goto free_and_return; 281*29e2dbd4SRam Kishore Vegesna } 282*29e2dbd4SRam Kishore Vegesna rem_bytes -= num_bytes; 283*29e2dbd4SRam Kishore Vegesna } 284*29e2dbd4SRam Kishore Vegesna 285*29e2dbd4SRam Kishore Vegesna rc = ocs_hw_set_dump_location(&ocs->hw, num_buffers, dump_buffers, 0); 286*29e2dbd4SRam Kishore Vegesna if (rc) { 287*29e2dbd4SRam Kishore Vegesna ocs_log_test(ocs, "ocs_hw_set_dump_location failed\n"); 288*29e2dbd4SRam Kishore Vegesna goto free_and_return; 289*29e2dbd4SRam Kishore Vegesna } 290*29e2dbd4SRam Kishore Vegesna 291*29e2dbd4SRam Kishore Vegesna /* Generate the dump */ 292*29e2dbd4SRam Kishore Vegesna rc = ocs_gen_dump(ocs); 293*29e2dbd4SRam Kishore Vegesna if (rc) { 294*29e2dbd4SRam Kishore Vegesna ocs_log_test(ocs, "ocs_gen_dump failed\n"); 295*29e2dbd4SRam Kishore Vegesna goto free_and_return; 296*29e2dbd4SRam Kishore Vegesna } 297*29e2dbd4SRam Kishore Vegesna 298*29e2dbd4SRam Kishore Vegesna /* Copy the dump from the DMA buffer into the user buffer */ 299*29e2dbd4SRam Kishore Vegesna offset = 0; 300*29e2dbd4SRam Kishore Vegesna for (i = 0; i < num_buffers; i++) { 301*29e2dbd4SRam Kishore Vegesna if (ocs_copy_to_user((uint8_t*)buf + offset, 302*29e2dbd4SRam Kishore Vegesna dump_buffers[i].virt, dump_buffers[i].size)) { 303*29e2dbd4SRam Kishore Vegesna ocs_log_test(ocs, "ocs_copy_to_user failed\n"); 304*29e2dbd4SRam Kishore Vegesna rc = -1; 305*29e2dbd4SRam Kishore Vegesna } 306*29e2dbd4SRam Kishore Vegesna offset += dump_buffers[i].size; 307*29e2dbd4SRam Kishore Vegesna } 308*29e2dbd4SRam Kishore Vegesna 309*29e2dbd4SRam Kishore Vegesna free_and_return: 310*29e2dbd4SRam Kishore Vegesna /* Free the DMA buffer and return */ 311*29e2dbd4SRam Kishore Vegesna for (i = 0; i < num_buffers; i++) { 312*29e2dbd4SRam Kishore Vegesna ocs_dma_free(ocs, &dump_buffers[i]); 313*29e2dbd4SRam Kishore Vegesna } 314*29e2dbd4SRam Kishore Vegesna ocs_free(ocs, dump_buffers, sizeof(ocs_dma_t) * num_buffers); 315*29e2dbd4SRam Kishore Vegesna return rc; 316*29e2dbd4SRam Kishore Vegesna } 317*29e2dbd4SRam Kishore Vegesna 318*29e2dbd4SRam Kishore Vegesna int 319*29e2dbd4SRam Kishore Vegesna ocs_function_speciic_dump(ocs_t *ocs, void *buf, uint32_t buflen) 320*29e2dbd4SRam Kishore Vegesna { 321*29e2dbd4SRam Kishore Vegesna int rc; 322*29e2dbd4SRam Kishore Vegesna uint32_t i, num_buffers; 323*29e2dbd4SRam Kishore Vegesna ocs_dma_t *dump_buffers; 324*29e2dbd4SRam Kishore Vegesna uint32_t rem_bytes, offset; 325*29e2dbd4SRam Kishore Vegesna 326*29e2dbd4SRam Kishore Vegesna if (buflen == 0) { 327*29e2dbd4SRam Kishore Vegesna ocs_log_err(ocs, "zero buffer length is invalid\n"); 328*29e2dbd4SRam Kishore Vegesna return -1; 329*29e2dbd4SRam Kishore Vegesna } 330*29e2dbd4SRam Kishore Vegesna 331*29e2dbd4SRam Kishore Vegesna num_buffers = ((buflen + OCS_MAX_DMA_ALLOC - 1) / OCS_MAX_DMA_ALLOC); 332*29e2dbd4SRam Kishore Vegesna 333*29e2dbd4SRam Kishore Vegesna dump_buffers = ocs_malloc(ocs, sizeof(ocs_dma_t) * num_buffers, 334*29e2dbd4SRam Kishore Vegesna OCS_M_ZERO | OCS_M_NOWAIT); 335*29e2dbd4SRam Kishore Vegesna if (dump_buffers == NULL) { 336*29e2dbd4SRam Kishore Vegesna ocs_log_err(ocs, "Failed to allocate dump buffers\n"); 337*29e2dbd4SRam Kishore Vegesna return -1; 338*29e2dbd4SRam Kishore Vegesna } 339*29e2dbd4SRam Kishore Vegesna 340*29e2dbd4SRam Kishore Vegesna /* Allocate a DMA buffers to hold the dump */ 341*29e2dbd4SRam Kishore Vegesna rem_bytes = buflen; 342*29e2dbd4SRam Kishore Vegesna for (i = 0; i < num_buffers; i++) { 343*29e2dbd4SRam Kishore Vegesna uint32_t num_bytes = MIN(rem_bytes, OCS_MAX_DMA_ALLOC); 344*29e2dbd4SRam Kishore Vegesna rc = ocs_dma_alloc(ocs, &dump_buffers[i], num_bytes, 345*29e2dbd4SRam Kishore Vegesna OCS_MIN_DMA_ALIGNMENT); 346*29e2dbd4SRam Kishore Vegesna if (rc) { 347*29e2dbd4SRam Kishore Vegesna ocs_log_err(ocs, "Failed to allocate dma buffer\n"); 348*29e2dbd4SRam Kishore Vegesna 349*29e2dbd4SRam Kishore Vegesna /* Free any previously allocated buffers */ 350*29e2dbd4SRam Kishore Vegesna goto free_and_return; 351*29e2dbd4SRam Kishore Vegesna } 352*29e2dbd4SRam Kishore Vegesna rem_bytes -= num_bytes; 353*29e2dbd4SRam Kishore Vegesna } 354*29e2dbd4SRam Kishore Vegesna 355*29e2dbd4SRam Kishore Vegesna /* register buffers for function spcific dump */ 356*29e2dbd4SRam Kishore Vegesna rc = ocs_hw_set_dump_location(&ocs->hw, num_buffers, dump_buffers, 1); 357*29e2dbd4SRam Kishore Vegesna if (rc) { 358*29e2dbd4SRam Kishore Vegesna ocs_log_err(ocs, "ocs_hw_set_dump_location failed\n"); 359*29e2dbd4SRam Kishore Vegesna goto free_and_return; 360*29e2dbd4SRam Kishore Vegesna } 361*29e2dbd4SRam Kishore Vegesna 362*29e2dbd4SRam Kishore Vegesna /* Invoke dump by setting fdd=1 and ip=1 in sliport_control register */ 363*29e2dbd4SRam Kishore Vegesna rc = ocs_fdb_dump(ocs); 364*29e2dbd4SRam Kishore Vegesna if (rc) { 365*29e2dbd4SRam Kishore Vegesna ocs_log_err(ocs, "ocs_gen_dump failed\n"); 366*29e2dbd4SRam Kishore Vegesna goto free_and_return; 367*29e2dbd4SRam Kishore Vegesna } 368*29e2dbd4SRam Kishore Vegesna 369*29e2dbd4SRam Kishore Vegesna /* Copy the dump from the DMA buffer into the user buffer */ 370*29e2dbd4SRam Kishore Vegesna offset = 0; 371*29e2dbd4SRam Kishore Vegesna for (i = 0; i < num_buffers; i++) { 372*29e2dbd4SRam Kishore Vegesna if (ocs_copy_to_user((uint8_t*)buf + offset, 373*29e2dbd4SRam Kishore Vegesna dump_buffers[i].virt, dump_buffers[i].size)) { 374*29e2dbd4SRam Kishore Vegesna ocs_log_err(ocs, "ocs_copy_to_user failed\n"); 375*29e2dbd4SRam Kishore Vegesna rc = -1; 376*29e2dbd4SRam Kishore Vegesna } 377*29e2dbd4SRam Kishore Vegesna offset += dump_buffers[i].size; 378*29e2dbd4SRam Kishore Vegesna } 379*29e2dbd4SRam Kishore Vegesna 380*29e2dbd4SRam Kishore Vegesna free_and_return: 381*29e2dbd4SRam Kishore Vegesna /* Free the DMA buffer and return */ 382*29e2dbd4SRam Kishore Vegesna for (i = 0; i < num_buffers; i++) { 383*29e2dbd4SRam Kishore Vegesna ocs_dma_free(ocs, &dump_buffers[i]); 384*29e2dbd4SRam Kishore Vegesna } 385*29e2dbd4SRam Kishore Vegesna ocs_free(ocs, dump_buffers, sizeof(ocs_dma_t) * num_buffers); 386*29e2dbd4SRam Kishore Vegesna return rc; 387*29e2dbd4SRam Kishore Vegesna 388*29e2dbd4SRam Kishore Vegesna } 389