1316485Sdavidcs/* 2316485Sdavidcs * Copyright (c) 2017-2018 Cavium, Inc. 3316485Sdavidcs * All rights reserved. 4316485Sdavidcs * 5316485Sdavidcs * Redistribution and use in source and binary forms, with or without 6316485Sdavidcs * modification, are permitted provided that the following conditions 7316485Sdavidcs * are met: 8316485Sdavidcs * 9316485Sdavidcs * 1. Redistributions of source code must retain the above copyright 10316485Sdavidcs * notice, this list of conditions and the following disclaimer. 11316485Sdavidcs * 2. Redistributions in binary form must reproduce the above copyright 12316485Sdavidcs * notice, this list of conditions and the following disclaimer in the 13316485Sdavidcs * documentation and/or other materials provided with the distribution. 14316485Sdavidcs * 15316485Sdavidcs * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16316485Sdavidcs * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17316485Sdavidcs * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18316485Sdavidcs * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 19316485Sdavidcs * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20316485Sdavidcs * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21316485Sdavidcs * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22316485Sdavidcs * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23316485Sdavidcs * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24316485Sdavidcs * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25316485Sdavidcs * POSSIBILITY OF SUCH DAMAGE. 26316485Sdavidcs */ 27316485Sdavidcs 28316485Sdavidcs 29316485Sdavidcs/* 30316485Sdavidcs * File: qlnx_ioctl.c 31316485Sdavidcs * Author : David C Somayajulu, Qlogic Corporation, Aliso Viejo, CA 92656. 32316485Sdavidcs */ 33316485Sdavidcs 34316485Sdavidcs#include <sys/cdefs.h> 35316485Sdavidcs__FBSDID("$FreeBSD: stable/10/sys/dev/qlnx/qlnxe/qlnx_ioctl.c 337519 2018-08-09 01:39:47Z davidcs $"); 36316485Sdavidcs 37316485Sdavidcs#include "qlnx_os.h" 38316485Sdavidcs#include "bcm_osal.h" 39316485Sdavidcs 40316485Sdavidcs#include "reg_addr.h" 41316485Sdavidcs#include "ecore_gtt_reg_addr.h" 42316485Sdavidcs#include "ecore.h" 43316485Sdavidcs#include "ecore_chain.h" 44316485Sdavidcs#include "ecore_status.h" 45316485Sdavidcs#include "ecore_hw.h" 46316485Sdavidcs#include "ecore_rt_defs.h" 47316485Sdavidcs#include "ecore_init_ops.h" 48316485Sdavidcs#include "ecore_int.h" 49316485Sdavidcs#include "ecore_cxt.h" 50316485Sdavidcs#include "ecore_spq.h" 51316485Sdavidcs#include "ecore_init_fw_funcs.h" 52316485Sdavidcs#include "ecore_sp_commands.h" 53316485Sdavidcs#include "ecore_dev_api.h" 54316485Sdavidcs#include "ecore_l2_api.h" 55316485Sdavidcs#include "ecore_mcp.h" 56316485Sdavidcs#include "ecore_hw_defs.h" 57316485Sdavidcs#include "mcp_public.h" 58316485Sdavidcs#include "ecore_iro.h" 59316485Sdavidcs#include "nvm_cfg.h" 60316485Sdavidcs#include "ecore_dev_api.h" 61316485Sdavidcs#include "ecore_dbg_fw_funcs.h" 62337519Sdavidcs#include "ecore_dcbx_api.h" 63316485Sdavidcs 64316485Sdavidcs#include "qlnx_ioctl.h" 65316485Sdavidcs#include "qlnx_def.h" 66316485Sdavidcs#include "qlnx_ver.h" 67316485Sdavidcs#include <sys/smp.h> 68316485Sdavidcs 69316485Sdavidcs 70316485Sdavidcsstatic int qlnx_eioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag, 71316485Sdavidcs struct thread *td); 72316485Sdavidcs 73316485Sdavidcsstatic struct cdevsw qlnx_cdevsw = { 74316485Sdavidcs .d_version = D_VERSION, 75316485Sdavidcs .d_ioctl = qlnx_eioctl, 76316485Sdavidcs .d_name = "qlnxioctl", 77316485Sdavidcs}; 78316485Sdavidcs 79316485Sdavidcsint 80316485Sdavidcsqlnx_make_cdev(qlnx_host_t *ha) 81316485Sdavidcs{ 82316485Sdavidcs ha->ioctl_dev = make_dev(&qlnx_cdevsw, 83316485Sdavidcs ha->ifp->if_dunit, 84316485Sdavidcs UID_ROOT, 85316485Sdavidcs GID_WHEEL, 86316485Sdavidcs 0600, 87316485Sdavidcs "%s", 88316485Sdavidcs if_name(ha->ifp)); 89316485Sdavidcs 90316485Sdavidcs if (ha->ioctl_dev == NULL) 91316485Sdavidcs return (-1); 92316485Sdavidcs 93316485Sdavidcs ha->ioctl_dev->si_drv1 = ha; 94316485Sdavidcs 95316485Sdavidcs return (0); 96316485Sdavidcs} 97316485Sdavidcs 98316485Sdavidcsvoid 99316485Sdavidcsqlnx_del_cdev(qlnx_host_t *ha) 100316485Sdavidcs{ 101316485Sdavidcs if (ha->ioctl_dev != NULL) 102316485Sdavidcs destroy_dev(ha->ioctl_dev); 103316485Sdavidcs return; 104316485Sdavidcs} 105316485Sdavidcs 106316485Sdavidcsint 107316485Sdavidcsqlnx_grc_dump(qlnx_host_t *ha, uint32_t *num_dumped_dwords, int hwfn_index) 108316485Sdavidcs{ 109316485Sdavidcs int rval = EINVAL; 110316485Sdavidcs struct ecore_hwfn *p_hwfn; 111316485Sdavidcs struct ecore_ptt *p_ptt; 112316485Sdavidcs 113316485Sdavidcs if (ha->grcdump_dwords[hwfn_index]) { 114316485Sdavidcs /* the grcdump is already available */ 115316485Sdavidcs *num_dumped_dwords = ha->grcdump_dwords[hwfn_index]; 116316485Sdavidcs return (0); 117316485Sdavidcs } 118316485Sdavidcs 119316485Sdavidcs ecore_dbg_set_app_ver(ecore_dbg_get_fw_func_ver()); 120316485Sdavidcs 121316485Sdavidcs p_hwfn = &ha->cdev.hwfns[hwfn_index]; 122316485Sdavidcs p_ptt = ecore_ptt_acquire(p_hwfn); 123316485Sdavidcs 124316485Sdavidcs if (!p_ptt) { 125318662Sdavidcs QL_DPRINT1(ha,"ecore_ptt_acquire failed\n"); 126316485Sdavidcs return (rval); 127316485Sdavidcs } 128316485Sdavidcs 129316485Sdavidcs if ((rval = ecore_dbg_grc_dump(p_hwfn, p_ptt, 130316485Sdavidcs ha->grcdump[hwfn_index], 131316485Sdavidcs (ha->grcdump_size[hwfn_index] >> 2), 132316485Sdavidcs num_dumped_dwords)) == DBG_STATUS_OK) { 133316485Sdavidcs rval = 0; 134316485Sdavidcs ha->grcdump_taken = 1; 135316485Sdavidcs } else 136318662Sdavidcs QL_DPRINT1(ha,"ecore_dbg_grc_dump failed [%d, 0x%x]\n", 137318662Sdavidcs hwfn_index, rval); 138316485Sdavidcs 139316485Sdavidcs ecore_ptt_release(p_hwfn, p_ptt); 140316485Sdavidcs 141316485Sdavidcs return (rval); 142316485Sdavidcs} 143316485Sdavidcs 144316485Sdavidcsstatic void 145316485Sdavidcsqlnx_get_grc_dump_size(qlnx_host_t *ha, qlnx_grcdump_t *grcdump) 146316485Sdavidcs{ 147316485Sdavidcs int i; 148316485Sdavidcs 149316485Sdavidcs grcdump->pci_func = ha->pci_func; 150316485Sdavidcs 151316485Sdavidcs for (i = 0; i < ha->cdev.num_hwfns; i++) 152316485Sdavidcs grcdump->grcdump_size[i] = ha->grcdump_size[i]; 153316485Sdavidcs 154316485Sdavidcs return; 155316485Sdavidcs} 156316485Sdavidcs 157316485Sdavidcsstatic int 158316485Sdavidcsqlnx_get_grc_dump(qlnx_host_t *ha, qlnx_grcdump_t *grcdump) 159316485Sdavidcs{ 160316485Sdavidcs int i; 161316485Sdavidcs int rval = 0; 162316485Sdavidcs uint32_t dwords = 0; 163316485Sdavidcs 164316485Sdavidcs grcdump->pci_func = ha->pci_func; 165316485Sdavidcs 166316485Sdavidcs for (i = 0; i < ha->cdev.num_hwfns; i++) { 167316485Sdavidcs 168316485Sdavidcs if ((ha->grcdump[i] == NULL) || (grcdump->grcdump[i] == NULL) || 169316485Sdavidcs (grcdump->grcdump_size[i] < ha->grcdump_size[i])) 170316485Sdavidcs return (EINVAL); 171316485Sdavidcs 172316485Sdavidcs rval = qlnx_grc_dump(ha, &dwords, i); 173316485Sdavidcs 174316485Sdavidcs if (rval) 175316485Sdavidcs break; 176316485Sdavidcs 177316485Sdavidcs grcdump->grcdump_dwords[i] = dwords; 178316485Sdavidcs 179318662Sdavidcs QL_DPRINT1(ha,"grcdump_dwords[%d] = 0x%x\n", i, dwords); 180316485Sdavidcs 181316485Sdavidcs rval = copyout(ha->grcdump[i], grcdump->grcdump[i], 182316485Sdavidcs ha->grcdump_size[i]); 183316485Sdavidcs 184316485Sdavidcs if (rval) 185316485Sdavidcs break; 186316485Sdavidcs 187316485Sdavidcs ha->grcdump_dwords[i] = 0; 188316485Sdavidcs } 189316485Sdavidcs 190316485Sdavidcs ha->grcdump_taken = 0; 191316485Sdavidcs 192316485Sdavidcs return (rval); 193316485Sdavidcs} 194316485Sdavidcs 195316485Sdavidcsint 196316485Sdavidcsqlnx_idle_chk(qlnx_host_t *ha, uint32_t *num_dumped_dwords, int hwfn_index) 197316485Sdavidcs{ 198316485Sdavidcs int rval = EINVAL; 199316485Sdavidcs struct ecore_hwfn *p_hwfn; 200316485Sdavidcs struct ecore_ptt *p_ptt; 201316485Sdavidcs 202316485Sdavidcs if (ha->idle_chk_dwords[hwfn_index]) { 203316485Sdavidcs /* the idle check is already available */ 204316485Sdavidcs *num_dumped_dwords = ha->idle_chk_dwords[hwfn_index]; 205316485Sdavidcs return (0); 206316485Sdavidcs } 207316485Sdavidcs 208316485Sdavidcs ecore_dbg_set_app_ver(ecore_dbg_get_fw_func_ver()); 209316485Sdavidcs 210316485Sdavidcs p_hwfn = &ha->cdev.hwfns[hwfn_index]; 211316485Sdavidcs p_ptt = ecore_ptt_acquire(p_hwfn); 212316485Sdavidcs 213316485Sdavidcs if (!p_ptt) { 214318662Sdavidcs QL_DPRINT1(ha,"ecore_ptt_acquire failed\n"); 215316485Sdavidcs return (rval); 216316485Sdavidcs } 217316485Sdavidcs 218316485Sdavidcs if ((rval = ecore_dbg_idle_chk_dump(p_hwfn, p_ptt, 219316485Sdavidcs ha->idle_chk[hwfn_index], 220316485Sdavidcs (ha->idle_chk_size[hwfn_index] >> 2), 221316485Sdavidcs num_dumped_dwords)) == DBG_STATUS_OK) { 222316485Sdavidcs rval = 0; 223316485Sdavidcs ha->idle_chk_taken = 1; 224316485Sdavidcs } else 225318662Sdavidcs QL_DPRINT1(ha,"ecore_dbg_idle_chk_dump failed [%d, 0x%x]\n", 226318662Sdavidcs hwfn_index, rval); 227316485Sdavidcs 228316485Sdavidcs ecore_ptt_release(p_hwfn, p_ptt); 229316485Sdavidcs 230316485Sdavidcs return (rval); 231316485Sdavidcs} 232316485Sdavidcs 233316485Sdavidcsstatic void 234316485Sdavidcsqlnx_get_idle_chk_size(qlnx_host_t *ha, qlnx_idle_chk_t *idle_chk) 235316485Sdavidcs{ 236316485Sdavidcs int i; 237316485Sdavidcs 238316485Sdavidcs idle_chk->pci_func = ha->pci_func; 239316485Sdavidcs 240316485Sdavidcs for (i = 0; i < ha->cdev.num_hwfns; i++) 241316485Sdavidcs idle_chk->idle_chk_size[i] = ha->idle_chk_size[i]; 242316485Sdavidcs 243316485Sdavidcs return; 244316485Sdavidcs} 245316485Sdavidcs 246316485Sdavidcsstatic int 247316485Sdavidcsqlnx_get_idle_chk(qlnx_host_t *ha, qlnx_idle_chk_t *idle_chk) 248316485Sdavidcs{ 249316485Sdavidcs int i; 250316485Sdavidcs int rval = 0; 251316485Sdavidcs uint32_t dwords = 0; 252316485Sdavidcs 253316485Sdavidcs idle_chk->pci_func = ha->pci_func; 254316485Sdavidcs 255316485Sdavidcs for (i = 0; i < ha->cdev.num_hwfns; i++) { 256316485Sdavidcs 257316485Sdavidcs if ((ha->idle_chk[i] == NULL) || 258316485Sdavidcs (idle_chk->idle_chk[i] == NULL) || 259316485Sdavidcs (idle_chk->idle_chk_size[i] < 260316485Sdavidcs ha->idle_chk_size[i])) 261316485Sdavidcs return (EINVAL); 262316485Sdavidcs 263316485Sdavidcs rval = qlnx_idle_chk(ha, &dwords, i); 264316485Sdavidcs 265316485Sdavidcs if (rval) 266316485Sdavidcs break; 267316485Sdavidcs 268316485Sdavidcs idle_chk->idle_chk_dwords[i] = dwords; 269316485Sdavidcs 270318662Sdavidcs QL_DPRINT1(ha,"idle_chk_dwords[%d] = 0x%x\n", i, dwords); 271316485Sdavidcs 272316485Sdavidcs rval = copyout(ha->idle_chk[i], idle_chk->idle_chk[i], 273316485Sdavidcs ha->idle_chk_size[i]); 274316485Sdavidcs 275316485Sdavidcs if (rval) 276316485Sdavidcs break; 277316485Sdavidcs 278316485Sdavidcs ha->idle_chk_dwords[i] = 0; 279316485Sdavidcs } 280316485Sdavidcs ha->idle_chk_taken = 0; 281316485Sdavidcs 282316485Sdavidcs return (rval); 283316485Sdavidcs} 284316485Sdavidcs 285316485Sdavidcsstatic uint32_t 286316485Sdavidcsqlnx_get_trace_cmd_size(qlnx_host_t *ha, int hwfn_index, uint16_t cmd) 287316485Sdavidcs{ 288316485Sdavidcs int rval = -1; 289316485Sdavidcs struct ecore_hwfn *p_hwfn; 290316485Sdavidcs struct ecore_ptt *p_ptt; 291316485Sdavidcs uint32_t num_dwords = 0; 292316485Sdavidcs 293316485Sdavidcs p_hwfn = &ha->cdev.hwfns[hwfn_index]; 294316485Sdavidcs p_ptt = ecore_ptt_acquire(p_hwfn); 295316485Sdavidcs 296316485Sdavidcs if (!p_ptt) { 297318662Sdavidcs QL_DPRINT1(ha, "ecore_ptt_acquire [%d, 0x%x]failed\n", 298318662Sdavidcs hwfn_index, cmd); 299316485Sdavidcs return (0); 300316485Sdavidcs } 301316485Sdavidcs 302316485Sdavidcs switch (cmd) { 303316485Sdavidcs 304316485Sdavidcs case QLNX_MCP_TRACE: 305316485Sdavidcs rval = ecore_dbg_mcp_trace_get_dump_buf_size(p_hwfn, 306316485Sdavidcs p_ptt, &num_dwords); 307316485Sdavidcs break; 308316485Sdavidcs 309316485Sdavidcs case QLNX_REG_FIFO: 310316485Sdavidcs rval = ecore_dbg_reg_fifo_get_dump_buf_size(p_hwfn, 311316485Sdavidcs p_ptt, &num_dwords); 312316485Sdavidcs break; 313316485Sdavidcs 314316485Sdavidcs case QLNX_IGU_FIFO: 315316485Sdavidcs rval = ecore_dbg_igu_fifo_get_dump_buf_size(p_hwfn, 316316485Sdavidcs p_ptt, &num_dwords); 317316485Sdavidcs break; 318316485Sdavidcs 319316485Sdavidcs case QLNX_PROTECTION_OVERRIDE: 320316485Sdavidcs rval = ecore_dbg_protection_override_get_dump_buf_size(p_hwfn, 321316485Sdavidcs p_ptt, &num_dwords); 322316485Sdavidcs break; 323316485Sdavidcs 324316485Sdavidcs case QLNX_FW_ASSERTS: 325316485Sdavidcs rval = ecore_dbg_fw_asserts_get_dump_buf_size(p_hwfn, 326316485Sdavidcs p_ptt, &num_dwords); 327316485Sdavidcs break; 328316485Sdavidcs } 329316485Sdavidcs 330316485Sdavidcs if (rval != DBG_STATUS_OK) { 331318662Sdavidcs QL_DPRINT1(ha,"cmd = 0x%x failed [0x%x]\n", cmd, rval); 332316485Sdavidcs num_dwords = 0; 333316485Sdavidcs } 334316485Sdavidcs 335316485Sdavidcs ecore_ptt_release(p_hwfn, p_ptt); 336316485Sdavidcs 337316485Sdavidcs return ((num_dwords * sizeof (uint32_t))); 338316485Sdavidcs} 339316485Sdavidcs 340316485Sdavidcsstatic void 341316485Sdavidcsqlnx_get_trace_size(qlnx_host_t *ha, qlnx_trace_t *trace) 342316485Sdavidcs{ 343316485Sdavidcs int i; 344316485Sdavidcs 345316485Sdavidcs trace->pci_func = ha->pci_func; 346316485Sdavidcs 347316485Sdavidcs for (i = 0; i < ha->cdev.num_hwfns; i++) { 348316485Sdavidcs trace->size[i] = qlnx_get_trace_cmd_size(ha, i, trace->cmd); 349316485Sdavidcs } 350316485Sdavidcs 351316485Sdavidcs return; 352316485Sdavidcs} 353316485Sdavidcs 354316485Sdavidcsstatic int 355316485Sdavidcsqlnx_get_trace(qlnx_host_t *ha, int hwfn_index, qlnx_trace_t *trace) 356316485Sdavidcs{ 357316485Sdavidcs int rval = -1; 358316485Sdavidcs struct ecore_hwfn *p_hwfn; 359316485Sdavidcs struct ecore_ptt *p_ptt; 360316485Sdavidcs uint32_t num_dwords = 0; 361316485Sdavidcs void *buffer; 362316485Sdavidcs 363316485Sdavidcs buffer = qlnx_zalloc(trace->size[hwfn_index]); 364316485Sdavidcs if (buffer == NULL) { 365318662Sdavidcs QL_DPRINT1(ha,"qlnx_zalloc [%d, 0x%x]failed\n", 366318662Sdavidcs hwfn_index, trace->cmd); 367316485Sdavidcs return (ENXIO); 368316485Sdavidcs } 369316485Sdavidcs ecore_dbg_set_app_ver(ecore_dbg_get_fw_func_ver()); 370316485Sdavidcs 371316485Sdavidcs p_hwfn = &ha->cdev.hwfns[hwfn_index]; 372316485Sdavidcs p_ptt = ecore_ptt_acquire(p_hwfn); 373316485Sdavidcs 374316485Sdavidcs if (!p_ptt) { 375318662Sdavidcs QL_DPRINT1(ha, "ecore_ptt_acquire [%d, 0x%x]failed\n", 376318662Sdavidcs hwfn_index, trace->cmd); 377316485Sdavidcs return (ENXIO); 378316485Sdavidcs } 379316485Sdavidcs 380316485Sdavidcs switch (trace->cmd) { 381316485Sdavidcs 382316485Sdavidcs case QLNX_MCP_TRACE: 383316485Sdavidcs rval = ecore_dbg_mcp_trace_dump(p_hwfn, p_ptt, 384316485Sdavidcs buffer, (trace->size[hwfn_index] >> 2), 385316485Sdavidcs &num_dwords); 386316485Sdavidcs break; 387316485Sdavidcs 388316485Sdavidcs case QLNX_REG_FIFO: 389316485Sdavidcs rval = ecore_dbg_reg_fifo_dump(p_hwfn, p_ptt, 390316485Sdavidcs buffer, (trace->size[hwfn_index] >> 2), 391316485Sdavidcs &num_dwords); 392316485Sdavidcs break; 393316485Sdavidcs 394316485Sdavidcs case QLNX_IGU_FIFO: 395316485Sdavidcs rval = ecore_dbg_igu_fifo_dump(p_hwfn, p_ptt, 396316485Sdavidcs buffer, (trace->size[hwfn_index] >> 2), 397316485Sdavidcs &num_dwords); 398316485Sdavidcs break; 399316485Sdavidcs 400316485Sdavidcs case QLNX_PROTECTION_OVERRIDE: 401316485Sdavidcs rval = ecore_dbg_protection_override_dump(p_hwfn, p_ptt, 402316485Sdavidcs buffer, (trace->size[hwfn_index] >> 2), 403316485Sdavidcs &num_dwords); 404316485Sdavidcs break; 405316485Sdavidcs 406316485Sdavidcs case QLNX_FW_ASSERTS: 407316485Sdavidcs rval = ecore_dbg_fw_asserts_dump(p_hwfn, p_ptt, 408316485Sdavidcs buffer, (trace->size[hwfn_index] >> 2), 409316485Sdavidcs &num_dwords); 410316485Sdavidcs break; 411316485Sdavidcs } 412316485Sdavidcs 413316485Sdavidcs if (rval != DBG_STATUS_OK) { 414318662Sdavidcs QL_DPRINT1(ha,"cmd = 0x%x failed [0x%x]\n", trace->cmd, rval); 415316485Sdavidcs num_dwords = 0; 416316485Sdavidcs } 417316485Sdavidcs 418316485Sdavidcs ecore_ptt_release(p_hwfn, p_ptt); 419316485Sdavidcs 420316485Sdavidcs trace->dwords[hwfn_index] = num_dwords; 421316485Sdavidcs 422316485Sdavidcs if (num_dwords) { 423316485Sdavidcs rval = copyout(buffer, trace->buffer[hwfn_index], 424316485Sdavidcs (num_dwords << 2)); 425316485Sdavidcs } 426316485Sdavidcs 427316485Sdavidcs return (rval); 428316485Sdavidcs} 429316485Sdavidcs 430316485Sdavidcsstatic int 431316485Sdavidcsqlnx_reg_rd_wr(qlnx_host_t *ha, qlnx_reg_rd_wr_t *reg_rd_wr) 432316485Sdavidcs{ 433316485Sdavidcs int rval = 0; 434316485Sdavidcs struct ecore_hwfn *p_hwfn; 435316485Sdavidcs 436316485Sdavidcs if (reg_rd_wr->hwfn_index >= QLNX_MAX_HW_FUNCS) { 437316485Sdavidcs return (EINVAL); 438316485Sdavidcs } 439316485Sdavidcs 440316485Sdavidcs p_hwfn = &ha->cdev.hwfns[reg_rd_wr->hwfn_index]; 441316485Sdavidcs 442316485Sdavidcs switch (reg_rd_wr->cmd) { 443316485Sdavidcs 444316485Sdavidcs case QLNX_REG_READ_CMD: 445316485Sdavidcs if (reg_rd_wr->access_type == QLNX_REG_ACCESS_DIRECT) { 446316485Sdavidcs reg_rd_wr->val = qlnx_reg_rd32(p_hwfn, 447316485Sdavidcs reg_rd_wr->addr); 448316485Sdavidcs } 449316485Sdavidcs break; 450316485Sdavidcs 451316485Sdavidcs case QLNX_REG_WRITE_CMD: 452316485Sdavidcs if (reg_rd_wr->access_type == QLNX_REG_ACCESS_DIRECT) { 453316485Sdavidcs qlnx_reg_wr32(p_hwfn, reg_rd_wr->addr, 454316485Sdavidcs reg_rd_wr->val); 455316485Sdavidcs } 456316485Sdavidcs break; 457316485Sdavidcs 458316485Sdavidcs default: 459316485Sdavidcs rval = EINVAL; 460316485Sdavidcs break; 461316485Sdavidcs } 462316485Sdavidcs 463316485Sdavidcs return (rval); 464316485Sdavidcs} 465316485Sdavidcs 466316485Sdavidcsstatic int 467316485Sdavidcsqlnx_rd_wr_pci_config(qlnx_host_t *ha, qlnx_pcicfg_rd_wr_t *pci_cfg_rd_wr) 468316485Sdavidcs{ 469316485Sdavidcs int rval = 0; 470316485Sdavidcs 471316485Sdavidcs switch (pci_cfg_rd_wr->cmd) { 472316485Sdavidcs 473316485Sdavidcs case QLNX_PCICFG_READ: 474316485Sdavidcs pci_cfg_rd_wr->val = pci_read_config(ha->pci_dev, 475316485Sdavidcs pci_cfg_rd_wr->reg, 476316485Sdavidcs pci_cfg_rd_wr->width); 477316485Sdavidcs break; 478316485Sdavidcs 479316485Sdavidcs case QLNX_PCICFG_WRITE: 480316485Sdavidcs pci_write_config(ha->pci_dev, pci_cfg_rd_wr->reg, 481316485Sdavidcs pci_cfg_rd_wr->val, pci_cfg_rd_wr->width); 482316485Sdavidcs break; 483316485Sdavidcs 484316485Sdavidcs default: 485316485Sdavidcs rval = EINVAL; 486316485Sdavidcs break; 487316485Sdavidcs } 488316485Sdavidcs 489316485Sdavidcs return (rval); 490316485Sdavidcs} 491316485Sdavidcs 492316485Sdavidcsstatic void 493316485Sdavidcsqlnx_mac_addr(qlnx_host_t *ha, qlnx_perm_mac_addr_t *mac_addr) 494316485Sdavidcs{ 495316485Sdavidcs bzero(mac_addr->addr, sizeof(mac_addr->addr)); 496316485Sdavidcs snprintf(mac_addr->addr, sizeof(mac_addr->addr), 497316485Sdavidcs "%02x:%02x:%02x:%02x:%02x:%02x", 498316485Sdavidcs ha->primary_mac[0], ha->primary_mac[1], ha->primary_mac[2], 499316485Sdavidcs ha->primary_mac[3], ha->primary_mac[4], ha->primary_mac[5]); 500316485Sdavidcs 501316485Sdavidcs return; 502316485Sdavidcs} 503316485Sdavidcs 504316485Sdavidcsstatic int 505316485Sdavidcsqlnx_get_regs(qlnx_host_t *ha, qlnx_get_regs_t *regs) 506316485Sdavidcs{ 507316485Sdavidcs int i; 508316485Sdavidcs int rval = 0; 509316485Sdavidcs uint32_t dwords = 0; 510316485Sdavidcs uint8_t *outb; 511316485Sdavidcs 512316485Sdavidcs regs->reg_buf_len = 0; 513316485Sdavidcs outb = regs->reg_buf; 514316485Sdavidcs 515316485Sdavidcs for (i = 0; i < ha->cdev.num_hwfns; i++) { 516316485Sdavidcs 517316485Sdavidcs rval = qlnx_grc_dump(ha, &dwords, i); 518316485Sdavidcs 519316485Sdavidcs if (rval) 520316485Sdavidcs break; 521316485Sdavidcs 522316485Sdavidcs regs->reg_buf_len += (dwords << 2); 523316485Sdavidcs 524316485Sdavidcs rval = copyout(ha->grcdump[i], outb, ha->grcdump_size[i]); 525316485Sdavidcs 526316485Sdavidcs if (rval) 527316485Sdavidcs break; 528316485Sdavidcs 529316485Sdavidcs ha->grcdump_dwords[i] = 0; 530316485Sdavidcs outb += regs->reg_buf_len; 531316485Sdavidcs } 532316485Sdavidcs 533316485Sdavidcs ha->grcdump_taken = 0; 534316485Sdavidcs 535316485Sdavidcs return (rval); 536316485Sdavidcs} 537316485Sdavidcs 538316485Sdavidcsstatic int 539316485Sdavidcsqlnx_drv_info(qlnx_host_t *ha, qlnx_drvinfo_t *drv_info) 540316485Sdavidcs{ 541316485Sdavidcs int i; 542316485Sdavidcs extern char qlnx_name_str[]; 543316485Sdavidcs extern char qlnx_ver_str[]; 544316485Sdavidcs 545316485Sdavidcs bzero(drv_info, sizeof(qlnx_drvinfo_t)); 546316485Sdavidcs 547316485Sdavidcs snprintf(drv_info->drv_name, sizeof(drv_info->drv_name), "%s", 548316485Sdavidcs qlnx_name_str); 549316485Sdavidcs snprintf(drv_info->drv_version, sizeof(drv_info->drv_version), "%s", 550316485Sdavidcs qlnx_ver_str); 551316485Sdavidcs snprintf(drv_info->mfw_version, sizeof(drv_info->mfw_version), "%s", 552316485Sdavidcs ha->mfw_ver); 553316485Sdavidcs snprintf(drv_info->stormfw_version, sizeof(drv_info->stormfw_version), 554316485Sdavidcs "%s", ha->stormfw_ver); 555316485Sdavidcs 556316485Sdavidcs drv_info->eeprom_dump_len = ha->flash_size; 557316485Sdavidcs 558316485Sdavidcs for (i = 0; i < ha->cdev.num_hwfns; i++) { 559316485Sdavidcs drv_info->reg_dump_len += ha->grcdump_size[i]; 560316485Sdavidcs } 561316485Sdavidcs 562316485Sdavidcs snprintf(drv_info->bus_info, sizeof(drv_info->bus_info), 563316485Sdavidcs "%d:%d:%d", pci_get_bus(ha->pci_dev), 564316485Sdavidcs pci_get_slot(ha->pci_dev), ha->pci_func); 565316485Sdavidcs 566316485Sdavidcs return (0); 567316485Sdavidcs} 568316485Sdavidcs 569316485Sdavidcsstatic int 570316485Sdavidcsqlnx_dev_settings(qlnx_host_t *ha, qlnx_dev_setting_t *dev_info) 571316485Sdavidcs{ 572316485Sdavidcs struct ecore_hwfn *p_hwfn; 573316485Sdavidcs struct qlnx_link_output if_link; 574316485Sdavidcs 575316485Sdavidcs p_hwfn = &ha->cdev.hwfns[0]; 576316485Sdavidcs 577337519Sdavidcs qlnx_fill_link(ha, p_hwfn, &if_link); 578316485Sdavidcs 579316485Sdavidcs dev_info->supported = if_link.supported_caps; 580316485Sdavidcs dev_info->advertising = if_link.advertised_caps; 581316485Sdavidcs dev_info->speed = if_link.speed; 582316485Sdavidcs dev_info->duplex = if_link.duplex; 583316485Sdavidcs dev_info->port = ha->pci_func & 0x1; 584316485Sdavidcs dev_info->autoneg = if_link.autoneg; 585316485Sdavidcs 586316485Sdavidcs return (0); 587316485Sdavidcs} 588316485Sdavidcs 589316485Sdavidcsstatic int 590316485Sdavidcsqlnx_write_nvram(qlnx_host_t *ha, qlnx_nvram_t *nvram, uint32_t cmd) 591316485Sdavidcs{ 592316485Sdavidcs uint8_t *buf; 593316485Sdavidcs int ret = 0; 594316485Sdavidcs 595316485Sdavidcs if ((nvram->data == NULL) || (nvram->data_len == 0)) 596316485Sdavidcs return (EINVAL); 597316485Sdavidcs 598316485Sdavidcs buf = qlnx_zalloc(nvram->data_len); 599316485Sdavidcs 600316485Sdavidcs ret = copyin(nvram->data, buf, nvram->data_len); 601316485Sdavidcs 602318662Sdavidcs QL_DPRINT9(ha, "issue cmd = 0x%x data = %p \ 603318662Sdavidcs data_len = 0x%x ret = 0x%x exit\n", 604318662Sdavidcs cmd, nvram->data, nvram->data_len, ret); 605316485Sdavidcs 606316485Sdavidcs if (ret == 0) { 607316485Sdavidcs ret = ecore_mcp_nvm_write(&ha->cdev, cmd, 608316485Sdavidcs nvram->offset, buf, nvram->data_len); 609316485Sdavidcs } 610316485Sdavidcs 611318662Sdavidcs QL_DPRINT9(ha, "cmd = 0x%x data = %p \ 612318662Sdavidcs data_len = 0x%x resp = 0x%x ret = 0x%x exit\n", 613318662Sdavidcs cmd, nvram->data, nvram->data_len, ha->cdev.mcp_nvm_resp, ret); 614316485Sdavidcs 615316485Sdavidcs free(buf, M_QLNXBUF); 616316485Sdavidcs 617316485Sdavidcs return (ret); 618316485Sdavidcs} 619316485Sdavidcs 620316485Sdavidcsstatic int 621316485Sdavidcsqlnx_read_nvram(qlnx_host_t *ha, qlnx_nvram_t *nvram) 622316485Sdavidcs{ 623316485Sdavidcs uint8_t *buf; 624316485Sdavidcs int ret = 0; 625316485Sdavidcs 626316485Sdavidcs if ((nvram->data == NULL) || (nvram->data_len == 0)) 627316485Sdavidcs return (EINVAL); 628316485Sdavidcs 629316485Sdavidcs buf = qlnx_zalloc(nvram->data_len); 630316485Sdavidcs 631316485Sdavidcs ret = ecore_mcp_nvm_read(&ha->cdev, nvram->offset, buf, 632316485Sdavidcs nvram->data_len); 633316485Sdavidcs 634318662Sdavidcs QL_DPRINT9(ha, " data = %p data_len = 0x%x \ 635318662Sdavidcs resp = 0x%x ret = 0x%x exit\n", 636318662Sdavidcs nvram->data, nvram->data_len, ha->cdev.mcp_nvm_resp, ret); 637316485Sdavidcs 638316485Sdavidcs if (ret == 0) { 639316485Sdavidcs ret = copyout(buf, nvram->data, nvram->data_len); 640316485Sdavidcs } 641316485Sdavidcs 642316485Sdavidcs free(buf, M_QLNXBUF); 643316485Sdavidcs 644316485Sdavidcs return (ret); 645316485Sdavidcs} 646316485Sdavidcs 647316485Sdavidcsstatic int 648316485Sdavidcsqlnx_get_nvram_resp(qlnx_host_t *ha, qlnx_nvram_t *nvram) 649316485Sdavidcs{ 650316485Sdavidcs uint8_t *buf; 651316485Sdavidcs int ret = 0; 652316485Sdavidcs 653316485Sdavidcs if ((nvram->data == NULL) || (nvram->data_len == 0)) 654316485Sdavidcs return (EINVAL); 655316485Sdavidcs 656316485Sdavidcs buf = qlnx_zalloc(nvram->data_len); 657316485Sdavidcs 658316485Sdavidcs 659316485Sdavidcs ret = ecore_mcp_nvm_resp(&ha->cdev, buf); 660316485Sdavidcs 661318662Sdavidcs QL_DPRINT9(ha, "data = %p data_len = 0x%x \ 662318662Sdavidcs resp = 0x%x ret = 0x%x exit\n", 663318662Sdavidcs nvram->data, nvram->data_len, ha->cdev.mcp_nvm_resp, ret); 664316485Sdavidcs 665316485Sdavidcs if (ret == 0) { 666316485Sdavidcs ret = copyout(buf, nvram->data, nvram->data_len); 667316485Sdavidcs } 668316485Sdavidcs 669316485Sdavidcs free(buf, M_QLNXBUF); 670316485Sdavidcs 671316485Sdavidcs return (ret); 672316485Sdavidcs} 673316485Sdavidcs 674316485Sdavidcsstatic int 675316485Sdavidcsqlnx_nvram(qlnx_host_t *ha, qlnx_nvram_t *nvram) 676316485Sdavidcs{ 677316485Sdavidcs int ret = 0; 678316485Sdavidcs 679316485Sdavidcs switch (nvram->cmd) { 680316485Sdavidcs 681316485Sdavidcs case QLNX_NVRAM_CMD_WRITE_NVRAM: 682316485Sdavidcs ret = qlnx_write_nvram(ha, nvram, ECORE_NVM_WRITE_NVRAM); 683316485Sdavidcs break; 684316485Sdavidcs 685316485Sdavidcs case QLNX_NVRAM_CMD_PUT_FILE_DATA: 686316485Sdavidcs ret = qlnx_write_nvram(ha, nvram, ECORE_PUT_FILE_DATA); 687316485Sdavidcs break; 688316485Sdavidcs 689316485Sdavidcs case QLNX_NVRAM_CMD_READ_NVRAM: 690316485Sdavidcs ret = qlnx_read_nvram(ha, nvram); 691316485Sdavidcs break; 692316485Sdavidcs 693316485Sdavidcs case QLNX_NVRAM_CMD_SET_SECURE_MODE: 694316485Sdavidcs ret = ecore_mcp_nvm_set_secure_mode(&ha->cdev, nvram->offset); 695316485Sdavidcs 696318662Sdavidcs QL_DPRINT9(ha, "QLNX_NVRAM_CMD_SET_SECURE_MODE \ 697318662Sdavidcs resp = 0x%x ret = 0x%x exit\n", 698318662Sdavidcs ha->cdev.mcp_nvm_resp, ret); 699316485Sdavidcs break; 700316485Sdavidcs 701316485Sdavidcs case QLNX_NVRAM_CMD_DEL_FILE: 702316485Sdavidcs ret = ecore_mcp_nvm_del_file(&ha->cdev, nvram->offset); 703316485Sdavidcs 704318662Sdavidcs QL_DPRINT9(ha, "QLNX_NVRAM_CMD_DEL_FILE \ 705318662Sdavidcs resp = 0x%x ret = 0x%x exit\n", 706318662Sdavidcs ha->cdev.mcp_nvm_resp, ret); 707316485Sdavidcs break; 708316485Sdavidcs 709316485Sdavidcs case QLNX_NVRAM_CMD_PUT_FILE_BEGIN: 710316485Sdavidcs ret = ecore_mcp_nvm_put_file_begin(&ha->cdev, nvram->offset); 711316485Sdavidcs 712318662Sdavidcs QL_DPRINT9(ha, "QLNX_NVRAM_CMD_PUT_FILE_BEGIN \ 713318662Sdavidcs resp = 0x%x ret = 0x%x exit\n", 714318662Sdavidcs ha->cdev.mcp_nvm_resp, ret); 715316485Sdavidcs break; 716316485Sdavidcs 717316485Sdavidcs case QLNX_NVRAM_CMD_GET_NVRAM_RESP: 718316485Sdavidcs ret = qlnx_get_nvram_resp(ha, nvram); 719316485Sdavidcs break; 720316485Sdavidcs 721316485Sdavidcs default: 722316485Sdavidcs ret = EINVAL; 723316485Sdavidcs break; 724316485Sdavidcs } 725316485Sdavidcs 726316485Sdavidcs return (ret); 727316485Sdavidcs} 728316485Sdavidcs 729316485Sdavidcsstatic void 730316485Sdavidcsqlnx_storm_stats(qlnx_host_t *ha, qlnx_storm_stats_dump_t *s_stats) 731316485Sdavidcs{ 732316485Sdavidcs int i; 733316485Sdavidcs int index; 734316485Sdavidcs int ret; 735316485Sdavidcs int stats_copied = 0; 736316485Sdavidcs 737316485Sdavidcs s_stats->num_hwfns = ha->cdev.num_hwfns; 738316485Sdavidcs 739316485Sdavidcs// if (ha->storm_stats_index < QLNX_STORM_STATS_SAMPLES_PER_HWFN) 740316485Sdavidcs// return; 741316485Sdavidcs 742316485Sdavidcs s_stats->num_samples = ha->storm_stats_index; 743316485Sdavidcs 744316485Sdavidcs for (i = 0; i < ha->cdev.num_hwfns; i++) { 745316485Sdavidcs 746316485Sdavidcs index = (QLNX_STORM_STATS_SAMPLES_PER_HWFN * i); 747316485Sdavidcs 748316485Sdavidcs if (s_stats->buffer[i]) { 749316485Sdavidcs 750316485Sdavidcs ret = copyout(&ha->storm_stats[index], 751316485Sdavidcs s_stats->buffer[i], 752316485Sdavidcs QLNX_STORM_STATS_BYTES_PER_HWFN); 753316485Sdavidcs if (ret) { 754316485Sdavidcs printf("%s [%d]: failed\n", __func__, i); 755316485Sdavidcs } 756316485Sdavidcs 757316485Sdavidcs if (s_stats->num_samples == 758316485Sdavidcs QLNX_STORM_STATS_SAMPLES_PER_HWFN) { 759316485Sdavidcs 760316485Sdavidcs bzero((void *)&ha->storm_stats[i], 761316485Sdavidcs QLNX_STORM_STATS_BYTES_PER_HWFN); 762316485Sdavidcs 763316485Sdavidcs stats_copied = 1; 764316485Sdavidcs } 765316485Sdavidcs } 766316485Sdavidcs } 767316485Sdavidcs 768316485Sdavidcs if (stats_copied) 769316485Sdavidcs ha->storm_stats_index = 0; 770316485Sdavidcs 771316485Sdavidcs return; 772316485Sdavidcs} 773316485Sdavidcs 774337519Sdavidcs#ifdef QLNX_USER_LLDP 775316485Sdavidcs 776316485Sdavidcsstatic int 777337519Sdavidcsqlnx_lldp_configure(qlnx_host_t *ha, struct ecore_hwfn *p_hwfn, 778337519Sdavidcs struct ecore_ptt *p_ptt, uint32_t enable) 779337519Sdavidcs{ 780337519Sdavidcs int ret = 0; 781337519Sdavidcs uint8_t lldp_mac[6] = {0}; 782337519Sdavidcs struct ecore_lldp_config_params lldp_params; 783337519Sdavidcs struct ecore_lldp_sys_tlvs tlv_params; 784337519Sdavidcs 785337519Sdavidcs ret = ecore_mcp_get_lldp_mac(p_hwfn, p_ptt, lldp_mac); 786337519Sdavidcs 787337519Sdavidcs if (ret != ECORE_SUCCESS) { 788337519Sdavidcs device_printf(ha->pci_dev, 789337519Sdavidcs "%s: ecore_mcp_get_lldp_mac failed\n", __func__); 790337519Sdavidcs return (-1); 791337519Sdavidcs } 792337519Sdavidcs 793337519Sdavidcs bzero(&lldp_params, sizeof(struct ecore_lldp_config_params)); 794337519Sdavidcs bzero(&tlv_params, sizeof(struct ecore_lldp_sys_tlvs)); 795337519Sdavidcs 796337519Sdavidcs lldp_params.agent = ECORE_LLDP_NEAREST_BRIDGE; 797337519Sdavidcs lldp_params.tx_interval = 30; //Default value used as suggested by MFW 798337519Sdavidcs lldp_params.tx_hold = 4; //Default value used as suggested by MFW 799337519Sdavidcs lldp_params.tx_credit = 5; //Default value used as suggested by MFW 800337519Sdavidcs lldp_params.rx_enable = enable ? 1 : 0; 801337519Sdavidcs lldp_params.tx_enable = enable ? 1 : 0; 802337519Sdavidcs 803337519Sdavidcs lldp_params.chassis_id_tlv[0] = 0; 804337519Sdavidcs lldp_params.chassis_id_tlv[0] |= (QLNX_LLDP_TYPE_CHASSIS_ID << 1); 805337519Sdavidcs lldp_params.chassis_id_tlv[0] |= 806337519Sdavidcs ((QLNX_LLDP_CHASSIS_ID_SUBTYPE_OCTETS + 807337519Sdavidcs QLNX_LLDP_CHASSIS_ID_MAC_ADDR_LEN) << 8); 808337519Sdavidcs lldp_params.chassis_id_tlv[0] |= (QLNX_LLDP_CHASSIS_ID_SUBTYPE_MAC << 16); 809337519Sdavidcs lldp_params.chassis_id_tlv[0] |= lldp_mac[0] << 24; 810337519Sdavidcs lldp_params.chassis_id_tlv[1] = lldp_mac[1] | (lldp_mac[2] << 8) | 811337519Sdavidcs (lldp_mac[3] << 16) | (lldp_mac[4] << 24); 812337519Sdavidcs lldp_params.chassis_id_tlv[2] = lldp_mac[5]; 813337519Sdavidcs 814337519Sdavidcs 815337519Sdavidcs lldp_params.port_id_tlv[0] = 0; 816337519Sdavidcs lldp_params.port_id_tlv[0] |= (QLNX_LLDP_TYPE_PORT_ID << 1); 817337519Sdavidcs lldp_params.port_id_tlv[0] |= 818337519Sdavidcs ((QLNX_LLDP_PORT_ID_SUBTYPE_OCTETS + 819337519Sdavidcs QLNX_LLDP_PORT_ID_MAC_ADDR_LEN) << 8); 820337519Sdavidcs lldp_params.port_id_tlv[0] |= (QLNX_LLDP_PORT_ID_SUBTYPE_MAC << 16); 821337519Sdavidcs lldp_params.port_id_tlv[0] |= lldp_mac[0] << 24; 822337519Sdavidcs lldp_params.port_id_tlv[1] = lldp_mac[1] | (lldp_mac[2] << 8) | 823337519Sdavidcs (lldp_mac[3] << 16) | (lldp_mac[4] << 24); 824337519Sdavidcs lldp_params.port_id_tlv[2] = lldp_mac[5]; 825337519Sdavidcs 826337519Sdavidcs ret = ecore_lldp_set_params(p_hwfn, p_ptt, &lldp_params); 827337519Sdavidcs 828337519Sdavidcs if (ret != ECORE_SUCCESS) { 829337519Sdavidcs device_printf(ha->pci_dev, 830337519Sdavidcs "%s: ecore_lldp_set_params failed\n", __func__); 831337519Sdavidcs return (-1); 832337519Sdavidcs } 833337519Sdavidcs 834337519Sdavidcs //If LLDP is disable then disable discard_mandatory_tlv flag 835337519Sdavidcs if (!enable) { 836337519Sdavidcs tlv_params.discard_mandatory_tlv = false; 837337519Sdavidcs tlv_params.buf_size = 0; 838337519Sdavidcs ret = ecore_lldp_set_system_tlvs(p_hwfn, p_ptt, &tlv_params); 839337519Sdavidcs } 840337519Sdavidcs 841337519Sdavidcs if (ret != ECORE_SUCCESS) { 842337519Sdavidcs device_printf(ha->pci_dev, 843337519Sdavidcs "%s: ecore_lldp_set_system_tlvs failed\n", __func__); 844337519Sdavidcs } 845337519Sdavidcs 846337519Sdavidcs return (ret); 847337519Sdavidcs} 848337519Sdavidcs 849337519Sdavidcsstatic int 850337519Sdavidcsqlnx_register_default_lldp_tlvs(qlnx_host_t *ha, struct ecore_hwfn *p_hwfn, 851337519Sdavidcs struct ecore_ptt *p_ptt) 852337519Sdavidcs{ 853337519Sdavidcs int ret = 0; 854337519Sdavidcs 855337519Sdavidcs ret = ecore_lldp_register_tlv(p_hwfn, p_ptt, 856337519Sdavidcs ECORE_LLDP_NEAREST_BRIDGE, QLNX_LLDP_TYPE_CHASSIS_ID); 857337519Sdavidcs if (ret != ECORE_SUCCESS) { 858337519Sdavidcs device_printf(ha->pci_dev, 859337519Sdavidcs "%s: QLNX_LLDP_TYPE_CHASSIS_ID failed\n", __func__); 860337519Sdavidcs goto qlnx_register_default_lldp_tlvs_exit; 861337519Sdavidcs } 862337519Sdavidcs 863337519Sdavidcs //register Port ID TLV 864337519Sdavidcs ret = ecore_lldp_register_tlv(p_hwfn, p_ptt, 865337519Sdavidcs ECORE_LLDP_NEAREST_BRIDGE, QLNX_LLDP_TYPE_PORT_ID); 866337519Sdavidcs if (ret != ECORE_SUCCESS) { 867337519Sdavidcs device_printf(ha->pci_dev, 868337519Sdavidcs "%s: QLNX_LLDP_TYPE_PORT_ID failed\n", __func__); 869337519Sdavidcs goto qlnx_register_default_lldp_tlvs_exit; 870337519Sdavidcs } 871337519Sdavidcs 872337519Sdavidcs //register TTL TLV 873337519Sdavidcs ret = ecore_lldp_register_tlv(p_hwfn, p_ptt, 874337519Sdavidcs ECORE_LLDP_NEAREST_BRIDGE, QLNX_LLDP_TYPE_TTL); 875337519Sdavidcs if (ret != ECORE_SUCCESS) { 876337519Sdavidcs device_printf(ha->pci_dev, 877337519Sdavidcs "%s: QLNX_LLDP_TYPE_TTL failed\n", __func__); 878337519Sdavidcs goto qlnx_register_default_lldp_tlvs_exit; 879337519Sdavidcs } 880337519Sdavidcs 881337519Sdavidcs //register Port Description TLV 882337519Sdavidcs ret = ecore_lldp_register_tlv(p_hwfn, p_ptt, 883337519Sdavidcs ECORE_LLDP_NEAREST_BRIDGE, QLNX_LLDP_TYPE_PORT_DESC); 884337519Sdavidcs if (ret != ECORE_SUCCESS) { 885337519Sdavidcs device_printf(ha->pci_dev, 886337519Sdavidcs "%s: QLNX_LLDP_TYPE_PORT_DESC failed\n", __func__); 887337519Sdavidcs goto qlnx_register_default_lldp_tlvs_exit; 888337519Sdavidcs } 889337519Sdavidcs 890337519Sdavidcs //register System Name TLV 891337519Sdavidcs ret = ecore_lldp_register_tlv(p_hwfn, p_ptt, 892337519Sdavidcs ECORE_LLDP_NEAREST_BRIDGE, QLNX_LLDP_TYPE_SYS_NAME); 893337519Sdavidcs if (ret != ECORE_SUCCESS) { 894337519Sdavidcs device_printf(ha->pci_dev, 895337519Sdavidcs "%s: QLNX_LLDP_TYPE_SYS_NAME failed\n", __func__); 896337519Sdavidcs goto qlnx_register_default_lldp_tlvs_exit; 897337519Sdavidcs } 898337519Sdavidcs 899337519Sdavidcs //register System Description TLV 900337519Sdavidcs ret = ecore_lldp_register_tlv(p_hwfn, p_ptt, 901337519Sdavidcs ECORE_LLDP_NEAREST_BRIDGE, QLNX_LLDP_TYPE_SYS_DESC); 902337519Sdavidcs if (ret != ECORE_SUCCESS) { 903337519Sdavidcs device_printf(ha->pci_dev, 904337519Sdavidcs "%s: QLNX_LLDP_TYPE_SYS_DESC failed\n", __func__); 905337519Sdavidcs goto qlnx_register_default_lldp_tlvs_exit; 906337519Sdavidcs } 907337519Sdavidcs 908337519Sdavidcs //register System Capabilities TLV 909337519Sdavidcs ret = ecore_lldp_register_tlv(p_hwfn, p_ptt, 910337519Sdavidcs ECORE_LLDP_NEAREST_BRIDGE, QLNX_LLDP_TYPE_SYS_CAPS); 911337519Sdavidcs if (ret != ECORE_SUCCESS) { 912337519Sdavidcs device_printf(ha->pci_dev, 913337519Sdavidcs "%s: QLNX_LLDP_TYPE_SYS_CAPS failed\n", __func__); 914337519Sdavidcs goto qlnx_register_default_lldp_tlvs_exit; 915337519Sdavidcs } 916337519Sdavidcs 917337519Sdavidcs //register Management Address TLV 918337519Sdavidcs ret = ecore_lldp_register_tlv(p_hwfn, p_ptt, 919337519Sdavidcs ECORE_LLDP_NEAREST_BRIDGE, QLNX_LLDP_TYPE_MGMT_ADDR); 920337519Sdavidcs if (ret != ECORE_SUCCESS) { 921337519Sdavidcs device_printf(ha->pci_dev, 922337519Sdavidcs "%s: QLNX_LLDP_TYPE_MGMT_ADDR failed\n", __func__); 923337519Sdavidcs goto qlnx_register_default_lldp_tlvs_exit; 924337519Sdavidcs } 925337519Sdavidcs 926337519Sdavidcs //register Organizationally Specific TLVs 927337519Sdavidcs ret = ecore_lldp_register_tlv(p_hwfn, p_ptt, 928337519Sdavidcs ECORE_LLDP_NEAREST_BRIDGE, QLNX_LLDP_TYPE_ORG_SPECIFIC); 929337519Sdavidcs if (ret != ECORE_SUCCESS) { 930337519Sdavidcs device_printf(ha->pci_dev, 931337519Sdavidcs "%s: QLNX_LLDP_TYPE_ORG_SPECIFIC failed\n", __func__); 932337519Sdavidcs } 933337519Sdavidcs 934337519Sdavidcsqlnx_register_default_lldp_tlvs_exit: 935337519Sdavidcs return (ret); 936337519Sdavidcs} 937337519Sdavidcs 938337519Sdavidcsint 939337519Sdavidcsqlnx_set_lldp_tlvx(qlnx_host_t *ha, qlnx_lldp_sys_tlvs_t *lldp_tlvs) 940337519Sdavidcs{ 941337519Sdavidcs int ret = 0; 942337519Sdavidcs struct ecore_hwfn *p_hwfn; 943337519Sdavidcs struct ecore_ptt *p_ptt; 944337519Sdavidcs struct ecore_lldp_sys_tlvs tlv_params; 945337519Sdavidcs 946337519Sdavidcs p_hwfn = &ha->cdev.hwfns[0]; 947337519Sdavidcs p_ptt = ecore_ptt_acquire(p_hwfn); 948337519Sdavidcs 949337519Sdavidcs if (!p_ptt) { 950337519Sdavidcs device_printf(ha->pci_dev, 951337519Sdavidcs "%s: ecore_ptt_acquire failed\n", __func__); 952337519Sdavidcs return (ENXIO); 953337519Sdavidcs } 954337519Sdavidcs 955337519Sdavidcs ret = qlnx_lldp_configure(ha, p_hwfn, p_ptt, 0); 956337519Sdavidcs 957337519Sdavidcs if (ret) { 958337519Sdavidcs device_printf(ha->pci_dev, 959337519Sdavidcs "%s: qlnx_lldp_configure disable failed\n", __func__); 960337519Sdavidcs goto qlnx_set_lldp_tlvx_exit; 961337519Sdavidcs } 962337519Sdavidcs 963337519Sdavidcs ret = qlnx_register_default_lldp_tlvs(ha, p_hwfn, p_ptt); 964337519Sdavidcs 965337519Sdavidcs if (ret) { 966337519Sdavidcs device_printf(ha->pci_dev, 967337519Sdavidcs "%s: qlnx_register_default_lldp_tlvs failed\n", 968337519Sdavidcs __func__); 969337519Sdavidcs goto qlnx_set_lldp_tlvx_exit; 970337519Sdavidcs } 971337519Sdavidcs 972337519Sdavidcs ret = qlnx_lldp_configure(ha, p_hwfn, p_ptt, 1); 973337519Sdavidcs 974337519Sdavidcs if (ret) { 975337519Sdavidcs device_printf(ha->pci_dev, 976337519Sdavidcs "%s: qlnx_lldp_configure enable failed\n", __func__); 977337519Sdavidcs goto qlnx_set_lldp_tlvx_exit; 978337519Sdavidcs } 979337519Sdavidcs 980337519Sdavidcs if (lldp_tlvs != NULL) { 981337519Sdavidcs bzero(&tlv_params, sizeof(struct ecore_lldp_sys_tlvs)); 982337519Sdavidcs 983337519Sdavidcs tlv_params.discard_mandatory_tlv = 984337519Sdavidcs (lldp_tlvs->discard_mandatory_tlv ? true: false); 985337519Sdavidcs tlv_params.buf_size = lldp_tlvs->buf_size; 986337519Sdavidcs memcpy(tlv_params.buf, lldp_tlvs->buf, lldp_tlvs->buf_size); 987337519Sdavidcs 988337519Sdavidcs ret = ecore_lldp_set_system_tlvs(p_hwfn, p_ptt, &tlv_params); 989337519Sdavidcs 990337519Sdavidcs if (ret) { 991337519Sdavidcs device_printf(ha->pci_dev, 992337519Sdavidcs "%s: ecore_lldp_set_system_tlvs failed\n", 993337519Sdavidcs __func__); 994337519Sdavidcs } 995337519Sdavidcs } 996337519Sdavidcsqlnx_set_lldp_tlvx_exit: 997337519Sdavidcs 998337519Sdavidcs ecore_ptt_release(p_hwfn, p_ptt); 999337519Sdavidcs return (ret); 1000337519Sdavidcs} 1001337519Sdavidcs 1002337519Sdavidcs#endif /* #ifdef QLNX_USER_LLDP */ 1003337519Sdavidcs 1004337519Sdavidcsstatic int 1005316485Sdavidcsqlnx_eioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag, 1006316485Sdavidcs struct thread *td) 1007316485Sdavidcs{ 1008316485Sdavidcs qlnx_host_t *ha; 1009316485Sdavidcs int rval = 0; 1010316485Sdavidcs struct ifnet *ifp; 1011316485Sdavidcs qlnx_trace_t *trace; 1012316485Sdavidcs int i; 1013316485Sdavidcs 1014316485Sdavidcs if ((ha = (qlnx_host_t *)dev->si_drv1) == NULL) 1015316485Sdavidcs return ENXIO; 1016316485Sdavidcs 1017316485Sdavidcs ifp = ha->ifp; 1018316485Sdavidcs 1019316485Sdavidcs switch (cmd) { 1020316485Sdavidcs 1021316485Sdavidcs case QLNX_GRC_DUMP_SIZE: 1022316485Sdavidcs qlnx_get_grc_dump_size(ha, (qlnx_grcdump_t *)data); 1023316485Sdavidcs break; 1024316485Sdavidcs 1025316485Sdavidcs case QLNX_GRC_DUMP: 1026316485Sdavidcs rval = qlnx_get_grc_dump(ha, (qlnx_grcdump_t *)data); 1027316485Sdavidcs break; 1028316485Sdavidcs 1029316485Sdavidcs case QLNX_IDLE_CHK_SIZE: 1030316485Sdavidcs qlnx_get_idle_chk_size(ha, (qlnx_idle_chk_t *)data); 1031316485Sdavidcs break; 1032316485Sdavidcs 1033316485Sdavidcs case QLNX_IDLE_CHK: 1034316485Sdavidcs rval = qlnx_get_idle_chk(ha, (qlnx_idle_chk_t *)data); 1035316485Sdavidcs break; 1036316485Sdavidcs 1037316485Sdavidcs case QLNX_DRV_INFO: 1038316485Sdavidcs rval = qlnx_drv_info(ha, (qlnx_drvinfo_t *)data); 1039316485Sdavidcs break; 1040316485Sdavidcs 1041316485Sdavidcs case QLNX_DEV_SETTING: 1042316485Sdavidcs rval = qlnx_dev_settings(ha, (qlnx_dev_setting_t *)data); 1043316485Sdavidcs break; 1044316485Sdavidcs 1045316485Sdavidcs case QLNX_GET_REGS: 1046316485Sdavidcs rval = qlnx_get_regs(ha, (qlnx_get_regs_t *)data); 1047316485Sdavidcs break; 1048316485Sdavidcs 1049316485Sdavidcs case QLNX_NVRAM: 1050316485Sdavidcs rval = qlnx_nvram(ha, (qlnx_nvram_t *)data); 1051316485Sdavidcs break; 1052316485Sdavidcs 1053316485Sdavidcs case QLNX_RD_WR_REG: 1054316485Sdavidcs rval = qlnx_reg_rd_wr(ha, (qlnx_reg_rd_wr_t *)data); 1055316485Sdavidcs break; 1056316485Sdavidcs 1057316485Sdavidcs case QLNX_RD_WR_PCICFG: 1058316485Sdavidcs rval = qlnx_rd_wr_pci_config(ha, (qlnx_pcicfg_rd_wr_t *)data); 1059316485Sdavidcs break; 1060316485Sdavidcs 1061316485Sdavidcs case QLNX_MAC_ADDR: 1062316485Sdavidcs qlnx_mac_addr(ha, (qlnx_perm_mac_addr_t *)data); 1063316485Sdavidcs break; 1064316485Sdavidcs 1065316485Sdavidcs case QLNX_STORM_STATS: 1066316485Sdavidcs qlnx_storm_stats(ha, (qlnx_storm_stats_dump_t *)data); 1067316485Sdavidcs break; 1068316485Sdavidcs 1069316485Sdavidcs case QLNX_TRACE_SIZE: 1070316485Sdavidcs qlnx_get_trace_size(ha, (qlnx_trace_t *)data); 1071316485Sdavidcs break; 1072316485Sdavidcs 1073316485Sdavidcs case QLNX_TRACE: 1074316485Sdavidcs trace = (qlnx_trace_t *)data; 1075316485Sdavidcs 1076316485Sdavidcs for (i = 0; i < ha->cdev.num_hwfns; i++) { 1077316485Sdavidcs 1078316485Sdavidcs if (trace->size[i] && trace->cmd && trace->buffer[i]) 1079316485Sdavidcs rval = qlnx_get_trace(ha, i, trace); 1080316485Sdavidcs 1081316485Sdavidcs if (rval) 1082316485Sdavidcs break; 1083316485Sdavidcs } 1084316485Sdavidcs break; 1085316485Sdavidcs 1086337519Sdavidcs#ifdef QLNX_USER_LLDP 1087337519Sdavidcs case QLNX_SET_LLDP_TLVS: 1088337519Sdavidcs rval = qlnx_set_lldp_tlvx(ha, (qlnx_lldp_sys_tlvs_t *)data); 1089337519Sdavidcs break; 1090337519Sdavidcs#endif /* #ifdef QLNX_USER_LLDP */ 1091337519Sdavidcs 1092316485Sdavidcs default: 1093316485Sdavidcs rval = EINVAL; 1094316485Sdavidcs break; 1095316485Sdavidcs } 1096316485Sdavidcs 1097316485Sdavidcs return (rval); 1098316485Sdavidcs} 1099316485Sdavidcs 1100