Linux Audio

Check our new training course

Real-Time Linux with PREEMPT_RT training

Feb 18-20, 2025
Register
Loading...
Note: File does not exist in v4.17.
   1// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
   2/* Copyright (c) 2019-2020 Marvell International Ltd. */
   3
   4#include <linux/types.h>
   5#include <asm/byteorder.h>
   6#include <linux/bug.h>
   7#include <linux/errno.h>
   8#include <linux/kernel.h>
   9#include <linux/slab.h>
  10#include <linux/string.h>
  11#include <linux/vmalloc.h>
  12#include "qed.h"
  13#include "qed_hw.h"
  14#include "qed_mcp.h"
  15#include "qed_reg_addr.h"
  16
  17#define TLV_TYPE(p)     (p[0])
  18#define TLV_LENGTH(p)   (p[1])
  19#define TLV_FLAGS(p)    (p[3])
  20
  21#define QED_TLV_DATA_MAX (14)
  22struct qed_tlv_parsed_buf {
  23	/* To be filled with the address to set in Value field */
  24	void *p_val;
  25
  26	/* To be used internally in case the value has to be modified */
  27	u8 data[QED_TLV_DATA_MAX];
  28};
  29
  30static int qed_mfw_get_tlv_group(u8 tlv_type, u8 *tlv_group)
  31{
  32	switch (tlv_type) {
  33	case DRV_TLV_FEATURE_FLAGS:
  34	case DRV_TLV_LOCAL_ADMIN_ADDR:
  35	case DRV_TLV_ADDITIONAL_MAC_ADDR_1:
  36	case DRV_TLV_ADDITIONAL_MAC_ADDR_2:
  37	case DRV_TLV_OS_DRIVER_STATES:
  38	case DRV_TLV_PXE_BOOT_PROGRESS:
  39	case DRV_TLV_RX_FRAMES_RECEIVED:
  40	case DRV_TLV_RX_BYTES_RECEIVED:
  41	case DRV_TLV_TX_FRAMES_SENT:
  42	case DRV_TLV_TX_BYTES_SENT:
  43	case DRV_TLV_NPIV_ENABLED:
  44	case DRV_TLV_PCIE_BUS_RX_UTILIZATION:
  45	case DRV_TLV_PCIE_BUS_TX_UTILIZATION:
  46	case DRV_TLV_DEVICE_CPU_CORES_UTILIZATION:
  47	case DRV_TLV_LAST_VALID_DCC_TLV_RECEIVED:
  48	case DRV_TLV_NCSI_RX_BYTES_RECEIVED:
  49	case DRV_TLV_NCSI_TX_BYTES_SENT:
  50		*tlv_group |= QED_MFW_TLV_GENERIC;
  51		break;
  52	case DRV_TLV_LSO_MAX_OFFLOAD_SIZE:
  53	case DRV_TLV_LSO_MIN_SEGMENT_COUNT:
  54	case DRV_TLV_PROMISCUOUS_MODE:
  55	case DRV_TLV_TX_DESCRIPTORS_QUEUE_SIZE:
  56	case DRV_TLV_RX_DESCRIPTORS_QUEUE_SIZE:
  57	case DRV_TLV_NUM_OF_NET_QUEUE_VMQ_CFG:
  58	case DRV_TLV_NUM_OFFLOADED_CONNECTIONS_TCP_IPV4:
  59	case DRV_TLV_NUM_OFFLOADED_CONNECTIONS_TCP_IPV6:
  60	case DRV_TLV_TX_DESCRIPTOR_QUEUE_AVG_DEPTH:
  61	case DRV_TLV_RX_DESCRIPTORS_QUEUE_AVG_DEPTH:
  62	case DRV_TLV_IOV_OFFLOAD:
  63	case DRV_TLV_TX_QUEUES_EMPTY:
  64	case DRV_TLV_RX_QUEUES_EMPTY:
  65	case DRV_TLV_TX_QUEUES_FULL:
  66	case DRV_TLV_RX_QUEUES_FULL:
  67		*tlv_group |= QED_MFW_TLV_ETH;
  68		break;
  69	case DRV_TLV_SCSI_TO:
  70	case DRV_TLV_R_T_TOV:
  71	case DRV_TLV_R_A_TOV:
  72	case DRV_TLV_E_D_TOV:
  73	case DRV_TLV_CR_TOV:
  74	case DRV_TLV_BOOT_TYPE:
  75	case DRV_TLV_NPIV_STATE:
  76	case DRV_TLV_NUM_OF_NPIV_IDS:
  77	case DRV_TLV_SWITCH_NAME:
  78	case DRV_TLV_SWITCH_PORT_NUM:
  79	case DRV_TLV_SWITCH_PORT_ID:
  80	case DRV_TLV_VENDOR_NAME:
  81	case DRV_TLV_SWITCH_MODEL:
  82	case DRV_TLV_SWITCH_FW_VER:
  83	case DRV_TLV_QOS_PRIORITY_PER_802_1P:
  84	case DRV_TLV_PORT_ALIAS:
  85	case DRV_TLV_PORT_STATE:
  86	case DRV_TLV_FIP_TX_DESCRIPTORS_QUEUE_SIZE:
  87	case DRV_TLV_FCOE_RX_DESCRIPTORS_QUEUE_SIZE:
  88	case DRV_TLV_LINK_FAILURE_COUNT:
  89	case DRV_TLV_FCOE_BOOT_PROGRESS:
  90	case DRV_TLV_RX_BROADCAST_PACKETS:
  91	case DRV_TLV_TX_BROADCAST_PACKETS:
  92	case DRV_TLV_FCOE_TX_DESCRIPTOR_QUEUE_AVG_DEPTH:
  93	case DRV_TLV_FCOE_RX_DESCRIPTORS_QUEUE_AVG_DEPTH:
  94	case DRV_TLV_FCOE_RX_FRAMES_RECEIVED:
  95	case DRV_TLV_FCOE_RX_BYTES_RECEIVED:
  96	case DRV_TLV_FCOE_TX_FRAMES_SENT:
  97	case DRV_TLV_FCOE_TX_BYTES_SENT:
  98	case DRV_TLV_CRC_ERROR_COUNT:
  99	case DRV_TLV_CRC_ERROR_1_RECEIVED_SOURCE_FC_ID:
 100	case DRV_TLV_CRC_ERROR_1_TIMESTAMP:
 101	case DRV_TLV_CRC_ERROR_2_RECEIVED_SOURCE_FC_ID:
 102	case DRV_TLV_CRC_ERROR_2_TIMESTAMP:
 103	case DRV_TLV_CRC_ERROR_3_RECEIVED_SOURCE_FC_ID:
 104	case DRV_TLV_CRC_ERROR_3_TIMESTAMP:
 105	case DRV_TLV_CRC_ERROR_4_RECEIVED_SOURCE_FC_ID:
 106	case DRV_TLV_CRC_ERROR_4_TIMESTAMP:
 107	case DRV_TLV_CRC_ERROR_5_RECEIVED_SOURCE_FC_ID:
 108	case DRV_TLV_CRC_ERROR_5_TIMESTAMP:
 109	case DRV_TLV_LOSS_OF_SYNC_ERROR_COUNT:
 110	case DRV_TLV_LOSS_OF_SIGNAL_ERRORS:
 111	case DRV_TLV_PRIMITIVE_SEQUENCE_PROTOCOL_ERROR_COUNT:
 112	case DRV_TLV_DISPARITY_ERROR_COUNT:
 113	case DRV_TLV_CODE_VIOLATION_ERROR_COUNT:
 114	case DRV_TLV_LAST_FLOGI_ISSUED_COMMON_PARAMETERS_WORD_1:
 115	case DRV_TLV_LAST_FLOGI_ISSUED_COMMON_PARAMETERS_WORD_2:
 116	case DRV_TLV_LAST_FLOGI_ISSUED_COMMON_PARAMETERS_WORD_3:
 117	case DRV_TLV_LAST_FLOGI_ISSUED_COMMON_PARAMETERS_WORD_4:
 118	case DRV_TLV_LAST_FLOGI_TIMESTAMP:
 119	case DRV_TLV_LAST_FLOGI_ACC_COMMON_PARAMETERS_WORD_1:
 120	case DRV_TLV_LAST_FLOGI_ACC_COMMON_PARAMETERS_WORD_2:
 121	case DRV_TLV_LAST_FLOGI_ACC_COMMON_PARAMETERS_WORD_3:
 122	case DRV_TLV_LAST_FLOGI_ACC_COMMON_PARAMETERS_WORD_4:
 123	case DRV_TLV_LAST_FLOGI_ACC_TIMESTAMP:
 124	case DRV_TLV_LAST_FLOGI_RJT:
 125	case DRV_TLV_LAST_FLOGI_RJT_TIMESTAMP:
 126	case DRV_TLV_FDISCS_SENT_COUNT:
 127	case DRV_TLV_FDISC_ACCS_RECEIVED:
 128	case DRV_TLV_FDISC_RJTS_RECEIVED:
 129	case DRV_TLV_PLOGI_SENT_COUNT:
 130	case DRV_TLV_PLOGI_ACCS_RECEIVED:
 131	case DRV_TLV_PLOGI_RJTS_RECEIVED:
 132	case DRV_TLV_PLOGI_1_SENT_DESTINATION_FC_ID:
 133	case DRV_TLV_PLOGI_1_TIMESTAMP:
 134	case DRV_TLV_PLOGI_2_SENT_DESTINATION_FC_ID:
 135	case DRV_TLV_PLOGI_2_TIMESTAMP:
 136	case DRV_TLV_PLOGI_3_SENT_DESTINATION_FC_ID:
 137	case DRV_TLV_PLOGI_3_TIMESTAMP:
 138	case DRV_TLV_PLOGI_4_SENT_DESTINATION_FC_ID:
 139	case DRV_TLV_PLOGI_4_TIMESTAMP:
 140	case DRV_TLV_PLOGI_5_SENT_DESTINATION_FC_ID:
 141	case DRV_TLV_PLOGI_5_TIMESTAMP:
 142	case DRV_TLV_PLOGI_1_ACC_RECEIVED_SOURCE_FC_ID:
 143	case DRV_TLV_PLOGI_1_ACC_TIMESTAMP:
 144	case DRV_TLV_PLOGI_2_ACC_RECEIVED_SOURCE_FC_ID:
 145	case DRV_TLV_PLOGI_2_ACC_TIMESTAMP:
 146	case DRV_TLV_PLOGI_3_ACC_RECEIVED_SOURCE_FC_ID:
 147	case DRV_TLV_PLOGI_3_ACC_TIMESTAMP:
 148	case DRV_TLV_PLOGI_4_ACC_RECEIVED_SOURCE_FC_ID:
 149	case DRV_TLV_PLOGI_4_ACC_TIMESTAMP:
 150	case DRV_TLV_PLOGI_5_ACC_RECEIVED_SOURCE_FC_ID:
 151	case DRV_TLV_PLOGI_5_ACC_TIMESTAMP:
 152	case DRV_TLV_LOGOS_ISSUED:
 153	case DRV_TLV_LOGO_ACCS_RECEIVED:
 154	case DRV_TLV_LOGO_RJTS_RECEIVED:
 155	case DRV_TLV_LOGO_1_RECEIVED_SOURCE_FC_ID:
 156	case DRV_TLV_LOGO_1_TIMESTAMP:
 157	case DRV_TLV_LOGO_2_RECEIVED_SOURCE_FC_ID:
 158	case DRV_TLV_LOGO_2_TIMESTAMP:
 159	case DRV_TLV_LOGO_3_RECEIVED_SOURCE_FC_ID:
 160	case DRV_TLV_LOGO_3_TIMESTAMP:
 161	case DRV_TLV_LOGO_4_RECEIVED_SOURCE_FC_ID:
 162	case DRV_TLV_LOGO_4_TIMESTAMP:
 163	case DRV_TLV_LOGO_5_RECEIVED_SOURCE_FC_ID:
 164	case DRV_TLV_LOGO_5_TIMESTAMP:
 165	case DRV_TLV_LOGOS_RECEIVED:
 166	case DRV_TLV_ACCS_ISSUED:
 167	case DRV_TLV_PRLIS_ISSUED:
 168	case DRV_TLV_ACCS_RECEIVED:
 169	case DRV_TLV_ABTS_SENT_COUNT:
 170	case DRV_TLV_ABTS_ACCS_RECEIVED:
 171	case DRV_TLV_ABTS_RJTS_RECEIVED:
 172	case DRV_TLV_ABTS_1_SENT_DESTINATION_FC_ID:
 173	case DRV_TLV_ABTS_1_TIMESTAMP:
 174	case DRV_TLV_ABTS_2_SENT_DESTINATION_FC_ID:
 175	case DRV_TLV_ABTS_2_TIMESTAMP:
 176	case DRV_TLV_ABTS_3_SENT_DESTINATION_FC_ID:
 177	case DRV_TLV_ABTS_3_TIMESTAMP:
 178	case DRV_TLV_ABTS_4_SENT_DESTINATION_FC_ID:
 179	case DRV_TLV_ABTS_4_TIMESTAMP:
 180	case DRV_TLV_ABTS_5_SENT_DESTINATION_FC_ID:
 181	case DRV_TLV_ABTS_5_TIMESTAMP:
 182	case DRV_TLV_RSCNS_RECEIVED:
 183	case DRV_TLV_LAST_RSCN_RECEIVED_N_PORT_1:
 184	case DRV_TLV_LAST_RSCN_RECEIVED_N_PORT_2:
 185	case DRV_TLV_LAST_RSCN_RECEIVED_N_PORT_3:
 186	case DRV_TLV_LAST_RSCN_RECEIVED_N_PORT_4:
 187	case DRV_TLV_LUN_RESETS_ISSUED:
 188	case DRV_TLV_ABORT_TASK_SETS_ISSUED:
 189	case DRV_TLV_TPRLOS_SENT:
 190	case DRV_TLV_NOS_SENT_COUNT:
 191	case DRV_TLV_NOS_RECEIVED_COUNT:
 192	case DRV_TLV_OLS_COUNT:
 193	case DRV_TLV_LR_COUNT:
 194	case DRV_TLV_LRR_COUNT:
 195	case DRV_TLV_LIP_SENT_COUNT:
 196	case DRV_TLV_LIP_RECEIVED_COUNT:
 197	case DRV_TLV_EOFA_COUNT:
 198	case DRV_TLV_EOFNI_COUNT:
 199	case DRV_TLV_SCSI_STATUS_CHECK_CONDITION_COUNT:
 200	case DRV_TLV_SCSI_STATUS_CONDITION_MET_COUNT:
 201	case DRV_TLV_SCSI_STATUS_BUSY_COUNT:
 202	case DRV_TLV_SCSI_STATUS_INTERMEDIATE_COUNT:
 203	case DRV_TLV_SCSI_STATUS_INTERMEDIATE_CONDITION_MET_COUNT:
 204	case DRV_TLV_SCSI_STATUS_RESERVATION_CONFLICT_COUNT:
 205	case DRV_TLV_SCSI_STATUS_TASK_SET_FULL_COUNT:
 206	case DRV_TLV_SCSI_STATUS_ACA_ACTIVE_COUNT:
 207	case DRV_TLV_SCSI_STATUS_TASK_ABORTED_COUNT:
 208	case DRV_TLV_SCSI_CHECK_CONDITION_1_RECEIVED_SK_ASC_ASCQ:
 209	case DRV_TLV_SCSI_CHECK_1_TIMESTAMP:
 210	case DRV_TLV_SCSI_CHECK_CONDITION_2_RECEIVED_SK_ASC_ASCQ:
 211	case DRV_TLV_SCSI_CHECK_2_TIMESTAMP:
 212	case DRV_TLV_SCSI_CHECK_CONDITION_3_RECEIVED_SK_ASC_ASCQ:
 213	case DRV_TLV_SCSI_CHECK_3_TIMESTAMP:
 214	case DRV_TLV_SCSI_CHECK_CONDITION_4_RECEIVED_SK_ASC_ASCQ:
 215	case DRV_TLV_SCSI_CHECK_4_TIMESTAMP:
 216	case DRV_TLV_SCSI_CHECK_CONDITION_5_RECEIVED_SK_ASC_ASCQ:
 217	case DRV_TLV_SCSI_CHECK_5_TIMESTAMP:
 218		*tlv_group = QED_MFW_TLV_FCOE;
 219		break;
 220	case DRV_TLV_TARGET_LLMNR_ENABLED:
 221	case DRV_TLV_HEADER_DIGEST_FLAG_ENABLED:
 222	case DRV_TLV_DATA_DIGEST_FLAG_ENABLED:
 223	case DRV_TLV_AUTHENTICATION_METHOD:
 224	case DRV_TLV_ISCSI_BOOT_TARGET_PORTAL:
 225	case DRV_TLV_MAX_FRAME_SIZE:
 226	case DRV_TLV_PDU_TX_DESCRIPTORS_QUEUE_SIZE:
 227	case DRV_TLV_PDU_RX_DESCRIPTORS_QUEUE_SIZE:
 228	case DRV_TLV_ISCSI_BOOT_PROGRESS:
 229	case DRV_TLV_PDU_TX_DESCRIPTOR_QUEUE_AVG_DEPTH:
 230	case DRV_TLV_PDU_RX_DESCRIPTORS_QUEUE_AVG_DEPTH:
 231	case DRV_TLV_ISCSI_PDU_RX_FRAMES_RECEIVED:
 232	case DRV_TLV_ISCSI_PDU_RX_BYTES_RECEIVED:
 233	case DRV_TLV_ISCSI_PDU_TX_FRAMES_SENT:
 234	case DRV_TLV_ISCSI_PDU_TX_BYTES_SENT:
 235		*tlv_group |= QED_MFW_TLV_ISCSI;
 236		break;
 237	default:
 238		return -EINVAL;
 239	}
 240
 241	return 0;
 242}
 243
 244/* Returns size of the data buffer or, -1 in case TLV data is not available. */
 245static int
 246qed_mfw_get_gen_tlv_value(struct qed_drv_tlv_hdr *p_tlv,
 247			  struct qed_mfw_tlv_generic *p_drv_buf,
 248			  struct qed_tlv_parsed_buf *p_buf)
 249{
 250	switch (p_tlv->tlv_type) {
 251	case DRV_TLV_FEATURE_FLAGS:
 252		if (p_drv_buf->flags.b_set) {
 253			memset(p_buf->data, 0, sizeof(u8) * QED_TLV_DATA_MAX);
 254			p_buf->data[0] = p_drv_buf->flags.ipv4_csum_offload ?
 255			    1 : 0;
 256			p_buf->data[0] |= (p_drv_buf->flags.lso_supported ?
 257					   1 : 0) << 1;
 258			p_buf->p_val = p_buf->data;
 259			return QED_MFW_TLV_FLAGS_SIZE;
 260		}
 261		break;
 262
 263	case DRV_TLV_LOCAL_ADMIN_ADDR:
 264	case DRV_TLV_ADDITIONAL_MAC_ADDR_1:
 265	case DRV_TLV_ADDITIONAL_MAC_ADDR_2:
 266		{
 267			int idx = p_tlv->tlv_type - DRV_TLV_LOCAL_ADMIN_ADDR;
 268
 269			if (p_drv_buf->mac_set[idx]) {
 270				p_buf->p_val = p_drv_buf->mac[idx];
 271				return ETH_ALEN;
 272			}
 273			break;
 274		}
 275
 276	case DRV_TLV_RX_FRAMES_RECEIVED:
 277		if (p_drv_buf->rx_frames_set) {
 278			p_buf->p_val = &p_drv_buf->rx_frames;
 279			return sizeof(p_drv_buf->rx_frames);
 280		}
 281		break;
 282	case DRV_TLV_RX_BYTES_RECEIVED:
 283		if (p_drv_buf->rx_bytes_set) {
 284			p_buf->p_val = &p_drv_buf->rx_bytes;
 285			return sizeof(p_drv_buf->rx_bytes);
 286		}
 287		break;
 288	case DRV_TLV_TX_FRAMES_SENT:
 289		if (p_drv_buf->tx_frames_set) {
 290			p_buf->p_val = &p_drv_buf->tx_frames;
 291			return sizeof(p_drv_buf->tx_frames);
 292		}
 293		break;
 294	case DRV_TLV_TX_BYTES_SENT:
 295		if (p_drv_buf->tx_bytes_set) {
 296			p_buf->p_val = &p_drv_buf->tx_bytes;
 297			return sizeof(p_drv_buf->tx_bytes);
 298		}
 299		break;
 300	default:
 301		break;
 302	}
 303
 304	return -1;
 305}
 306
 307static int
 308qed_mfw_get_eth_tlv_value(struct qed_drv_tlv_hdr *p_tlv,
 309			  struct qed_mfw_tlv_eth *p_drv_buf,
 310			  struct qed_tlv_parsed_buf *p_buf)
 311{
 312	switch (p_tlv->tlv_type) {
 313	case DRV_TLV_LSO_MAX_OFFLOAD_SIZE:
 314		if (p_drv_buf->lso_maxoff_size_set) {
 315			p_buf->p_val = &p_drv_buf->lso_maxoff_size;
 316			return sizeof(p_drv_buf->lso_maxoff_size);
 317		}
 318		break;
 319	case DRV_TLV_LSO_MIN_SEGMENT_COUNT:
 320		if (p_drv_buf->lso_minseg_size_set) {
 321			p_buf->p_val = &p_drv_buf->lso_minseg_size;
 322			return sizeof(p_drv_buf->lso_minseg_size);
 323		}
 324		break;
 325	case DRV_TLV_PROMISCUOUS_MODE:
 326		if (p_drv_buf->prom_mode_set) {
 327			p_buf->p_val = &p_drv_buf->prom_mode;
 328			return sizeof(p_drv_buf->prom_mode);
 329		}
 330		break;
 331	case DRV_TLV_TX_DESCRIPTORS_QUEUE_SIZE:
 332		if (p_drv_buf->tx_descr_size_set) {
 333			p_buf->p_val = &p_drv_buf->tx_descr_size;
 334			return sizeof(p_drv_buf->tx_descr_size);
 335		}
 336		break;
 337	case DRV_TLV_RX_DESCRIPTORS_QUEUE_SIZE:
 338		if (p_drv_buf->rx_descr_size_set) {
 339			p_buf->p_val = &p_drv_buf->rx_descr_size;
 340			return sizeof(p_drv_buf->rx_descr_size);
 341		}
 342		break;
 343	case DRV_TLV_NUM_OF_NET_QUEUE_VMQ_CFG:
 344		if (p_drv_buf->netq_count_set) {
 345			p_buf->p_val = &p_drv_buf->netq_count;
 346			return sizeof(p_drv_buf->netq_count);
 347		}
 348		break;
 349	case DRV_TLV_NUM_OFFLOADED_CONNECTIONS_TCP_IPV4:
 350		if (p_drv_buf->tcp4_offloads_set) {
 351			p_buf->p_val = &p_drv_buf->tcp4_offloads;
 352			return sizeof(p_drv_buf->tcp4_offloads);
 353		}
 354		break;
 355	case DRV_TLV_NUM_OFFLOADED_CONNECTIONS_TCP_IPV6:
 356		if (p_drv_buf->tcp6_offloads_set) {
 357			p_buf->p_val = &p_drv_buf->tcp6_offloads;
 358			return sizeof(p_drv_buf->tcp6_offloads);
 359		}
 360		break;
 361	case DRV_TLV_TX_DESCRIPTOR_QUEUE_AVG_DEPTH:
 362		if (p_drv_buf->tx_descr_qdepth_set) {
 363			p_buf->p_val = &p_drv_buf->tx_descr_qdepth;
 364			return sizeof(p_drv_buf->tx_descr_qdepth);
 365		}
 366		break;
 367	case DRV_TLV_RX_DESCRIPTORS_QUEUE_AVG_DEPTH:
 368		if (p_drv_buf->rx_descr_qdepth_set) {
 369			p_buf->p_val = &p_drv_buf->rx_descr_qdepth;
 370			return sizeof(p_drv_buf->rx_descr_qdepth);
 371		}
 372		break;
 373	case DRV_TLV_IOV_OFFLOAD:
 374		if (p_drv_buf->iov_offload_set) {
 375			p_buf->p_val = &p_drv_buf->iov_offload;
 376			return sizeof(p_drv_buf->iov_offload);
 377		}
 378		break;
 379	case DRV_TLV_TX_QUEUES_EMPTY:
 380		if (p_drv_buf->txqs_empty_set) {
 381			p_buf->p_val = &p_drv_buf->txqs_empty;
 382			return sizeof(p_drv_buf->txqs_empty);
 383		}
 384		break;
 385	case DRV_TLV_RX_QUEUES_EMPTY:
 386		if (p_drv_buf->rxqs_empty_set) {
 387			p_buf->p_val = &p_drv_buf->rxqs_empty;
 388			return sizeof(p_drv_buf->rxqs_empty);
 389		}
 390		break;
 391	case DRV_TLV_TX_QUEUES_FULL:
 392		if (p_drv_buf->num_txqs_full_set) {
 393			p_buf->p_val = &p_drv_buf->num_txqs_full;
 394			return sizeof(p_drv_buf->num_txqs_full);
 395		}
 396		break;
 397	case DRV_TLV_RX_QUEUES_FULL:
 398		if (p_drv_buf->num_rxqs_full_set) {
 399			p_buf->p_val = &p_drv_buf->num_rxqs_full;
 400			return sizeof(p_drv_buf->num_rxqs_full);
 401		}
 402		break;
 403	default:
 404		break;
 405	}
 406
 407	return -1;
 408}
 409
 410static int
 411qed_mfw_get_tlv_time_value(struct qed_mfw_tlv_time *p_time,
 412			   struct qed_tlv_parsed_buf *p_buf)
 413{
 414	if (!p_time->b_set)
 415		return -1;
 416
 417	/* Validate numbers */
 418	if (p_time->month > 12)
 419		p_time->month = 0;
 420	if (p_time->day > 31)
 421		p_time->day = 0;
 422	if (p_time->hour > 23)
 423		p_time->hour = 0;
 424	if (p_time->min > 59)
 425		p_time->min = 0;
 426	if (p_time->msec > 999)
 427		p_time->msec = 0;
 428	if (p_time->usec > 999)
 429		p_time->usec = 0;
 430
 431	memset(p_buf->data, 0, sizeof(u8) * QED_TLV_DATA_MAX);
 432	snprintf(p_buf->data, 14, "%d%d%d%d%d%d",
 433		 p_time->month, p_time->day,
 434		 p_time->hour, p_time->min, p_time->msec, p_time->usec);
 435
 436	p_buf->p_val = p_buf->data;
 437
 438	return QED_MFW_TLV_TIME_SIZE;
 439}
 440
 441static int
 442qed_mfw_get_fcoe_tlv_value(struct qed_drv_tlv_hdr *p_tlv,
 443			   struct qed_mfw_tlv_fcoe *p_drv_buf,
 444			   struct qed_tlv_parsed_buf *p_buf)
 445{
 446	struct qed_mfw_tlv_time *p_time;
 447	u8 idx;
 448
 449	switch (p_tlv->tlv_type) {
 450	case DRV_TLV_SCSI_TO:
 451		if (p_drv_buf->scsi_timeout_set) {
 452			p_buf->p_val = &p_drv_buf->scsi_timeout;
 453			return sizeof(p_drv_buf->scsi_timeout);
 454		}
 455		break;
 456	case DRV_TLV_R_T_TOV:
 457		if (p_drv_buf->rt_tov_set) {
 458			p_buf->p_val = &p_drv_buf->rt_tov;
 459			return sizeof(p_drv_buf->rt_tov);
 460		}
 461		break;
 462	case DRV_TLV_R_A_TOV:
 463		if (p_drv_buf->ra_tov_set) {
 464			p_buf->p_val = &p_drv_buf->ra_tov;
 465			return sizeof(p_drv_buf->ra_tov);
 466		}
 467		break;
 468	case DRV_TLV_E_D_TOV:
 469		if (p_drv_buf->ed_tov_set) {
 470			p_buf->p_val = &p_drv_buf->ed_tov;
 471			return sizeof(p_drv_buf->ed_tov);
 472		}
 473		break;
 474	case DRV_TLV_CR_TOV:
 475		if (p_drv_buf->cr_tov_set) {
 476			p_buf->p_val = &p_drv_buf->cr_tov;
 477			return sizeof(p_drv_buf->cr_tov);
 478		}
 479		break;
 480	case DRV_TLV_BOOT_TYPE:
 481		if (p_drv_buf->boot_type_set) {
 482			p_buf->p_val = &p_drv_buf->boot_type;
 483			return sizeof(p_drv_buf->boot_type);
 484		}
 485		break;
 486	case DRV_TLV_NPIV_STATE:
 487		if (p_drv_buf->npiv_state_set) {
 488			p_buf->p_val = &p_drv_buf->npiv_state;
 489			return sizeof(p_drv_buf->npiv_state);
 490		}
 491		break;
 492	case DRV_TLV_NUM_OF_NPIV_IDS:
 493		if (p_drv_buf->num_npiv_ids_set) {
 494			p_buf->p_val = &p_drv_buf->num_npiv_ids;
 495			return sizeof(p_drv_buf->num_npiv_ids);
 496		}
 497		break;
 498	case DRV_TLV_SWITCH_NAME:
 499		if (p_drv_buf->switch_name_set) {
 500			p_buf->p_val = &p_drv_buf->switch_name;
 501			return sizeof(p_drv_buf->switch_name);
 502		}
 503		break;
 504	case DRV_TLV_SWITCH_PORT_NUM:
 505		if (p_drv_buf->switch_portnum_set) {
 506			p_buf->p_val = &p_drv_buf->switch_portnum;
 507			return sizeof(p_drv_buf->switch_portnum);
 508		}
 509		break;
 510	case DRV_TLV_SWITCH_PORT_ID:
 511		if (p_drv_buf->switch_portid_set) {
 512			p_buf->p_val = &p_drv_buf->switch_portid;
 513			return sizeof(p_drv_buf->switch_portid);
 514		}
 515		break;
 516	case DRV_TLV_VENDOR_NAME:
 517		if (p_drv_buf->vendor_name_set) {
 518			p_buf->p_val = &p_drv_buf->vendor_name;
 519			return sizeof(p_drv_buf->vendor_name);
 520		}
 521		break;
 522	case DRV_TLV_SWITCH_MODEL:
 523		if (p_drv_buf->switch_model_set) {
 524			p_buf->p_val = &p_drv_buf->switch_model;
 525			return sizeof(p_drv_buf->switch_model);
 526		}
 527		break;
 528	case DRV_TLV_SWITCH_FW_VER:
 529		if (p_drv_buf->switch_fw_version_set) {
 530			p_buf->p_val = &p_drv_buf->switch_fw_version;
 531			return sizeof(p_drv_buf->switch_fw_version);
 532		}
 533		break;
 534	case DRV_TLV_QOS_PRIORITY_PER_802_1P:
 535		if (p_drv_buf->qos_pri_set) {
 536			p_buf->p_val = &p_drv_buf->qos_pri;
 537			return sizeof(p_drv_buf->qos_pri);
 538		}
 539		break;
 540	case DRV_TLV_PORT_ALIAS:
 541		if (p_drv_buf->port_alias_set) {
 542			p_buf->p_val = &p_drv_buf->port_alias;
 543			return sizeof(p_drv_buf->port_alias);
 544		}
 545		break;
 546	case DRV_TLV_PORT_STATE:
 547		if (p_drv_buf->port_state_set) {
 548			p_buf->p_val = &p_drv_buf->port_state;
 549			return sizeof(p_drv_buf->port_state);
 550		}
 551		break;
 552	case DRV_TLV_FIP_TX_DESCRIPTORS_QUEUE_SIZE:
 553		if (p_drv_buf->fip_tx_descr_size_set) {
 554			p_buf->p_val = &p_drv_buf->fip_tx_descr_size;
 555			return sizeof(p_drv_buf->fip_tx_descr_size);
 556		}
 557		break;
 558	case DRV_TLV_FCOE_RX_DESCRIPTORS_QUEUE_SIZE:
 559		if (p_drv_buf->fip_rx_descr_size_set) {
 560			p_buf->p_val = &p_drv_buf->fip_rx_descr_size;
 561			return sizeof(p_drv_buf->fip_rx_descr_size);
 562		}
 563		break;
 564	case DRV_TLV_LINK_FAILURE_COUNT:
 565		if (p_drv_buf->link_failures_set) {
 566			p_buf->p_val = &p_drv_buf->link_failures;
 567			return sizeof(p_drv_buf->link_failures);
 568		}
 569		break;
 570	case DRV_TLV_FCOE_BOOT_PROGRESS:
 571		if (p_drv_buf->fcoe_boot_progress_set) {
 572			p_buf->p_val = &p_drv_buf->fcoe_boot_progress;
 573			return sizeof(p_drv_buf->fcoe_boot_progress);
 574		}
 575		break;
 576	case DRV_TLV_RX_BROADCAST_PACKETS:
 577		if (p_drv_buf->rx_bcast_set) {
 578			p_buf->p_val = &p_drv_buf->rx_bcast;
 579			return sizeof(p_drv_buf->rx_bcast);
 580		}
 581		break;
 582	case DRV_TLV_TX_BROADCAST_PACKETS:
 583		if (p_drv_buf->tx_bcast_set) {
 584			p_buf->p_val = &p_drv_buf->tx_bcast;
 585			return sizeof(p_drv_buf->tx_bcast);
 586		}
 587		break;
 588	case DRV_TLV_FCOE_TX_DESCRIPTOR_QUEUE_AVG_DEPTH:
 589		if (p_drv_buf->fcoe_txq_depth_set) {
 590			p_buf->p_val = &p_drv_buf->fcoe_txq_depth;
 591			return sizeof(p_drv_buf->fcoe_txq_depth);
 592		}
 593		break;
 594	case DRV_TLV_FCOE_RX_DESCRIPTORS_QUEUE_AVG_DEPTH:
 595		if (p_drv_buf->fcoe_rxq_depth_set) {
 596			p_buf->p_val = &p_drv_buf->fcoe_rxq_depth;
 597			return sizeof(p_drv_buf->fcoe_rxq_depth);
 598		}
 599		break;
 600	case DRV_TLV_FCOE_RX_FRAMES_RECEIVED:
 601		if (p_drv_buf->fcoe_rx_frames_set) {
 602			p_buf->p_val = &p_drv_buf->fcoe_rx_frames;
 603			return sizeof(p_drv_buf->fcoe_rx_frames);
 604		}
 605		break;
 606	case DRV_TLV_FCOE_RX_BYTES_RECEIVED:
 607		if (p_drv_buf->fcoe_rx_bytes_set) {
 608			p_buf->p_val = &p_drv_buf->fcoe_rx_bytes;
 609			return sizeof(p_drv_buf->fcoe_rx_bytes);
 610		}
 611		break;
 612	case DRV_TLV_FCOE_TX_FRAMES_SENT:
 613		if (p_drv_buf->fcoe_tx_frames_set) {
 614			p_buf->p_val = &p_drv_buf->fcoe_tx_frames;
 615			return sizeof(p_drv_buf->fcoe_tx_frames);
 616		}
 617		break;
 618	case DRV_TLV_FCOE_TX_BYTES_SENT:
 619		if (p_drv_buf->fcoe_tx_bytes_set) {
 620			p_buf->p_val = &p_drv_buf->fcoe_tx_bytes;
 621			return sizeof(p_drv_buf->fcoe_tx_bytes);
 622		}
 623		break;
 624	case DRV_TLV_CRC_ERROR_COUNT:
 625		if (p_drv_buf->crc_count_set) {
 626			p_buf->p_val = &p_drv_buf->crc_count;
 627			return sizeof(p_drv_buf->crc_count);
 628		}
 629		break;
 630	case DRV_TLV_CRC_ERROR_1_RECEIVED_SOURCE_FC_ID:
 631	case DRV_TLV_CRC_ERROR_2_RECEIVED_SOURCE_FC_ID:
 632	case DRV_TLV_CRC_ERROR_3_RECEIVED_SOURCE_FC_ID:
 633	case DRV_TLV_CRC_ERROR_4_RECEIVED_SOURCE_FC_ID:
 634	case DRV_TLV_CRC_ERROR_5_RECEIVED_SOURCE_FC_ID:
 635		idx = (p_tlv->tlv_type -
 636		       DRV_TLV_CRC_ERROR_1_RECEIVED_SOURCE_FC_ID) / 2;
 637
 638		if (p_drv_buf->crc_err_src_fcid_set[idx]) {
 639			p_buf->p_val = &p_drv_buf->crc_err_src_fcid[idx];
 640			return sizeof(p_drv_buf->crc_err_src_fcid[idx]);
 641		}
 642		break;
 643	case DRV_TLV_CRC_ERROR_1_TIMESTAMP:
 644	case DRV_TLV_CRC_ERROR_2_TIMESTAMP:
 645	case DRV_TLV_CRC_ERROR_3_TIMESTAMP:
 646	case DRV_TLV_CRC_ERROR_4_TIMESTAMP:
 647	case DRV_TLV_CRC_ERROR_5_TIMESTAMP:
 648		idx = (p_tlv->tlv_type - DRV_TLV_CRC_ERROR_1_TIMESTAMP) / 2;
 649
 650		return qed_mfw_get_tlv_time_value(&p_drv_buf->crc_err[idx],
 651						  p_buf);
 652	case DRV_TLV_LOSS_OF_SYNC_ERROR_COUNT:
 653		if (p_drv_buf->losync_err_set) {
 654			p_buf->p_val = &p_drv_buf->losync_err;
 655			return sizeof(p_drv_buf->losync_err);
 656		}
 657		break;
 658	case DRV_TLV_LOSS_OF_SIGNAL_ERRORS:
 659		if (p_drv_buf->losig_err_set) {
 660			p_buf->p_val = &p_drv_buf->losig_err;
 661			return sizeof(p_drv_buf->losig_err);
 662		}
 663		break;
 664	case DRV_TLV_PRIMITIVE_SEQUENCE_PROTOCOL_ERROR_COUNT:
 665		if (p_drv_buf->primtive_err_set) {
 666			p_buf->p_val = &p_drv_buf->primtive_err;
 667			return sizeof(p_drv_buf->primtive_err);
 668		}
 669		break;
 670	case DRV_TLV_DISPARITY_ERROR_COUNT:
 671		if (p_drv_buf->disparity_err_set) {
 672			p_buf->p_val = &p_drv_buf->disparity_err;
 673			return sizeof(p_drv_buf->disparity_err);
 674		}
 675		break;
 676	case DRV_TLV_CODE_VIOLATION_ERROR_COUNT:
 677		if (p_drv_buf->code_violation_err_set) {
 678			p_buf->p_val = &p_drv_buf->code_violation_err;
 679			return sizeof(p_drv_buf->code_violation_err);
 680		}
 681		break;
 682	case DRV_TLV_LAST_FLOGI_ISSUED_COMMON_PARAMETERS_WORD_1:
 683	case DRV_TLV_LAST_FLOGI_ISSUED_COMMON_PARAMETERS_WORD_2:
 684	case DRV_TLV_LAST_FLOGI_ISSUED_COMMON_PARAMETERS_WORD_3:
 685	case DRV_TLV_LAST_FLOGI_ISSUED_COMMON_PARAMETERS_WORD_4:
 686		idx = p_tlv->tlv_type -
 687			DRV_TLV_LAST_FLOGI_ISSUED_COMMON_PARAMETERS_WORD_1;
 688		if (p_drv_buf->flogi_param_set[idx]) {
 689			p_buf->p_val = &p_drv_buf->flogi_param[idx];
 690			return sizeof(p_drv_buf->flogi_param[idx]);
 691		}
 692		break;
 693	case DRV_TLV_LAST_FLOGI_TIMESTAMP:
 694		return qed_mfw_get_tlv_time_value(&p_drv_buf->flogi_tstamp,
 695						  p_buf);
 696	case DRV_TLV_LAST_FLOGI_ACC_COMMON_PARAMETERS_WORD_1:
 697	case DRV_TLV_LAST_FLOGI_ACC_COMMON_PARAMETERS_WORD_2:
 698	case DRV_TLV_LAST_FLOGI_ACC_COMMON_PARAMETERS_WORD_3:
 699	case DRV_TLV_LAST_FLOGI_ACC_COMMON_PARAMETERS_WORD_4:
 700		idx = p_tlv->tlv_type -
 701			DRV_TLV_LAST_FLOGI_ACC_COMMON_PARAMETERS_WORD_1;
 702
 703		if (p_drv_buf->flogi_acc_param_set[idx]) {
 704			p_buf->p_val = &p_drv_buf->flogi_acc_param[idx];
 705			return sizeof(p_drv_buf->flogi_acc_param[idx]);
 706		}
 707		break;
 708	case DRV_TLV_LAST_FLOGI_ACC_TIMESTAMP:
 709		return qed_mfw_get_tlv_time_value(&p_drv_buf->flogi_acc_tstamp,
 710						  p_buf);
 711	case DRV_TLV_LAST_FLOGI_RJT:
 712		if (p_drv_buf->flogi_rjt_set) {
 713			p_buf->p_val = &p_drv_buf->flogi_rjt;
 714			return sizeof(p_drv_buf->flogi_rjt);
 715		}
 716		break;
 717	case DRV_TLV_LAST_FLOGI_RJT_TIMESTAMP:
 718		return qed_mfw_get_tlv_time_value(&p_drv_buf->flogi_rjt_tstamp,
 719						  p_buf);
 720	case DRV_TLV_FDISCS_SENT_COUNT:
 721		if (p_drv_buf->fdiscs_set) {
 722			p_buf->p_val = &p_drv_buf->fdiscs;
 723			return sizeof(p_drv_buf->fdiscs);
 724		}
 725		break;
 726	case DRV_TLV_FDISC_ACCS_RECEIVED:
 727		if (p_drv_buf->fdisc_acc_set) {
 728			p_buf->p_val = &p_drv_buf->fdisc_acc;
 729			return sizeof(p_drv_buf->fdisc_acc);
 730		}
 731		break;
 732	case DRV_TLV_FDISC_RJTS_RECEIVED:
 733		if (p_drv_buf->fdisc_rjt_set) {
 734			p_buf->p_val = &p_drv_buf->fdisc_rjt;
 735			return sizeof(p_drv_buf->fdisc_rjt);
 736		}
 737		break;
 738	case DRV_TLV_PLOGI_SENT_COUNT:
 739		if (p_drv_buf->plogi_set) {
 740			p_buf->p_val = &p_drv_buf->plogi;
 741			return sizeof(p_drv_buf->plogi);
 742		}
 743		break;
 744	case DRV_TLV_PLOGI_ACCS_RECEIVED:
 745		if (p_drv_buf->plogi_acc_set) {
 746			p_buf->p_val = &p_drv_buf->plogi_acc;
 747			return sizeof(p_drv_buf->plogi_acc);
 748		}
 749		break;
 750	case DRV_TLV_PLOGI_RJTS_RECEIVED:
 751		if (p_drv_buf->plogi_rjt_set) {
 752			p_buf->p_val = &p_drv_buf->plogi_rjt;
 753			return sizeof(p_drv_buf->plogi_rjt);
 754		}
 755		break;
 756	case DRV_TLV_PLOGI_1_SENT_DESTINATION_FC_ID:
 757	case DRV_TLV_PLOGI_2_SENT_DESTINATION_FC_ID:
 758	case DRV_TLV_PLOGI_3_SENT_DESTINATION_FC_ID:
 759	case DRV_TLV_PLOGI_4_SENT_DESTINATION_FC_ID:
 760	case DRV_TLV_PLOGI_5_SENT_DESTINATION_FC_ID:
 761		idx = (p_tlv->tlv_type -
 762		       DRV_TLV_PLOGI_1_SENT_DESTINATION_FC_ID) / 2;
 763
 764		if (p_drv_buf->plogi_dst_fcid_set[idx]) {
 765			p_buf->p_val = &p_drv_buf->plogi_dst_fcid[idx];
 766			return sizeof(p_drv_buf->plogi_dst_fcid[idx]);
 767		}
 768		break;
 769	case DRV_TLV_PLOGI_1_TIMESTAMP:
 770	case DRV_TLV_PLOGI_2_TIMESTAMP:
 771	case DRV_TLV_PLOGI_3_TIMESTAMP:
 772	case DRV_TLV_PLOGI_4_TIMESTAMP:
 773	case DRV_TLV_PLOGI_5_TIMESTAMP:
 774		idx = (p_tlv->tlv_type - DRV_TLV_PLOGI_1_TIMESTAMP) / 2;
 775
 776		return qed_mfw_get_tlv_time_value(&p_drv_buf->plogi_tstamp[idx],
 777						  p_buf);
 778	case DRV_TLV_PLOGI_1_ACC_RECEIVED_SOURCE_FC_ID:
 779	case DRV_TLV_PLOGI_2_ACC_RECEIVED_SOURCE_FC_ID:
 780	case DRV_TLV_PLOGI_3_ACC_RECEIVED_SOURCE_FC_ID:
 781	case DRV_TLV_PLOGI_4_ACC_RECEIVED_SOURCE_FC_ID:
 782	case DRV_TLV_PLOGI_5_ACC_RECEIVED_SOURCE_FC_ID:
 783		idx = (p_tlv->tlv_type -
 784		       DRV_TLV_PLOGI_1_ACC_RECEIVED_SOURCE_FC_ID) / 2;
 785
 786		if (p_drv_buf->plogi_acc_src_fcid_set[idx]) {
 787			p_buf->p_val = &p_drv_buf->plogi_acc_src_fcid[idx];
 788			return sizeof(p_drv_buf->plogi_acc_src_fcid[idx]);
 789		}
 790		break;
 791	case DRV_TLV_PLOGI_1_ACC_TIMESTAMP:
 792	case DRV_TLV_PLOGI_2_ACC_TIMESTAMP:
 793	case DRV_TLV_PLOGI_3_ACC_TIMESTAMP:
 794	case DRV_TLV_PLOGI_4_ACC_TIMESTAMP:
 795	case DRV_TLV_PLOGI_5_ACC_TIMESTAMP:
 796		idx = (p_tlv->tlv_type - DRV_TLV_PLOGI_1_ACC_TIMESTAMP) / 2;
 797		p_time = &p_drv_buf->plogi_acc_tstamp[idx];
 798
 799		return qed_mfw_get_tlv_time_value(p_time, p_buf);
 800	case DRV_TLV_LOGOS_ISSUED:
 801		if (p_drv_buf->tx_plogos_set) {
 802			p_buf->p_val = &p_drv_buf->tx_plogos;
 803			return sizeof(p_drv_buf->tx_plogos);
 804		}
 805		break;
 806	case DRV_TLV_LOGO_ACCS_RECEIVED:
 807		if (p_drv_buf->plogo_acc_set) {
 808			p_buf->p_val = &p_drv_buf->plogo_acc;
 809			return sizeof(p_drv_buf->plogo_acc);
 810		}
 811		break;
 812	case DRV_TLV_LOGO_RJTS_RECEIVED:
 813		if (p_drv_buf->plogo_rjt_set) {
 814			p_buf->p_val = &p_drv_buf->plogo_rjt;
 815			return sizeof(p_drv_buf->plogo_rjt);
 816		}
 817		break;
 818	case DRV_TLV_LOGO_1_RECEIVED_SOURCE_FC_ID:
 819	case DRV_TLV_LOGO_2_RECEIVED_SOURCE_FC_ID:
 820	case DRV_TLV_LOGO_3_RECEIVED_SOURCE_FC_ID:
 821	case DRV_TLV_LOGO_4_RECEIVED_SOURCE_FC_ID:
 822	case DRV_TLV_LOGO_5_RECEIVED_SOURCE_FC_ID:
 823		idx = (p_tlv->tlv_type - DRV_TLV_LOGO_1_RECEIVED_SOURCE_FC_ID) /
 824			2;
 825
 826		if (p_drv_buf->plogo_src_fcid_set[idx]) {
 827			p_buf->p_val = &p_drv_buf->plogo_src_fcid[idx];
 828			return sizeof(p_drv_buf->plogo_src_fcid[idx]);
 829		}
 830		break;
 831	case DRV_TLV_LOGO_1_TIMESTAMP:
 832	case DRV_TLV_LOGO_2_TIMESTAMP:
 833	case DRV_TLV_LOGO_3_TIMESTAMP:
 834	case DRV_TLV_LOGO_4_TIMESTAMP:
 835	case DRV_TLV_LOGO_5_TIMESTAMP:
 836		idx = (p_tlv->tlv_type - DRV_TLV_LOGO_1_TIMESTAMP) / 2;
 837
 838		return qed_mfw_get_tlv_time_value(&p_drv_buf->plogo_tstamp[idx],
 839						  p_buf);
 840	case DRV_TLV_LOGOS_RECEIVED:
 841		if (p_drv_buf->rx_logos_set) {
 842			p_buf->p_val = &p_drv_buf->rx_logos;
 843			return sizeof(p_drv_buf->rx_logos);
 844		}
 845		break;
 846	case DRV_TLV_ACCS_ISSUED:
 847		if (p_drv_buf->tx_accs_set) {
 848			p_buf->p_val = &p_drv_buf->tx_accs;
 849			return sizeof(p_drv_buf->tx_accs);
 850		}
 851		break;
 852	case DRV_TLV_PRLIS_ISSUED:
 853		if (p_drv_buf->tx_prlis_set) {
 854			p_buf->p_val = &p_drv_buf->tx_prlis;
 855			return sizeof(p_drv_buf->tx_prlis);
 856		}
 857		break;
 858	case DRV_TLV_ACCS_RECEIVED:
 859		if (p_drv_buf->rx_accs_set) {
 860			p_buf->p_val = &p_drv_buf->rx_accs;
 861			return sizeof(p_drv_buf->rx_accs);
 862		}
 863		break;
 864	case DRV_TLV_ABTS_SENT_COUNT:
 865		if (p_drv_buf->tx_abts_set) {
 866			p_buf->p_val = &p_drv_buf->tx_abts;
 867			return sizeof(p_drv_buf->tx_abts);
 868		}
 869		break;
 870	case DRV_TLV_ABTS_ACCS_RECEIVED:
 871		if (p_drv_buf->rx_abts_acc_set) {
 872			p_buf->p_val = &p_drv_buf->rx_abts_acc;
 873			return sizeof(p_drv_buf->rx_abts_acc);
 874		}
 875		break;
 876	case DRV_TLV_ABTS_RJTS_RECEIVED:
 877		if (p_drv_buf->rx_abts_rjt_set) {
 878			p_buf->p_val = &p_drv_buf->rx_abts_rjt;
 879			return sizeof(p_drv_buf->rx_abts_rjt);
 880		}
 881		break;
 882	case DRV_TLV_ABTS_1_SENT_DESTINATION_FC_ID:
 883	case DRV_TLV_ABTS_2_SENT_DESTINATION_FC_ID:
 884	case DRV_TLV_ABTS_3_SENT_DESTINATION_FC_ID:
 885	case DRV_TLV_ABTS_4_SENT_DESTINATION_FC_ID:
 886	case DRV_TLV_ABTS_5_SENT_DESTINATION_FC_ID:
 887		idx = (p_tlv->tlv_type -
 888		       DRV_TLV_ABTS_1_SENT_DESTINATION_FC_ID) / 2;
 889
 890		if (p_drv_buf->abts_dst_fcid_set[idx]) {
 891			p_buf->p_val = &p_drv_buf->abts_dst_fcid[idx];
 892			return sizeof(p_drv_buf->abts_dst_fcid[idx]);
 893		}
 894		break;
 895	case DRV_TLV_ABTS_1_TIMESTAMP:
 896	case DRV_TLV_ABTS_2_TIMESTAMP:
 897	case DRV_TLV_ABTS_3_TIMESTAMP:
 898	case DRV_TLV_ABTS_4_TIMESTAMP:
 899	case DRV_TLV_ABTS_5_TIMESTAMP:
 900		idx = (p_tlv->tlv_type - DRV_TLV_ABTS_1_TIMESTAMP) / 2;
 901
 902		return qed_mfw_get_tlv_time_value(&p_drv_buf->abts_tstamp[idx],
 903						  p_buf);
 904	case DRV_TLV_RSCNS_RECEIVED:
 905		if (p_drv_buf->rx_rscn_set) {
 906			p_buf->p_val = &p_drv_buf->rx_rscn;
 907			return sizeof(p_drv_buf->rx_rscn);
 908		}
 909		break;
 910	case DRV_TLV_LAST_RSCN_RECEIVED_N_PORT_1:
 911	case DRV_TLV_LAST_RSCN_RECEIVED_N_PORT_2:
 912	case DRV_TLV_LAST_RSCN_RECEIVED_N_PORT_3:
 913	case DRV_TLV_LAST_RSCN_RECEIVED_N_PORT_4:
 914		idx = p_tlv->tlv_type - DRV_TLV_LAST_RSCN_RECEIVED_N_PORT_1;
 915
 916		if (p_drv_buf->rx_rscn_nport_set[idx]) {
 917			p_buf->p_val = &p_drv_buf->rx_rscn_nport[idx];
 918			return sizeof(p_drv_buf->rx_rscn_nport[idx]);
 919		}
 920		break;
 921	case DRV_TLV_LUN_RESETS_ISSUED:
 922		if (p_drv_buf->tx_lun_rst_set) {
 923			p_buf->p_val = &p_drv_buf->tx_lun_rst;
 924			return sizeof(p_drv_buf->tx_lun_rst);
 925		}
 926		break;
 927	case DRV_TLV_ABORT_TASK_SETS_ISSUED:
 928		if (p_drv_buf->abort_task_sets_set) {
 929			p_buf->p_val = &p_drv_buf->abort_task_sets;
 930			return sizeof(p_drv_buf->abort_task_sets);
 931		}
 932		break;
 933	case DRV_TLV_TPRLOS_SENT:
 934		if (p_drv_buf->tx_tprlos_set) {
 935			p_buf->p_val = &p_drv_buf->tx_tprlos;
 936			return sizeof(p_drv_buf->tx_tprlos);
 937		}
 938		break;
 939	case DRV_TLV_NOS_SENT_COUNT:
 940		if (p_drv_buf->tx_nos_set) {
 941			p_buf->p_val = &p_drv_buf->tx_nos;
 942			return sizeof(p_drv_buf->tx_nos);
 943		}
 944		break;
 945	case DRV_TLV_NOS_RECEIVED_COUNT:
 946		if (p_drv_buf->rx_nos_set) {
 947			p_buf->p_val = &p_drv_buf->rx_nos;
 948			return sizeof(p_drv_buf->rx_nos);
 949		}
 950		break;
 951	case DRV_TLV_OLS_COUNT:
 952		if (p_drv_buf->ols_set) {
 953			p_buf->p_val = &p_drv_buf->ols;
 954			return sizeof(p_drv_buf->ols);
 955		}
 956		break;
 957	case DRV_TLV_LR_COUNT:
 958		if (p_drv_buf->lr_set) {
 959			p_buf->p_val = &p_drv_buf->lr;
 960			return sizeof(p_drv_buf->lr);
 961		}
 962		break;
 963	case DRV_TLV_LRR_COUNT:
 964		if (p_drv_buf->lrr_set) {
 965			p_buf->p_val = &p_drv_buf->lrr;
 966			return sizeof(p_drv_buf->lrr);
 967		}
 968		break;
 969	case DRV_TLV_LIP_SENT_COUNT:
 970		if (p_drv_buf->tx_lip_set) {
 971			p_buf->p_val = &p_drv_buf->tx_lip;
 972			return sizeof(p_drv_buf->tx_lip);
 973		}
 974		break;
 975	case DRV_TLV_LIP_RECEIVED_COUNT:
 976		if (p_drv_buf->rx_lip_set) {
 977			p_buf->p_val = &p_drv_buf->rx_lip;
 978			return sizeof(p_drv_buf->rx_lip);
 979		}
 980		break;
 981	case DRV_TLV_EOFA_COUNT:
 982		if (p_drv_buf->eofa_set) {
 983			p_buf->p_val = &p_drv_buf->eofa;
 984			return sizeof(p_drv_buf->eofa);
 985		}
 986		break;
 987	case DRV_TLV_EOFNI_COUNT:
 988		if (p_drv_buf->eofni_set) {
 989			p_buf->p_val = &p_drv_buf->eofni;
 990			return sizeof(p_drv_buf->eofni);
 991		}
 992		break;
 993	case DRV_TLV_SCSI_STATUS_CHECK_CONDITION_COUNT:
 994		if (p_drv_buf->scsi_chks_set) {
 995			p_buf->p_val = &p_drv_buf->scsi_chks;
 996			return sizeof(p_drv_buf->scsi_chks);
 997		}
 998		break;
 999	case DRV_TLV_SCSI_STATUS_CONDITION_MET_COUNT:
1000		if (p_drv_buf->scsi_cond_met_set) {
1001			p_buf->p_val = &p_drv_buf->scsi_cond_met;
1002			return sizeof(p_drv_buf->scsi_cond_met);
1003		}
1004		break;
1005	case DRV_TLV_SCSI_STATUS_BUSY_COUNT:
1006		if (p_drv_buf->scsi_busy_set) {
1007			p_buf->p_val = &p_drv_buf->scsi_busy;
1008			return sizeof(p_drv_buf->scsi_busy);
1009		}
1010		break;
1011	case DRV_TLV_SCSI_STATUS_INTERMEDIATE_COUNT:
1012		if (p_drv_buf->scsi_inter_set) {
1013			p_buf->p_val = &p_drv_buf->scsi_inter;
1014			return sizeof(p_drv_buf->scsi_inter);
1015		}
1016		break;
1017	case DRV_TLV_SCSI_STATUS_INTERMEDIATE_CONDITION_MET_COUNT:
1018		if (p_drv_buf->scsi_inter_cond_met_set) {
1019			p_buf->p_val = &p_drv_buf->scsi_inter_cond_met;
1020			return sizeof(p_drv_buf->scsi_inter_cond_met);
1021		}
1022		break;
1023	case DRV_TLV_SCSI_STATUS_RESERVATION_CONFLICT_COUNT:
1024		if (p_drv_buf->scsi_rsv_conflicts_set) {
1025			p_buf->p_val = &p_drv_buf->scsi_rsv_conflicts;
1026			return sizeof(p_drv_buf->scsi_rsv_conflicts);
1027		}
1028		break;
1029	case DRV_TLV_SCSI_STATUS_TASK_SET_FULL_COUNT:
1030		if (p_drv_buf->scsi_tsk_full_set) {
1031			p_buf->p_val = &p_drv_buf->scsi_tsk_full;
1032			return sizeof(p_drv_buf->scsi_tsk_full);
1033		}
1034		break;
1035	case DRV_TLV_SCSI_STATUS_ACA_ACTIVE_COUNT:
1036		if (p_drv_buf->scsi_aca_active_set) {
1037			p_buf->p_val = &p_drv_buf->scsi_aca_active;
1038			return sizeof(p_drv_buf->scsi_aca_active);
1039		}
1040		break;
1041	case DRV_TLV_SCSI_STATUS_TASK_ABORTED_COUNT:
1042		if (p_drv_buf->scsi_tsk_abort_set) {
1043			p_buf->p_val = &p_drv_buf->scsi_tsk_abort;
1044			return sizeof(p_drv_buf->scsi_tsk_abort);
1045		}
1046		break;
1047	case DRV_TLV_SCSI_CHECK_CONDITION_1_RECEIVED_SK_ASC_ASCQ:
1048	case DRV_TLV_SCSI_CHECK_CONDITION_2_RECEIVED_SK_ASC_ASCQ:
1049	case DRV_TLV_SCSI_CHECK_CONDITION_3_RECEIVED_SK_ASC_ASCQ:
1050	case DRV_TLV_SCSI_CHECK_CONDITION_4_RECEIVED_SK_ASC_ASCQ:
1051	case DRV_TLV_SCSI_CHECK_CONDITION_5_RECEIVED_SK_ASC_ASCQ:
1052		idx = (p_tlv->tlv_type -
1053		       DRV_TLV_SCSI_CHECK_CONDITION_1_RECEIVED_SK_ASC_ASCQ) / 2;
1054
1055		if (p_drv_buf->scsi_rx_chk_set[idx]) {
1056			p_buf->p_val = &p_drv_buf->scsi_rx_chk[idx];
1057			return sizeof(p_drv_buf->scsi_rx_chk[idx]);
1058		}
1059		break;
1060	case DRV_TLV_SCSI_CHECK_1_TIMESTAMP:
1061	case DRV_TLV_SCSI_CHECK_2_TIMESTAMP:
1062	case DRV_TLV_SCSI_CHECK_3_TIMESTAMP:
1063	case DRV_TLV_SCSI_CHECK_4_TIMESTAMP:
1064	case DRV_TLV_SCSI_CHECK_5_TIMESTAMP:
1065		idx = (p_tlv->tlv_type - DRV_TLV_SCSI_CHECK_1_TIMESTAMP) / 2;
1066		p_time = &p_drv_buf->scsi_chk_tstamp[idx];
1067
1068		return qed_mfw_get_tlv_time_value(p_time, p_buf);
1069	default:
1070		break;
1071	}
1072
1073	return -1;
1074}
1075
1076static int
1077qed_mfw_get_iscsi_tlv_value(struct qed_drv_tlv_hdr *p_tlv,
1078			    struct qed_mfw_tlv_iscsi *p_drv_buf,
1079			    struct qed_tlv_parsed_buf *p_buf)
1080{
1081	switch (p_tlv->tlv_type) {
1082	case DRV_TLV_TARGET_LLMNR_ENABLED:
1083		if (p_drv_buf->target_llmnr_set) {
1084			p_buf->p_val = &p_drv_buf->target_llmnr;
1085			return sizeof(p_drv_buf->target_llmnr);
1086		}
1087		break;
1088	case DRV_TLV_HEADER_DIGEST_FLAG_ENABLED:
1089		if (p_drv_buf->header_digest_set) {
1090			p_buf->p_val = &p_drv_buf->header_digest;
1091			return sizeof(p_drv_buf->header_digest);
1092		}
1093		break;
1094	case DRV_TLV_DATA_DIGEST_FLAG_ENABLED:
1095		if (p_drv_buf->data_digest_set) {
1096			p_buf->p_val = &p_drv_buf->data_digest;
1097			return sizeof(p_drv_buf->data_digest);
1098		}
1099		break;
1100	case DRV_TLV_AUTHENTICATION_METHOD:
1101		if (p_drv_buf->auth_method_set) {
1102			p_buf->p_val = &p_drv_buf->auth_method;
1103			return sizeof(p_drv_buf->auth_method);
1104		}
1105		break;
1106	case DRV_TLV_ISCSI_BOOT_TARGET_PORTAL:
1107		if (p_drv_buf->boot_taget_portal_set) {
1108			p_buf->p_val = &p_drv_buf->boot_taget_portal;
1109			return sizeof(p_drv_buf->boot_taget_portal);
1110		}
1111		break;
1112	case DRV_TLV_MAX_FRAME_SIZE:
1113		if (p_drv_buf->frame_size_set) {
1114			p_buf->p_val = &p_drv_buf->frame_size;
1115			return sizeof(p_drv_buf->frame_size);
1116		}
1117		break;
1118	case DRV_TLV_PDU_TX_DESCRIPTORS_QUEUE_SIZE:
1119		if (p_drv_buf->tx_desc_size_set) {
1120			p_buf->p_val = &p_drv_buf->tx_desc_size;
1121			return sizeof(p_drv_buf->tx_desc_size);
1122		}
1123		break;
1124	case DRV_TLV_PDU_RX_DESCRIPTORS_QUEUE_SIZE:
1125		if (p_drv_buf->rx_desc_size_set) {
1126			p_buf->p_val = &p_drv_buf->rx_desc_size;
1127			return sizeof(p_drv_buf->rx_desc_size);
1128		}
1129		break;
1130	case DRV_TLV_ISCSI_BOOT_PROGRESS:
1131		if (p_drv_buf->boot_progress_set) {
1132			p_buf->p_val = &p_drv_buf->boot_progress;
1133			return sizeof(p_drv_buf->boot_progress);
1134		}
1135		break;
1136	case DRV_TLV_PDU_TX_DESCRIPTOR_QUEUE_AVG_DEPTH:
1137		if (p_drv_buf->tx_desc_qdepth_set) {
1138			p_buf->p_val = &p_drv_buf->tx_desc_qdepth;
1139			return sizeof(p_drv_buf->tx_desc_qdepth);
1140		}
1141		break;
1142	case DRV_TLV_PDU_RX_DESCRIPTORS_QUEUE_AVG_DEPTH:
1143		if (p_drv_buf->rx_desc_qdepth_set) {
1144			p_buf->p_val = &p_drv_buf->rx_desc_qdepth;
1145			return sizeof(p_drv_buf->rx_desc_qdepth);
1146		}
1147		break;
1148	case DRV_TLV_ISCSI_PDU_RX_FRAMES_RECEIVED:
1149		if (p_drv_buf->rx_frames_set) {
1150			p_buf->p_val = &p_drv_buf->rx_frames;
1151			return sizeof(p_drv_buf->rx_frames);
1152		}
1153		break;
1154	case DRV_TLV_ISCSI_PDU_RX_BYTES_RECEIVED:
1155		if (p_drv_buf->rx_bytes_set) {
1156			p_buf->p_val = &p_drv_buf->rx_bytes;
1157			return sizeof(p_drv_buf->rx_bytes);
1158		}
1159		break;
1160	case DRV_TLV_ISCSI_PDU_TX_FRAMES_SENT:
1161		if (p_drv_buf->tx_frames_set) {
1162			p_buf->p_val = &p_drv_buf->tx_frames;
1163			return sizeof(p_drv_buf->tx_frames);
1164		}
1165		break;
1166	case DRV_TLV_ISCSI_PDU_TX_BYTES_SENT:
1167		if (p_drv_buf->tx_bytes_set) {
1168			p_buf->p_val = &p_drv_buf->tx_bytes;
1169			return sizeof(p_drv_buf->tx_bytes);
1170		}
1171		break;
1172	default:
1173		break;
1174	}
1175
1176	return -1;
1177}
1178
1179static int qed_mfw_update_tlvs(struct qed_hwfn *p_hwfn,
1180			       u8 tlv_group, u8 *p_mfw_buf, u32 size)
1181{
1182	union qed_mfw_tlv_data *p_tlv_data;
1183	struct qed_tlv_parsed_buf buffer;
1184	struct qed_drv_tlv_hdr tlv;
1185	int len = 0;
1186	u32 offset;
1187	u8 *p_tlv;
1188
1189	p_tlv_data = vzalloc(sizeof(*p_tlv_data));
1190	if (!p_tlv_data)
1191		return -ENOMEM;
1192
1193	if (qed_mfw_fill_tlv_data(p_hwfn, tlv_group, p_tlv_data)) {
1194		vfree(p_tlv_data);
1195		return -EINVAL;
1196	}
1197
1198	memset(&tlv, 0, sizeof(tlv));
1199	for (offset = 0; offset < size;
1200	     offset += sizeof(tlv) + sizeof(u32) * tlv.tlv_length) {
1201		p_tlv = &p_mfw_buf[offset];
1202		tlv.tlv_type = TLV_TYPE(p_tlv);
1203		tlv.tlv_length = TLV_LENGTH(p_tlv);
1204		tlv.tlv_flags = TLV_FLAGS(p_tlv);
1205
1206		DP_VERBOSE(p_hwfn, QED_MSG_SP,
1207			   "Type %d length = %d flags = 0x%x\n", tlv.tlv_type,
1208			   tlv.tlv_length, tlv.tlv_flags);
1209
1210		if (tlv_group == QED_MFW_TLV_GENERIC)
1211			len = qed_mfw_get_gen_tlv_value(&tlv,
1212							&p_tlv_data->generic,
1213							&buffer);
1214		else if (tlv_group == QED_MFW_TLV_ETH)
1215			len = qed_mfw_get_eth_tlv_value(&tlv,
1216							&p_tlv_data->eth,
1217							&buffer);
1218		else if (tlv_group == QED_MFW_TLV_FCOE)
1219			len = qed_mfw_get_fcoe_tlv_value(&tlv,
1220							 &p_tlv_data->fcoe,
1221							 &buffer);
1222		else
1223			len = qed_mfw_get_iscsi_tlv_value(&tlv,
1224							  &p_tlv_data->iscsi,
1225							  &buffer);
1226
1227		if (len > 0) {
1228			WARN(len > 4 * tlv.tlv_length,
1229			     "Incorrect MFW TLV length %d, it shouldn't be greater than %d\n",
1230			     len, 4 * tlv.tlv_length);
1231			len = min_t(int, len, 4 * tlv.tlv_length);
1232			tlv.tlv_flags |= QED_DRV_TLV_FLAGS_CHANGED;
1233			TLV_FLAGS(p_tlv) = tlv.tlv_flags;
1234			memcpy(p_mfw_buf + offset + sizeof(tlv),
1235			       buffer.p_val, len);
1236		}
1237	}
1238
1239	vfree(p_tlv_data);
1240
1241	return 0;
1242}
1243
1244int qed_mfw_process_tlv_req(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt)
1245{
1246	u32 addr, size, offset, resp, param, val, global_offsize, global_addr;
1247	u8 tlv_group = 0, id, *p_mfw_buf = NULL, *p_temp;
1248	struct qed_drv_tlv_hdr tlv;
1249	int rc;
1250
1251	addr = SECTION_OFFSIZE_ADDR(p_hwfn->mcp_info->public_base,
1252				    PUBLIC_GLOBAL);
1253	global_offsize = qed_rd(p_hwfn, p_ptt, addr);
1254	global_addr = SECTION_ADDR(global_offsize, 0);
1255	addr = global_addr + offsetof(struct public_global, data_ptr);
1256	addr = qed_rd(p_hwfn, p_ptt, addr);
1257	size = qed_rd(p_hwfn, p_ptt, global_addr +
1258		      offsetof(struct public_global, data_size));
1259
1260	if (!size) {
1261		DP_NOTICE(p_hwfn, "Invalid TLV req size = %d\n", size);
1262		goto drv_done;
1263	}
1264
1265	p_mfw_buf = vzalloc(size);
1266	if (!p_mfw_buf) {
1267		DP_NOTICE(p_hwfn, "Failed allocate memory for p_mfw_buf\n");
1268		goto drv_done;
1269	}
1270
1271	/* Read the TLV request to local buffer. MFW represents the TLV in
1272	 * little endian format and mcp returns it bigendian format. Hence
1273	 * driver need to convert data to little endian first and then do the
1274	 * memcpy (casting) to preserve the MFW TLV format in the driver buffer.
1275	 *
1276	 */
1277	for (offset = 0; offset < size; offset += sizeof(u32)) {
1278		val = qed_rd(p_hwfn, p_ptt, addr + offset);
1279		val = be32_to_cpu((__force __be32)val);
1280		memcpy(&p_mfw_buf[offset], &val, sizeof(u32));
1281	}
1282
1283	/* Parse the headers to enumerate the requested TLV groups */
1284	for (offset = 0; offset < size;
1285	     offset += sizeof(tlv) + sizeof(u32) * tlv.tlv_length) {
1286		p_temp = &p_mfw_buf[offset];
1287		tlv.tlv_type = TLV_TYPE(p_temp);
1288		tlv.tlv_length = TLV_LENGTH(p_temp);
1289		if (qed_mfw_get_tlv_group(tlv.tlv_type, &tlv_group))
1290			DP_VERBOSE(p_hwfn, NETIF_MSG_DRV,
1291				   "Un recognized TLV %d\n", tlv.tlv_type);
1292	}
1293
1294	/* Sanitize the TLV groups according to personality */
1295	if ((tlv_group & QED_MFW_TLV_ETH) && !QED_IS_L2_PERSONALITY(p_hwfn)) {
1296		DP_VERBOSE(p_hwfn, QED_MSG_SP,
1297			   "Skipping L2 TLVs for non-L2 function\n");
1298		tlv_group &= ~QED_MFW_TLV_ETH;
1299	}
1300
1301	if ((tlv_group & QED_MFW_TLV_FCOE) &&
1302	    p_hwfn->hw_info.personality != QED_PCI_FCOE) {
1303		DP_VERBOSE(p_hwfn, QED_MSG_SP,
1304			   "Skipping FCoE TLVs for non-FCoE function\n");
1305		tlv_group &= ~QED_MFW_TLV_FCOE;
1306	}
1307
1308	if ((tlv_group & QED_MFW_TLV_ISCSI) &&
1309	    p_hwfn->hw_info.personality != QED_PCI_ISCSI &&
1310		p_hwfn->hw_info.personality != QED_PCI_NVMETCP) {
1311		DP_VERBOSE(p_hwfn, QED_MSG_SP,
1312			   "Skipping iSCSI TLVs for non-iSCSI function\n");
1313		tlv_group &= ~QED_MFW_TLV_ISCSI;
1314	}
1315
1316	/* Update the TLV values in the local buffer */
1317	for (id = QED_MFW_TLV_GENERIC; id < QED_MFW_TLV_MAX; id <<= 1) {
1318		if (tlv_group & id)
1319			if (qed_mfw_update_tlvs(p_hwfn, id, p_mfw_buf, size))
1320				goto drv_done;
1321	}
1322
1323	/* Write the TLV data to shared memory. The stream of 4 bytes first need
1324	 * to be mem-copied to u32 element to make it as LSB format. And then
1325	 * converted to big endian as required by mcp-write.
1326	 */
1327	for (offset = 0; offset < size; offset += sizeof(u32)) {
1328		memcpy(&val, &p_mfw_buf[offset], sizeof(u32));
1329		val = (__force u32)cpu_to_be32(val);
1330		qed_wr(p_hwfn, p_ptt, addr + offset, val);
1331	}
1332
1333drv_done:
1334	rc = qed_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_GET_TLV_DONE, 0, &resp,
1335			 &param);
1336
1337	vfree(p_mfw_buf);
1338
1339	return rc;
1340}