1718cf2ccSPedro F. Giffuni /*- 2718cf2ccSPedro F. Giffuni * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3718cf2ccSPedro F. Giffuni * 435291c22SDavid C Somayajulu * Copyright (c) 2013-2016 Qlogic Corporation 5f10a77bbSDavid C Somayajulu * All rights reserved. 6f10a77bbSDavid C Somayajulu * 7f10a77bbSDavid C Somayajulu * Redistribution and use in source and binary forms, with or without 8f10a77bbSDavid C Somayajulu * modification, are permitted provided that the following conditions 9f10a77bbSDavid C Somayajulu * are met: 10f10a77bbSDavid C Somayajulu * 11f10a77bbSDavid C Somayajulu * 1. Redistributions of source code must retain the above copyright 12f10a77bbSDavid C Somayajulu * notice, this list of conditions and the following disclaimer. 13f10a77bbSDavid C Somayajulu * 2. Redistributions in binary form must reproduce the above copyright 14f10a77bbSDavid C Somayajulu * notice, this list of conditions and the following disclaimer in the 15f10a77bbSDavid C Somayajulu * documentation and/or other materials provided with the distribution. 16f10a77bbSDavid C Somayajulu * 17f10a77bbSDavid C Somayajulu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18f10a77bbSDavid C Somayajulu * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19f10a77bbSDavid C Somayajulu * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20f10a77bbSDavid C Somayajulu * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 21f10a77bbSDavid C Somayajulu * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22f10a77bbSDavid C Somayajulu * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23f10a77bbSDavid C Somayajulu * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24f10a77bbSDavid C Somayajulu * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25f10a77bbSDavid C Somayajulu * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26f10a77bbSDavid C Somayajulu * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27f10a77bbSDavid C Somayajulu * POSSIBILITY OF SUCH DAMAGE. 28f10a77bbSDavid C Somayajulu */ 29f10a77bbSDavid C Somayajulu /* 30f10a77bbSDavid C Somayajulu * File: ql_ioctl.c 31f10a77bbSDavid C Somayajulu * Author : David C Somayajulu, Qlogic Corporation, Aliso Viejo, CA 92656. 32f10a77bbSDavid C Somayajulu */ 33f10a77bbSDavid C Somayajulu 34f10a77bbSDavid C Somayajulu #include <sys/cdefs.h> 35f10a77bbSDavid C Somayajulu __FBSDID("$FreeBSD$"); 36f10a77bbSDavid C Somayajulu 37f10a77bbSDavid C Somayajulu #include "ql_os.h" 38f10a77bbSDavid C Somayajulu #include "ql_hw.h" 39f10a77bbSDavid C Somayajulu #include "ql_def.h" 40f10a77bbSDavid C Somayajulu #include "ql_inline.h" 41f10a77bbSDavid C Somayajulu #include "ql_glbl.h" 42f10a77bbSDavid C Somayajulu #include "ql_ioctl.h" 43ab142b3fSDavid C Somayajulu #include "ql_ver.h" 44ab142b3fSDavid C Somayajulu #include "ql_dbg.h" 45f10a77bbSDavid C Somayajulu 46b65c0c07SDavid C Somayajulu static int ql_slowpath_log(qla_host_t *ha, qla_sp_log_t *log); 47ab142b3fSDavid C Somayajulu static int ql_drvr_state(qla_host_t *ha, qla_driver_state_t *drvr_state); 48ab142b3fSDavid C Somayajulu static uint32_t ql_drvr_state_size(qla_host_t *ha); 49f10a77bbSDavid C Somayajulu static int ql_eioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag, 50f10a77bbSDavid C Somayajulu struct thread *td); 51f10a77bbSDavid C Somayajulu 52f10a77bbSDavid C Somayajulu static struct cdevsw qla_cdevsw = { 53f10a77bbSDavid C Somayajulu .d_version = D_VERSION, 54f10a77bbSDavid C Somayajulu .d_ioctl = ql_eioctl, 55f10a77bbSDavid C Somayajulu .d_name = "qlcnic", 56f10a77bbSDavid C Somayajulu }; 57f10a77bbSDavid C Somayajulu 58f10a77bbSDavid C Somayajulu int 59f10a77bbSDavid C Somayajulu ql_make_cdev(qla_host_t *ha) 60f10a77bbSDavid C Somayajulu { 61f10a77bbSDavid C Somayajulu ha->ioctl_dev = make_dev(&qla_cdevsw, 62*54ab3b4aSJustin Hibbits if_getdunit(ha->ifp), 63f10a77bbSDavid C Somayajulu UID_ROOT, 64f10a77bbSDavid C Somayajulu GID_WHEEL, 65f10a77bbSDavid C Somayajulu 0600, 66f10a77bbSDavid C Somayajulu "%s", 67f10a77bbSDavid C Somayajulu if_name(ha->ifp)); 68f10a77bbSDavid C Somayajulu 69f10a77bbSDavid C Somayajulu if (ha->ioctl_dev == NULL) 70f10a77bbSDavid C Somayajulu return (-1); 71f10a77bbSDavid C Somayajulu 72f10a77bbSDavid C Somayajulu ha->ioctl_dev->si_drv1 = ha; 73f10a77bbSDavid C Somayajulu 74f10a77bbSDavid C Somayajulu return (0); 75f10a77bbSDavid C Somayajulu } 76f10a77bbSDavid C Somayajulu 77f10a77bbSDavid C Somayajulu void 78f10a77bbSDavid C Somayajulu ql_del_cdev(qla_host_t *ha) 79f10a77bbSDavid C Somayajulu { 80f10a77bbSDavid C Somayajulu if (ha->ioctl_dev != NULL) 81f10a77bbSDavid C Somayajulu destroy_dev(ha->ioctl_dev); 82f10a77bbSDavid C Somayajulu return; 83f10a77bbSDavid C Somayajulu } 84f10a77bbSDavid C Somayajulu 85f10a77bbSDavid C Somayajulu static int 86f10a77bbSDavid C Somayajulu ql_eioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag, 87f10a77bbSDavid C Somayajulu struct thread *td) 88f10a77bbSDavid C Somayajulu { 89f10a77bbSDavid C Somayajulu qla_host_t *ha; 90f10a77bbSDavid C Somayajulu int rval = 0; 91f10a77bbSDavid C Somayajulu device_t pci_dev; 92*54ab3b4aSJustin Hibbits if_t ifp; 936a62bec0SDavid C Somayajulu int count; 94f10a77bbSDavid C Somayajulu 95f10a77bbSDavid C Somayajulu q80_offchip_mem_val_t val; 96f10a77bbSDavid C Somayajulu qla_rd_pci_ids_t *pci_ids; 97f10a77bbSDavid C Somayajulu qla_rd_fw_dump_t *fw_dump; 98f10a77bbSDavid C Somayajulu union { 99f10a77bbSDavid C Somayajulu qla_reg_val_t *rv; 100f10a77bbSDavid C Somayajulu qla_rd_flash_t *rdf; 101f10a77bbSDavid C Somayajulu qla_wr_flash_t *wrf; 102f10a77bbSDavid C Somayajulu qla_erase_flash_t *erf; 103f10a77bbSDavid C Somayajulu qla_offchip_mem_val_t *mem; 104f10a77bbSDavid C Somayajulu } u; 105f10a77bbSDavid C Somayajulu 106f10a77bbSDavid C Somayajulu if ((ha = (qla_host_t *)dev->si_drv1) == NULL) 107f10a77bbSDavid C Somayajulu return ENXIO; 108f10a77bbSDavid C Somayajulu 109f10a77bbSDavid C Somayajulu pci_dev= ha->pci_dev; 110f10a77bbSDavid C Somayajulu 111f10a77bbSDavid C Somayajulu switch(cmd) { 112f10a77bbSDavid C Somayajulu case QLA_RDWR_REG: 113f10a77bbSDavid C Somayajulu 114f10a77bbSDavid C Somayajulu u.rv = (qla_reg_val_t *)data; 115f10a77bbSDavid C Somayajulu 116f10a77bbSDavid C Somayajulu if (u.rv->direct) { 117f10a77bbSDavid C Somayajulu if (u.rv->rd) { 118f10a77bbSDavid C Somayajulu u.rv->val = READ_REG32(ha, u.rv->reg); 119f10a77bbSDavid C Somayajulu } else { 120f10a77bbSDavid C Somayajulu WRITE_REG32(ha, u.rv->reg, u.rv->val); 121f10a77bbSDavid C Somayajulu } 122f10a77bbSDavid C Somayajulu } else { 123f10a77bbSDavid C Somayajulu if ((rval = ql_rdwr_indreg32(ha, u.rv->reg, &u.rv->val, 124f10a77bbSDavid C Somayajulu u.rv->rd))) 125f10a77bbSDavid C Somayajulu rval = ENXIO; 126f10a77bbSDavid C Somayajulu } 127f10a77bbSDavid C Somayajulu break; 128f10a77bbSDavid C Somayajulu 129f10a77bbSDavid C Somayajulu case QLA_RD_FLASH: 130f10a77bbSDavid C Somayajulu 131f10a77bbSDavid C Somayajulu if (!ha->hw.flags.fdt_valid) { 132f10a77bbSDavid C Somayajulu rval = EIO; 133f10a77bbSDavid C Somayajulu break; 134f10a77bbSDavid C Somayajulu } 135f10a77bbSDavid C Somayajulu 136f10a77bbSDavid C Somayajulu u.rdf = (qla_rd_flash_t *)data; 137f10a77bbSDavid C Somayajulu if ((rval = ql_rd_flash32(ha, u.rdf->off, &u.rdf->data))) 138f10a77bbSDavid C Somayajulu rval = ENXIO; 139f10a77bbSDavid C Somayajulu break; 140f10a77bbSDavid C Somayajulu 141f10a77bbSDavid C Somayajulu case QLA_WR_FLASH: 142f10a77bbSDavid C Somayajulu 143f10a77bbSDavid C Somayajulu ifp = ha->ifp; 144f10a77bbSDavid C Somayajulu 145f10a77bbSDavid C Somayajulu if (ifp == NULL) { 146f10a77bbSDavid C Somayajulu rval = ENXIO; 147f10a77bbSDavid C Somayajulu break; 148f10a77bbSDavid C Somayajulu } 149f10a77bbSDavid C Somayajulu 150*54ab3b4aSJustin Hibbits if (if_getdrvflags(ifp) & IFF_DRV_RUNNING) { 151f10a77bbSDavid C Somayajulu rval = ENXIO; 152f10a77bbSDavid C Somayajulu break; 153f10a77bbSDavid C Somayajulu } 154f10a77bbSDavid C Somayajulu 155f10a77bbSDavid C Somayajulu if (!ha->hw.flags.fdt_valid) { 156f10a77bbSDavid C Somayajulu rval = EIO; 157f10a77bbSDavid C Somayajulu break; 158f10a77bbSDavid C Somayajulu } 159f10a77bbSDavid C Somayajulu 160f10a77bbSDavid C Somayajulu u.wrf = (qla_wr_flash_t *)data; 161f10a77bbSDavid C Somayajulu if ((rval = ql_wr_flash_buffer(ha, u.wrf->off, u.wrf->size, 162f10a77bbSDavid C Somayajulu u.wrf->buffer))) { 163f10a77bbSDavid C Somayajulu printf("flash write failed[%d]\n", rval); 164f10a77bbSDavid C Somayajulu rval = ENXIO; 165f10a77bbSDavid C Somayajulu } 166f10a77bbSDavid C Somayajulu break; 167f10a77bbSDavid C Somayajulu 168f10a77bbSDavid C Somayajulu case QLA_ERASE_FLASH: 169f10a77bbSDavid C Somayajulu 170f10a77bbSDavid C Somayajulu ifp = ha->ifp; 171f10a77bbSDavid C Somayajulu 172f10a77bbSDavid C Somayajulu if (ifp == NULL) { 173f10a77bbSDavid C Somayajulu rval = ENXIO; 174f10a77bbSDavid C Somayajulu break; 175f10a77bbSDavid C Somayajulu } 176f10a77bbSDavid C Somayajulu 177*54ab3b4aSJustin Hibbits if (if_getdrvflags(ifp) & IFF_DRV_RUNNING) { 178f10a77bbSDavid C Somayajulu rval = ENXIO; 179f10a77bbSDavid C Somayajulu break; 180f10a77bbSDavid C Somayajulu } 181f10a77bbSDavid C Somayajulu 182f10a77bbSDavid C Somayajulu if (!ha->hw.flags.fdt_valid) { 183f10a77bbSDavid C Somayajulu rval = EIO; 184f10a77bbSDavid C Somayajulu break; 185f10a77bbSDavid C Somayajulu } 186f10a77bbSDavid C Somayajulu 187f10a77bbSDavid C Somayajulu u.erf = (qla_erase_flash_t *)data; 188f10a77bbSDavid C Somayajulu if ((rval = ql_erase_flash(ha, u.erf->off, 189f10a77bbSDavid C Somayajulu u.erf->size))) { 190f10a77bbSDavid C Somayajulu printf("flash erase failed[%d]\n", rval); 191f10a77bbSDavid C Somayajulu rval = ENXIO; 192f10a77bbSDavid C Somayajulu } 193f10a77bbSDavid C Somayajulu break; 194f10a77bbSDavid C Somayajulu 195f10a77bbSDavid C Somayajulu case QLA_RDWR_MS_MEM: 196f10a77bbSDavid C Somayajulu u.mem = (qla_offchip_mem_val_t *)data; 197f10a77bbSDavid C Somayajulu 198f10a77bbSDavid C Somayajulu if ((rval = ql_rdwr_offchip_mem(ha, u.mem->off, &val, 199f10a77bbSDavid C Somayajulu u.mem->rd))) 200f10a77bbSDavid C Somayajulu rval = ENXIO; 201f10a77bbSDavid C Somayajulu else { 202f10a77bbSDavid C Somayajulu u.mem->data_lo = val.data_lo; 203f10a77bbSDavid C Somayajulu u.mem->data_hi = val.data_hi; 204f10a77bbSDavid C Somayajulu u.mem->data_ulo = val.data_ulo; 205f10a77bbSDavid C Somayajulu u.mem->data_uhi = val.data_uhi; 206f10a77bbSDavid C Somayajulu } 207f10a77bbSDavid C Somayajulu 208f10a77bbSDavid C Somayajulu break; 209f10a77bbSDavid C Somayajulu 210f10a77bbSDavid C Somayajulu case QLA_RD_FW_DUMP_SIZE: 211f10a77bbSDavid C Somayajulu 212f10a77bbSDavid C Somayajulu if (ha->hw.mdump_init == 0) { 213f10a77bbSDavid C Somayajulu rval = EINVAL; 214f10a77bbSDavid C Somayajulu break; 215f10a77bbSDavid C Somayajulu } 216f10a77bbSDavid C Somayajulu 217f10a77bbSDavid C Somayajulu fw_dump = (qla_rd_fw_dump_t *)data; 2186a62bec0SDavid C Somayajulu fw_dump->minidump_size = ha->hw.mdump_buffer_size + 2196a62bec0SDavid C Somayajulu ha->hw.mdump_template_size; 220f10a77bbSDavid C Somayajulu fw_dump->pci_func = ha->pci_func; 221f10a77bbSDavid C Somayajulu 222f10a77bbSDavid C Somayajulu break; 223f10a77bbSDavid C Somayajulu 224f10a77bbSDavid C Somayajulu case QLA_RD_FW_DUMP: 225f10a77bbSDavid C Somayajulu 226f10a77bbSDavid C Somayajulu if (ha->hw.mdump_init == 0) { 227b65c0c07SDavid C Somayajulu device_printf(pci_dev, "%s: minidump not initialized\n", __func__); 228f10a77bbSDavid C Somayajulu rval = EINVAL; 229f10a77bbSDavid C Somayajulu break; 230f10a77bbSDavid C Somayajulu } 231f10a77bbSDavid C Somayajulu 232f10a77bbSDavid C Somayajulu fw_dump = (qla_rd_fw_dump_t *)data; 233c12c5bfbSDavid C Somayajulu 2346a62bec0SDavid C Somayajulu if ((fw_dump->minidump == NULL) || 2356a62bec0SDavid C Somayajulu (fw_dump->minidump_size != (ha->hw.mdump_buffer_size + 2366a62bec0SDavid C Somayajulu ha->hw.mdump_template_size))) { 237b65c0c07SDavid C Somayajulu device_printf(pci_dev, 238b65c0c07SDavid C Somayajulu "%s: minidump buffer [%p] size = [%d, %d] invalid\n", __func__, 239b65c0c07SDavid C Somayajulu fw_dump->minidump, fw_dump->minidump_size, 240b65c0c07SDavid C Somayajulu (ha->hw.mdump_buffer_size + ha->hw.mdump_template_size)); 241c12c5bfbSDavid C Somayajulu rval = EINVAL; 242c12c5bfbSDavid C Somayajulu break; 243c12c5bfbSDavid C Somayajulu } 244c12c5bfbSDavid C Somayajulu 245b65c0c07SDavid C Somayajulu if ((ha->pci_func & 0x1)) { 246b65c0c07SDavid C Somayajulu device_printf(pci_dev, "%s: mindump allowed only on Port0\n", __func__); 247b65c0c07SDavid C Somayajulu rval = ENXIO; 248b65c0c07SDavid C Somayajulu break; 249b65c0c07SDavid C Somayajulu } 250b65c0c07SDavid C Somayajulu 251b65c0c07SDavid C Somayajulu fw_dump->saved = 1; 252b65c0c07SDavid C Somayajulu 253b65c0c07SDavid C Somayajulu if (ha->offline) { 254b65c0c07SDavid C Somayajulu if (ha->enable_minidump) 255b65c0c07SDavid C Somayajulu ql_minidump(ha); 256b65c0c07SDavid C Somayajulu 257b65c0c07SDavid C Somayajulu fw_dump->saved = 0; 258b65c0c07SDavid C Somayajulu fw_dump->usec_ts = ha->hw.mdump_usec_ts; 259b65c0c07SDavid C Somayajulu 260b65c0c07SDavid C Somayajulu if (!ha->hw.mdump_done) { 261b65c0c07SDavid C Somayajulu device_printf(pci_dev, 262b65c0c07SDavid C Somayajulu "%s: port offline minidump failed\n", __func__); 263b65c0c07SDavid C Somayajulu rval = ENXIO; 264b65c0c07SDavid C Somayajulu break; 265b65c0c07SDavid C Somayajulu } 266b65c0c07SDavid C Somayajulu } else { 267971e53c9SDavid C Somayajulu #define QLA_LOCK_MDUMP_MS_TIMEOUT (QLA_LOCK_DEFAULT_MS_TIMEOUT * 5) 268971e53c9SDavid C Somayajulu if (QLA_LOCK(ha, __func__, QLA_LOCK_MDUMP_MS_TIMEOUT, 0) == 0) { 269b65c0c07SDavid C Somayajulu if (!ha->hw.mdump_done) { 270b65c0c07SDavid C Somayajulu fw_dump->saved = 0; 271b65c0c07SDavid C Somayajulu QL_INITIATE_RECOVERY(ha); 272b65c0c07SDavid C Somayajulu device_printf(pci_dev, "%s: recovery initiated " 273b65c0c07SDavid C Somayajulu " to trigger minidump\n", 274b65c0c07SDavid C Somayajulu __func__); 275b65c0c07SDavid C Somayajulu } 2767fb51846SDavid C Somayajulu QLA_UNLOCK(ha, __func__); 2777fb51846SDavid C Somayajulu } else { 278b65c0c07SDavid C Somayajulu device_printf(pci_dev, "%s: QLA_LOCK() failed0\n", __func__); 2797fb51846SDavid C Somayajulu rval = ENXIO; 2807fb51846SDavid C Somayajulu break; 2817fb51846SDavid C Somayajulu } 2826a62bec0SDavid C Somayajulu 2836a62bec0SDavid C Somayajulu #define QLNX_DUMP_WAIT_SECS 30 2846a62bec0SDavid C Somayajulu 2856a62bec0SDavid C Somayajulu count = QLNX_DUMP_WAIT_SECS * 1000; 2866a62bec0SDavid C Somayajulu 2876a62bec0SDavid C Somayajulu while (count) { 2886a62bec0SDavid C Somayajulu if (ha->hw.mdump_done) 2896a62bec0SDavid C Somayajulu break; 2906a62bec0SDavid C Somayajulu qla_mdelay(__func__, 100); 2916a62bec0SDavid C Somayajulu count -= 100; 2926a62bec0SDavid C Somayajulu } 2936a62bec0SDavid C Somayajulu 2946a62bec0SDavid C Somayajulu if (!ha->hw.mdump_done) { 295b65c0c07SDavid C Somayajulu device_printf(pci_dev, 296b65c0c07SDavid C Somayajulu "%s: port not offline minidump failed\n", __func__); 2976a62bec0SDavid C Somayajulu rval = ENXIO; 2986a62bec0SDavid C Somayajulu break; 2996a62bec0SDavid C Somayajulu } 300b65c0c07SDavid C Somayajulu fw_dump->usec_ts = ha->hw.mdump_usec_ts; 3016a62bec0SDavid C Somayajulu 302971e53c9SDavid C Somayajulu if (QLA_LOCK(ha, __func__, QLA_LOCK_MDUMP_MS_TIMEOUT, 0) == 0) { 3036a62bec0SDavid C Somayajulu ha->hw.mdump_done = 0; 3047fb51846SDavid C Somayajulu QLA_UNLOCK(ha, __func__); 3057fb51846SDavid C Somayajulu } else { 306b65c0c07SDavid C Somayajulu device_printf(pci_dev, "%s: QLA_LOCK() failed1\n", __func__); 3077fb51846SDavid C Somayajulu rval = ENXIO; 3087fb51846SDavid C Somayajulu break; 3097fb51846SDavid C Somayajulu } 310b65c0c07SDavid C Somayajulu } 3116a62bec0SDavid C Somayajulu 3126a62bec0SDavid C Somayajulu if ((rval = copyout(ha->hw.mdump_template, 3136a62bec0SDavid C Somayajulu fw_dump->minidump, ha->hw.mdump_template_size))) { 314b65c0c07SDavid C Somayajulu device_printf(pci_dev, "%s: template copyout failed\n", __func__); 3156a62bec0SDavid C Somayajulu rval = ENXIO; 3166a62bec0SDavid C Somayajulu break; 3176a62bec0SDavid C Somayajulu } 3186a62bec0SDavid C Somayajulu 3196a62bec0SDavid C Somayajulu if ((rval = copyout(ha->hw.mdump_buffer, 3206a62bec0SDavid C Somayajulu ((uint8_t *)fw_dump->minidump + 3216a62bec0SDavid C Somayajulu ha->hw.mdump_template_size), 322b65c0c07SDavid C Somayajulu ha->hw.mdump_buffer_size))) { 323b65c0c07SDavid C Somayajulu device_printf(pci_dev, "%s: minidump copyout failed\n", __func__); 324f10a77bbSDavid C Somayajulu rval = ENXIO; 325b65c0c07SDavid C Somayajulu } 326f10a77bbSDavid C Somayajulu break; 327f10a77bbSDavid C Somayajulu 328ab142b3fSDavid C Somayajulu case QLA_RD_DRVR_STATE: 329ab142b3fSDavid C Somayajulu rval = ql_drvr_state(ha, (qla_driver_state_t *)data); 330ab142b3fSDavid C Somayajulu break; 331ab142b3fSDavid C Somayajulu 332b65c0c07SDavid C Somayajulu case QLA_RD_SLOWPATH_LOG: 333b65c0c07SDavid C Somayajulu rval = ql_slowpath_log(ha, (qla_sp_log_t *)data); 334b65c0c07SDavid C Somayajulu break; 335b65c0c07SDavid C Somayajulu 336f10a77bbSDavid C Somayajulu case QLA_RD_PCI_IDS: 337f10a77bbSDavid C Somayajulu pci_ids = (qla_rd_pci_ids_t *)data; 338f10a77bbSDavid C Somayajulu pci_ids->ven_id = pci_get_vendor(pci_dev); 339f10a77bbSDavid C Somayajulu pci_ids->dev_id = pci_get_device(pci_dev); 340f10a77bbSDavid C Somayajulu pci_ids->subsys_ven_id = pci_get_subvendor(pci_dev); 341f10a77bbSDavid C Somayajulu pci_ids->subsys_dev_id = pci_get_subdevice(pci_dev); 342f10a77bbSDavid C Somayajulu pci_ids->rev_id = pci_read_config(pci_dev, PCIR_REVID, 1); 343f10a77bbSDavid C Somayajulu break; 344f10a77bbSDavid C Somayajulu 345f10a77bbSDavid C Somayajulu default: 346f10a77bbSDavid C Somayajulu break; 347f10a77bbSDavid C Somayajulu } 348f10a77bbSDavid C Somayajulu 349f10a77bbSDavid C Somayajulu return rval; 350f10a77bbSDavid C Somayajulu } 351f10a77bbSDavid C Somayajulu 352ab142b3fSDavid C Somayajulu static int 353ab142b3fSDavid C Somayajulu ql_drvr_state(qla_host_t *ha, qla_driver_state_t *state) 354ab142b3fSDavid C Somayajulu { 355ab142b3fSDavid C Somayajulu int rval = 0; 356ab142b3fSDavid C Somayajulu uint32_t drvr_state_size; 357ab142b3fSDavid C Somayajulu 358ab142b3fSDavid C Somayajulu drvr_state_size = ql_drvr_state_size(ha); 359ab142b3fSDavid C Somayajulu 360ab142b3fSDavid C Somayajulu if (state->buffer == NULL) { 361ab142b3fSDavid C Somayajulu state->size = drvr_state_size; 362ab142b3fSDavid C Somayajulu return (0); 363ab142b3fSDavid C Somayajulu } 364ab142b3fSDavid C Somayajulu 365ab142b3fSDavid C Somayajulu if (state->size < drvr_state_size) 366ab142b3fSDavid C Somayajulu return (ENXIO); 367ab142b3fSDavid C Somayajulu 368ab142b3fSDavid C Somayajulu if (ha->hw.drvr_state == NULL) 369ab142b3fSDavid C Somayajulu return (ENOMEM); 370ab142b3fSDavid C Somayajulu 371ab142b3fSDavid C Somayajulu ql_capture_drvr_state(ha); 372ab142b3fSDavid C Somayajulu 373ab142b3fSDavid C Somayajulu rval = copyout(ha->hw.drvr_state, state->buffer, drvr_state_size); 374ab142b3fSDavid C Somayajulu 375ab142b3fSDavid C Somayajulu bzero(ha->hw.drvr_state, drvr_state_size); 376ab142b3fSDavid C Somayajulu 377ab142b3fSDavid C Somayajulu return (rval); 378ab142b3fSDavid C Somayajulu } 379ab142b3fSDavid C Somayajulu 380ab142b3fSDavid C Somayajulu static uint32_t 381ab142b3fSDavid C Somayajulu ql_drvr_state_size(qla_host_t *ha) 382ab142b3fSDavid C Somayajulu { 383ab142b3fSDavid C Somayajulu uint32_t drvr_state_size; 384ab142b3fSDavid C Somayajulu uint32_t size; 385ab142b3fSDavid C Somayajulu 386ab142b3fSDavid C Somayajulu size = sizeof (qla_drvr_state_hdr_t); 387ab142b3fSDavid C Somayajulu drvr_state_size = QL_ALIGN(size, 64); 388ab142b3fSDavid C Somayajulu 389ab142b3fSDavid C Somayajulu size = ha->hw.num_tx_rings * (sizeof (qla_drvr_state_tx_t)); 390ab142b3fSDavid C Somayajulu drvr_state_size += QL_ALIGN(size, 64); 391ab142b3fSDavid C Somayajulu 392ab142b3fSDavid C Somayajulu size = ha->hw.num_rds_rings * (sizeof (qla_drvr_state_rx_t)); 393ab142b3fSDavid C Somayajulu drvr_state_size += QL_ALIGN(size, 64); 394ab142b3fSDavid C Somayajulu 395ab142b3fSDavid C Somayajulu size = ha->hw.num_sds_rings * (sizeof (qla_drvr_state_sds_t)); 396ab142b3fSDavid C Somayajulu drvr_state_size += QL_ALIGN(size, 64); 397ab142b3fSDavid C Somayajulu 398ab142b3fSDavid C Somayajulu size = sizeof(q80_tx_cmd_t) * NUM_TX_DESCRIPTORS * ha->hw.num_tx_rings; 399ab142b3fSDavid C Somayajulu drvr_state_size += QL_ALIGN(size, 64); 400ab142b3fSDavid C Somayajulu 401ab142b3fSDavid C Somayajulu size = sizeof(q80_recv_desc_t) * NUM_RX_DESCRIPTORS * ha->hw.num_rds_rings; 402ab142b3fSDavid C Somayajulu drvr_state_size += QL_ALIGN(size, 64); 403ab142b3fSDavid C Somayajulu 404ab142b3fSDavid C Somayajulu size = sizeof(q80_stat_desc_t) * NUM_STATUS_DESCRIPTORS * 405ab142b3fSDavid C Somayajulu ha->hw.num_sds_rings; 406ab142b3fSDavid C Somayajulu drvr_state_size += QL_ALIGN(size, 64); 407ab142b3fSDavid C Somayajulu 408ab142b3fSDavid C Somayajulu return (drvr_state_size); 409ab142b3fSDavid C Somayajulu } 410ab142b3fSDavid C Somayajulu 411ab142b3fSDavid C Somayajulu static void 412ab142b3fSDavid C Somayajulu ql_get_tx_state(qla_host_t *ha, qla_drvr_state_tx_t *tx_state) 413ab142b3fSDavid C Somayajulu { 414ab142b3fSDavid C Somayajulu int i; 415ab142b3fSDavid C Somayajulu 416ab142b3fSDavid C Somayajulu for (i = 0; i < ha->hw.num_tx_rings; i++) { 417ab142b3fSDavid C Somayajulu tx_state->base_p_addr = ha->hw.tx_cntxt[i].tx_ring_paddr; 418ab142b3fSDavid C Somayajulu tx_state->cons_p_addr = ha->hw.tx_cntxt[i].tx_cons_paddr; 419ab142b3fSDavid C Somayajulu tx_state->tx_prod_reg = ha->hw.tx_cntxt[i].tx_prod_reg; 420ab142b3fSDavid C Somayajulu tx_state->tx_cntxt_id = ha->hw.tx_cntxt[i].tx_cntxt_id; 421ab142b3fSDavid C Somayajulu tx_state->txr_free = ha->hw.tx_cntxt[i].txr_free; 422ab142b3fSDavid C Somayajulu tx_state->txr_next = ha->hw.tx_cntxt[i].txr_next; 423ab142b3fSDavid C Somayajulu tx_state->txr_comp = ha->hw.tx_cntxt[i].txr_comp; 424ab142b3fSDavid C Somayajulu tx_state++; 425ab142b3fSDavid C Somayajulu } 426ab142b3fSDavid C Somayajulu return; 427ab142b3fSDavid C Somayajulu } 428ab142b3fSDavid C Somayajulu 429ab142b3fSDavid C Somayajulu static void 430ab142b3fSDavid C Somayajulu ql_get_rx_state(qla_host_t *ha, qla_drvr_state_rx_t *rx_state) 431ab142b3fSDavid C Somayajulu { 432ab142b3fSDavid C Somayajulu int i; 433ab142b3fSDavid C Somayajulu 434ab142b3fSDavid C Somayajulu for (i = 0; i < ha->hw.num_rds_rings; i++) { 435ab142b3fSDavid C Somayajulu rx_state->prod_std = ha->hw.rds[i].prod_std; 436ab142b3fSDavid C Somayajulu rx_state->rx_next = ha->hw.rds[i].rx_next; 437ab142b3fSDavid C Somayajulu rx_state++; 438ab142b3fSDavid C Somayajulu } 439ab142b3fSDavid C Somayajulu return; 440ab142b3fSDavid C Somayajulu } 441ab142b3fSDavid C Somayajulu 442ab142b3fSDavid C Somayajulu static void 443ab142b3fSDavid C Somayajulu ql_get_sds_state(qla_host_t *ha, qla_drvr_state_sds_t *sds_state) 444ab142b3fSDavid C Somayajulu { 445ab142b3fSDavid C Somayajulu int i; 446ab142b3fSDavid C Somayajulu 447ab142b3fSDavid C Somayajulu for (i = 0; i < ha->hw.num_sds_rings; i++) { 448ab142b3fSDavid C Somayajulu sds_state->sdsr_next = ha->hw.sds[i].sdsr_next; 449ab142b3fSDavid C Somayajulu sds_state->sds_consumer = ha->hw.sds[i].sds_consumer; 450ab142b3fSDavid C Somayajulu sds_state++; 451ab142b3fSDavid C Somayajulu } 452ab142b3fSDavid C Somayajulu return; 453ab142b3fSDavid C Somayajulu } 454ab142b3fSDavid C Somayajulu 455ab142b3fSDavid C Somayajulu void 456ab142b3fSDavid C Somayajulu ql_capture_drvr_state(qla_host_t *ha) 457ab142b3fSDavid C Somayajulu { 458ab142b3fSDavid C Somayajulu uint8_t *state_buffer; 459ab142b3fSDavid C Somayajulu uint8_t *ptr; 460ab142b3fSDavid C Somayajulu qla_drvr_state_hdr_t *hdr; 461ab142b3fSDavid C Somayajulu uint32_t size; 462ab142b3fSDavid C Somayajulu int i; 463ab142b3fSDavid C Somayajulu 464ab142b3fSDavid C Somayajulu state_buffer = ha->hw.drvr_state; 465ab142b3fSDavid C Somayajulu 466ab142b3fSDavid C Somayajulu if (state_buffer == NULL) 467ab142b3fSDavid C Somayajulu return; 468ab142b3fSDavid C Somayajulu 469ab142b3fSDavid C Somayajulu hdr = (qla_drvr_state_hdr_t *)state_buffer; 470ab142b3fSDavid C Somayajulu 471b65c0c07SDavid C Somayajulu hdr->saved = 0; 472b65c0c07SDavid C Somayajulu 473b65c0c07SDavid C Somayajulu if (hdr->drvr_version_major) { 474b65c0c07SDavid C Somayajulu hdr->saved = 1; 475b65c0c07SDavid C Somayajulu return; 476b65c0c07SDavid C Somayajulu } 477b65c0c07SDavid C Somayajulu 478b65c0c07SDavid C Somayajulu hdr->usec_ts = qla_get_usec_timestamp(); 479b65c0c07SDavid C Somayajulu 480ab142b3fSDavid C Somayajulu hdr->drvr_version_major = QLA_VERSION_MAJOR; 481ab142b3fSDavid C Somayajulu hdr->drvr_version_minor = QLA_VERSION_MINOR; 482ab142b3fSDavid C Somayajulu hdr->drvr_version_build = QLA_VERSION_BUILD; 483ab142b3fSDavid C Somayajulu 484ab142b3fSDavid C Somayajulu bcopy(ha->hw.mac_addr, hdr->mac_addr, ETHER_ADDR_LEN); 485ab142b3fSDavid C Somayajulu 486ab142b3fSDavid C Somayajulu hdr->link_speed = ha->hw.link_speed; 487ab142b3fSDavid C Somayajulu hdr->cable_length = ha->hw.cable_length; 488ab142b3fSDavid C Somayajulu hdr->cable_oui = ha->hw.cable_oui; 489ab142b3fSDavid C Somayajulu hdr->link_up = ha->hw.link_up; 490ab142b3fSDavid C Somayajulu hdr->module_type = ha->hw.module_type; 491ab142b3fSDavid C Somayajulu hdr->link_faults = ha->hw.link_faults; 492ab142b3fSDavid C Somayajulu hdr->rcv_intr_coalesce = ha->hw.rcv_intr_coalesce; 493ab142b3fSDavid C Somayajulu hdr->xmt_intr_coalesce = ha->hw.xmt_intr_coalesce; 494ab142b3fSDavid C Somayajulu 495ab142b3fSDavid C Somayajulu size = sizeof (qla_drvr_state_hdr_t); 496ab142b3fSDavid C Somayajulu hdr->tx_state_offset = QL_ALIGN(size, 64); 497ab142b3fSDavid C Somayajulu 498ab142b3fSDavid C Somayajulu ptr = state_buffer + hdr->tx_state_offset; 499ab142b3fSDavid C Somayajulu 500ab142b3fSDavid C Somayajulu ql_get_tx_state(ha, (qla_drvr_state_tx_t *)ptr); 501ab142b3fSDavid C Somayajulu 502ab142b3fSDavid C Somayajulu size = ha->hw.num_tx_rings * (sizeof (qla_drvr_state_tx_t)); 503ab142b3fSDavid C Somayajulu hdr->rx_state_offset = hdr->tx_state_offset + QL_ALIGN(size, 64); 504ab142b3fSDavid C Somayajulu ptr = state_buffer + hdr->rx_state_offset; 505ab142b3fSDavid C Somayajulu 506ab142b3fSDavid C Somayajulu ql_get_rx_state(ha, (qla_drvr_state_rx_t *)ptr); 507ab142b3fSDavid C Somayajulu 508ab142b3fSDavid C Somayajulu size = ha->hw.num_rds_rings * (sizeof (qla_drvr_state_rx_t)); 509ab142b3fSDavid C Somayajulu hdr->sds_state_offset = hdr->rx_state_offset + QL_ALIGN(size, 64); 510ab142b3fSDavid C Somayajulu ptr = state_buffer + hdr->sds_state_offset; 511ab142b3fSDavid C Somayajulu 512ab142b3fSDavid C Somayajulu ql_get_sds_state(ha, (qla_drvr_state_sds_t *)ptr); 513ab142b3fSDavid C Somayajulu 514ab142b3fSDavid C Somayajulu size = ha->hw.num_sds_rings * (sizeof (qla_drvr_state_sds_t)); 515ab142b3fSDavid C Somayajulu hdr->txr_offset = hdr->sds_state_offset + QL_ALIGN(size, 64); 516ab142b3fSDavid C Somayajulu ptr = state_buffer + hdr->txr_offset; 517ab142b3fSDavid C Somayajulu 518ab142b3fSDavid C Somayajulu hdr->num_tx_rings = ha->hw.num_tx_rings; 519ab142b3fSDavid C Somayajulu hdr->txr_size = sizeof(q80_tx_cmd_t) * NUM_TX_DESCRIPTORS; 520ab142b3fSDavid C Somayajulu hdr->txr_entries = NUM_TX_DESCRIPTORS; 521ab142b3fSDavid C Somayajulu 522ab142b3fSDavid C Somayajulu size = hdr->num_tx_rings * hdr->txr_size; 523ab142b3fSDavid C Somayajulu bcopy(ha->hw.dma_buf.tx_ring.dma_b, ptr, size); 524ab142b3fSDavid C Somayajulu 525ab142b3fSDavid C Somayajulu hdr->rxr_offset = hdr->txr_offset + QL_ALIGN(size, 64); 526ab142b3fSDavid C Somayajulu ptr = state_buffer + hdr->rxr_offset; 527ab142b3fSDavid C Somayajulu 528ab142b3fSDavid C Somayajulu hdr->rxr_size = sizeof(q80_recv_desc_t) * NUM_RX_DESCRIPTORS; 529ab142b3fSDavid C Somayajulu hdr->rxr_entries = NUM_RX_DESCRIPTORS; 530ab142b3fSDavid C Somayajulu hdr->num_rx_rings = ha->hw.num_rds_rings; 531ab142b3fSDavid C Somayajulu 532ab142b3fSDavid C Somayajulu for (i = 0; i < ha->hw.num_rds_rings; i++) { 533ab142b3fSDavid C Somayajulu bcopy(ha->hw.dma_buf.rds_ring[i].dma_b, ptr, hdr->rxr_size); 534ab142b3fSDavid C Somayajulu ptr += hdr->rxr_size; 535ab142b3fSDavid C Somayajulu } 536ab142b3fSDavid C Somayajulu 537ab142b3fSDavid C Somayajulu size = hdr->rxr_size * hdr->num_rx_rings; 538ab142b3fSDavid C Somayajulu hdr->sds_offset = hdr->rxr_offset + QL_ALIGN(size, 64); 539ab142b3fSDavid C Somayajulu hdr->sds_ring_size = sizeof(q80_stat_desc_t) * NUM_STATUS_DESCRIPTORS; 540ab142b3fSDavid C Somayajulu hdr->sds_entries = NUM_STATUS_DESCRIPTORS; 541ab142b3fSDavid C Somayajulu hdr->num_sds_rings = ha->hw.num_sds_rings; 542ab142b3fSDavid C Somayajulu 543ab142b3fSDavid C Somayajulu ptr = state_buffer + hdr->sds_offset; 544ab142b3fSDavid C Somayajulu for (i = 0; i < ha->hw.num_sds_rings; i++) { 545ab142b3fSDavid C Somayajulu bcopy(ha->hw.dma_buf.sds_ring[i].dma_b, ptr, hdr->sds_ring_size); 546ab142b3fSDavid C Somayajulu ptr += hdr->sds_ring_size; 547ab142b3fSDavid C Somayajulu } 548ab142b3fSDavid C Somayajulu return; 549ab142b3fSDavid C Somayajulu } 550ab142b3fSDavid C Somayajulu 551ab142b3fSDavid C Somayajulu void 552ab142b3fSDavid C Somayajulu ql_alloc_drvr_state_buffer(qla_host_t *ha) 553ab142b3fSDavid C Somayajulu { 554ab142b3fSDavid C Somayajulu uint32_t drvr_state_size; 555ab142b3fSDavid C Somayajulu 556ab142b3fSDavid C Somayajulu drvr_state_size = ql_drvr_state_size(ha); 557ab142b3fSDavid C Somayajulu 558ab142b3fSDavid C Somayajulu ha->hw.drvr_state = malloc(drvr_state_size, M_QLA83XXBUF, M_NOWAIT); 559ab142b3fSDavid C Somayajulu 560b65c0c07SDavid C Somayajulu if (ha->hw.drvr_state != NULL) 561b65c0c07SDavid C Somayajulu bzero(ha->hw.drvr_state, drvr_state_size); 562b65c0c07SDavid C Somayajulu 563ab142b3fSDavid C Somayajulu return; 564ab142b3fSDavid C Somayajulu } 565ab142b3fSDavid C Somayajulu 566ab142b3fSDavid C Somayajulu void 567ab142b3fSDavid C Somayajulu ql_free_drvr_state_buffer(qla_host_t *ha) 568ab142b3fSDavid C Somayajulu { 569ab142b3fSDavid C Somayajulu if (ha->hw.drvr_state != NULL) 570ab142b3fSDavid C Somayajulu free(ha->hw.drvr_state, M_QLA83XXBUF); 571ab142b3fSDavid C Somayajulu return; 572ab142b3fSDavid C Somayajulu } 573ab142b3fSDavid C Somayajulu 574b65c0c07SDavid C Somayajulu void 575b65c0c07SDavid C Somayajulu ql_sp_log(qla_host_t *ha, uint16_t fmtstr_idx, uint16_t num_params, 576b65c0c07SDavid C Somayajulu uint32_t param0, uint32_t param1, uint32_t param2, uint32_t param3, 577b65c0c07SDavid C Somayajulu uint32_t param4) 578b65c0c07SDavid C Somayajulu { 579b65c0c07SDavid C Somayajulu qla_sp_log_entry_t *sp_e, *sp_log; 580b65c0c07SDavid C Somayajulu 581b65c0c07SDavid C Somayajulu if (((sp_log = ha->hw.sp_log) == NULL) || ha->hw.sp_log_stop) 582b65c0c07SDavid C Somayajulu return; 583b65c0c07SDavid C Somayajulu 584b65c0c07SDavid C Somayajulu mtx_lock(&ha->sp_log_lock); 585b65c0c07SDavid C Somayajulu 586b65c0c07SDavid C Somayajulu sp_e = &sp_log[ha->hw.sp_log_index]; 587b65c0c07SDavid C Somayajulu 588b65c0c07SDavid C Somayajulu bzero(sp_e, sizeof (qla_sp_log_entry_t)); 589b65c0c07SDavid C Somayajulu 590b65c0c07SDavid C Somayajulu sp_e->fmtstr_idx = fmtstr_idx; 591b65c0c07SDavid C Somayajulu sp_e->num_params = num_params; 592b65c0c07SDavid C Somayajulu 593b65c0c07SDavid C Somayajulu sp_e->usec_ts = qla_get_usec_timestamp(); 594b65c0c07SDavid C Somayajulu 595b65c0c07SDavid C Somayajulu sp_e->params[0] = param0; 596b65c0c07SDavid C Somayajulu sp_e->params[1] = param1; 597b65c0c07SDavid C Somayajulu sp_e->params[2] = param2; 598b65c0c07SDavid C Somayajulu sp_e->params[3] = param3; 599b65c0c07SDavid C Somayajulu sp_e->params[4] = param4; 600b65c0c07SDavid C Somayajulu 601b65c0c07SDavid C Somayajulu ha->hw.sp_log_index = (ha->hw.sp_log_index + 1) & (NUM_LOG_ENTRIES - 1); 602b65c0c07SDavid C Somayajulu 603b65c0c07SDavid C Somayajulu if (ha->hw.sp_log_num_entries < NUM_LOG_ENTRIES) 604b65c0c07SDavid C Somayajulu ha->hw.sp_log_num_entries++; 605b65c0c07SDavid C Somayajulu 606b65c0c07SDavid C Somayajulu mtx_unlock(&ha->sp_log_lock); 607b65c0c07SDavid C Somayajulu 608b65c0c07SDavid C Somayajulu return; 609b65c0c07SDavid C Somayajulu } 610b65c0c07SDavid C Somayajulu 611b65c0c07SDavid C Somayajulu void 612b65c0c07SDavid C Somayajulu ql_alloc_sp_log_buffer(qla_host_t *ha) 613b65c0c07SDavid C Somayajulu { 614b65c0c07SDavid C Somayajulu uint32_t size; 615b65c0c07SDavid C Somayajulu 616b65c0c07SDavid C Somayajulu size = (sizeof(qla_sp_log_entry_t)) * NUM_LOG_ENTRIES; 617b65c0c07SDavid C Somayajulu 618b65c0c07SDavid C Somayajulu ha->hw.sp_log = malloc(size, M_QLA83XXBUF, M_NOWAIT); 619b65c0c07SDavid C Somayajulu 620b65c0c07SDavid C Somayajulu if (ha->hw.sp_log != NULL) 621b65c0c07SDavid C Somayajulu bzero(ha->hw.sp_log, size); 622b65c0c07SDavid C Somayajulu 623b65c0c07SDavid C Somayajulu ha->hw.sp_log_index = 0; 624b65c0c07SDavid C Somayajulu ha->hw.sp_log_num_entries = 0; 625b65c0c07SDavid C Somayajulu 626b65c0c07SDavid C Somayajulu return; 627b65c0c07SDavid C Somayajulu } 628b65c0c07SDavid C Somayajulu 629b65c0c07SDavid C Somayajulu void 630b65c0c07SDavid C Somayajulu ql_free_sp_log_buffer(qla_host_t *ha) 631b65c0c07SDavid C Somayajulu { 632b65c0c07SDavid C Somayajulu if (ha->hw.sp_log != NULL) 633b65c0c07SDavid C Somayajulu free(ha->hw.sp_log, M_QLA83XXBUF); 634b65c0c07SDavid C Somayajulu return; 635b65c0c07SDavid C Somayajulu } 636b65c0c07SDavid C Somayajulu 637b65c0c07SDavid C Somayajulu static int 638b65c0c07SDavid C Somayajulu ql_slowpath_log(qla_host_t *ha, qla_sp_log_t *log) 639b65c0c07SDavid C Somayajulu { 640b65c0c07SDavid C Somayajulu int rval = 0; 641b65c0c07SDavid C Somayajulu uint32_t size; 642b65c0c07SDavid C Somayajulu 643b65c0c07SDavid C Somayajulu if ((ha->hw.sp_log == NULL) || (log->buffer == NULL)) 644b65c0c07SDavid C Somayajulu return (EINVAL); 645b65c0c07SDavid C Somayajulu 646b65c0c07SDavid C Somayajulu size = (sizeof(qla_sp_log_entry_t) * NUM_LOG_ENTRIES); 647b65c0c07SDavid C Somayajulu 648b65c0c07SDavid C Somayajulu mtx_lock(&ha->sp_log_lock); 649b65c0c07SDavid C Somayajulu 650b65c0c07SDavid C Somayajulu rval = copyout(ha->hw.sp_log, log->buffer, size); 651b65c0c07SDavid C Somayajulu 652b65c0c07SDavid C Somayajulu if (!rval) { 653b65c0c07SDavid C Somayajulu log->next_idx = ha->hw.sp_log_index; 654b65c0c07SDavid C Somayajulu log->num_entries = ha->hw.sp_log_num_entries; 655b65c0c07SDavid C Somayajulu } 656b65c0c07SDavid C Somayajulu device_printf(ha->pci_dev, 657b65c0c07SDavid C Somayajulu "%s: exit [rval = %d][%p, next_idx = %d, %d entries, %d bytes]\n", 658b65c0c07SDavid C Somayajulu __func__, rval, log->buffer, log->next_idx, log->num_entries, size); 659b65c0c07SDavid C Somayajulu mtx_unlock(&ha->sp_log_lock); 660b65c0c07SDavid C Somayajulu 661b65c0c07SDavid C Somayajulu return (rval); 662b65c0c07SDavid C Somayajulu } 663