111e25f0dSDavid C Somayajulu /* 211e25f0dSDavid C Somayajulu * Copyright (c) 2017-2018 Cavium, Inc. 311e25f0dSDavid C Somayajulu * All rights reserved. 411e25f0dSDavid C Somayajulu * 511e25f0dSDavid C Somayajulu * Redistribution and use in source and binary forms, with or without 611e25f0dSDavid C Somayajulu * modification, are permitted provided that the following conditions 711e25f0dSDavid C Somayajulu * are met: 811e25f0dSDavid C Somayajulu * 911e25f0dSDavid C Somayajulu * 1. Redistributions of source code must retain the above copyright 1011e25f0dSDavid C Somayajulu * notice, this list of conditions and the following disclaimer. 1111e25f0dSDavid C Somayajulu * 2. Redistributions in binary form must reproduce the above copyright 1211e25f0dSDavid C Somayajulu * notice, this list of conditions and the following disclaimer in the 1311e25f0dSDavid C Somayajulu * documentation and/or other materials provided with the distribution. 1411e25f0dSDavid C Somayajulu * 1511e25f0dSDavid C Somayajulu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 1611e25f0dSDavid C Somayajulu * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1711e25f0dSDavid C Somayajulu * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1811e25f0dSDavid C Somayajulu * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 1911e25f0dSDavid C Somayajulu * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 2011e25f0dSDavid C Somayajulu * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 2111e25f0dSDavid C Somayajulu * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 2211e25f0dSDavid C Somayajulu * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 2311e25f0dSDavid C Somayajulu * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 2411e25f0dSDavid C Somayajulu * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 2511e25f0dSDavid C Somayajulu * POSSIBILITY OF SUCH DAMAGE. 2611e25f0dSDavid C Somayajulu */ 2711e25f0dSDavid C Somayajulu 2811e25f0dSDavid C Somayajulu 2911e25f0dSDavid C Somayajulu /* 3011e25f0dSDavid C Somayajulu * File: qlnx_ioctl.c 3111e25f0dSDavid C Somayajulu * Author : David C Somayajulu, Qlogic Corporation, Aliso Viejo, CA 92656. 3211e25f0dSDavid C Somayajulu */ 3311e25f0dSDavid C Somayajulu 3411e25f0dSDavid C Somayajulu #include <sys/cdefs.h> 3511e25f0dSDavid C Somayajulu __FBSDID("$FreeBSD$"); 3611e25f0dSDavid C Somayajulu 3711e25f0dSDavid C Somayajulu #include "qlnx_os.h" 3811e25f0dSDavid C Somayajulu #include "bcm_osal.h" 3911e25f0dSDavid C Somayajulu 4011e25f0dSDavid C Somayajulu #include "reg_addr.h" 4111e25f0dSDavid C Somayajulu #include "ecore_gtt_reg_addr.h" 4211e25f0dSDavid C Somayajulu #include "ecore.h" 4311e25f0dSDavid C Somayajulu #include "ecore_chain.h" 4411e25f0dSDavid C Somayajulu #include "ecore_status.h" 4511e25f0dSDavid C Somayajulu #include "ecore_hw.h" 4611e25f0dSDavid C Somayajulu #include "ecore_rt_defs.h" 4711e25f0dSDavid C Somayajulu #include "ecore_init_ops.h" 4811e25f0dSDavid C Somayajulu #include "ecore_int.h" 4911e25f0dSDavid C Somayajulu #include "ecore_cxt.h" 5011e25f0dSDavid C Somayajulu #include "ecore_spq.h" 5111e25f0dSDavid C Somayajulu #include "ecore_init_fw_funcs.h" 5211e25f0dSDavid C Somayajulu #include "ecore_sp_commands.h" 5311e25f0dSDavid C Somayajulu #include "ecore_dev_api.h" 5411e25f0dSDavid C Somayajulu #include "ecore_l2_api.h" 5511e25f0dSDavid C Somayajulu #include "ecore_mcp.h" 5611e25f0dSDavid C Somayajulu #include "ecore_hw_defs.h" 5711e25f0dSDavid C Somayajulu #include "mcp_public.h" 5811e25f0dSDavid C Somayajulu #include "ecore_iro.h" 5911e25f0dSDavid C Somayajulu #include "nvm_cfg.h" 6011e25f0dSDavid C Somayajulu #include "ecore_dev_api.h" 6111e25f0dSDavid C Somayajulu #include "ecore_dbg_fw_funcs.h" 6211e25f0dSDavid C Somayajulu 6311e25f0dSDavid C Somayajulu #include "qlnx_ioctl.h" 6411e25f0dSDavid C Somayajulu #include "qlnx_def.h" 6511e25f0dSDavid C Somayajulu #include "qlnx_ver.h" 6611e25f0dSDavid C Somayajulu #include <sys/smp.h> 6711e25f0dSDavid C Somayajulu 6811e25f0dSDavid C Somayajulu 6911e25f0dSDavid C Somayajulu static int qlnx_eioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag, 7011e25f0dSDavid C Somayajulu struct thread *td); 7111e25f0dSDavid C Somayajulu 7211e25f0dSDavid C Somayajulu static struct cdevsw qlnx_cdevsw = { 7311e25f0dSDavid C Somayajulu .d_version = D_VERSION, 7411e25f0dSDavid C Somayajulu .d_ioctl = qlnx_eioctl, 7511e25f0dSDavid C Somayajulu .d_name = "qlnxioctl", 7611e25f0dSDavid C Somayajulu }; 7711e25f0dSDavid C Somayajulu 7811e25f0dSDavid C Somayajulu int 7911e25f0dSDavid C Somayajulu qlnx_make_cdev(qlnx_host_t *ha) 8011e25f0dSDavid C Somayajulu { 8111e25f0dSDavid C Somayajulu ha->ioctl_dev = make_dev(&qlnx_cdevsw, 8211e25f0dSDavid C Somayajulu ha->ifp->if_dunit, 8311e25f0dSDavid C Somayajulu UID_ROOT, 8411e25f0dSDavid C Somayajulu GID_WHEEL, 8511e25f0dSDavid C Somayajulu 0600, 8611e25f0dSDavid C Somayajulu "%s", 8711e25f0dSDavid C Somayajulu if_name(ha->ifp)); 8811e25f0dSDavid C Somayajulu 8911e25f0dSDavid C Somayajulu if (ha->ioctl_dev == NULL) 9011e25f0dSDavid C Somayajulu return (-1); 9111e25f0dSDavid C Somayajulu 9211e25f0dSDavid C Somayajulu ha->ioctl_dev->si_drv1 = ha; 9311e25f0dSDavid C Somayajulu 9411e25f0dSDavid C Somayajulu return (0); 9511e25f0dSDavid C Somayajulu } 9611e25f0dSDavid C Somayajulu 9711e25f0dSDavid C Somayajulu void 9811e25f0dSDavid C Somayajulu qlnx_del_cdev(qlnx_host_t *ha) 9911e25f0dSDavid C Somayajulu { 10011e25f0dSDavid C Somayajulu if (ha->ioctl_dev != NULL) 10111e25f0dSDavid C Somayajulu destroy_dev(ha->ioctl_dev); 10211e25f0dSDavid C Somayajulu return; 10311e25f0dSDavid C Somayajulu } 10411e25f0dSDavid C Somayajulu 10511e25f0dSDavid C Somayajulu int 10611e25f0dSDavid C Somayajulu qlnx_grc_dump(qlnx_host_t *ha, uint32_t *num_dumped_dwords, int hwfn_index) 10711e25f0dSDavid C Somayajulu { 10811e25f0dSDavid C Somayajulu int rval = EINVAL; 10911e25f0dSDavid C Somayajulu struct ecore_hwfn *p_hwfn; 11011e25f0dSDavid C Somayajulu struct ecore_ptt *p_ptt; 11111e25f0dSDavid C Somayajulu 11211e25f0dSDavid C Somayajulu if (ha->grcdump_dwords[hwfn_index]) { 11311e25f0dSDavid C Somayajulu /* the grcdump is already available */ 11411e25f0dSDavid C Somayajulu *num_dumped_dwords = ha->grcdump_dwords[hwfn_index]; 11511e25f0dSDavid C Somayajulu return (0); 11611e25f0dSDavid C Somayajulu } 11711e25f0dSDavid C Somayajulu 11811e25f0dSDavid C Somayajulu ecore_dbg_set_app_ver(ecore_dbg_get_fw_func_ver()); 11911e25f0dSDavid C Somayajulu 12011e25f0dSDavid C Somayajulu p_hwfn = &ha->cdev.hwfns[hwfn_index]; 12111e25f0dSDavid C Somayajulu p_ptt = ecore_ptt_acquire(p_hwfn); 12211e25f0dSDavid C Somayajulu 12311e25f0dSDavid C Somayajulu if (!p_ptt) { 1247a377fbeSDavid C Somayajulu QL_DPRINT1(ha,"ecore_ptt_acquire failed\n"); 12511e25f0dSDavid C Somayajulu return (rval); 12611e25f0dSDavid C Somayajulu } 12711e25f0dSDavid C Somayajulu 12811e25f0dSDavid C Somayajulu if ((rval = ecore_dbg_grc_dump(p_hwfn, p_ptt, 12911e25f0dSDavid C Somayajulu ha->grcdump[hwfn_index], 13011e25f0dSDavid C Somayajulu (ha->grcdump_size[hwfn_index] >> 2), 13111e25f0dSDavid C Somayajulu num_dumped_dwords)) == DBG_STATUS_OK) { 13211e25f0dSDavid C Somayajulu rval = 0; 13311e25f0dSDavid C Somayajulu ha->grcdump_taken = 1; 13411e25f0dSDavid C Somayajulu } else 1357a377fbeSDavid C Somayajulu QL_DPRINT1(ha,"ecore_dbg_grc_dump failed [%d, 0x%x]\n", 1367a377fbeSDavid C Somayajulu hwfn_index, rval); 13711e25f0dSDavid C Somayajulu 13811e25f0dSDavid C Somayajulu ecore_ptt_release(p_hwfn, p_ptt); 13911e25f0dSDavid C Somayajulu 14011e25f0dSDavid C Somayajulu return (rval); 14111e25f0dSDavid C Somayajulu } 14211e25f0dSDavid C Somayajulu 14311e25f0dSDavid C Somayajulu static void 14411e25f0dSDavid C Somayajulu qlnx_get_grc_dump_size(qlnx_host_t *ha, qlnx_grcdump_t *grcdump) 14511e25f0dSDavid C Somayajulu { 14611e25f0dSDavid C Somayajulu int i; 14711e25f0dSDavid C Somayajulu 14811e25f0dSDavid C Somayajulu grcdump->pci_func = ha->pci_func; 14911e25f0dSDavid C Somayajulu 15011e25f0dSDavid C Somayajulu for (i = 0; i < ha->cdev.num_hwfns; i++) 15111e25f0dSDavid C Somayajulu grcdump->grcdump_size[i] = ha->grcdump_size[i]; 15211e25f0dSDavid C Somayajulu 15311e25f0dSDavid C Somayajulu return; 15411e25f0dSDavid C Somayajulu } 15511e25f0dSDavid C Somayajulu 15611e25f0dSDavid C Somayajulu static int 15711e25f0dSDavid C Somayajulu qlnx_get_grc_dump(qlnx_host_t *ha, qlnx_grcdump_t *grcdump) 15811e25f0dSDavid C Somayajulu { 15911e25f0dSDavid C Somayajulu int i; 16011e25f0dSDavid C Somayajulu int rval = 0; 16111e25f0dSDavid C Somayajulu uint32_t dwords = 0; 16211e25f0dSDavid C Somayajulu 16311e25f0dSDavid C Somayajulu grcdump->pci_func = ha->pci_func; 16411e25f0dSDavid C Somayajulu 16511e25f0dSDavid C Somayajulu for (i = 0; i < ha->cdev.num_hwfns; i++) { 16611e25f0dSDavid C Somayajulu 16711e25f0dSDavid C Somayajulu if ((ha->grcdump[i] == NULL) || (grcdump->grcdump[i] == NULL) || 16811e25f0dSDavid C Somayajulu (grcdump->grcdump_size[i] < ha->grcdump_size[i])) 16911e25f0dSDavid C Somayajulu return (EINVAL); 17011e25f0dSDavid C Somayajulu 17111e25f0dSDavid C Somayajulu rval = qlnx_grc_dump(ha, &dwords, i); 17211e25f0dSDavid C Somayajulu 17311e25f0dSDavid C Somayajulu if (rval) 17411e25f0dSDavid C Somayajulu break; 17511e25f0dSDavid C Somayajulu 17611e25f0dSDavid C Somayajulu grcdump->grcdump_dwords[i] = dwords; 17711e25f0dSDavid C Somayajulu 1787a377fbeSDavid C Somayajulu QL_DPRINT1(ha,"grcdump_dwords[%d] = 0x%x\n", i, dwords); 17911e25f0dSDavid C Somayajulu 18011e25f0dSDavid C Somayajulu rval = copyout(ha->grcdump[i], grcdump->grcdump[i], 18111e25f0dSDavid C Somayajulu ha->grcdump_size[i]); 18211e25f0dSDavid C Somayajulu 18311e25f0dSDavid C Somayajulu if (rval) 18411e25f0dSDavid C Somayajulu break; 18511e25f0dSDavid C Somayajulu 18611e25f0dSDavid C Somayajulu ha->grcdump_dwords[i] = 0; 18711e25f0dSDavid C Somayajulu } 18811e25f0dSDavid C Somayajulu 18911e25f0dSDavid C Somayajulu ha->grcdump_taken = 0; 19011e25f0dSDavid C Somayajulu 19111e25f0dSDavid C Somayajulu return (rval); 19211e25f0dSDavid C Somayajulu } 19311e25f0dSDavid C Somayajulu 19411e25f0dSDavid C Somayajulu int 19511e25f0dSDavid C Somayajulu qlnx_idle_chk(qlnx_host_t *ha, uint32_t *num_dumped_dwords, int hwfn_index) 19611e25f0dSDavid C Somayajulu { 19711e25f0dSDavid C Somayajulu int rval = EINVAL; 19811e25f0dSDavid C Somayajulu struct ecore_hwfn *p_hwfn; 19911e25f0dSDavid C Somayajulu struct ecore_ptt *p_ptt; 20011e25f0dSDavid C Somayajulu 20111e25f0dSDavid C Somayajulu if (ha->idle_chk_dwords[hwfn_index]) { 20211e25f0dSDavid C Somayajulu /* the idle check is already available */ 20311e25f0dSDavid C Somayajulu *num_dumped_dwords = ha->idle_chk_dwords[hwfn_index]; 20411e25f0dSDavid C Somayajulu return (0); 20511e25f0dSDavid C Somayajulu } 20611e25f0dSDavid C Somayajulu 20711e25f0dSDavid C Somayajulu ecore_dbg_set_app_ver(ecore_dbg_get_fw_func_ver()); 20811e25f0dSDavid C Somayajulu 20911e25f0dSDavid C Somayajulu p_hwfn = &ha->cdev.hwfns[hwfn_index]; 21011e25f0dSDavid C Somayajulu p_ptt = ecore_ptt_acquire(p_hwfn); 21111e25f0dSDavid C Somayajulu 21211e25f0dSDavid C Somayajulu if (!p_ptt) { 2137a377fbeSDavid C Somayajulu QL_DPRINT1(ha,"ecore_ptt_acquire failed\n"); 21411e25f0dSDavid C Somayajulu return (rval); 21511e25f0dSDavid C Somayajulu } 21611e25f0dSDavid C Somayajulu 21711e25f0dSDavid C Somayajulu if ((rval = ecore_dbg_idle_chk_dump(p_hwfn, p_ptt, 21811e25f0dSDavid C Somayajulu ha->idle_chk[hwfn_index], 21911e25f0dSDavid C Somayajulu (ha->idle_chk_size[hwfn_index] >> 2), 22011e25f0dSDavid C Somayajulu num_dumped_dwords)) == DBG_STATUS_OK) { 22111e25f0dSDavid C Somayajulu rval = 0; 22211e25f0dSDavid C Somayajulu ha->idle_chk_taken = 1; 22311e25f0dSDavid C Somayajulu } else 2247a377fbeSDavid C Somayajulu QL_DPRINT1(ha,"ecore_dbg_idle_chk_dump failed [%d, 0x%x]\n", 2257a377fbeSDavid C Somayajulu hwfn_index, rval); 22611e25f0dSDavid C Somayajulu 22711e25f0dSDavid C Somayajulu ecore_ptt_release(p_hwfn, p_ptt); 22811e25f0dSDavid C Somayajulu 22911e25f0dSDavid C Somayajulu return (rval); 23011e25f0dSDavid C Somayajulu } 23111e25f0dSDavid C Somayajulu 23211e25f0dSDavid C Somayajulu static void 23311e25f0dSDavid C Somayajulu qlnx_get_idle_chk_size(qlnx_host_t *ha, qlnx_idle_chk_t *idle_chk) 23411e25f0dSDavid C Somayajulu { 23511e25f0dSDavid C Somayajulu int i; 23611e25f0dSDavid C Somayajulu 23711e25f0dSDavid C Somayajulu idle_chk->pci_func = ha->pci_func; 23811e25f0dSDavid C Somayajulu 23911e25f0dSDavid C Somayajulu for (i = 0; i < ha->cdev.num_hwfns; i++) 24011e25f0dSDavid C Somayajulu idle_chk->idle_chk_size[i] = ha->idle_chk_size[i]; 24111e25f0dSDavid C Somayajulu 24211e25f0dSDavid C Somayajulu return; 24311e25f0dSDavid C Somayajulu } 24411e25f0dSDavid C Somayajulu 24511e25f0dSDavid C Somayajulu static int 24611e25f0dSDavid C Somayajulu qlnx_get_idle_chk(qlnx_host_t *ha, qlnx_idle_chk_t *idle_chk) 24711e25f0dSDavid C Somayajulu { 24811e25f0dSDavid C Somayajulu int i; 24911e25f0dSDavid C Somayajulu int rval = 0; 25011e25f0dSDavid C Somayajulu uint32_t dwords = 0; 25111e25f0dSDavid C Somayajulu 25211e25f0dSDavid C Somayajulu idle_chk->pci_func = ha->pci_func; 25311e25f0dSDavid C Somayajulu 25411e25f0dSDavid C Somayajulu for (i = 0; i < ha->cdev.num_hwfns; i++) { 25511e25f0dSDavid C Somayajulu 25611e25f0dSDavid C Somayajulu if ((ha->idle_chk[i] == NULL) || 25711e25f0dSDavid C Somayajulu (idle_chk->idle_chk[i] == NULL) || 25811e25f0dSDavid C Somayajulu (idle_chk->idle_chk_size[i] < 25911e25f0dSDavid C Somayajulu ha->idle_chk_size[i])) 26011e25f0dSDavid C Somayajulu return (EINVAL); 26111e25f0dSDavid C Somayajulu 26211e25f0dSDavid C Somayajulu rval = qlnx_idle_chk(ha, &dwords, i); 26311e25f0dSDavid C Somayajulu 26411e25f0dSDavid C Somayajulu if (rval) 26511e25f0dSDavid C Somayajulu break; 26611e25f0dSDavid C Somayajulu 26711e25f0dSDavid C Somayajulu idle_chk->idle_chk_dwords[i] = dwords; 26811e25f0dSDavid C Somayajulu 2697a377fbeSDavid C Somayajulu QL_DPRINT1(ha,"idle_chk_dwords[%d] = 0x%x\n", i, dwords); 27011e25f0dSDavid C Somayajulu 27111e25f0dSDavid C Somayajulu rval = copyout(ha->idle_chk[i], idle_chk->idle_chk[i], 27211e25f0dSDavid C Somayajulu ha->idle_chk_size[i]); 27311e25f0dSDavid C Somayajulu 27411e25f0dSDavid C Somayajulu if (rval) 27511e25f0dSDavid C Somayajulu break; 27611e25f0dSDavid C Somayajulu 27711e25f0dSDavid C Somayajulu ha->idle_chk_dwords[i] = 0; 27811e25f0dSDavid C Somayajulu } 27911e25f0dSDavid C Somayajulu ha->idle_chk_taken = 0; 28011e25f0dSDavid C Somayajulu 28111e25f0dSDavid C Somayajulu return (rval); 28211e25f0dSDavid C Somayajulu } 28311e25f0dSDavid C Somayajulu 28411e25f0dSDavid C Somayajulu static uint32_t 28511e25f0dSDavid C Somayajulu qlnx_get_trace_cmd_size(qlnx_host_t *ha, int hwfn_index, uint16_t cmd) 28611e25f0dSDavid C Somayajulu { 28711e25f0dSDavid C Somayajulu int rval = -1; 28811e25f0dSDavid C Somayajulu struct ecore_hwfn *p_hwfn; 28911e25f0dSDavid C Somayajulu struct ecore_ptt *p_ptt; 29011e25f0dSDavid C Somayajulu uint32_t num_dwords = 0; 29111e25f0dSDavid C Somayajulu 29211e25f0dSDavid C Somayajulu p_hwfn = &ha->cdev.hwfns[hwfn_index]; 29311e25f0dSDavid C Somayajulu p_ptt = ecore_ptt_acquire(p_hwfn); 29411e25f0dSDavid C Somayajulu 29511e25f0dSDavid C Somayajulu if (!p_ptt) { 2967a377fbeSDavid C Somayajulu QL_DPRINT1(ha, "ecore_ptt_acquire [%d, 0x%x]failed\n", 2977a377fbeSDavid C Somayajulu hwfn_index, cmd); 29811e25f0dSDavid C Somayajulu return (0); 29911e25f0dSDavid C Somayajulu } 30011e25f0dSDavid C Somayajulu 30111e25f0dSDavid C Somayajulu switch (cmd) { 30211e25f0dSDavid C Somayajulu 30311e25f0dSDavid C Somayajulu case QLNX_MCP_TRACE: 30411e25f0dSDavid C Somayajulu rval = ecore_dbg_mcp_trace_get_dump_buf_size(p_hwfn, 30511e25f0dSDavid C Somayajulu p_ptt, &num_dwords); 30611e25f0dSDavid C Somayajulu break; 30711e25f0dSDavid C Somayajulu 30811e25f0dSDavid C Somayajulu case QLNX_REG_FIFO: 30911e25f0dSDavid C Somayajulu rval = ecore_dbg_reg_fifo_get_dump_buf_size(p_hwfn, 31011e25f0dSDavid C Somayajulu p_ptt, &num_dwords); 31111e25f0dSDavid C Somayajulu break; 31211e25f0dSDavid C Somayajulu 31311e25f0dSDavid C Somayajulu case QLNX_IGU_FIFO: 31411e25f0dSDavid C Somayajulu rval = ecore_dbg_igu_fifo_get_dump_buf_size(p_hwfn, 31511e25f0dSDavid C Somayajulu p_ptt, &num_dwords); 31611e25f0dSDavid C Somayajulu break; 31711e25f0dSDavid C Somayajulu 31811e25f0dSDavid C Somayajulu case QLNX_PROTECTION_OVERRIDE: 31911e25f0dSDavid C Somayajulu rval = ecore_dbg_protection_override_get_dump_buf_size(p_hwfn, 32011e25f0dSDavid C Somayajulu p_ptt, &num_dwords); 32111e25f0dSDavid C Somayajulu break; 32211e25f0dSDavid C Somayajulu 32311e25f0dSDavid C Somayajulu case QLNX_FW_ASSERTS: 32411e25f0dSDavid C Somayajulu rval = ecore_dbg_fw_asserts_get_dump_buf_size(p_hwfn, 32511e25f0dSDavid C Somayajulu p_ptt, &num_dwords); 32611e25f0dSDavid C Somayajulu break; 32711e25f0dSDavid C Somayajulu } 32811e25f0dSDavid C Somayajulu 32911e25f0dSDavid C Somayajulu if (rval != DBG_STATUS_OK) { 3307a377fbeSDavid C Somayajulu QL_DPRINT1(ha,"cmd = 0x%x failed [0x%x]\n", cmd, rval); 33111e25f0dSDavid C Somayajulu num_dwords = 0; 33211e25f0dSDavid C Somayajulu } 33311e25f0dSDavid C Somayajulu 33411e25f0dSDavid C Somayajulu ecore_ptt_release(p_hwfn, p_ptt); 33511e25f0dSDavid C Somayajulu 33611e25f0dSDavid C Somayajulu return ((num_dwords * sizeof (uint32_t))); 33711e25f0dSDavid C Somayajulu } 33811e25f0dSDavid C Somayajulu 33911e25f0dSDavid C Somayajulu static void 34011e25f0dSDavid C Somayajulu qlnx_get_trace_size(qlnx_host_t *ha, qlnx_trace_t *trace) 34111e25f0dSDavid C Somayajulu { 34211e25f0dSDavid C Somayajulu int i; 34311e25f0dSDavid C Somayajulu 34411e25f0dSDavid C Somayajulu trace->pci_func = ha->pci_func; 34511e25f0dSDavid C Somayajulu 34611e25f0dSDavid C Somayajulu for (i = 0; i < ha->cdev.num_hwfns; i++) { 34711e25f0dSDavid C Somayajulu trace->size[i] = qlnx_get_trace_cmd_size(ha, i, trace->cmd); 34811e25f0dSDavid C Somayajulu } 34911e25f0dSDavid C Somayajulu 35011e25f0dSDavid C Somayajulu return; 35111e25f0dSDavid C Somayajulu } 35211e25f0dSDavid C Somayajulu 35311e25f0dSDavid C Somayajulu static int 35411e25f0dSDavid C Somayajulu qlnx_get_trace(qlnx_host_t *ha, int hwfn_index, qlnx_trace_t *trace) 35511e25f0dSDavid C Somayajulu { 35611e25f0dSDavid C Somayajulu int rval = -1; 35711e25f0dSDavid C Somayajulu struct ecore_hwfn *p_hwfn; 35811e25f0dSDavid C Somayajulu struct ecore_ptt *p_ptt; 35911e25f0dSDavid C Somayajulu uint32_t num_dwords = 0; 36011e25f0dSDavid C Somayajulu void *buffer; 36111e25f0dSDavid C Somayajulu 36211e25f0dSDavid C Somayajulu buffer = qlnx_zalloc(trace->size[hwfn_index]); 36311e25f0dSDavid C Somayajulu if (buffer == NULL) { 3647a377fbeSDavid C Somayajulu QL_DPRINT1(ha,"qlnx_zalloc [%d, 0x%x]failed\n", 3657a377fbeSDavid C Somayajulu hwfn_index, trace->cmd); 36611e25f0dSDavid C Somayajulu return (ENXIO); 36711e25f0dSDavid C Somayajulu } 36811e25f0dSDavid C Somayajulu ecore_dbg_set_app_ver(ecore_dbg_get_fw_func_ver()); 36911e25f0dSDavid C Somayajulu 37011e25f0dSDavid C Somayajulu p_hwfn = &ha->cdev.hwfns[hwfn_index]; 37111e25f0dSDavid C Somayajulu p_ptt = ecore_ptt_acquire(p_hwfn); 37211e25f0dSDavid C Somayajulu 37311e25f0dSDavid C Somayajulu if (!p_ptt) { 3747a377fbeSDavid C Somayajulu QL_DPRINT1(ha, "ecore_ptt_acquire [%d, 0x%x]failed\n", 3757a377fbeSDavid C Somayajulu hwfn_index, trace->cmd); 37611e25f0dSDavid C Somayajulu return (ENXIO); 37711e25f0dSDavid C Somayajulu } 37811e25f0dSDavid C Somayajulu 37911e25f0dSDavid C Somayajulu switch (trace->cmd) { 38011e25f0dSDavid C Somayajulu 38111e25f0dSDavid C Somayajulu case QLNX_MCP_TRACE: 38211e25f0dSDavid C Somayajulu rval = ecore_dbg_mcp_trace_dump(p_hwfn, p_ptt, 38311e25f0dSDavid C Somayajulu buffer, (trace->size[hwfn_index] >> 2), 38411e25f0dSDavid C Somayajulu &num_dwords); 38511e25f0dSDavid C Somayajulu break; 38611e25f0dSDavid C Somayajulu 38711e25f0dSDavid C Somayajulu case QLNX_REG_FIFO: 38811e25f0dSDavid C Somayajulu rval = ecore_dbg_reg_fifo_dump(p_hwfn, p_ptt, 38911e25f0dSDavid C Somayajulu buffer, (trace->size[hwfn_index] >> 2), 39011e25f0dSDavid C Somayajulu &num_dwords); 39111e25f0dSDavid C Somayajulu break; 39211e25f0dSDavid C Somayajulu 39311e25f0dSDavid C Somayajulu case QLNX_IGU_FIFO: 39411e25f0dSDavid C Somayajulu rval = ecore_dbg_igu_fifo_dump(p_hwfn, p_ptt, 39511e25f0dSDavid C Somayajulu buffer, (trace->size[hwfn_index] >> 2), 39611e25f0dSDavid C Somayajulu &num_dwords); 39711e25f0dSDavid C Somayajulu break; 39811e25f0dSDavid C Somayajulu 39911e25f0dSDavid C Somayajulu case QLNX_PROTECTION_OVERRIDE: 40011e25f0dSDavid C Somayajulu rval = ecore_dbg_protection_override_dump(p_hwfn, p_ptt, 40111e25f0dSDavid C Somayajulu buffer, (trace->size[hwfn_index] >> 2), 40211e25f0dSDavid C Somayajulu &num_dwords); 40311e25f0dSDavid C Somayajulu break; 40411e25f0dSDavid C Somayajulu 40511e25f0dSDavid C Somayajulu case QLNX_FW_ASSERTS: 40611e25f0dSDavid C Somayajulu rval = ecore_dbg_fw_asserts_dump(p_hwfn, p_ptt, 40711e25f0dSDavid C Somayajulu buffer, (trace->size[hwfn_index] >> 2), 40811e25f0dSDavid C Somayajulu &num_dwords); 40911e25f0dSDavid C Somayajulu break; 41011e25f0dSDavid C Somayajulu } 41111e25f0dSDavid C Somayajulu 41211e25f0dSDavid C Somayajulu if (rval != DBG_STATUS_OK) { 4137a377fbeSDavid C Somayajulu QL_DPRINT1(ha,"cmd = 0x%x failed [0x%x]\n", trace->cmd, rval); 41411e25f0dSDavid C Somayajulu num_dwords = 0; 41511e25f0dSDavid C Somayajulu } 41611e25f0dSDavid C Somayajulu 41711e25f0dSDavid C Somayajulu ecore_ptt_release(p_hwfn, p_ptt); 41811e25f0dSDavid C Somayajulu 41911e25f0dSDavid C Somayajulu trace->dwords[hwfn_index] = num_dwords; 42011e25f0dSDavid C Somayajulu 42111e25f0dSDavid C Somayajulu if (num_dwords) { 42211e25f0dSDavid C Somayajulu rval = copyout(buffer, trace->buffer[hwfn_index], 42311e25f0dSDavid C Somayajulu (num_dwords << 2)); 42411e25f0dSDavid C Somayajulu } 42511e25f0dSDavid C Somayajulu 42611e25f0dSDavid C Somayajulu return (rval); 42711e25f0dSDavid C Somayajulu } 42811e25f0dSDavid C Somayajulu 42911e25f0dSDavid C Somayajulu static int 43011e25f0dSDavid C Somayajulu qlnx_reg_rd_wr(qlnx_host_t *ha, qlnx_reg_rd_wr_t *reg_rd_wr) 43111e25f0dSDavid C Somayajulu { 43211e25f0dSDavid C Somayajulu int rval = 0; 43311e25f0dSDavid C Somayajulu struct ecore_hwfn *p_hwfn; 43411e25f0dSDavid C Somayajulu 43511e25f0dSDavid C Somayajulu if (reg_rd_wr->hwfn_index >= QLNX_MAX_HW_FUNCS) { 43611e25f0dSDavid C Somayajulu return (EINVAL); 43711e25f0dSDavid C Somayajulu } 43811e25f0dSDavid C Somayajulu 43911e25f0dSDavid C Somayajulu p_hwfn = &ha->cdev.hwfns[reg_rd_wr->hwfn_index]; 44011e25f0dSDavid C Somayajulu 44111e25f0dSDavid C Somayajulu switch (reg_rd_wr->cmd) { 44211e25f0dSDavid C Somayajulu 44311e25f0dSDavid C Somayajulu case QLNX_REG_READ_CMD: 44411e25f0dSDavid C Somayajulu if (reg_rd_wr->access_type == QLNX_REG_ACCESS_DIRECT) { 44511e25f0dSDavid C Somayajulu reg_rd_wr->val = qlnx_reg_rd32(p_hwfn, 44611e25f0dSDavid C Somayajulu reg_rd_wr->addr); 44711e25f0dSDavid C Somayajulu } 44811e25f0dSDavid C Somayajulu break; 44911e25f0dSDavid C Somayajulu 45011e25f0dSDavid C Somayajulu case QLNX_REG_WRITE_CMD: 45111e25f0dSDavid C Somayajulu if (reg_rd_wr->access_type == QLNX_REG_ACCESS_DIRECT) { 45211e25f0dSDavid C Somayajulu qlnx_reg_wr32(p_hwfn, reg_rd_wr->addr, 45311e25f0dSDavid C Somayajulu reg_rd_wr->val); 45411e25f0dSDavid C Somayajulu } 45511e25f0dSDavid C Somayajulu break; 45611e25f0dSDavid C Somayajulu 45711e25f0dSDavid C Somayajulu default: 45811e25f0dSDavid C Somayajulu rval = EINVAL; 45911e25f0dSDavid C Somayajulu break; 46011e25f0dSDavid C Somayajulu } 46111e25f0dSDavid C Somayajulu 46211e25f0dSDavid C Somayajulu return (rval); 46311e25f0dSDavid C Somayajulu } 46411e25f0dSDavid C Somayajulu 46511e25f0dSDavid C Somayajulu static int 46611e25f0dSDavid C Somayajulu qlnx_rd_wr_pci_config(qlnx_host_t *ha, qlnx_pcicfg_rd_wr_t *pci_cfg_rd_wr) 46711e25f0dSDavid C Somayajulu { 46811e25f0dSDavid C Somayajulu int rval = 0; 46911e25f0dSDavid C Somayajulu 47011e25f0dSDavid C Somayajulu switch (pci_cfg_rd_wr->cmd) { 47111e25f0dSDavid C Somayajulu 47211e25f0dSDavid C Somayajulu case QLNX_PCICFG_READ: 47311e25f0dSDavid C Somayajulu pci_cfg_rd_wr->val = pci_read_config(ha->pci_dev, 47411e25f0dSDavid C Somayajulu pci_cfg_rd_wr->reg, 47511e25f0dSDavid C Somayajulu pci_cfg_rd_wr->width); 47611e25f0dSDavid C Somayajulu break; 47711e25f0dSDavid C Somayajulu 47811e25f0dSDavid C Somayajulu case QLNX_PCICFG_WRITE: 47911e25f0dSDavid C Somayajulu pci_write_config(ha->pci_dev, pci_cfg_rd_wr->reg, 48011e25f0dSDavid C Somayajulu pci_cfg_rd_wr->val, pci_cfg_rd_wr->width); 48111e25f0dSDavid C Somayajulu break; 48211e25f0dSDavid C Somayajulu 48311e25f0dSDavid C Somayajulu default: 48411e25f0dSDavid C Somayajulu rval = EINVAL; 48511e25f0dSDavid C Somayajulu break; 48611e25f0dSDavid C Somayajulu } 48711e25f0dSDavid C Somayajulu 48811e25f0dSDavid C Somayajulu return (rval); 48911e25f0dSDavid C Somayajulu } 49011e25f0dSDavid C Somayajulu 49111e25f0dSDavid C Somayajulu static void 49211e25f0dSDavid C Somayajulu qlnx_mac_addr(qlnx_host_t *ha, qlnx_perm_mac_addr_t *mac_addr) 49311e25f0dSDavid C Somayajulu { 49411e25f0dSDavid C Somayajulu bzero(mac_addr->addr, sizeof(mac_addr->addr)); 49511e25f0dSDavid C Somayajulu snprintf(mac_addr->addr, sizeof(mac_addr->addr), 49611e25f0dSDavid C Somayajulu "%02x:%02x:%02x:%02x:%02x:%02x", 49711e25f0dSDavid C Somayajulu ha->primary_mac[0], ha->primary_mac[1], ha->primary_mac[2], 49811e25f0dSDavid C Somayajulu ha->primary_mac[3], ha->primary_mac[4], ha->primary_mac[5]); 49911e25f0dSDavid C Somayajulu 50011e25f0dSDavid C Somayajulu return; 50111e25f0dSDavid C Somayajulu } 50211e25f0dSDavid C Somayajulu 50311e25f0dSDavid C Somayajulu static int 50411e25f0dSDavid C Somayajulu qlnx_get_regs(qlnx_host_t *ha, qlnx_get_regs_t *regs) 50511e25f0dSDavid C Somayajulu { 50611e25f0dSDavid C Somayajulu int i; 50711e25f0dSDavid C Somayajulu int rval = 0; 50811e25f0dSDavid C Somayajulu uint32_t dwords = 0; 50911e25f0dSDavid C Somayajulu uint8_t *outb; 51011e25f0dSDavid C Somayajulu 51111e25f0dSDavid C Somayajulu regs->reg_buf_len = 0; 51211e25f0dSDavid C Somayajulu outb = regs->reg_buf; 51311e25f0dSDavid C Somayajulu 51411e25f0dSDavid C Somayajulu for (i = 0; i < ha->cdev.num_hwfns; i++) { 51511e25f0dSDavid C Somayajulu 51611e25f0dSDavid C Somayajulu rval = qlnx_grc_dump(ha, &dwords, i); 51711e25f0dSDavid C Somayajulu 51811e25f0dSDavid C Somayajulu if (rval) 51911e25f0dSDavid C Somayajulu break; 52011e25f0dSDavid C Somayajulu 52111e25f0dSDavid C Somayajulu regs->reg_buf_len += (dwords << 2); 52211e25f0dSDavid C Somayajulu 52311e25f0dSDavid C Somayajulu rval = copyout(ha->grcdump[i], outb, ha->grcdump_size[i]); 52411e25f0dSDavid C Somayajulu 52511e25f0dSDavid C Somayajulu if (rval) 52611e25f0dSDavid C Somayajulu break; 52711e25f0dSDavid C Somayajulu 52811e25f0dSDavid C Somayajulu ha->grcdump_dwords[i] = 0; 52911e25f0dSDavid C Somayajulu outb += regs->reg_buf_len; 53011e25f0dSDavid C Somayajulu } 53111e25f0dSDavid C Somayajulu 53211e25f0dSDavid C Somayajulu ha->grcdump_taken = 0; 53311e25f0dSDavid C Somayajulu 53411e25f0dSDavid C Somayajulu return (rval); 53511e25f0dSDavid C Somayajulu } 53611e25f0dSDavid C Somayajulu 537*d576ccdfSRyan Libby extern char qlnx_name_str[]; 538*d576ccdfSRyan Libby extern char qlnx_ver_str[]; 539*d576ccdfSRyan Libby 54011e25f0dSDavid C Somayajulu static int 54111e25f0dSDavid C Somayajulu qlnx_drv_info(qlnx_host_t *ha, qlnx_drvinfo_t *drv_info) 54211e25f0dSDavid C Somayajulu { 54311e25f0dSDavid C Somayajulu int i; 54411e25f0dSDavid C Somayajulu 54511e25f0dSDavid C Somayajulu bzero(drv_info, sizeof(qlnx_drvinfo_t)); 54611e25f0dSDavid C Somayajulu 54711e25f0dSDavid C Somayajulu snprintf(drv_info->drv_name, sizeof(drv_info->drv_name), "%s", 54811e25f0dSDavid C Somayajulu qlnx_name_str); 54911e25f0dSDavid C Somayajulu snprintf(drv_info->drv_version, sizeof(drv_info->drv_version), "%s", 55011e25f0dSDavid C Somayajulu qlnx_ver_str); 55111e25f0dSDavid C Somayajulu snprintf(drv_info->mfw_version, sizeof(drv_info->mfw_version), "%s", 55211e25f0dSDavid C Somayajulu ha->mfw_ver); 55311e25f0dSDavid C Somayajulu snprintf(drv_info->stormfw_version, sizeof(drv_info->stormfw_version), 55411e25f0dSDavid C Somayajulu "%s", ha->stormfw_ver); 55511e25f0dSDavid C Somayajulu 55611e25f0dSDavid C Somayajulu drv_info->eeprom_dump_len = ha->flash_size; 55711e25f0dSDavid C Somayajulu 55811e25f0dSDavid C Somayajulu for (i = 0; i < ha->cdev.num_hwfns; i++) { 55911e25f0dSDavid C Somayajulu drv_info->reg_dump_len += ha->grcdump_size[i]; 56011e25f0dSDavid C Somayajulu } 56111e25f0dSDavid C Somayajulu 56211e25f0dSDavid C Somayajulu snprintf(drv_info->bus_info, sizeof(drv_info->bus_info), 56311e25f0dSDavid C Somayajulu "%d:%d:%d", pci_get_bus(ha->pci_dev), 56411e25f0dSDavid C Somayajulu pci_get_slot(ha->pci_dev), ha->pci_func); 56511e25f0dSDavid C Somayajulu 56611e25f0dSDavid C Somayajulu return (0); 56711e25f0dSDavid C Somayajulu } 56811e25f0dSDavid C Somayajulu 56911e25f0dSDavid C Somayajulu static int 57011e25f0dSDavid C Somayajulu qlnx_dev_settings(qlnx_host_t *ha, qlnx_dev_setting_t *dev_info) 57111e25f0dSDavid C Somayajulu { 57211e25f0dSDavid C Somayajulu struct ecore_hwfn *p_hwfn; 57311e25f0dSDavid C Somayajulu struct qlnx_link_output if_link; 57411e25f0dSDavid C Somayajulu 57511e25f0dSDavid C Somayajulu p_hwfn = &ha->cdev.hwfns[0]; 57611e25f0dSDavid C Somayajulu 57711e25f0dSDavid C Somayajulu qlnx_fill_link(p_hwfn, &if_link); 57811e25f0dSDavid C Somayajulu 57911e25f0dSDavid C Somayajulu dev_info->supported = if_link.supported_caps; 58011e25f0dSDavid C Somayajulu dev_info->advertising = if_link.advertised_caps; 58111e25f0dSDavid C Somayajulu dev_info->speed = if_link.speed; 58211e25f0dSDavid C Somayajulu dev_info->duplex = if_link.duplex; 58311e25f0dSDavid C Somayajulu dev_info->port = ha->pci_func & 0x1; 58411e25f0dSDavid C Somayajulu dev_info->autoneg = if_link.autoneg; 58511e25f0dSDavid C Somayajulu 58611e25f0dSDavid C Somayajulu return (0); 58711e25f0dSDavid C Somayajulu } 58811e25f0dSDavid C Somayajulu 58911e25f0dSDavid C Somayajulu static int 59011e25f0dSDavid C Somayajulu qlnx_write_nvram(qlnx_host_t *ha, qlnx_nvram_t *nvram, uint32_t cmd) 59111e25f0dSDavid C Somayajulu { 59211e25f0dSDavid C Somayajulu uint8_t *buf; 59311e25f0dSDavid C Somayajulu int ret = 0; 59411e25f0dSDavid C Somayajulu 59511e25f0dSDavid C Somayajulu if ((nvram->data == NULL) || (nvram->data_len == 0)) 59611e25f0dSDavid C Somayajulu return (EINVAL); 59711e25f0dSDavid C Somayajulu 59811e25f0dSDavid C Somayajulu buf = qlnx_zalloc(nvram->data_len); 59911e25f0dSDavid C Somayajulu 60011e25f0dSDavid C Somayajulu ret = copyin(nvram->data, buf, nvram->data_len); 60111e25f0dSDavid C Somayajulu 6027a377fbeSDavid C Somayajulu QL_DPRINT9(ha, "issue cmd = 0x%x data = %p \ 6037a377fbeSDavid C Somayajulu data_len = 0x%x ret = 0x%x exit\n", 6047a377fbeSDavid C Somayajulu cmd, nvram->data, nvram->data_len, ret); 60511e25f0dSDavid C Somayajulu 60611e25f0dSDavid C Somayajulu if (ret == 0) { 60711e25f0dSDavid C Somayajulu ret = ecore_mcp_nvm_write(&ha->cdev, cmd, 60811e25f0dSDavid C Somayajulu nvram->offset, buf, nvram->data_len); 60911e25f0dSDavid C Somayajulu } 61011e25f0dSDavid C Somayajulu 6117a377fbeSDavid C Somayajulu QL_DPRINT9(ha, "cmd = 0x%x data = %p \ 6127a377fbeSDavid C Somayajulu data_len = 0x%x resp = 0x%x ret = 0x%x exit\n", 6137a377fbeSDavid C Somayajulu cmd, nvram->data, nvram->data_len, ha->cdev.mcp_nvm_resp, ret); 61411e25f0dSDavid C Somayajulu 61511e25f0dSDavid C Somayajulu free(buf, M_QLNXBUF); 61611e25f0dSDavid C Somayajulu 61711e25f0dSDavid C Somayajulu return (ret); 61811e25f0dSDavid C Somayajulu } 61911e25f0dSDavid C Somayajulu 62011e25f0dSDavid C Somayajulu static int 62111e25f0dSDavid C Somayajulu qlnx_read_nvram(qlnx_host_t *ha, qlnx_nvram_t *nvram) 62211e25f0dSDavid C Somayajulu { 62311e25f0dSDavid C Somayajulu uint8_t *buf; 62411e25f0dSDavid C Somayajulu int ret = 0; 62511e25f0dSDavid C Somayajulu 62611e25f0dSDavid C Somayajulu if ((nvram->data == NULL) || (nvram->data_len == 0)) 62711e25f0dSDavid C Somayajulu return (EINVAL); 62811e25f0dSDavid C Somayajulu 62911e25f0dSDavid C Somayajulu buf = qlnx_zalloc(nvram->data_len); 63011e25f0dSDavid C Somayajulu 63111e25f0dSDavid C Somayajulu ret = ecore_mcp_nvm_read(&ha->cdev, nvram->offset, buf, 63211e25f0dSDavid C Somayajulu nvram->data_len); 63311e25f0dSDavid C Somayajulu 6347a377fbeSDavid C Somayajulu QL_DPRINT9(ha, " data = %p data_len = 0x%x \ 6357a377fbeSDavid C Somayajulu resp = 0x%x ret = 0x%x exit\n", 6367a377fbeSDavid C Somayajulu nvram->data, nvram->data_len, ha->cdev.mcp_nvm_resp, ret); 63711e25f0dSDavid C Somayajulu 63811e25f0dSDavid C Somayajulu if (ret == 0) { 63911e25f0dSDavid C Somayajulu ret = copyout(buf, nvram->data, nvram->data_len); 64011e25f0dSDavid C Somayajulu } 64111e25f0dSDavid C Somayajulu 64211e25f0dSDavid C Somayajulu free(buf, M_QLNXBUF); 64311e25f0dSDavid C Somayajulu 64411e25f0dSDavid C Somayajulu return (ret); 64511e25f0dSDavid C Somayajulu } 64611e25f0dSDavid C Somayajulu 64711e25f0dSDavid C Somayajulu static int 64811e25f0dSDavid C Somayajulu qlnx_get_nvram_resp(qlnx_host_t *ha, qlnx_nvram_t *nvram) 64911e25f0dSDavid C Somayajulu { 65011e25f0dSDavid C Somayajulu uint8_t *buf; 65111e25f0dSDavid C Somayajulu int ret = 0; 65211e25f0dSDavid C Somayajulu 65311e25f0dSDavid C Somayajulu if ((nvram->data == NULL) || (nvram->data_len == 0)) 65411e25f0dSDavid C Somayajulu return (EINVAL); 65511e25f0dSDavid C Somayajulu 65611e25f0dSDavid C Somayajulu buf = qlnx_zalloc(nvram->data_len); 65711e25f0dSDavid C Somayajulu 65811e25f0dSDavid C Somayajulu 65911e25f0dSDavid C Somayajulu ret = ecore_mcp_nvm_resp(&ha->cdev, buf); 66011e25f0dSDavid C Somayajulu 6617a377fbeSDavid C Somayajulu QL_DPRINT9(ha, "data = %p data_len = 0x%x \ 6627a377fbeSDavid C Somayajulu resp = 0x%x ret = 0x%x exit\n", 6637a377fbeSDavid C Somayajulu nvram->data, nvram->data_len, ha->cdev.mcp_nvm_resp, ret); 66411e25f0dSDavid C Somayajulu 66511e25f0dSDavid C Somayajulu if (ret == 0) { 66611e25f0dSDavid C Somayajulu ret = copyout(buf, nvram->data, nvram->data_len); 66711e25f0dSDavid C Somayajulu } 66811e25f0dSDavid C Somayajulu 66911e25f0dSDavid C Somayajulu free(buf, M_QLNXBUF); 67011e25f0dSDavid C Somayajulu 67111e25f0dSDavid C Somayajulu return (ret); 67211e25f0dSDavid C Somayajulu } 67311e25f0dSDavid C Somayajulu 67411e25f0dSDavid C Somayajulu static int 67511e25f0dSDavid C Somayajulu qlnx_nvram(qlnx_host_t *ha, qlnx_nvram_t *nvram) 67611e25f0dSDavid C Somayajulu { 67711e25f0dSDavid C Somayajulu int ret = 0; 67811e25f0dSDavid C Somayajulu 67911e25f0dSDavid C Somayajulu switch (nvram->cmd) { 68011e25f0dSDavid C Somayajulu 68111e25f0dSDavid C Somayajulu case QLNX_NVRAM_CMD_WRITE_NVRAM: 68211e25f0dSDavid C Somayajulu ret = qlnx_write_nvram(ha, nvram, ECORE_NVM_WRITE_NVRAM); 68311e25f0dSDavid C Somayajulu break; 68411e25f0dSDavid C Somayajulu 68511e25f0dSDavid C Somayajulu case QLNX_NVRAM_CMD_PUT_FILE_DATA: 68611e25f0dSDavid C Somayajulu ret = qlnx_write_nvram(ha, nvram, ECORE_PUT_FILE_DATA); 68711e25f0dSDavid C Somayajulu break; 68811e25f0dSDavid C Somayajulu 68911e25f0dSDavid C Somayajulu case QLNX_NVRAM_CMD_READ_NVRAM: 69011e25f0dSDavid C Somayajulu ret = qlnx_read_nvram(ha, nvram); 69111e25f0dSDavid C Somayajulu break; 69211e25f0dSDavid C Somayajulu 69311e25f0dSDavid C Somayajulu case QLNX_NVRAM_CMD_SET_SECURE_MODE: 69411e25f0dSDavid C Somayajulu ret = ecore_mcp_nvm_set_secure_mode(&ha->cdev, nvram->offset); 69511e25f0dSDavid C Somayajulu 6967a377fbeSDavid C Somayajulu QL_DPRINT9(ha, "QLNX_NVRAM_CMD_SET_SECURE_MODE \ 6977a377fbeSDavid C Somayajulu resp = 0x%x ret = 0x%x exit\n", 6987a377fbeSDavid C Somayajulu ha->cdev.mcp_nvm_resp, ret); 69911e25f0dSDavid C Somayajulu break; 70011e25f0dSDavid C Somayajulu 70111e25f0dSDavid C Somayajulu case QLNX_NVRAM_CMD_DEL_FILE: 70211e25f0dSDavid C Somayajulu ret = ecore_mcp_nvm_del_file(&ha->cdev, nvram->offset); 70311e25f0dSDavid C Somayajulu 7047a377fbeSDavid C Somayajulu QL_DPRINT9(ha, "QLNX_NVRAM_CMD_DEL_FILE \ 7057a377fbeSDavid C Somayajulu resp = 0x%x ret = 0x%x exit\n", 7067a377fbeSDavid C Somayajulu ha->cdev.mcp_nvm_resp, ret); 70711e25f0dSDavid C Somayajulu break; 70811e25f0dSDavid C Somayajulu 70911e25f0dSDavid C Somayajulu case QLNX_NVRAM_CMD_PUT_FILE_BEGIN: 71011e25f0dSDavid C Somayajulu ret = ecore_mcp_nvm_put_file_begin(&ha->cdev, nvram->offset); 71111e25f0dSDavid C Somayajulu 7127a377fbeSDavid C Somayajulu QL_DPRINT9(ha, "QLNX_NVRAM_CMD_PUT_FILE_BEGIN \ 7137a377fbeSDavid C Somayajulu resp = 0x%x ret = 0x%x exit\n", 7147a377fbeSDavid C Somayajulu ha->cdev.mcp_nvm_resp, ret); 71511e25f0dSDavid C Somayajulu break; 71611e25f0dSDavid C Somayajulu 71711e25f0dSDavid C Somayajulu case QLNX_NVRAM_CMD_GET_NVRAM_RESP: 71811e25f0dSDavid C Somayajulu ret = qlnx_get_nvram_resp(ha, nvram); 71911e25f0dSDavid C Somayajulu break; 72011e25f0dSDavid C Somayajulu 72111e25f0dSDavid C Somayajulu default: 72211e25f0dSDavid C Somayajulu ret = EINVAL; 72311e25f0dSDavid C Somayajulu break; 72411e25f0dSDavid C Somayajulu } 72511e25f0dSDavid C Somayajulu 72611e25f0dSDavid C Somayajulu return (ret); 72711e25f0dSDavid C Somayajulu } 72811e25f0dSDavid C Somayajulu 72911e25f0dSDavid C Somayajulu static void 73011e25f0dSDavid C Somayajulu qlnx_storm_stats(qlnx_host_t *ha, qlnx_storm_stats_dump_t *s_stats) 73111e25f0dSDavid C Somayajulu { 73211e25f0dSDavid C Somayajulu int i; 73311e25f0dSDavid C Somayajulu int index; 73411e25f0dSDavid C Somayajulu int ret; 73511e25f0dSDavid C Somayajulu int stats_copied = 0; 73611e25f0dSDavid C Somayajulu 73711e25f0dSDavid C Somayajulu s_stats->num_hwfns = ha->cdev.num_hwfns; 73811e25f0dSDavid C Somayajulu 73911e25f0dSDavid C Somayajulu // if (ha->storm_stats_index < QLNX_STORM_STATS_SAMPLES_PER_HWFN) 74011e25f0dSDavid C Somayajulu // return; 74111e25f0dSDavid C Somayajulu 74211e25f0dSDavid C Somayajulu s_stats->num_samples = ha->storm_stats_index; 74311e25f0dSDavid C Somayajulu 74411e25f0dSDavid C Somayajulu for (i = 0; i < ha->cdev.num_hwfns; i++) { 74511e25f0dSDavid C Somayajulu 74611e25f0dSDavid C Somayajulu index = (QLNX_STORM_STATS_SAMPLES_PER_HWFN * i); 74711e25f0dSDavid C Somayajulu 74811e25f0dSDavid C Somayajulu if (s_stats->buffer[i]) { 74911e25f0dSDavid C Somayajulu 75011e25f0dSDavid C Somayajulu ret = copyout(&ha->storm_stats[index], 75111e25f0dSDavid C Somayajulu s_stats->buffer[i], 75211e25f0dSDavid C Somayajulu QLNX_STORM_STATS_BYTES_PER_HWFN); 75311e25f0dSDavid C Somayajulu if (ret) { 75411e25f0dSDavid C Somayajulu printf("%s [%d]: failed\n", __func__, i); 75511e25f0dSDavid C Somayajulu } 75611e25f0dSDavid C Somayajulu 75711e25f0dSDavid C Somayajulu if (s_stats->num_samples == 75811e25f0dSDavid C Somayajulu QLNX_STORM_STATS_SAMPLES_PER_HWFN) { 75911e25f0dSDavid C Somayajulu 76011e25f0dSDavid C Somayajulu bzero((void *)&ha->storm_stats[i], 76111e25f0dSDavid C Somayajulu QLNX_STORM_STATS_BYTES_PER_HWFN); 76211e25f0dSDavid C Somayajulu 76311e25f0dSDavid C Somayajulu stats_copied = 1; 76411e25f0dSDavid C Somayajulu } 76511e25f0dSDavid C Somayajulu } 76611e25f0dSDavid C Somayajulu } 76711e25f0dSDavid C Somayajulu 76811e25f0dSDavid C Somayajulu if (stats_copied) 76911e25f0dSDavid C Somayajulu ha->storm_stats_index = 0; 77011e25f0dSDavid C Somayajulu 77111e25f0dSDavid C Somayajulu return; 77211e25f0dSDavid C Somayajulu } 77311e25f0dSDavid C Somayajulu 77411e25f0dSDavid C Somayajulu 77511e25f0dSDavid C Somayajulu static int 77611e25f0dSDavid C Somayajulu qlnx_eioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag, 77711e25f0dSDavid C Somayajulu struct thread *td) 77811e25f0dSDavid C Somayajulu { 77911e25f0dSDavid C Somayajulu qlnx_host_t *ha; 78011e25f0dSDavid C Somayajulu int rval = 0; 78111e25f0dSDavid C Somayajulu struct ifnet *ifp; 78211e25f0dSDavid C Somayajulu qlnx_trace_t *trace; 78311e25f0dSDavid C Somayajulu int i; 78411e25f0dSDavid C Somayajulu 78511e25f0dSDavid C Somayajulu if ((ha = (qlnx_host_t *)dev->si_drv1) == NULL) 78611e25f0dSDavid C Somayajulu return ENXIO; 78711e25f0dSDavid C Somayajulu 78811e25f0dSDavid C Somayajulu ifp = ha->ifp; 78911e25f0dSDavid C Somayajulu 79011e25f0dSDavid C Somayajulu switch (cmd) { 79111e25f0dSDavid C Somayajulu 79211e25f0dSDavid C Somayajulu case QLNX_GRC_DUMP_SIZE: 79311e25f0dSDavid C Somayajulu qlnx_get_grc_dump_size(ha, (qlnx_grcdump_t *)data); 79411e25f0dSDavid C Somayajulu break; 79511e25f0dSDavid C Somayajulu 79611e25f0dSDavid C Somayajulu case QLNX_GRC_DUMP: 79711e25f0dSDavid C Somayajulu rval = qlnx_get_grc_dump(ha, (qlnx_grcdump_t *)data); 79811e25f0dSDavid C Somayajulu break; 79911e25f0dSDavid C Somayajulu 80011e25f0dSDavid C Somayajulu case QLNX_IDLE_CHK_SIZE: 80111e25f0dSDavid C Somayajulu qlnx_get_idle_chk_size(ha, (qlnx_idle_chk_t *)data); 80211e25f0dSDavid C Somayajulu break; 80311e25f0dSDavid C Somayajulu 80411e25f0dSDavid C Somayajulu case QLNX_IDLE_CHK: 80511e25f0dSDavid C Somayajulu rval = qlnx_get_idle_chk(ha, (qlnx_idle_chk_t *)data); 80611e25f0dSDavid C Somayajulu break; 80711e25f0dSDavid C Somayajulu 80811e25f0dSDavid C Somayajulu case QLNX_DRV_INFO: 80911e25f0dSDavid C Somayajulu rval = qlnx_drv_info(ha, (qlnx_drvinfo_t *)data); 81011e25f0dSDavid C Somayajulu break; 81111e25f0dSDavid C Somayajulu 81211e25f0dSDavid C Somayajulu case QLNX_DEV_SETTING: 81311e25f0dSDavid C Somayajulu rval = qlnx_dev_settings(ha, (qlnx_dev_setting_t *)data); 81411e25f0dSDavid C Somayajulu break; 81511e25f0dSDavid C Somayajulu 81611e25f0dSDavid C Somayajulu case QLNX_GET_REGS: 81711e25f0dSDavid C Somayajulu rval = qlnx_get_regs(ha, (qlnx_get_regs_t *)data); 81811e25f0dSDavid C Somayajulu break; 81911e25f0dSDavid C Somayajulu 82011e25f0dSDavid C Somayajulu case QLNX_NVRAM: 82111e25f0dSDavid C Somayajulu rval = qlnx_nvram(ha, (qlnx_nvram_t *)data); 82211e25f0dSDavid C Somayajulu break; 82311e25f0dSDavid C Somayajulu 82411e25f0dSDavid C Somayajulu case QLNX_RD_WR_REG: 82511e25f0dSDavid C Somayajulu rval = qlnx_reg_rd_wr(ha, (qlnx_reg_rd_wr_t *)data); 82611e25f0dSDavid C Somayajulu break; 82711e25f0dSDavid C Somayajulu 82811e25f0dSDavid C Somayajulu case QLNX_RD_WR_PCICFG: 82911e25f0dSDavid C Somayajulu rval = qlnx_rd_wr_pci_config(ha, (qlnx_pcicfg_rd_wr_t *)data); 83011e25f0dSDavid C Somayajulu break; 83111e25f0dSDavid C Somayajulu 83211e25f0dSDavid C Somayajulu case QLNX_MAC_ADDR: 83311e25f0dSDavid C Somayajulu qlnx_mac_addr(ha, (qlnx_perm_mac_addr_t *)data); 83411e25f0dSDavid C Somayajulu break; 83511e25f0dSDavid C Somayajulu 83611e25f0dSDavid C Somayajulu case QLNX_STORM_STATS: 83711e25f0dSDavid C Somayajulu qlnx_storm_stats(ha, (qlnx_storm_stats_dump_t *)data); 83811e25f0dSDavid C Somayajulu break; 83911e25f0dSDavid C Somayajulu 84011e25f0dSDavid C Somayajulu case QLNX_TRACE_SIZE: 84111e25f0dSDavid C Somayajulu qlnx_get_trace_size(ha, (qlnx_trace_t *)data); 84211e25f0dSDavid C Somayajulu break; 84311e25f0dSDavid C Somayajulu 84411e25f0dSDavid C Somayajulu case QLNX_TRACE: 84511e25f0dSDavid C Somayajulu trace = (qlnx_trace_t *)data; 84611e25f0dSDavid C Somayajulu 84711e25f0dSDavid C Somayajulu for (i = 0; i < ha->cdev.num_hwfns; i++) { 84811e25f0dSDavid C Somayajulu 84911e25f0dSDavid C Somayajulu if (trace->size[i] && trace->cmd && trace->buffer[i]) 85011e25f0dSDavid C Somayajulu rval = qlnx_get_trace(ha, i, trace); 85111e25f0dSDavid C Somayajulu 85211e25f0dSDavid C Somayajulu if (rval) 85311e25f0dSDavid C Somayajulu break; 85411e25f0dSDavid C Somayajulu } 85511e25f0dSDavid C Somayajulu break; 85611e25f0dSDavid C Somayajulu 85711e25f0dSDavid C Somayajulu default: 85811e25f0dSDavid C Somayajulu rval = EINVAL; 85911e25f0dSDavid C Somayajulu break; 86011e25f0dSDavid C Somayajulu } 86111e25f0dSDavid C Somayajulu 86211e25f0dSDavid C Somayajulu return (rval); 86311e25f0dSDavid C Somayajulu } 86411e25f0dSDavid C Somayajulu 865