1*718cf2ccSPedro F. Giffuni /*- 2*718cf2ccSPedro F. Giffuni * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3*718cf2ccSPedro 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 38f10a77bbSDavid C Somayajulu #include "ql_os.h" 39f10a77bbSDavid C Somayajulu #include "ql_hw.h" 40f10a77bbSDavid C Somayajulu #include "ql_def.h" 41f10a77bbSDavid C Somayajulu #include "ql_inline.h" 42f10a77bbSDavid C Somayajulu #include "ql_glbl.h" 43f10a77bbSDavid C Somayajulu #include "ql_ioctl.h" 44ab142b3fSDavid C Somayajulu #include "ql_ver.h" 45ab142b3fSDavid C Somayajulu #include "ql_dbg.h" 46f10a77bbSDavid C Somayajulu 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, 62f10a77bbSDavid C Somayajulu ha->ifp->if_dunit, 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; 92f10a77bbSDavid C Somayajulu struct ifnet *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 107f10a77bbSDavid C Somayajulu if ((ha = (qla_host_t *)dev->si_drv1) == NULL) 108f10a77bbSDavid C Somayajulu return ENXIO; 109f10a77bbSDavid C Somayajulu 110f10a77bbSDavid C Somayajulu pci_dev= ha->pci_dev; 111f10a77bbSDavid C Somayajulu 112f10a77bbSDavid C Somayajulu switch(cmd) { 113f10a77bbSDavid C Somayajulu 114f10a77bbSDavid C Somayajulu case QLA_RDWR_REG: 115f10a77bbSDavid C Somayajulu 116f10a77bbSDavid C Somayajulu u.rv = (qla_reg_val_t *)data; 117f10a77bbSDavid C Somayajulu 118f10a77bbSDavid C Somayajulu if (u.rv->direct) { 119f10a77bbSDavid C Somayajulu if (u.rv->rd) { 120f10a77bbSDavid C Somayajulu u.rv->val = READ_REG32(ha, u.rv->reg); 121f10a77bbSDavid C Somayajulu } else { 122f10a77bbSDavid C Somayajulu WRITE_REG32(ha, u.rv->reg, u.rv->val); 123f10a77bbSDavid C Somayajulu } 124f10a77bbSDavid C Somayajulu } else { 125f10a77bbSDavid C Somayajulu if ((rval = ql_rdwr_indreg32(ha, u.rv->reg, &u.rv->val, 126f10a77bbSDavid C Somayajulu u.rv->rd))) 127f10a77bbSDavid C Somayajulu rval = ENXIO; 128f10a77bbSDavid C Somayajulu } 129f10a77bbSDavid C Somayajulu break; 130f10a77bbSDavid C Somayajulu 131f10a77bbSDavid C Somayajulu case QLA_RD_FLASH: 132f10a77bbSDavid C Somayajulu 133f10a77bbSDavid C Somayajulu if (!ha->hw.flags.fdt_valid) { 134f10a77bbSDavid C Somayajulu rval = EIO; 135f10a77bbSDavid C Somayajulu break; 136f10a77bbSDavid C Somayajulu } 137f10a77bbSDavid C Somayajulu 138f10a77bbSDavid C Somayajulu u.rdf = (qla_rd_flash_t *)data; 139f10a77bbSDavid C Somayajulu if ((rval = ql_rd_flash32(ha, u.rdf->off, &u.rdf->data))) 140f10a77bbSDavid C Somayajulu rval = ENXIO; 141f10a77bbSDavid C Somayajulu break; 142f10a77bbSDavid C Somayajulu 143f10a77bbSDavid C Somayajulu case QLA_WR_FLASH: 144f10a77bbSDavid C Somayajulu 145f10a77bbSDavid C Somayajulu ifp = ha->ifp; 146f10a77bbSDavid C Somayajulu 147f10a77bbSDavid C Somayajulu if (ifp == NULL) { 148f10a77bbSDavid C Somayajulu rval = ENXIO; 149f10a77bbSDavid C Somayajulu break; 150f10a77bbSDavid C Somayajulu } 151f10a77bbSDavid C Somayajulu 1527fb51846SDavid C Somayajulu if (ifp->if_drv_flags & IFF_DRV_RUNNING) { 153f10a77bbSDavid C Somayajulu rval = ENXIO; 154f10a77bbSDavid C Somayajulu break; 155f10a77bbSDavid C Somayajulu } 156f10a77bbSDavid C Somayajulu 157f10a77bbSDavid C Somayajulu if (!ha->hw.flags.fdt_valid) { 158f10a77bbSDavid C Somayajulu rval = EIO; 159f10a77bbSDavid C Somayajulu break; 160f10a77bbSDavid C Somayajulu } 161f10a77bbSDavid C Somayajulu 162f10a77bbSDavid C Somayajulu u.wrf = (qla_wr_flash_t *)data; 163f10a77bbSDavid C Somayajulu if ((rval = ql_wr_flash_buffer(ha, u.wrf->off, u.wrf->size, 164f10a77bbSDavid C Somayajulu u.wrf->buffer))) { 165f10a77bbSDavid C Somayajulu printf("flash write failed[%d]\n", rval); 166f10a77bbSDavid C Somayajulu rval = ENXIO; 167f10a77bbSDavid C Somayajulu } 168f10a77bbSDavid C Somayajulu break; 169f10a77bbSDavid C Somayajulu 170f10a77bbSDavid C Somayajulu case QLA_ERASE_FLASH: 171f10a77bbSDavid C Somayajulu 172f10a77bbSDavid C Somayajulu ifp = ha->ifp; 173f10a77bbSDavid C Somayajulu 174f10a77bbSDavid C Somayajulu if (ifp == NULL) { 175f10a77bbSDavid C Somayajulu rval = ENXIO; 176f10a77bbSDavid C Somayajulu break; 177f10a77bbSDavid C Somayajulu } 178f10a77bbSDavid C Somayajulu 1797fb51846SDavid C Somayajulu if (ifp->if_drv_flags & IFF_DRV_RUNNING) { 180f10a77bbSDavid C Somayajulu rval = ENXIO; 181f10a77bbSDavid C Somayajulu break; 182f10a77bbSDavid C Somayajulu } 183f10a77bbSDavid C Somayajulu 184f10a77bbSDavid C Somayajulu if (!ha->hw.flags.fdt_valid) { 185f10a77bbSDavid C Somayajulu rval = EIO; 186f10a77bbSDavid C Somayajulu break; 187f10a77bbSDavid C Somayajulu } 188f10a77bbSDavid C Somayajulu 189f10a77bbSDavid C Somayajulu u.erf = (qla_erase_flash_t *)data; 190f10a77bbSDavid C Somayajulu if ((rval = ql_erase_flash(ha, u.erf->off, 191f10a77bbSDavid C Somayajulu u.erf->size))) { 192f10a77bbSDavid C Somayajulu printf("flash erase failed[%d]\n", rval); 193f10a77bbSDavid C Somayajulu rval = ENXIO; 194f10a77bbSDavid C Somayajulu } 195f10a77bbSDavid C Somayajulu break; 196f10a77bbSDavid C Somayajulu 197f10a77bbSDavid C Somayajulu case QLA_RDWR_MS_MEM: 198f10a77bbSDavid C Somayajulu u.mem = (qla_offchip_mem_val_t *)data; 199f10a77bbSDavid C Somayajulu 200f10a77bbSDavid C Somayajulu if ((rval = ql_rdwr_offchip_mem(ha, u.mem->off, &val, 201f10a77bbSDavid C Somayajulu u.mem->rd))) 202f10a77bbSDavid C Somayajulu rval = ENXIO; 203f10a77bbSDavid C Somayajulu else { 204f10a77bbSDavid C Somayajulu u.mem->data_lo = val.data_lo; 205f10a77bbSDavid C Somayajulu u.mem->data_hi = val.data_hi; 206f10a77bbSDavid C Somayajulu u.mem->data_ulo = val.data_ulo; 207f10a77bbSDavid C Somayajulu u.mem->data_uhi = val.data_uhi; 208f10a77bbSDavid C Somayajulu } 209f10a77bbSDavid C Somayajulu 210f10a77bbSDavid C Somayajulu break; 211f10a77bbSDavid C Somayajulu 212f10a77bbSDavid C Somayajulu case QLA_RD_FW_DUMP_SIZE: 213f10a77bbSDavid C Somayajulu 214f10a77bbSDavid C Somayajulu if (ha->hw.mdump_init == 0) { 215f10a77bbSDavid C Somayajulu rval = EINVAL; 216f10a77bbSDavid C Somayajulu break; 217f10a77bbSDavid C Somayajulu } 218f10a77bbSDavid C Somayajulu 219f10a77bbSDavid C Somayajulu fw_dump = (qla_rd_fw_dump_t *)data; 2206a62bec0SDavid C Somayajulu fw_dump->minidump_size = ha->hw.mdump_buffer_size + 2216a62bec0SDavid C Somayajulu ha->hw.mdump_template_size; 222f10a77bbSDavid C Somayajulu fw_dump->pci_func = ha->pci_func; 223f10a77bbSDavid C Somayajulu 224f10a77bbSDavid C Somayajulu break; 225f10a77bbSDavid C Somayajulu 226f10a77bbSDavid C Somayajulu case QLA_RD_FW_DUMP: 227f10a77bbSDavid C Somayajulu 228f10a77bbSDavid C Somayajulu if (ha->hw.mdump_init == 0) { 229f10a77bbSDavid C Somayajulu rval = EINVAL; 230f10a77bbSDavid C Somayajulu break; 231f10a77bbSDavid C Somayajulu } 232f10a77bbSDavid C Somayajulu 233f10a77bbSDavid C Somayajulu fw_dump = (qla_rd_fw_dump_t *)data; 234c12c5bfbSDavid C Somayajulu 2356a62bec0SDavid C Somayajulu if ((fw_dump->minidump == NULL) || 2366a62bec0SDavid C Somayajulu (fw_dump->minidump_size != (ha->hw.mdump_buffer_size + 2376a62bec0SDavid C Somayajulu ha->hw.mdump_template_size))) { 238c12c5bfbSDavid C Somayajulu rval = EINVAL; 239c12c5bfbSDavid C Somayajulu break; 240c12c5bfbSDavid C Somayajulu } 241c12c5bfbSDavid C Somayajulu 2427fb51846SDavid C Somayajulu if (QLA_LOCK(ha, __func__, QLA_LOCK_DEFAULT_MS_TIMEOUT, 0) == 0) { 2436a62bec0SDavid C Somayajulu if (!ha->hw.mdump_done) 2446a62bec0SDavid C Somayajulu ha->qla_initiate_recovery = 1; 2457fb51846SDavid C Somayajulu QLA_UNLOCK(ha, __func__); 2467fb51846SDavid C Somayajulu } else { 2477fb51846SDavid C Somayajulu rval = ENXIO; 2487fb51846SDavid C Somayajulu break; 2497fb51846SDavid C Somayajulu } 2506a62bec0SDavid C Somayajulu 2516a62bec0SDavid C Somayajulu #define QLNX_DUMP_WAIT_SECS 30 2526a62bec0SDavid C Somayajulu 2536a62bec0SDavid C Somayajulu count = QLNX_DUMP_WAIT_SECS * 1000; 2546a62bec0SDavid C Somayajulu 2556a62bec0SDavid C Somayajulu while (count) { 2566a62bec0SDavid C Somayajulu if (ha->hw.mdump_done) 2576a62bec0SDavid C Somayajulu break; 2586a62bec0SDavid C Somayajulu qla_mdelay(__func__, 100); 2596a62bec0SDavid C Somayajulu count -= 100; 2606a62bec0SDavid C Somayajulu } 2616a62bec0SDavid C Somayajulu 2626a62bec0SDavid C Somayajulu if (!ha->hw.mdump_done) { 2636a62bec0SDavid C Somayajulu rval = ENXIO; 2646a62bec0SDavid C Somayajulu break; 2656a62bec0SDavid C Somayajulu } 2666a62bec0SDavid C Somayajulu 2677fb51846SDavid C Somayajulu if (QLA_LOCK(ha, __func__, QLA_LOCK_DEFAULT_MS_TIMEOUT, 0) == 0) { 2686a62bec0SDavid C Somayajulu ha->hw.mdump_done = 0; 2697fb51846SDavid C Somayajulu QLA_UNLOCK(ha, __func__); 2707fb51846SDavid C Somayajulu } else { 2717fb51846SDavid C Somayajulu rval = ENXIO; 2727fb51846SDavid C Somayajulu break; 2737fb51846SDavid C Somayajulu } 2746a62bec0SDavid C Somayajulu 2756a62bec0SDavid C Somayajulu if ((rval = copyout(ha->hw.mdump_template, 2766a62bec0SDavid C Somayajulu fw_dump->minidump, ha->hw.mdump_template_size))) { 2776a62bec0SDavid C Somayajulu rval = ENXIO; 2786a62bec0SDavid C Somayajulu break; 2796a62bec0SDavid C Somayajulu } 2806a62bec0SDavid C Somayajulu 2816a62bec0SDavid C Somayajulu if ((rval = copyout(ha->hw.mdump_buffer, 2826a62bec0SDavid C Somayajulu ((uint8_t *)fw_dump->minidump + 2836a62bec0SDavid C Somayajulu ha->hw.mdump_template_size), 2846a62bec0SDavid C Somayajulu ha->hw.mdump_buffer_size))) 285f10a77bbSDavid C Somayajulu rval = ENXIO; 286f10a77bbSDavid C Somayajulu break; 287f10a77bbSDavid C Somayajulu 288ab142b3fSDavid C Somayajulu case QLA_RD_DRVR_STATE: 289ab142b3fSDavid C Somayajulu rval = ql_drvr_state(ha, (qla_driver_state_t *)data); 290ab142b3fSDavid C Somayajulu break; 291ab142b3fSDavid C Somayajulu 292f10a77bbSDavid C Somayajulu case QLA_RD_PCI_IDS: 293f10a77bbSDavid C Somayajulu pci_ids = (qla_rd_pci_ids_t *)data; 294f10a77bbSDavid C Somayajulu pci_ids->ven_id = pci_get_vendor(pci_dev); 295f10a77bbSDavid C Somayajulu pci_ids->dev_id = pci_get_device(pci_dev); 296f10a77bbSDavid C Somayajulu pci_ids->subsys_ven_id = pci_get_subvendor(pci_dev); 297f10a77bbSDavid C Somayajulu pci_ids->subsys_dev_id = pci_get_subdevice(pci_dev); 298f10a77bbSDavid C Somayajulu pci_ids->rev_id = pci_read_config(pci_dev, PCIR_REVID, 1); 299f10a77bbSDavid C Somayajulu break; 300f10a77bbSDavid C Somayajulu 301f10a77bbSDavid C Somayajulu default: 302f10a77bbSDavid C Somayajulu break; 303f10a77bbSDavid C Somayajulu } 304f10a77bbSDavid C Somayajulu 305f10a77bbSDavid C Somayajulu return rval; 306f10a77bbSDavid C Somayajulu } 307f10a77bbSDavid C Somayajulu 308ab142b3fSDavid C Somayajulu 309ab142b3fSDavid C Somayajulu static int 310ab142b3fSDavid C Somayajulu ql_drvr_state(qla_host_t *ha, qla_driver_state_t *state) 311ab142b3fSDavid C Somayajulu { 312ab142b3fSDavid C Somayajulu int rval = 0; 313ab142b3fSDavid C Somayajulu uint32_t drvr_state_size; 314ab142b3fSDavid C Somayajulu qla_drvr_state_hdr_t *hdr; 315ab142b3fSDavid C Somayajulu 316ab142b3fSDavid C Somayajulu drvr_state_size = ql_drvr_state_size(ha); 317ab142b3fSDavid C Somayajulu 318ab142b3fSDavid C Somayajulu if (state->buffer == NULL) { 319ab142b3fSDavid C Somayajulu state->size = drvr_state_size; 320ab142b3fSDavid C Somayajulu return (0); 321ab142b3fSDavid C Somayajulu } 322ab142b3fSDavid C Somayajulu 323ab142b3fSDavid C Somayajulu if (state->size < drvr_state_size) 324ab142b3fSDavid C Somayajulu return (ENXIO); 325ab142b3fSDavid C Somayajulu 326ab142b3fSDavid C Somayajulu if (ha->hw.drvr_state == NULL) 327ab142b3fSDavid C Somayajulu return (ENOMEM); 328ab142b3fSDavid C Somayajulu 329ab142b3fSDavid C Somayajulu hdr = ha->hw.drvr_state; 330ab142b3fSDavid C Somayajulu 331ab142b3fSDavid C Somayajulu if (!hdr->drvr_version_major) 332ab142b3fSDavid C Somayajulu ql_capture_drvr_state(ha); 333ab142b3fSDavid C Somayajulu 334ab142b3fSDavid C Somayajulu rval = copyout(ha->hw.drvr_state, state->buffer, drvr_state_size); 335ab142b3fSDavid C Somayajulu 336ab142b3fSDavid C Somayajulu bzero(ha->hw.drvr_state, drvr_state_size); 337ab142b3fSDavid C Somayajulu 338ab142b3fSDavid C Somayajulu return (rval); 339ab142b3fSDavid C Somayajulu } 340ab142b3fSDavid C Somayajulu 341ab142b3fSDavid C Somayajulu static uint32_t 342ab142b3fSDavid C Somayajulu ql_drvr_state_size(qla_host_t *ha) 343ab142b3fSDavid C Somayajulu { 344ab142b3fSDavid C Somayajulu uint32_t drvr_state_size; 345ab142b3fSDavid C Somayajulu uint32_t size; 346ab142b3fSDavid C Somayajulu 347ab142b3fSDavid C Somayajulu size = sizeof (qla_drvr_state_hdr_t); 348ab142b3fSDavid C Somayajulu drvr_state_size = QL_ALIGN(size, 64); 349ab142b3fSDavid C Somayajulu 350ab142b3fSDavid C Somayajulu size = ha->hw.num_tx_rings * (sizeof (qla_drvr_state_tx_t)); 351ab142b3fSDavid C Somayajulu drvr_state_size += QL_ALIGN(size, 64); 352ab142b3fSDavid C Somayajulu 353ab142b3fSDavid C Somayajulu size = ha->hw.num_rds_rings * (sizeof (qla_drvr_state_rx_t)); 354ab142b3fSDavid C Somayajulu drvr_state_size += QL_ALIGN(size, 64); 355ab142b3fSDavid C Somayajulu 356ab142b3fSDavid C Somayajulu size = ha->hw.num_sds_rings * (sizeof (qla_drvr_state_sds_t)); 357ab142b3fSDavid C Somayajulu drvr_state_size += QL_ALIGN(size, 64); 358ab142b3fSDavid C Somayajulu 359ab142b3fSDavid C Somayajulu size = sizeof(q80_tx_cmd_t) * NUM_TX_DESCRIPTORS * ha->hw.num_tx_rings; 360ab142b3fSDavid C Somayajulu drvr_state_size += QL_ALIGN(size, 64); 361ab142b3fSDavid C Somayajulu 362ab142b3fSDavid C Somayajulu size = sizeof(q80_recv_desc_t) * NUM_RX_DESCRIPTORS * ha->hw.num_rds_rings; 363ab142b3fSDavid C Somayajulu drvr_state_size += QL_ALIGN(size, 64); 364ab142b3fSDavid C Somayajulu 365ab142b3fSDavid C Somayajulu size = sizeof(q80_stat_desc_t) * NUM_STATUS_DESCRIPTORS * 366ab142b3fSDavid C Somayajulu ha->hw.num_sds_rings; 367ab142b3fSDavid C Somayajulu drvr_state_size += QL_ALIGN(size, 64); 368ab142b3fSDavid C Somayajulu 369ab142b3fSDavid C Somayajulu return (drvr_state_size); 370ab142b3fSDavid C Somayajulu } 371ab142b3fSDavid C Somayajulu 372ab142b3fSDavid C Somayajulu static void 373ab142b3fSDavid C Somayajulu ql_get_tx_state(qla_host_t *ha, qla_drvr_state_tx_t *tx_state) 374ab142b3fSDavid C Somayajulu { 375ab142b3fSDavid C Somayajulu int i; 376ab142b3fSDavid C Somayajulu 377ab142b3fSDavid C Somayajulu for (i = 0; i < ha->hw.num_tx_rings; i++) { 378ab142b3fSDavid C Somayajulu tx_state->base_p_addr = ha->hw.tx_cntxt[i].tx_ring_paddr; 379ab142b3fSDavid C Somayajulu tx_state->cons_p_addr = ha->hw.tx_cntxt[i].tx_cons_paddr; 380ab142b3fSDavid C Somayajulu tx_state->tx_prod_reg = ha->hw.tx_cntxt[i].tx_prod_reg; 381ab142b3fSDavid C Somayajulu tx_state->tx_cntxt_id = ha->hw.tx_cntxt[i].tx_cntxt_id; 382ab142b3fSDavid C Somayajulu tx_state->txr_free = ha->hw.tx_cntxt[i].txr_free; 383ab142b3fSDavid C Somayajulu tx_state->txr_next = ha->hw.tx_cntxt[i].txr_next; 384ab142b3fSDavid C Somayajulu tx_state->txr_comp = ha->hw.tx_cntxt[i].txr_comp; 385ab142b3fSDavid C Somayajulu tx_state++; 386ab142b3fSDavid C Somayajulu } 387ab142b3fSDavid C Somayajulu return; 388ab142b3fSDavid C Somayajulu } 389ab142b3fSDavid C Somayajulu 390ab142b3fSDavid C Somayajulu static void 391ab142b3fSDavid C Somayajulu ql_get_rx_state(qla_host_t *ha, qla_drvr_state_rx_t *rx_state) 392ab142b3fSDavid C Somayajulu { 393ab142b3fSDavid C Somayajulu int i; 394ab142b3fSDavid C Somayajulu 395ab142b3fSDavid C Somayajulu for (i = 0; i < ha->hw.num_rds_rings; i++) { 396ab142b3fSDavid C Somayajulu rx_state->prod_std = ha->hw.rds[i].prod_std; 397ab142b3fSDavid C Somayajulu rx_state->rx_next = ha->hw.rds[i].rx_next; 398ab142b3fSDavid C Somayajulu rx_state++; 399ab142b3fSDavid C Somayajulu } 400ab142b3fSDavid C Somayajulu return; 401ab142b3fSDavid C Somayajulu } 402ab142b3fSDavid C Somayajulu 403ab142b3fSDavid C Somayajulu static void 404ab142b3fSDavid C Somayajulu ql_get_sds_state(qla_host_t *ha, qla_drvr_state_sds_t *sds_state) 405ab142b3fSDavid C Somayajulu { 406ab142b3fSDavid C Somayajulu int i; 407ab142b3fSDavid C Somayajulu 408ab142b3fSDavid C Somayajulu for (i = 0; i < ha->hw.num_sds_rings; i++) { 409ab142b3fSDavid C Somayajulu sds_state->sdsr_next = ha->hw.sds[i].sdsr_next; 410ab142b3fSDavid C Somayajulu sds_state->sds_consumer = ha->hw.sds[i].sds_consumer; 411ab142b3fSDavid C Somayajulu sds_state++; 412ab142b3fSDavid C Somayajulu } 413ab142b3fSDavid C Somayajulu return; 414ab142b3fSDavid C Somayajulu } 415ab142b3fSDavid C Somayajulu 416ab142b3fSDavid C Somayajulu void 417ab142b3fSDavid C Somayajulu ql_capture_drvr_state(qla_host_t *ha) 418ab142b3fSDavid C Somayajulu { 419ab142b3fSDavid C Somayajulu uint8_t *state_buffer; 420ab142b3fSDavid C Somayajulu uint8_t *ptr; 421ab142b3fSDavid C Somayajulu uint32_t drvr_state_size; 422ab142b3fSDavid C Somayajulu qla_drvr_state_hdr_t *hdr; 423ab142b3fSDavid C Somayajulu uint32_t size; 424ab142b3fSDavid C Somayajulu int i; 425ab142b3fSDavid C Somayajulu 426ab142b3fSDavid C Somayajulu drvr_state_size = ql_drvr_state_size(ha); 427ab142b3fSDavid C Somayajulu 428ab142b3fSDavid C Somayajulu state_buffer = ha->hw.drvr_state; 429ab142b3fSDavid C Somayajulu 430ab142b3fSDavid C Somayajulu if (state_buffer == NULL) 431ab142b3fSDavid C Somayajulu return; 432ab142b3fSDavid C Somayajulu 433ab142b3fSDavid C Somayajulu bzero(state_buffer, drvr_state_size); 434ab142b3fSDavid C Somayajulu 435ab142b3fSDavid C Somayajulu hdr = (qla_drvr_state_hdr_t *)state_buffer; 436ab142b3fSDavid C Somayajulu 437ab142b3fSDavid C Somayajulu hdr->drvr_version_major = QLA_VERSION_MAJOR; 438ab142b3fSDavid C Somayajulu hdr->drvr_version_minor = QLA_VERSION_MINOR; 439ab142b3fSDavid C Somayajulu hdr->drvr_version_build = QLA_VERSION_BUILD; 440ab142b3fSDavid C Somayajulu 441ab142b3fSDavid C Somayajulu bcopy(ha->hw.mac_addr, hdr->mac_addr, ETHER_ADDR_LEN); 442ab142b3fSDavid C Somayajulu 443ab142b3fSDavid C Somayajulu hdr->link_speed = ha->hw.link_speed; 444ab142b3fSDavid C Somayajulu hdr->cable_length = ha->hw.cable_length; 445ab142b3fSDavid C Somayajulu hdr->cable_oui = ha->hw.cable_oui; 446ab142b3fSDavid C Somayajulu hdr->link_up = ha->hw.link_up; 447ab142b3fSDavid C Somayajulu hdr->module_type = ha->hw.module_type; 448ab142b3fSDavid C Somayajulu hdr->link_faults = ha->hw.link_faults; 449ab142b3fSDavid C Somayajulu hdr->rcv_intr_coalesce = ha->hw.rcv_intr_coalesce; 450ab142b3fSDavid C Somayajulu hdr->xmt_intr_coalesce = ha->hw.xmt_intr_coalesce; 451ab142b3fSDavid C Somayajulu 452ab142b3fSDavid C Somayajulu size = sizeof (qla_drvr_state_hdr_t); 453ab142b3fSDavid C Somayajulu hdr->tx_state_offset = QL_ALIGN(size, 64); 454ab142b3fSDavid C Somayajulu 455ab142b3fSDavid C Somayajulu ptr = state_buffer + hdr->tx_state_offset; 456ab142b3fSDavid C Somayajulu 457ab142b3fSDavid C Somayajulu ql_get_tx_state(ha, (qla_drvr_state_tx_t *)ptr); 458ab142b3fSDavid C Somayajulu 459ab142b3fSDavid C Somayajulu size = ha->hw.num_tx_rings * (sizeof (qla_drvr_state_tx_t)); 460ab142b3fSDavid C Somayajulu hdr->rx_state_offset = hdr->tx_state_offset + QL_ALIGN(size, 64); 461ab142b3fSDavid C Somayajulu ptr = state_buffer + hdr->rx_state_offset; 462ab142b3fSDavid C Somayajulu 463ab142b3fSDavid C Somayajulu ql_get_rx_state(ha, (qla_drvr_state_rx_t *)ptr); 464ab142b3fSDavid C Somayajulu 465ab142b3fSDavid C Somayajulu size = ha->hw.num_rds_rings * (sizeof (qla_drvr_state_rx_t)); 466ab142b3fSDavid C Somayajulu hdr->sds_state_offset = hdr->rx_state_offset + QL_ALIGN(size, 64); 467ab142b3fSDavid C Somayajulu ptr = state_buffer + hdr->sds_state_offset; 468ab142b3fSDavid C Somayajulu 469ab142b3fSDavid C Somayajulu ql_get_sds_state(ha, (qla_drvr_state_sds_t *)ptr); 470ab142b3fSDavid C Somayajulu 471ab142b3fSDavid C Somayajulu size = ha->hw.num_sds_rings * (sizeof (qla_drvr_state_sds_t)); 472ab142b3fSDavid C Somayajulu hdr->txr_offset = hdr->sds_state_offset + QL_ALIGN(size, 64); 473ab142b3fSDavid C Somayajulu ptr = state_buffer + hdr->txr_offset; 474ab142b3fSDavid C Somayajulu 475ab142b3fSDavid C Somayajulu hdr->num_tx_rings = ha->hw.num_tx_rings; 476ab142b3fSDavid C Somayajulu hdr->txr_size = sizeof(q80_tx_cmd_t) * NUM_TX_DESCRIPTORS; 477ab142b3fSDavid C Somayajulu hdr->txr_entries = NUM_TX_DESCRIPTORS; 478ab142b3fSDavid C Somayajulu 479ab142b3fSDavid C Somayajulu size = hdr->num_tx_rings * hdr->txr_size; 480ab142b3fSDavid C Somayajulu bcopy(ha->hw.dma_buf.tx_ring.dma_b, ptr, size); 481ab142b3fSDavid C Somayajulu 482ab142b3fSDavid C Somayajulu hdr->rxr_offset = hdr->txr_offset + QL_ALIGN(size, 64); 483ab142b3fSDavid C Somayajulu ptr = state_buffer + hdr->rxr_offset; 484ab142b3fSDavid C Somayajulu 485ab142b3fSDavid C Somayajulu hdr->rxr_size = sizeof(q80_recv_desc_t) * NUM_RX_DESCRIPTORS; 486ab142b3fSDavid C Somayajulu hdr->rxr_entries = NUM_RX_DESCRIPTORS; 487ab142b3fSDavid C Somayajulu hdr->num_rx_rings = ha->hw.num_rds_rings; 488ab142b3fSDavid C Somayajulu 489ab142b3fSDavid C Somayajulu for (i = 0; i < ha->hw.num_rds_rings; i++) { 490ab142b3fSDavid C Somayajulu bcopy(ha->hw.dma_buf.rds_ring[i].dma_b, ptr, hdr->rxr_size); 491ab142b3fSDavid C Somayajulu ptr += hdr->rxr_size; 492ab142b3fSDavid C Somayajulu } 493ab142b3fSDavid C Somayajulu 494ab142b3fSDavid C Somayajulu size = hdr->rxr_size * hdr->num_rx_rings; 495ab142b3fSDavid C Somayajulu hdr->sds_offset = hdr->rxr_offset + QL_ALIGN(size, 64); 496ab142b3fSDavid C Somayajulu hdr->sds_ring_size = sizeof(q80_stat_desc_t) * NUM_STATUS_DESCRIPTORS; 497ab142b3fSDavid C Somayajulu hdr->sds_entries = NUM_STATUS_DESCRIPTORS; 498ab142b3fSDavid C Somayajulu hdr->num_sds_rings = ha->hw.num_sds_rings; 499ab142b3fSDavid C Somayajulu 500ab142b3fSDavid C Somayajulu ptr = state_buffer + hdr->sds_offset; 501ab142b3fSDavid C Somayajulu for (i = 0; i < ha->hw.num_sds_rings; i++) { 502ab142b3fSDavid C Somayajulu bcopy(ha->hw.dma_buf.sds_ring[i].dma_b, ptr, hdr->sds_ring_size); 503ab142b3fSDavid C Somayajulu ptr += hdr->sds_ring_size; 504ab142b3fSDavid C Somayajulu } 505ab142b3fSDavid C Somayajulu return; 506ab142b3fSDavid C Somayajulu } 507ab142b3fSDavid C Somayajulu 508ab142b3fSDavid C Somayajulu void 509ab142b3fSDavid C Somayajulu ql_alloc_drvr_state_buffer(qla_host_t *ha) 510ab142b3fSDavid C Somayajulu { 511ab142b3fSDavid C Somayajulu uint32_t drvr_state_size; 512ab142b3fSDavid C Somayajulu 513ab142b3fSDavid C Somayajulu drvr_state_size = ql_drvr_state_size(ha); 514ab142b3fSDavid C Somayajulu 515ab142b3fSDavid C Somayajulu ha->hw.drvr_state = malloc(drvr_state_size, M_QLA83XXBUF, M_NOWAIT); 516ab142b3fSDavid C Somayajulu 517ab142b3fSDavid C Somayajulu return; 518ab142b3fSDavid C Somayajulu } 519ab142b3fSDavid C Somayajulu 520ab142b3fSDavid C Somayajulu void 521ab142b3fSDavid C Somayajulu ql_free_drvr_state_buffer(qla_host_t *ha) 522ab142b3fSDavid C Somayajulu { 523ab142b3fSDavid C Somayajulu if (ha->hw.drvr_state != NULL) 524ab142b3fSDavid C Somayajulu free(ha->hw.drvr_state, M_QLA83XXBUF); 525ab142b3fSDavid C Somayajulu return; 526ab142b3fSDavid C Somayajulu } 527ab142b3fSDavid C Somayajulu 528