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/11/sys/dev/qlnx/qlnxe/qlnx_ioctl.c 337517 2018-08-09 01:17:35Z 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" 62337517Sdavidcs#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) { 125318659Sdavidcs 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 136318659Sdavidcs QL_DPRINT1(ha,"ecore_dbg_grc_dump failed [%d, 0x%x]\n", 137318659Sdavidcs 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 179318659Sdavidcs 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) { 214318659Sdavidcs 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 225318659Sdavidcs QL_DPRINT1(ha,"ecore_dbg_idle_chk_dump failed [%d, 0x%x]\n", 226318659Sdavidcs 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 270318659Sdavidcs 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) { 297318659Sdavidcs QL_DPRINT1(ha, "ecore_ptt_acquire [%d, 0x%x]failed\n", 298318659Sdavidcs 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) { 331318659Sdavidcs 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) { 365318659Sdavidcs QL_DPRINT1(ha,"qlnx_zalloc [%d, 0x%x]failed\n", 366318659Sdavidcs 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) { 375318659Sdavidcs QL_DPRINT1(ha, "ecore_ptt_acquire [%d, 0x%x]failed\n", 376318659Sdavidcs 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) { 414318659Sdavidcs 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 538323213Srlibbyextern char qlnx_name_str[]; 539323213Srlibbyextern char qlnx_ver_str[]; 540323213Srlibby 541316485Sdavidcsstatic int 542316485Sdavidcsqlnx_drv_info(qlnx_host_t *ha, qlnx_drvinfo_t *drv_info) 543316485Sdavidcs{ 544316485Sdavidcs int i; 545316485Sdavidcs 546316485Sdavidcs bzero(drv_info, sizeof(qlnx_drvinfo_t)); 547316485Sdavidcs 548316485Sdavidcs snprintf(drv_info->drv_name, sizeof(drv_info->drv_name), "%s", 549316485Sdavidcs qlnx_name_str); 550316485Sdavidcs snprintf(drv_info->drv_version, sizeof(drv_info->drv_version), "%s", 551316485Sdavidcs qlnx_ver_str); 552316485Sdavidcs snprintf(drv_info->mfw_version, sizeof(drv_info->mfw_version), "%s", 553316485Sdavidcs ha->mfw_ver); 554316485Sdavidcs snprintf(drv_info->stormfw_version, sizeof(drv_info->stormfw_version), 555316485Sdavidcs "%s", ha->stormfw_ver); 556316485Sdavidcs 557316485Sdavidcs drv_info->eeprom_dump_len = ha->flash_size; 558316485Sdavidcs 559316485Sdavidcs for (i = 0; i < ha->cdev.num_hwfns; i++) { 560316485Sdavidcs drv_info->reg_dump_len += ha->grcdump_size[i]; 561316485Sdavidcs } 562316485Sdavidcs 563316485Sdavidcs snprintf(drv_info->bus_info, sizeof(drv_info->bus_info), 564316485Sdavidcs "%d:%d:%d", pci_get_bus(ha->pci_dev), 565316485Sdavidcs pci_get_slot(ha->pci_dev), ha->pci_func); 566316485Sdavidcs 567316485Sdavidcs return (0); 568316485Sdavidcs} 569316485Sdavidcs 570316485Sdavidcsstatic int 571316485Sdavidcsqlnx_dev_settings(qlnx_host_t *ha, qlnx_dev_setting_t *dev_info) 572316485Sdavidcs{ 573316485Sdavidcs struct ecore_hwfn *p_hwfn; 574316485Sdavidcs struct qlnx_link_output if_link; 575316485Sdavidcs 576316485Sdavidcs p_hwfn = &ha->cdev.hwfns[0]; 577316485Sdavidcs 578337517Sdavidcs qlnx_fill_link(ha, p_hwfn, &if_link); 579316485Sdavidcs 580316485Sdavidcs dev_info->supported = if_link.supported_caps; 581316485Sdavidcs dev_info->advertising = if_link.advertised_caps; 582316485Sdavidcs dev_info->speed = if_link.speed; 583316485Sdavidcs dev_info->duplex = if_link.duplex; 584316485Sdavidcs dev_info->port = ha->pci_func & 0x1; 585316485Sdavidcs dev_info->autoneg = if_link.autoneg; 586316485Sdavidcs 587316485Sdavidcs return (0); 588316485Sdavidcs} 589316485Sdavidcs 590316485Sdavidcsstatic int 591316485Sdavidcsqlnx_write_nvram(qlnx_host_t *ha, qlnx_nvram_t *nvram, uint32_t cmd) 592316485Sdavidcs{ 593316485Sdavidcs uint8_t *buf; 594316485Sdavidcs int ret = 0; 595316485Sdavidcs 596316485Sdavidcs if ((nvram->data == NULL) || (nvram->data_len == 0)) 597316485Sdavidcs return (EINVAL); 598316485Sdavidcs 599316485Sdavidcs buf = qlnx_zalloc(nvram->data_len); 600316485Sdavidcs 601316485Sdavidcs ret = copyin(nvram->data, buf, nvram->data_len); 602316485Sdavidcs 603318659Sdavidcs QL_DPRINT9(ha, "issue cmd = 0x%x data = %p \ 604318659Sdavidcs data_len = 0x%x ret = 0x%x exit\n", 605318659Sdavidcs cmd, nvram->data, nvram->data_len, ret); 606316485Sdavidcs 607316485Sdavidcs if (ret == 0) { 608316485Sdavidcs ret = ecore_mcp_nvm_write(&ha->cdev, cmd, 609316485Sdavidcs nvram->offset, buf, nvram->data_len); 610316485Sdavidcs } 611316485Sdavidcs 612318659Sdavidcs QL_DPRINT9(ha, "cmd = 0x%x data = %p \ 613318659Sdavidcs data_len = 0x%x resp = 0x%x ret = 0x%x exit\n", 614318659Sdavidcs cmd, nvram->data, nvram->data_len, ha->cdev.mcp_nvm_resp, ret); 615316485Sdavidcs 616316485Sdavidcs free(buf, M_QLNXBUF); 617316485Sdavidcs 618316485Sdavidcs return (ret); 619316485Sdavidcs} 620316485Sdavidcs 621316485Sdavidcsstatic int 622316485Sdavidcsqlnx_read_nvram(qlnx_host_t *ha, qlnx_nvram_t *nvram) 623316485Sdavidcs{ 624316485Sdavidcs uint8_t *buf; 625316485Sdavidcs int ret = 0; 626316485Sdavidcs 627316485Sdavidcs if ((nvram->data == NULL) || (nvram->data_len == 0)) 628316485Sdavidcs return (EINVAL); 629316485Sdavidcs 630316485Sdavidcs buf = qlnx_zalloc(nvram->data_len); 631316485Sdavidcs 632316485Sdavidcs ret = ecore_mcp_nvm_read(&ha->cdev, nvram->offset, buf, 633316485Sdavidcs nvram->data_len); 634316485Sdavidcs 635318659Sdavidcs QL_DPRINT9(ha, " data = %p data_len = 0x%x \ 636318659Sdavidcs resp = 0x%x ret = 0x%x exit\n", 637318659Sdavidcs nvram->data, nvram->data_len, ha->cdev.mcp_nvm_resp, ret); 638316485Sdavidcs 639316485Sdavidcs if (ret == 0) { 640316485Sdavidcs ret = copyout(buf, nvram->data, nvram->data_len); 641316485Sdavidcs } 642316485Sdavidcs 643316485Sdavidcs free(buf, M_QLNXBUF); 644316485Sdavidcs 645316485Sdavidcs return (ret); 646316485Sdavidcs} 647316485Sdavidcs 648316485Sdavidcsstatic int 649316485Sdavidcsqlnx_get_nvram_resp(qlnx_host_t *ha, qlnx_nvram_t *nvram) 650316485Sdavidcs{ 651316485Sdavidcs uint8_t *buf; 652316485Sdavidcs int ret = 0; 653316485Sdavidcs 654316485Sdavidcs if ((nvram->data == NULL) || (nvram->data_len == 0)) 655316485Sdavidcs return (EINVAL); 656316485Sdavidcs 657316485Sdavidcs buf = qlnx_zalloc(nvram->data_len); 658316485Sdavidcs 659316485Sdavidcs 660316485Sdavidcs ret = ecore_mcp_nvm_resp(&ha->cdev, buf); 661316485Sdavidcs 662318659Sdavidcs QL_DPRINT9(ha, "data = %p data_len = 0x%x \ 663318659Sdavidcs resp = 0x%x ret = 0x%x exit\n", 664318659Sdavidcs nvram->data, nvram->data_len, ha->cdev.mcp_nvm_resp, ret); 665316485Sdavidcs 666316485Sdavidcs if (ret == 0) { 667316485Sdavidcs ret = copyout(buf, nvram->data, nvram->data_len); 668316485Sdavidcs } 669316485Sdavidcs 670316485Sdavidcs free(buf, M_QLNXBUF); 671316485Sdavidcs 672316485Sdavidcs return (ret); 673316485Sdavidcs} 674316485Sdavidcs 675316485Sdavidcsstatic int 676316485Sdavidcsqlnx_nvram(qlnx_host_t *ha, qlnx_nvram_t *nvram) 677316485Sdavidcs{ 678316485Sdavidcs int ret = 0; 679316485Sdavidcs 680316485Sdavidcs switch (nvram->cmd) { 681316485Sdavidcs 682316485Sdavidcs case QLNX_NVRAM_CMD_WRITE_NVRAM: 683316485Sdavidcs ret = qlnx_write_nvram(ha, nvram, ECORE_NVM_WRITE_NVRAM); 684316485Sdavidcs break; 685316485Sdavidcs 686316485Sdavidcs case QLNX_NVRAM_CMD_PUT_FILE_DATA: 687316485Sdavidcs ret = qlnx_write_nvram(ha, nvram, ECORE_PUT_FILE_DATA); 688316485Sdavidcs break; 689316485Sdavidcs 690316485Sdavidcs case QLNX_NVRAM_CMD_READ_NVRAM: 691316485Sdavidcs ret = qlnx_read_nvram(ha, nvram); 692316485Sdavidcs break; 693316485Sdavidcs 694316485Sdavidcs case QLNX_NVRAM_CMD_SET_SECURE_MODE: 695316485Sdavidcs ret = ecore_mcp_nvm_set_secure_mode(&ha->cdev, nvram->offset); 696316485Sdavidcs 697318659Sdavidcs QL_DPRINT9(ha, "QLNX_NVRAM_CMD_SET_SECURE_MODE \ 698318659Sdavidcs resp = 0x%x ret = 0x%x exit\n", 699318659Sdavidcs ha->cdev.mcp_nvm_resp, ret); 700316485Sdavidcs break; 701316485Sdavidcs 702316485Sdavidcs case QLNX_NVRAM_CMD_DEL_FILE: 703316485Sdavidcs ret = ecore_mcp_nvm_del_file(&ha->cdev, nvram->offset); 704316485Sdavidcs 705318659Sdavidcs QL_DPRINT9(ha, "QLNX_NVRAM_CMD_DEL_FILE \ 706318659Sdavidcs resp = 0x%x ret = 0x%x exit\n", 707318659Sdavidcs ha->cdev.mcp_nvm_resp, ret); 708316485Sdavidcs break; 709316485Sdavidcs 710316485Sdavidcs case QLNX_NVRAM_CMD_PUT_FILE_BEGIN: 711316485Sdavidcs ret = ecore_mcp_nvm_put_file_begin(&ha->cdev, nvram->offset); 712316485Sdavidcs 713318659Sdavidcs QL_DPRINT9(ha, "QLNX_NVRAM_CMD_PUT_FILE_BEGIN \ 714318659Sdavidcs resp = 0x%x ret = 0x%x exit\n", 715318659Sdavidcs ha->cdev.mcp_nvm_resp, ret); 716316485Sdavidcs break; 717316485Sdavidcs 718316485Sdavidcs case QLNX_NVRAM_CMD_GET_NVRAM_RESP: 719316485Sdavidcs ret = qlnx_get_nvram_resp(ha, nvram); 720316485Sdavidcs break; 721316485Sdavidcs 722316485Sdavidcs default: 723316485Sdavidcs ret = EINVAL; 724316485Sdavidcs break; 725316485Sdavidcs } 726316485Sdavidcs 727316485Sdavidcs return (ret); 728316485Sdavidcs} 729316485Sdavidcs 730316485Sdavidcsstatic void 731316485Sdavidcsqlnx_storm_stats(qlnx_host_t *ha, qlnx_storm_stats_dump_t *s_stats) 732316485Sdavidcs{ 733316485Sdavidcs int i; 734316485Sdavidcs int index; 735316485Sdavidcs int ret; 736316485Sdavidcs int stats_copied = 0; 737316485Sdavidcs 738316485Sdavidcs s_stats->num_hwfns = ha->cdev.num_hwfns; 739316485Sdavidcs 740316485Sdavidcs// if (ha->storm_stats_index < QLNX_STORM_STATS_SAMPLES_PER_HWFN) 741316485Sdavidcs// return; 742316485Sdavidcs 743316485Sdavidcs s_stats->num_samples = ha->storm_stats_index; 744316485Sdavidcs 745316485Sdavidcs for (i = 0; i < ha->cdev.num_hwfns; i++) { 746316485Sdavidcs 747316485Sdavidcs index = (QLNX_STORM_STATS_SAMPLES_PER_HWFN * i); 748316485Sdavidcs 749316485Sdavidcs if (s_stats->buffer[i]) { 750316485Sdavidcs 751316485Sdavidcs ret = copyout(&ha->storm_stats[index], 752316485Sdavidcs s_stats->buffer[i], 753316485Sdavidcs QLNX_STORM_STATS_BYTES_PER_HWFN); 754316485Sdavidcs if (ret) { 755316485Sdavidcs printf("%s [%d]: failed\n", __func__, i); 756316485Sdavidcs } 757316485Sdavidcs 758316485Sdavidcs if (s_stats->num_samples == 759316485Sdavidcs QLNX_STORM_STATS_SAMPLES_PER_HWFN) { 760316485Sdavidcs 761316485Sdavidcs bzero((void *)&ha->storm_stats[i], 762316485Sdavidcs QLNX_STORM_STATS_BYTES_PER_HWFN); 763316485Sdavidcs 764316485Sdavidcs stats_copied = 1; 765316485Sdavidcs } 766316485Sdavidcs } 767316485Sdavidcs } 768316485Sdavidcs 769316485Sdavidcs if (stats_copied) 770316485Sdavidcs ha->storm_stats_index = 0; 771316485Sdavidcs 772316485Sdavidcs return; 773316485Sdavidcs} 774316485Sdavidcs 775337517Sdavidcs#ifdef QLNX_USER_LLDP 776316485Sdavidcs 777316485Sdavidcsstatic int 778337517Sdavidcsqlnx_lldp_configure(qlnx_host_t *ha, struct ecore_hwfn *p_hwfn, 779337517Sdavidcs struct ecore_ptt *p_ptt, uint32_t enable) 780337517Sdavidcs{ 781337517Sdavidcs int ret = 0; 782337517Sdavidcs uint8_t lldp_mac[6] = {0}; 783337517Sdavidcs struct ecore_lldp_config_params lldp_params; 784337517Sdavidcs struct ecore_lldp_sys_tlvs tlv_params; 785337517Sdavidcs 786337517Sdavidcs ret = ecore_mcp_get_lldp_mac(p_hwfn, p_ptt, lldp_mac); 787337517Sdavidcs 788337517Sdavidcs if (ret != ECORE_SUCCESS) { 789337517Sdavidcs device_printf(ha->pci_dev, 790337517Sdavidcs "%s: ecore_mcp_get_lldp_mac failed\n", __func__); 791337517Sdavidcs return (-1); 792337517Sdavidcs } 793337517Sdavidcs 794337517Sdavidcs bzero(&lldp_params, sizeof(struct ecore_lldp_config_params)); 795337517Sdavidcs bzero(&tlv_params, sizeof(struct ecore_lldp_sys_tlvs)); 796337517Sdavidcs 797337517Sdavidcs lldp_params.agent = ECORE_LLDP_NEAREST_BRIDGE; 798337517Sdavidcs lldp_params.tx_interval = 30; //Default value used as suggested by MFW 799337517Sdavidcs lldp_params.tx_hold = 4; //Default value used as suggested by MFW 800337517Sdavidcs lldp_params.tx_credit = 5; //Default value used as suggested by MFW 801337517Sdavidcs lldp_params.rx_enable = enable ? 1 : 0; 802337517Sdavidcs lldp_params.tx_enable = enable ? 1 : 0; 803337517Sdavidcs 804337517Sdavidcs lldp_params.chassis_id_tlv[0] = 0; 805337517Sdavidcs lldp_params.chassis_id_tlv[0] |= (QLNX_LLDP_TYPE_CHASSIS_ID << 1); 806337517Sdavidcs lldp_params.chassis_id_tlv[0] |= 807337517Sdavidcs ((QLNX_LLDP_CHASSIS_ID_SUBTYPE_OCTETS + 808337517Sdavidcs QLNX_LLDP_CHASSIS_ID_MAC_ADDR_LEN) << 8); 809337517Sdavidcs lldp_params.chassis_id_tlv[0] |= (QLNX_LLDP_CHASSIS_ID_SUBTYPE_MAC << 16); 810337517Sdavidcs lldp_params.chassis_id_tlv[0] |= lldp_mac[0] << 24; 811337517Sdavidcs lldp_params.chassis_id_tlv[1] = lldp_mac[1] | (lldp_mac[2] << 8) | 812337517Sdavidcs (lldp_mac[3] << 16) | (lldp_mac[4] << 24); 813337517Sdavidcs lldp_params.chassis_id_tlv[2] = lldp_mac[5]; 814337517Sdavidcs 815337517Sdavidcs 816337517Sdavidcs lldp_params.port_id_tlv[0] = 0; 817337517Sdavidcs lldp_params.port_id_tlv[0] |= (QLNX_LLDP_TYPE_PORT_ID << 1); 818337517Sdavidcs lldp_params.port_id_tlv[0] |= 819337517Sdavidcs ((QLNX_LLDP_PORT_ID_SUBTYPE_OCTETS + 820337517Sdavidcs QLNX_LLDP_PORT_ID_MAC_ADDR_LEN) << 8); 821337517Sdavidcs lldp_params.port_id_tlv[0] |= (QLNX_LLDP_PORT_ID_SUBTYPE_MAC << 16); 822337517Sdavidcs lldp_params.port_id_tlv[0] |= lldp_mac[0] << 24; 823337517Sdavidcs lldp_params.port_id_tlv[1] = lldp_mac[1] | (lldp_mac[2] << 8) | 824337517Sdavidcs (lldp_mac[3] << 16) | (lldp_mac[4] << 24); 825337517Sdavidcs lldp_params.port_id_tlv[2] = lldp_mac[5]; 826337517Sdavidcs 827337517Sdavidcs ret = ecore_lldp_set_params(p_hwfn, p_ptt, &lldp_params); 828337517Sdavidcs 829337517Sdavidcs if (ret != ECORE_SUCCESS) { 830337517Sdavidcs device_printf(ha->pci_dev, 831337517Sdavidcs "%s: ecore_lldp_set_params failed\n", __func__); 832337517Sdavidcs return (-1); 833337517Sdavidcs } 834337517Sdavidcs 835337517Sdavidcs //If LLDP is disable then disable discard_mandatory_tlv flag 836337517Sdavidcs if (!enable) { 837337517Sdavidcs tlv_params.discard_mandatory_tlv = false; 838337517Sdavidcs tlv_params.buf_size = 0; 839337517Sdavidcs ret = ecore_lldp_set_system_tlvs(p_hwfn, p_ptt, &tlv_params); 840337517Sdavidcs } 841337517Sdavidcs 842337517Sdavidcs if (ret != ECORE_SUCCESS) { 843337517Sdavidcs device_printf(ha->pci_dev, 844337517Sdavidcs "%s: ecore_lldp_set_system_tlvs failed\n", __func__); 845337517Sdavidcs } 846337517Sdavidcs 847337517Sdavidcs return (ret); 848337517Sdavidcs} 849337517Sdavidcs 850337517Sdavidcsstatic int 851337517Sdavidcsqlnx_register_default_lldp_tlvs(qlnx_host_t *ha, struct ecore_hwfn *p_hwfn, 852337517Sdavidcs struct ecore_ptt *p_ptt) 853337517Sdavidcs{ 854337517Sdavidcs int ret = 0; 855337517Sdavidcs 856337517Sdavidcs ret = ecore_lldp_register_tlv(p_hwfn, p_ptt, 857337517Sdavidcs ECORE_LLDP_NEAREST_BRIDGE, QLNX_LLDP_TYPE_CHASSIS_ID); 858337517Sdavidcs if (ret != ECORE_SUCCESS) { 859337517Sdavidcs device_printf(ha->pci_dev, 860337517Sdavidcs "%s: QLNX_LLDP_TYPE_CHASSIS_ID failed\n", __func__); 861337517Sdavidcs goto qlnx_register_default_lldp_tlvs_exit; 862337517Sdavidcs } 863337517Sdavidcs 864337517Sdavidcs //register Port ID TLV 865337517Sdavidcs ret = ecore_lldp_register_tlv(p_hwfn, p_ptt, 866337517Sdavidcs ECORE_LLDP_NEAREST_BRIDGE, QLNX_LLDP_TYPE_PORT_ID); 867337517Sdavidcs if (ret != ECORE_SUCCESS) { 868337517Sdavidcs device_printf(ha->pci_dev, 869337517Sdavidcs "%s: QLNX_LLDP_TYPE_PORT_ID failed\n", __func__); 870337517Sdavidcs goto qlnx_register_default_lldp_tlvs_exit; 871337517Sdavidcs } 872337517Sdavidcs 873337517Sdavidcs //register TTL TLV 874337517Sdavidcs ret = ecore_lldp_register_tlv(p_hwfn, p_ptt, 875337517Sdavidcs ECORE_LLDP_NEAREST_BRIDGE, QLNX_LLDP_TYPE_TTL); 876337517Sdavidcs if (ret != ECORE_SUCCESS) { 877337517Sdavidcs device_printf(ha->pci_dev, 878337517Sdavidcs "%s: QLNX_LLDP_TYPE_TTL failed\n", __func__); 879337517Sdavidcs goto qlnx_register_default_lldp_tlvs_exit; 880337517Sdavidcs } 881337517Sdavidcs 882337517Sdavidcs //register Port Description TLV 883337517Sdavidcs ret = ecore_lldp_register_tlv(p_hwfn, p_ptt, 884337517Sdavidcs ECORE_LLDP_NEAREST_BRIDGE, QLNX_LLDP_TYPE_PORT_DESC); 885337517Sdavidcs if (ret != ECORE_SUCCESS) { 886337517Sdavidcs device_printf(ha->pci_dev, 887337517Sdavidcs "%s: QLNX_LLDP_TYPE_PORT_DESC failed\n", __func__); 888337517Sdavidcs goto qlnx_register_default_lldp_tlvs_exit; 889337517Sdavidcs } 890337517Sdavidcs 891337517Sdavidcs //register System Name TLV 892337517Sdavidcs ret = ecore_lldp_register_tlv(p_hwfn, p_ptt, 893337517Sdavidcs ECORE_LLDP_NEAREST_BRIDGE, QLNX_LLDP_TYPE_SYS_NAME); 894337517Sdavidcs if (ret != ECORE_SUCCESS) { 895337517Sdavidcs device_printf(ha->pci_dev, 896337517Sdavidcs "%s: QLNX_LLDP_TYPE_SYS_NAME failed\n", __func__); 897337517Sdavidcs goto qlnx_register_default_lldp_tlvs_exit; 898337517Sdavidcs } 899337517Sdavidcs 900337517Sdavidcs //register System Description TLV 901337517Sdavidcs ret = ecore_lldp_register_tlv(p_hwfn, p_ptt, 902337517Sdavidcs ECORE_LLDP_NEAREST_BRIDGE, QLNX_LLDP_TYPE_SYS_DESC); 903337517Sdavidcs if (ret != ECORE_SUCCESS) { 904337517Sdavidcs device_printf(ha->pci_dev, 905337517Sdavidcs "%s: QLNX_LLDP_TYPE_SYS_DESC failed\n", __func__); 906337517Sdavidcs goto qlnx_register_default_lldp_tlvs_exit; 907337517Sdavidcs } 908337517Sdavidcs 909337517Sdavidcs //register System Capabilities TLV 910337517Sdavidcs ret = ecore_lldp_register_tlv(p_hwfn, p_ptt, 911337517Sdavidcs ECORE_LLDP_NEAREST_BRIDGE, QLNX_LLDP_TYPE_SYS_CAPS); 912337517Sdavidcs if (ret != ECORE_SUCCESS) { 913337517Sdavidcs device_printf(ha->pci_dev, 914337517Sdavidcs "%s: QLNX_LLDP_TYPE_SYS_CAPS failed\n", __func__); 915337517Sdavidcs goto qlnx_register_default_lldp_tlvs_exit; 916337517Sdavidcs } 917337517Sdavidcs 918337517Sdavidcs //register Management Address TLV 919337517Sdavidcs ret = ecore_lldp_register_tlv(p_hwfn, p_ptt, 920337517Sdavidcs ECORE_LLDP_NEAREST_BRIDGE, QLNX_LLDP_TYPE_MGMT_ADDR); 921337517Sdavidcs if (ret != ECORE_SUCCESS) { 922337517Sdavidcs device_printf(ha->pci_dev, 923337517Sdavidcs "%s: QLNX_LLDP_TYPE_MGMT_ADDR failed\n", __func__); 924337517Sdavidcs goto qlnx_register_default_lldp_tlvs_exit; 925337517Sdavidcs } 926337517Sdavidcs 927337517Sdavidcs //register Organizationally Specific TLVs 928337517Sdavidcs ret = ecore_lldp_register_tlv(p_hwfn, p_ptt, 929337517Sdavidcs ECORE_LLDP_NEAREST_BRIDGE, QLNX_LLDP_TYPE_ORG_SPECIFIC); 930337517Sdavidcs if (ret != ECORE_SUCCESS) { 931337517Sdavidcs device_printf(ha->pci_dev, 932337517Sdavidcs "%s: QLNX_LLDP_TYPE_ORG_SPECIFIC failed\n", __func__); 933337517Sdavidcs } 934337517Sdavidcs 935337517Sdavidcsqlnx_register_default_lldp_tlvs_exit: 936337517Sdavidcs return (ret); 937337517Sdavidcs} 938337517Sdavidcs 939337517Sdavidcsint 940337517Sdavidcsqlnx_set_lldp_tlvx(qlnx_host_t *ha, qlnx_lldp_sys_tlvs_t *lldp_tlvs) 941337517Sdavidcs{ 942337517Sdavidcs int ret = 0; 943337517Sdavidcs struct ecore_hwfn *p_hwfn; 944337517Sdavidcs struct ecore_ptt *p_ptt; 945337517Sdavidcs struct ecore_lldp_sys_tlvs tlv_params; 946337517Sdavidcs 947337517Sdavidcs p_hwfn = &ha->cdev.hwfns[0]; 948337517Sdavidcs p_ptt = ecore_ptt_acquire(p_hwfn); 949337517Sdavidcs 950337517Sdavidcs if (!p_ptt) { 951337517Sdavidcs device_printf(ha->pci_dev, 952337517Sdavidcs "%s: ecore_ptt_acquire failed\n", __func__); 953337517Sdavidcs return (ENXIO); 954337517Sdavidcs } 955337517Sdavidcs 956337517Sdavidcs ret = qlnx_lldp_configure(ha, p_hwfn, p_ptt, 0); 957337517Sdavidcs 958337517Sdavidcs if (ret) { 959337517Sdavidcs device_printf(ha->pci_dev, 960337517Sdavidcs "%s: qlnx_lldp_configure disable failed\n", __func__); 961337517Sdavidcs goto qlnx_set_lldp_tlvx_exit; 962337517Sdavidcs } 963337517Sdavidcs 964337517Sdavidcs ret = qlnx_register_default_lldp_tlvs(ha, p_hwfn, p_ptt); 965337517Sdavidcs 966337517Sdavidcs if (ret) { 967337517Sdavidcs device_printf(ha->pci_dev, 968337517Sdavidcs "%s: qlnx_register_default_lldp_tlvs failed\n", 969337517Sdavidcs __func__); 970337517Sdavidcs goto qlnx_set_lldp_tlvx_exit; 971337517Sdavidcs } 972337517Sdavidcs 973337517Sdavidcs ret = qlnx_lldp_configure(ha, p_hwfn, p_ptt, 1); 974337517Sdavidcs 975337517Sdavidcs if (ret) { 976337517Sdavidcs device_printf(ha->pci_dev, 977337517Sdavidcs "%s: qlnx_lldp_configure enable failed\n", __func__); 978337517Sdavidcs goto qlnx_set_lldp_tlvx_exit; 979337517Sdavidcs } 980337517Sdavidcs 981337517Sdavidcs if (lldp_tlvs != NULL) { 982337517Sdavidcs bzero(&tlv_params, sizeof(struct ecore_lldp_sys_tlvs)); 983337517Sdavidcs 984337517Sdavidcs tlv_params.discard_mandatory_tlv = 985337517Sdavidcs (lldp_tlvs->discard_mandatory_tlv ? true: false); 986337517Sdavidcs tlv_params.buf_size = lldp_tlvs->buf_size; 987337517Sdavidcs memcpy(tlv_params.buf, lldp_tlvs->buf, lldp_tlvs->buf_size); 988337517Sdavidcs 989337517Sdavidcs ret = ecore_lldp_set_system_tlvs(p_hwfn, p_ptt, &tlv_params); 990337517Sdavidcs 991337517Sdavidcs if (ret) { 992337517Sdavidcs device_printf(ha->pci_dev, 993337517Sdavidcs "%s: ecore_lldp_set_system_tlvs failed\n", 994337517Sdavidcs __func__); 995337517Sdavidcs } 996337517Sdavidcs } 997337517Sdavidcsqlnx_set_lldp_tlvx_exit: 998337517Sdavidcs 999337517Sdavidcs ecore_ptt_release(p_hwfn, p_ptt); 1000337517Sdavidcs return (ret); 1001337517Sdavidcs} 1002337517Sdavidcs 1003337517Sdavidcs#endif /* #ifdef QLNX_USER_LLDP */ 1004337517Sdavidcs 1005337517Sdavidcsstatic int 1006316485Sdavidcsqlnx_eioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag, 1007316485Sdavidcs struct thread *td) 1008316485Sdavidcs{ 1009316485Sdavidcs qlnx_host_t *ha; 1010316485Sdavidcs int rval = 0; 1011316485Sdavidcs struct ifnet *ifp; 1012316485Sdavidcs qlnx_trace_t *trace; 1013316485Sdavidcs int i; 1014316485Sdavidcs 1015316485Sdavidcs if ((ha = (qlnx_host_t *)dev->si_drv1) == NULL) 1016316485Sdavidcs return ENXIO; 1017316485Sdavidcs 1018316485Sdavidcs ifp = ha->ifp; 1019316485Sdavidcs 1020316485Sdavidcs switch (cmd) { 1021316485Sdavidcs 1022316485Sdavidcs case QLNX_GRC_DUMP_SIZE: 1023316485Sdavidcs qlnx_get_grc_dump_size(ha, (qlnx_grcdump_t *)data); 1024316485Sdavidcs break; 1025316485Sdavidcs 1026316485Sdavidcs case QLNX_GRC_DUMP: 1027316485Sdavidcs rval = qlnx_get_grc_dump(ha, (qlnx_grcdump_t *)data); 1028316485Sdavidcs break; 1029316485Sdavidcs 1030316485Sdavidcs case QLNX_IDLE_CHK_SIZE: 1031316485Sdavidcs qlnx_get_idle_chk_size(ha, (qlnx_idle_chk_t *)data); 1032316485Sdavidcs break; 1033316485Sdavidcs 1034316485Sdavidcs case QLNX_IDLE_CHK: 1035316485Sdavidcs rval = qlnx_get_idle_chk(ha, (qlnx_idle_chk_t *)data); 1036316485Sdavidcs break; 1037316485Sdavidcs 1038316485Sdavidcs case QLNX_DRV_INFO: 1039316485Sdavidcs rval = qlnx_drv_info(ha, (qlnx_drvinfo_t *)data); 1040316485Sdavidcs break; 1041316485Sdavidcs 1042316485Sdavidcs case QLNX_DEV_SETTING: 1043316485Sdavidcs rval = qlnx_dev_settings(ha, (qlnx_dev_setting_t *)data); 1044316485Sdavidcs break; 1045316485Sdavidcs 1046316485Sdavidcs case QLNX_GET_REGS: 1047316485Sdavidcs rval = qlnx_get_regs(ha, (qlnx_get_regs_t *)data); 1048316485Sdavidcs break; 1049316485Sdavidcs 1050316485Sdavidcs case QLNX_NVRAM: 1051316485Sdavidcs rval = qlnx_nvram(ha, (qlnx_nvram_t *)data); 1052316485Sdavidcs break; 1053316485Sdavidcs 1054316485Sdavidcs case QLNX_RD_WR_REG: 1055316485Sdavidcs rval = qlnx_reg_rd_wr(ha, (qlnx_reg_rd_wr_t *)data); 1056316485Sdavidcs break; 1057316485Sdavidcs 1058316485Sdavidcs case QLNX_RD_WR_PCICFG: 1059316485Sdavidcs rval = qlnx_rd_wr_pci_config(ha, (qlnx_pcicfg_rd_wr_t *)data); 1060316485Sdavidcs break; 1061316485Sdavidcs 1062316485Sdavidcs case QLNX_MAC_ADDR: 1063316485Sdavidcs qlnx_mac_addr(ha, (qlnx_perm_mac_addr_t *)data); 1064316485Sdavidcs break; 1065316485Sdavidcs 1066316485Sdavidcs case QLNX_STORM_STATS: 1067316485Sdavidcs qlnx_storm_stats(ha, (qlnx_storm_stats_dump_t *)data); 1068316485Sdavidcs break; 1069316485Sdavidcs 1070316485Sdavidcs case QLNX_TRACE_SIZE: 1071316485Sdavidcs qlnx_get_trace_size(ha, (qlnx_trace_t *)data); 1072316485Sdavidcs break; 1073316485Sdavidcs 1074316485Sdavidcs case QLNX_TRACE: 1075316485Sdavidcs trace = (qlnx_trace_t *)data; 1076316485Sdavidcs 1077316485Sdavidcs for (i = 0; i < ha->cdev.num_hwfns; i++) { 1078316485Sdavidcs 1079316485Sdavidcs if (trace->size[i] && trace->cmd && trace->buffer[i]) 1080316485Sdavidcs rval = qlnx_get_trace(ha, i, trace); 1081316485Sdavidcs 1082316485Sdavidcs if (rval) 1083316485Sdavidcs break; 1084316485Sdavidcs } 1085316485Sdavidcs break; 1086316485Sdavidcs 1087337517Sdavidcs#ifdef QLNX_USER_LLDP 1088337517Sdavidcs case QLNX_SET_LLDP_TLVS: 1089337517Sdavidcs rval = qlnx_set_lldp_tlvx(ha, (qlnx_lldp_sys_tlvs_t *)data); 1090337517Sdavidcs break; 1091337517Sdavidcs#endif /* #ifdef QLNX_USER_LLDP */ 1092337517Sdavidcs 1093316485Sdavidcs default: 1094316485Sdavidcs rval = EINVAL; 1095316485Sdavidcs break; 1096316485Sdavidcs } 1097316485Sdavidcs 1098316485Sdavidcs return (rval); 1099316485Sdavidcs} 1100316485Sdavidcs 1101