Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
0002 /* Copyright (c) 2019-2020 Marvell International Ltd. */
0003 
0004 #include <linux/types.h>
0005 #include <asm/byteorder.h>
0006 #include <linux/bug.h>
0007 #include <linux/errno.h>
0008 #include <linux/kernel.h>
0009 #include <linux/slab.h>
0010 #include <linux/string.h>
0011 #include <linux/vmalloc.h>
0012 #include "qed.h"
0013 #include "qed_hw.h"
0014 #include "qed_mcp.h"
0015 #include "qed_reg_addr.h"
0016 
0017 #define TLV_TYPE(p)     (p[0])
0018 #define TLV_LENGTH(p)   (p[1])
0019 #define TLV_FLAGS(p)    (p[3])
0020 
0021 #define QED_TLV_DATA_MAX (14)
0022 struct qed_tlv_parsed_buf {
0023     /* To be filled with the address to set in Value field */
0024     void *p_val;
0025 
0026     /* To be used internally in case the value has to be modified */
0027     u8 data[QED_TLV_DATA_MAX];
0028 };
0029 
0030 static int qed_mfw_get_tlv_group(u8 tlv_type, u8 *tlv_group)
0031 {
0032     switch (tlv_type) {
0033     case DRV_TLV_FEATURE_FLAGS:
0034     case DRV_TLV_LOCAL_ADMIN_ADDR:
0035     case DRV_TLV_ADDITIONAL_MAC_ADDR_1:
0036     case DRV_TLV_ADDITIONAL_MAC_ADDR_2:
0037     case DRV_TLV_OS_DRIVER_STATES:
0038     case DRV_TLV_PXE_BOOT_PROGRESS:
0039     case DRV_TLV_RX_FRAMES_RECEIVED:
0040     case DRV_TLV_RX_BYTES_RECEIVED:
0041     case DRV_TLV_TX_FRAMES_SENT:
0042     case DRV_TLV_TX_BYTES_SENT:
0043     case DRV_TLV_NPIV_ENABLED:
0044     case DRV_TLV_PCIE_BUS_RX_UTILIZATION:
0045     case DRV_TLV_PCIE_BUS_TX_UTILIZATION:
0046     case DRV_TLV_DEVICE_CPU_CORES_UTILIZATION:
0047     case DRV_TLV_LAST_VALID_DCC_TLV_RECEIVED:
0048     case DRV_TLV_NCSI_RX_BYTES_RECEIVED:
0049     case DRV_TLV_NCSI_TX_BYTES_SENT:
0050         *tlv_group |= QED_MFW_TLV_GENERIC;
0051         break;
0052     case DRV_TLV_LSO_MAX_OFFLOAD_SIZE:
0053     case DRV_TLV_LSO_MIN_SEGMENT_COUNT:
0054     case DRV_TLV_PROMISCUOUS_MODE:
0055     case DRV_TLV_TX_DESCRIPTORS_QUEUE_SIZE:
0056     case DRV_TLV_RX_DESCRIPTORS_QUEUE_SIZE:
0057     case DRV_TLV_NUM_OF_NET_QUEUE_VMQ_CFG:
0058     case DRV_TLV_NUM_OFFLOADED_CONNECTIONS_TCP_IPV4:
0059     case DRV_TLV_NUM_OFFLOADED_CONNECTIONS_TCP_IPV6:
0060     case DRV_TLV_TX_DESCRIPTOR_QUEUE_AVG_DEPTH:
0061     case DRV_TLV_RX_DESCRIPTORS_QUEUE_AVG_DEPTH:
0062     case DRV_TLV_IOV_OFFLOAD:
0063     case DRV_TLV_TX_QUEUES_EMPTY:
0064     case DRV_TLV_RX_QUEUES_EMPTY:
0065     case DRV_TLV_TX_QUEUES_FULL:
0066     case DRV_TLV_RX_QUEUES_FULL:
0067         *tlv_group |= QED_MFW_TLV_ETH;
0068         break;
0069     case DRV_TLV_SCSI_TO:
0070     case DRV_TLV_R_T_TOV:
0071     case DRV_TLV_R_A_TOV:
0072     case DRV_TLV_E_D_TOV:
0073     case DRV_TLV_CR_TOV:
0074     case DRV_TLV_BOOT_TYPE:
0075     case DRV_TLV_NPIV_STATE:
0076     case DRV_TLV_NUM_OF_NPIV_IDS:
0077     case DRV_TLV_SWITCH_NAME:
0078     case DRV_TLV_SWITCH_PORT_NUM:
0079     case DRV_TLV_SWITCH_PORT_ID:
0080     case DRV_TLV_VENDOR_NAME:
0081     case DRV_TLV_SWITCH_MODEL:
0082     case DRV_TLV_SWITCH_FW_VER:
0083     case DRV_TLV_QOS_PRIORITY_PER_802_1P:
0084     case DRV_TLV_PORT_ALIAS:
0085     case DRV_TLV_PORT_STATE:
0086     case DRV_TLV_FIP_TX_DESCRIPTORS_QUEUE_SIZE:
0087     case DRV_TLV_FCOE_RX_DESCRIPTORS_QUEUE_SIZE:
0088     case DRV_TLV_LINK_FAILURE_COUNT:
0089     case DRV_TLV_FCOE_BOOT_PROGRESS:
0090     case DRV_TLV_RX_BROADCAST_PACKETS:
0091     case DRV_TLV_TX_BROADCAST_PACKETS:
0092     case DRV_TLV_FCOE_TX_DESCRIPTOR_QUEUE_AVG_DEPTH:
0093     case DRV_TLV_FCOE_RX_DESCRIPTORS_QUEUE_AVG_DEPTH:
0094     case DRV_TLV_FCOE_RX_FRAMES_RECEIVED:
0095     case DRV_TLV_FCOE_RX_BYTES_RECEIVED:
0096     case DRV_TLV_FCOE_TX_FRAMES_SENT:
0097     case DRV_TLV_FCOE_TX_BYTES_SENT:
0098     case DRV_TLV_CRC_ERROR_COUNT:
0099     case DRV_TLV_CRC_ERROR_1_RECEIVED_SOURCE_FC_ID:
0100     case DRV_TLV_CRC_ERROR_1_TIMESTAMP:
0101     case DRV_TLV_CRC_ERROR_2_RECEIVED_SOURCE_FC_ID:
0102     case DRV_TLV_CRC_ERROR_2_TIMESTAMP:
0103     case DRV_TLV_CRC_ERROR_3_RECEIVED_SOURCE_FC_ID:
0104     case DRV_TLV_CRC_ERROR_3_TIMESTAMP:
0105     case DRV_TLV_CRC_ERROR_4_RECEIVED_SOURCE_FC_ID:
0106     case DRV_TLV_CRC_ERROR_4_TIMESTAMP:
0107     case DRV_TLV_CRC_ERROR_5_RECEIVED_SOURCE_FC_ID:
0108     case DRV_TLV_CRC_ERROR_5_TIMESTAMP:
0109     case DRV_TLV_LOSS_OF_SYNC_ERROR_COUNT:
0110     case DRV_TLV_LOSS_OF_SIGNAL_ERRORS:
0111     case DRV_TLV_PRIMITIVE_SEQUENCE_PROTOCOL_ERROR_COUNT:
0112     case DRV_TLV_DISPARITY_ERROR_COUNT:
0113     case DRV_TLV_CODE_VIOLATION_ERROR_COUNT:
0114     case DRV_TLV_LAST_FLOGI_ISSUED_COMMON_PARAMETERS_WORD_1:
0115     case DRV_TLV_LAST_FLOGI_ISSUED_COMMON_PARAMETERS_WORD_2:
0116     case DRV_TLV_LAST_FLOGI_ISSUED_COMMON_PARAMETERS_WORD_3:
0117     case DRV_TLV_LAST_FLOGI_ISSUED_COMMON_PARAMETERS_WORD_4:
0118     case DRV_TLV_LAST_FLOGI_TIMESTAMP:
0119     case DRV_TLV_LAST_FLOGI_ACC_COMMON_PARAMETERS_WORD_1:
0120     case DRV_TLV_LAST_FLOGI_ACC_COMMON_PARAMETERS_WORD_2:
0121     case DRV_TLV_LAST_FLOGI_ACC_COMMON_PARAMETERS_WORD_3:
0122     case DRV_TLV_LAST_FLOGI_ACC_COMMON_PARAMETERS_WORD_4:
0123     case DRV_TLV_LAST_FLOGI_ACC_TIMESTAMP:
0124     case DRV_TLV_LAST_FLOGI_RJT:
0125     case DRV_TLV_LAST_FLOGI_RJT_TIMESTAMP:
0126     case DRV_TLV_FDISCS_SENT_COUNT:
0127     case DRV_TLV_FDISC_ACCS_RECEIVED:
0128     case DRV_TLV_FDISC_RJTS_RECEIVED:
0129     case DRV_TLV_PLOGI_SENT_COUNT:
0130     case DRV_TLV_PLOGI_ACCS_RECEIVED:
0131     case DRV_TLV_PLOGI_RJTS_RECEIVED:
0132     case DRV_TLV_PLOGI_1_SENT_DESTINATION_FC_ID:
0133     case DRV_TLV_PLOGI_1_TIMESTAMP:
0134     case DRV_TLV_PLOGI_2_SENT_DESTINATION_FC_ID:
0135     case DRV_TLV_PLOGI_2_TIMESTAMP:
0136     case DRV_TLV_PLOGI_3_SENT_DESTINATION_FC_ID:
0137     case DRV_TLV_PLOGI_3_TIMESTAMP:
0138     case DRV_TLV_PLOGI_4_SENT_DESTINATION_FC_ID:
0139     case DRV_TLV_PLOGI_4_TIMESTAMP:
0140     case DRV_TLV_PLOGI_5_SENT_DESTINATION_FC_ID:
0141     case DRV_TLV_PLOGI_5_TIMESTAMP:
0142     case DRV_TLV_PLOGI_1_ACC_RECEIVED_SOURCE_FC_ID:
0143     case DRV_TLV_PLOGI_1_ACC_TIMESTAMP:
0144     case DRV_TLV_PLOGI_2_ACC_RECEIVED_SOURCE_FC_ID:
0145     case DRV_TLV_PLOGI_2_ACC_TIMESTAMP:
0146     case DRV_TLV_PLOGI_3_ACC_RECEIVED_SOURCE_FC_ID:
0147     case DRV_TLV_PLOGI_3_ACC_TIMESTAMP:
0148     case DRV_TLV_PLOGI_4_ACC_RECEIVED_SOURCE_FC_ID:
0149     case DRV_TLV_PLOGI_4_ACC_TIMESTAMP:
0150     case DRV_TLV_PLOGI_5_ACC_RECEIVED_SOURCE_FC_ID:
0151     case DRV_TLV_PLOGI_5_ACC_TIMESTAMP:
0152     case DRV_TLV_LOGOS_ISSUED:
0153     case DRV_TLV_LOGO_ACCS_RECEIVED:
0154     case DRV_TLV_LOGO_RJTS_RECEIVED:
0155     case DRV_TLV_LOGO_1_RECEIVED_SOURCE_FC_ID:
0156     case DRV_TLV_LOGO_1_TIMESTAMP:
0157     case DRV_TLV_LOGO_2_RECEIVED_SOURCE_FC_ID:
0158     case DRV_TLV_LOGO_2_TIMESTAMP:
0159     case DRV_TLV_LOGO_3_RECEIVED_SOURCE_FC_ID:
0160     case DRV_TLV_LOGO_3_TIMESTAMP:
0161     case DRV_TLV_LOGO_4_RECEIVED_SOURCE_FC_ID:
0162     case DRV_TLV_LOGO_4_TIMESTAMP:
0163     case DRV_TLV_LOGO_5_RECEIVED_SOURCE_FC_ID:
0164     case DRV_TLV_LOGO_5_TIMESTAMP:
0165     case DRV_TLV_LOGOS_RECEIVED:
0166     case DRV_TLV_ACCS_ISSUED:
0167     case DRV_TLV_PRLIS_ISSUED:
0168     case DRV_TLV_ACCS_RECEIVED:
0169     case DRV_TLV_ABTS_SENT_COUNT:
0170     case DRV_TLV_ABTS_ACCS_RECEIVED:
0171     case DRV_TLV_ABTS_RJTS_RECEIVED:
0172     case DRV_TLV_ABTS_1_SENT_DESTINATION_FC_ID:
0173     case DRV_TLV_ABTS_1_TIMESTAMP:
0174     case DRV_TLV_ABTS_2_SENT_DESTINATION_FC_ID:
0175     case DRV_TLV_ABTS_2_TIMESTAMP:
0176     case DRV_TLV_ABTS_3_SENT_DESTINATION_FC_ID:
0177     case DRV_TLV_ABTS_3_TIMESTAMP:
0178     case DRV_TLV_ABTS_4_SENT_DESTINATION_FC_ID:
0179     case DRV_TLV_ABTS_4_TIMESTAMP:
0180     case DRV_TLV_ABTS_5_SENT_DESTINATION_FC_ID:
0181     case DRV_TLV_ABTS_5_TIMESTAMP:
0182     case DRV_TLV_RSCNS_RECEIVED:
0183     case DRV_TLV_LAST_RSCN_RECEIVED_N_PORT_1:
0184     case DRV_TLV_LAST_RSCN_RECEIVED_N_PORT_2:
0185     case DRV_TLV_LAST_RSCN_RECEIVED_N_PORT_3:
0186     case DRV_TLV_LAST_RSCN_RECEIVED_N_PORT_4:
0187     case DRV_TLV_LUN_RESETS_ISSUED:
0188     case DRV_TLV_ABORT_TASK_SETS_ISSUED:
0189     case DRV_TLV_TPRLOS_SENT:
0190     case DRV_TLV_NOS_SENT_COUNT:
0191     case DRV_TLV_NOS_RECEIVED_COUNT:
0192     case DRV_TLV_OLS_COUNT:
0193     case DRV_TLV_LR_COUNT:
0194     case DRV_TLV_LRR_COUNT:
0195     case DRV_TLV_LIP_SENT_COUNT:
0196     case DRV_TLV_LIP_RECEIVED_COUNT:
0197     case DRV_TLV_EOFA_COUNT:
0198     case DRV_TLV_EOFNI_COUNT:
0199     case DRV_TLV_SCSI_STATUS_CHECK_CONDITION_COUNT:
0200     case DRV_TLV_SCSI_STATUS_CONDITION_MET_COUNT:
0201     case DRV_TLV_SCSI_STATUS_BUSY_COUNT:
0202     case DRV_TLV_SCSI_STATUS_INTERMEDIATE_COUNT:
0203     case DRV_TLV_SCSI_STATUS_INTERMEDIATE_CONDITION_MET_COUNT:
0204     case DRV_TLV_SCSI_STATUS_RESERVATION_CONFLICT_COUNT:
0205     case DRV_TLV_SCSI_STATUS_TASK_SET_FULL_COUNT:
0206     case DRV_TLV_SCSI_STATUS_ACA_ACTIVE_COUNT:
0207     case DRV_TLV_SCSI_STATUS_TASK_ABORTED_COUNT:
0208     case DRV_TLV_SCSI_CHECK_CONDITION_1_RECEIVED_SK_ASC_ASCQ:
0209     case DRV_TLV_SCSI_CHECK_1_TIMESTAMP:
0210     case DRV_TLV_SCSI_CHECK_CONDITION_2_RECEIVED_SK_ASC_ASCQ:
0211     case DRV_TLV_SCSI_CHECK_2_TIMESTAMP:
0212     case DRV_TLV_SCSI_CHECK_CONDITION_3_RECEIVED_SK_ASC_ASCQ:
0213     case DRV_TLV_SCSI_CHECK_3_TIMESTAMP:
0214     case DRV_TLV_SCSI_CHECK_CONDITION_4_RECEIVED_SK_ASC_ASCQ:
0215     case DRV_TLV_SCSI_CHECK_4_TIMESTAMP:
0216     case DRV_TLV_SCSI_CHECK_CONDITION_5_RECEIVED_SK_ASC_ASCQ:
0217     case DRV_TLV_SCSI_CHECK_5_TIMESTAMP:
0218         *tlv_group = QED_MFW_TLV_FCOE;
0219         break;
0220     case DRV_TLV_TARGET_LLMNR_ENABLED:
0221     case DRV_TLV_HEADER_DIGEST_FLAG_ENABLED:
0222     case DRV_TLV_DATA_DIGEST_FLAG_ENABLED:
0223     case DRV_TLV_AUTHENTICATION_METHOD:
0224     case DRV_TLV_ISCSI_BOOT_TARGET_PORTAL:
0225     case DRV_TLV_MAX_FRAME_SIZE:
0226     case DRV_TLV_PDU_TX_DESCRIPTORS_QUEUE_SIZE:
0227     case DRV_TLV_PDU_RX_DESCRIPTORS_QUEUE_SIZE:
0228     case DRV_TLV_ISCSI_BOOT_PROGRESS:
0229     case DRV_TLV_PDU_TX_DESCRIPTOR_QUEUE_AVG_DEPTH:
0230     case DRV_TLV_PDU_RX_DESCRIPTORS_QUEUE_AVG_DEPTH:
0231     case DRV_TLV_ISCSI_PDU_RX_FRAMES_RECEIVED:
0232     case DRV_TLV_ISCSI_PDU_RX_BYTES_RECEIVED:
0233     case DRV_TLV_ISCSI_PDU_TX_FRAMES_SENT:
0234     case DRV_TLV_ISCSI_PDU_TX_BYTES_SENT:
0235         *tlv_group |= QED_MFW_TLV_ISCSI;
0236         break;
0237     default:
0238         return -EINVAL;
0239     }
0240 
0241     return 0;
0242 }
0243 
0244 /* Returns size of the data buffer or, -1 in case TLV data is not available. */
0245 static int
0246 qed_mfw_get_gen_tlv_value(struct qed_drv_tlv_hdr *p_tlv,
0247               struct qed_mfw_tlv_generic *p_drv_buf,
0248               struct qed_tlv_parsed_buf *p_buf)
0249 {
0250     switch (p_tlv->tlv_type) {
0251     case DRV_TLV_FEATURE_FLAGS:
0252         if (p_drv_buf->flags.b_set) {
0253             memset(p_buf->data, 0, sizeof(u8) * QED_TLV_DATA_MAX);
0254             p_buf->data[0] = p_drv_buf->flags.ipv4_csum_offload ?
0255                 1 : 0;
0256             p_buf->data[0] |= (p_drv_buf->flags.lso_supported ?
0257                        1 : 0) << 1;
0258             p_buf->p_val = p_buf->data;
0259             return QED_MFW_TLV_FLAGS_SIZE;
0260         }
0261         break;
0262 
0263     case DRV_TLV_LOCAL_ADMIN_ADDR:
0264     case DRV_TLV_ADDITIONAL_MAC_ADDR_1:
0265     case DRV_TLV_ADDITIONAL_MAC_ADDR_2:
0266         {
0267             int idx = p_tlv->tlv_type - DRV_TLV_LOCAL_ADMIN_ADDR;
0268 
0269             if (p_drv_buf->mac_set[idx]) {
0270                 p_buf->p_val = p_drv_buf->mac[idx];
0271                 return ETH_ALEN;
0272             }
0273             break;
0274         }
0275 
0276     case DRV_TLV_RX_FRAMES_RECEIVED:
0277         if (p_drv_buf->rx_frames_set) {
0278             p_buf->p_val = &p_drv_buf->rx_frames;
0279             return sizeof(p_drv_buf->rx_frames);
0280         }
0281         break;
0282     case DRV_TLV_RX_BYTES_RECEIVED:
0283         if (p_drv_buf->rx_bytes_set) {
0284             p_buf->p_val = &p_drv_buf->rx_bytes;
0285             return sizeof(p_drv_buf->rx_bytes);
0286         }
0287         break;
0288     case DRV_TLV_TX_FRAMES_SENT:
0289         if (p_drv_buf->tx_frames_set) {
0290             p_buf->p_val = &p_drv_buf->tx_frames;
0291             return sizeof(p_drv_buf->tx_frames);
0292         }
0293         break;
0294     case DRV_TLV_TX_BYTES_SENT:
0295         if (p_drv_buf->tx_bytes_set) {
0296             p_buf->p_val = &p_drv_buf->tx_bytes;
0297             return sizeof(p_drv_buf->tx_bytes);
0298         }
0299         break;
0300     default:
0301         break;
0302     }
0303 
0304     return -1;
0305 }
0306 
0307 static int
0308 qed_mfw_get_eth_tlv_value(struct qed_drv_tlv_hdr *p_tlv,
0309               struct qed_mfw_tlv_eth *p_drv_buf,
0310               struct qed_tlv_parsed_buf *p_buf)
0311 {
0312     switch (p_tlv->tlv_type) {
0313     case DRV_TLV_LSO_MAX_OFFLOAD_SIZE:
0314         if (p_drv_buf->lso_maxoff_size_set) {
0315             p_buf->p_val = &p_drv_buf->lso_maxoff_size;
0316             return sizeof(p_drv_buf->lso_maxoff_size);
0317         }
0318         break;
0319     case DRV_TLV_LSO_MIN_SEGMENT_COUNT:
0320         if (p_drv_buf->lso_minseg_size_set) {
0321             p_buf->p_val = &p_drv_buf->lso_minseg_size;
0322             return sizeof(p_drv_buf->lso_minseg_size);
0323         }
0324         break;
0325     case DRV_TLV_PROMISCUOUS_MODE:
0326         if (p_drv_buf->prom_mode_set) {
0327             p_buf->p_val = &p_drv_buf->prom_mode;
0328             return sizeof(p_drv_buf->prom_mode);
0329         }
0330         break;
0331     case DRV_TLV_TX_DESCRIPTORS_QUEUE_SIZE:
0332         if (p_drv_buf->tx_descr_size_set) {
0333             p_buf->p_val = &p_drv_buf->tx_descr_size;
0334             return sizeof(p_drv_buf->tx_descr_size);
0335         }
0336         break;
0337     case DRV_TLV_RX_DESCRIPTORS_QUEUE_SIZE:
0338         if (p_drv_buf->rx_descr_size_set) {
0339             p_buf->p_val = &p_drv_buf->rx_descr_size;
0340             return sizeof(p_drv_buf->rx_descr_size);
0341         }
0342         break;
0343     case DRV_TLV_NUM_OF_NET_QUEUE_VMQ_CFG:
0344         if (p_drv_buf->netq_count_set) {
0345             p_buf->p_val = &p_drv_buf->netq_count;
0346             return sizeof(p_drv_buf->netq_count);
0347         }
0348         break;
0349     case DRV_TLV_NUM_OFFLOADED_CONNECTIONS_TCP_IPV4:
0350         if (p_drv_buf->tcp4_offloads_set) {
0351             p_buf->p_val = &p_drv_buf->tcp4_offloads;
0352             return sizeof(p_drv_buf->tcp4_offloads);
0353         }
0354         break;
0355     case DRV_TLV_NUM_OFFLOADED_CONNECTIONS_TCP_IPV6:
0356         if (p_drv_buf->tcp6_offloads_set) {
0357             p_buf->p_val = &p_drv_buf->tcp6_offloads;
0358             return sizeof(p_drv_buf->tcp6_offloads);
0359         }
0360         break;
0361     case DRV_TLV_TX_DESCRIPTOR_QUEUE_AVG_DEPTH:
0362         if (p_drv_buf->tx_descr_qdepth_set) {
0363             p_buf->p_val = &p_drv_buf->tx_descr_qdepth;
0364             return sizeof(p_drv_buf->tx_descr_qdepth);
0365         }
0366         break;
0367     case DRV_TLV_RX_DESCRIPTORS_QUEUE_AVG_DEPTH:
0368         if (p_drv_buf->rx_descr_qdepth_set) {
0369             p_buf->p_val = &p_drv_buf->rx_descr_qdepth;
0370             return sizeof(p_drv_buf->rx_descr_qdepth);
0371         }
0372         break;
0373     case DRV_TLV_IOV_OFFLOAD:
0374         if (p_drv_buf->iov_offload_set) {
0375             p_buf->p_val = &p_drv_buf->iov_offload;
0376             return sizeof(p_drv_buf->iov_offload);
0377         }
0378         break;
0379     case DRV_TLV_TX_QUEUES_EMPTY:
0380         if (p_drv_buf->txqs_empty_set) {
0381             p_buf->p_val = &p_drv_buf->txqs_empty;
0382             return sizeof(p_drv_buf->txqs_empty);
0383         }
0384         break;
0385     case DRV_TLV_RX_QUEUES_EMPTY:
0386         if (p_drv_buf->rxqs_empty_set) {
0387             p_buf->p_val = &p_drv_buf->rxqs_empty;
0388             return sizeof(p_drv_buf->rxqs_empty);
0389         }
0390         break;
0391     case DRV_TLV_TX_QUEUES_FULL:
0392         if (p_drv_buf->num_txqs_full_set) {
0393             p_buf->p_val = &p_drv_buf->num_txqs_full;
0394             return sizeof(p_drv_buf->num_txqs_full);
0395         }
0396         break;
0397     case DRV_TLV_RX_QUEUES_FULL:
0398         if (p_drv_buf->num_rxqs_full_set) {
0399             p_buf->p_val = &p_drv_buf->num_rxqs_full;
0400             return sizeof(p_drv_buf->num_rxqs_full);
0401         }
0402         break;
0403     default:
0404         break;
0405     }
0406 
0407     return -1;
0408 }
0409 
0410 static int
0411 qed_mfw_get_tlv_time_value(struct qed_mfw_tlv_time *p_time,
0412                struct qed_tlv_parsed_buf *p_buf)
0413 {
0414     if (!p_time->b_set)
0415         return -1;
0416 
0417     /* Validate numbers */
0418     if (p_time->month > 12)
0419         p_time->month = 0;
0420     if (p_time->day > 31)
0421         p_time->day = 0;
0422     if (p_time->hour > 23)
0423         p_time->hour = 0;
0424     if (p_time->min > 59)
0425         p_time->hour = 0;
0426     if (p_time->msec > 999)
0427         p_time->msec = 0;
0428     if (p_time->usec > 999)
0429         p_time->usec = 0;
0430 
0431     memset(p_buf->data, 0, sizeof(u8) * QED_TLV_DATA_MAX);
0432     snprintf(p_buf->data, 14, "%d%d%d%d%d%d",
0433          p_time->month, p_time->day,
0434          p_time->hour, p_time->min, p_time->msec, p_time->usec);
0435 
0436     p_buf->p_val = p_buf->data;
0437 
0438     return QED_MFW_TLV_TIME_SIZE;
0439 }
0440 
0441 static int
0442 qed_mfw_get_fcoe_tlv_value(struct qed_drv_tlv_hdr *p_tlv,
0443                struct qed_mfw_tlv_fcoe *p_drv_buf,
0444                struct qed_tlv_parsed_buf *p_buf)
0445 {
0446     struct qed_mfw_tlv_time *p_time;
0447     u8 idx;
0448 
0449     switch (p_tlv->tlv_type) {
0450     case DRV_TLV_SCSI_TO:
0451         if (p_drv_buf->scsi_timeout_set) {
0452             p_buf->p_val = &p_drv_buf->scsi_timeout;
0453             return sizeof(p_drv_buf->scsi_timeout);
0454         }
0455         break;
0456     case DRV_TLV_R_T_TOV:
0457         if (p_drv_buf->rt_tov_set) {
0458             p_buf->p_val = &p_drv_buf->rt_tov;
0459             return sizeof(p_drv_buf->rt_tov);
0460         }
0461         break;
0462     case DRV_TLV_R_A_TOV:
0463         if (p_drv_buf->ra_tov_set) {
0464             p_buf->p_val = &p_drv_buf->ra_tov;
0465             return sizeof(p_drv_buf->ra_tov);
0466         }
0467         break;
0468     case DRV_TLV_E_D_TOV:
0469         if (p_drv_buf->ed_tov_set) {
0470             p_buf->p_val = &p_drv_buf->ed_tov;
0471             return sizeof(p_drv_buf->ed_tov);
0472         }
0473         break;
0474     case DRV_TLV_CR_TOV:
0475         if (p_drv_buf->cr_tov_set) {
0476             p_buf->p_val = &p_drv_buf->cr_tov;
0477             return sizeof(p_drv_buf->cr_tov);
0478         }
0479         break;
0480     case DRV_TLV_BOOT_TYPE:
0481         if (p_drv_buf->boot_type_set) {
0482             p_buf->p_val = &p_drv_buf->boot_type;
0483             return sizeof(p_drv_buf->boot_type);
0484         }
0485         break;
0486     case DRV_TLV_NPIV_STATE:
0487         if (p_drv_buf->npiv_state_set) {
0488             p_buf->p_val = &p_drv_buf->npiv_state;
0489             return sizeof(p_drv_buf->npiv_state);
0490         }
0491         break;
0492     case DRV_TLV_NUM_OF_NPIV_IDS:
0493         if (p_drv_buf->num_npiv_ids_set) {
0494             p_buf->p_val = &p_drv_buf->num_npiv_ids;
0495             return sizeof(p_drv_buf->num_npiv_ids);
0496         }
0497         break;
0498     case DRV_TLV_SWITCH_NAME:
0499         if (p_drv_buf->switch_name_set) {
0500             p_buf->p_val = &p_drv_buf->switch_name;
0501             return sizeof(p_drv_buf->switch_name);
0502         }
0503         break;
0504     case DRV_TLV_SWITCH_PORT_NUM:
0505         if (p_drv_buf->switch_portnum_set) {
0506             p_buf->p_val = &p_drv_buf->switch_portnum;
0507             return sizeof(p_drv_buf->switch_portnum);
0508         }
0509         break;
0510     case DRV_TLV_SWITCH_PORT_ID:
0511         if (p_drv_buf->switch_portid_set) {
0512             p_buf->p_val = &p_drv_buf->switch_portid;
0513             return sizeof(p_drv_buf->switch_portid);
0514         }
0515         break;
0516     case DRV_TLV_VENDOR_NAME:
0517         if (p_drv_buf->vendor_name_set) {
0518             p_buf->p_val = &p_drv_buf->vendor_name;
0519             return sizeof(p_drv_buf->vendor_name);
0520         }
0521         break;
0522     case DRV_TLV_SWITCH_MODEL:
0523         if (p_drv_buf->switch_model_set) {
0524             p_buf->p_val = &p_drv_buf->switch_model;
0525             return sizeof(p_drv_buf->switch_model);
0526         }
0527         break;
0528     case DRV_TLV_SWITCH_FW_VER:
0529         if (p_drv_buf->switch_fw_version_set) {
0530             p_buf->p_val = &p_drv_buf->switch_fw_version;
0531             return sizeof(p_drv_buf->switch_fw_version);
0532         }
0533         break;
0534     case DRV_TLV_QOS_PRIORITY_PER_802_1P:
0535         if (p_drv_buf->qos_pri_set) {
0536             p_buf->p_val = &p_drv_buf->qos_pri;
0537             return sizeof(p_drv_buf->qos_pri);
0538         }
0539         break;
0540     case DRV_TLV_PORT_ALIAS:
0541         if (p_drv_buf->port_alias_set) {
0542             p_buf->p_val = &p_drv_buf->port_alias;
0543             return sizeof(p_drv_buf->port_alias);
0544         }
0545         break;
0546     case DRV_TLV_PORT_STATE:
0547         if (p_drv_buf->port_state_set) {
0548             p_buf->p_val = &p_drv_buf->port_state;
0549             return sizeof(p_drv_buf->port_state);
0550         }
0551         break;
0552     case DRV_TLV_FIP_TX_DESCRIPTORS_QUEUE_SIZE:
0553         if (p_drv_buf->fip_tx_descr_size_set) {
0554             p_buf->p_val = &p_drv_buf->fip_tx_descr_size;
0555             return sizeof(p_drv_buf->fip_tx_descr_size);
0556         }
0557         break;
0558     case DRV_TLV_FCOE_RX_DESCRIPTORS_QUEUE_SIZE:
0559         if (p_drv_buf->fip_rx_descr_size_set) {
0560             p_buf->p_val = &p_drv_buf->fip_rx_descr_size;
0561             return sizeof(p_drv_buf->fip_rx_descr_size);
0562         }
0563         break;
0564     case DRV_TLV_LINK_FAILURE_COUNT:
0565         if (p_drv_buf->link_failures_set) {
0566             p_buf->p_val = &p_drv_buf->link_failures;
0567             return sizeof(p_drv_buf->link_failures);
0568         }
0569         break;
0570     case DRV_TLV_FCOE_BOOT_PROGRESS:
0571         if (p_drv_buf->fcoe_boot_progress_set) {
0572             p_buf->p_val = &p_drv_buf->fcoe_boot_progress;
0573             return sizeof(p_drv_buf->fcoe_boot_progress);
0574         }
0575         break;
0576     case DRV_TLV_RX_BROADCAST_PACKETS:
0577         if (p_drv_buf->rx_bcast_set) {
0578             p_buf->p_val = &p_drv_buf->rx_bcast;
0579             return sizeof(p_drv_buf->rx_bcast);
0580         }
0581         break;
0582     case DRV_TLV_TX_BROADCAST_PACKETS:
0583         if (p_drv_buf->tx_bcast_set) {
0584             p_buf->p_val = &p_drv_buf->tx_bcast;
0585             return sizeof(p_drv_buf->tx_bcast);
0586         }
0587         break;
0588     case DRV_TLV_FCOE_TX_DESCRIPTOR_QUEUE_AVG_DEPTH:
0589         if (p_drv_buf->fcoe_txq_depth_set) {
0590             p_buf->p_val = &p_drv_buf->fcoe_txq_depth;
0591             return sizeof(p_drv_buf->fcoe_txq_depth);
0592         }
0593         break;
0594     case DRV_TLV_FCOE_RX_DESCRIPTORS_QUEUE_AVG_DEPTH:
0595         if (p_drv_buf->fcoe_rxq_depth_set) {
0596             p_buf->p_val = &p_drv_buf->fcoe_rxq_depth;
0597             return sizeof(p_drv_buf->fcoe_rxq_depth);
0598         }
0599         break;
0600     case DRV_TLV_FCOE_RX_FRAMES_RECEIVED:
0601         if (p_drv_buf->fcoe_rx_frames_set) {
0602             p_buf->p_val = &p_drv_buf->fcoe_rx_frames;
0603             return sizeof(p_drv_buf->fcoe_rx_frames);
0604         }
0605         break;
0606     case DRV_TLV_FCOE_RX_BYTES_RECEIVED:
0607         if (p_drv_buf->fcoe_rx_bytes_set) {
0608             p_buf->p_val = &p_drv_buf->fcoe_rx_bytes;
0609             return sizeof(p_drv_buf->fcoe_rx_bytes);
0610         }
0611         break;
0612     case DRV_TLV_FCOE_TX_FRAMES_SENT:
0613         if (p_drv_buf->fcoe_tx_frames_set) {
0614             p_buf->p_val = &p_drv_buf->fcoe_tx_frames;
0615             return sizeof(p_drv_buf->fcoe_tx_frames);
0616         }
0617         break;
0618     case DRV_TLV_FCOE_TX_BYTES_SENT:
0619         if (p_drv_buf->fcoe_tx_bytes_set) {
0620             p_buf->p_val = &p_drv_buf->fcoe_tx_bytes;
0621             return sizeof(p_drv_buf->fcoe_tx_bytes);
0622         }
0623         break;
0624     case DRV_TLV_CRC_ERROR_COUNT:
0625         if (p_drv_buf->crc_count_set) {
0626             p_buf->p_val = &p_drv_buf->crc_count;
0627             return sizeof(p_drv_buf->crc_count);
0628         }
0629         break;
0630     case DRV_TLV_CRC_ERROR_1_RECEIVED_SOURCE_FC_ID:
0631     case DRV_TLV_CRC_ERROR_2_RECEIVED_SOURCE_FC_ID:
0632     case DRV_TLV_CRC_ERROR_3_RECEIVED_SOURCE_FC_ID:
0633     case DRV_TLV_CRC_ERROR_4_RECEIVED_SOURCE_FC_ID:
0634     case DRV_TLV_CRC_ERROR_5_RECEIVED_SOURCE_FC_ID:
0635         idx = (p_tlv->tlv_type -
0636                DRV_TLV_CRC_ERROR_1_RECEIVED_SOURCE_FC_ID) / 2;
0637 
0638         if (p_drv_buf->crc_err_src_fcid_set[idx]) {
0639             p_buf->p_val = &p_drv_buf->crc_err_src_fcid[idx];
0640             return sizeof(p_drv_buf->crc_err_src_fcid[idx]);
0641         }
0642         break;
0643     case DRV_TLV_CRC_ERROR_1_TIMESTAMP:
0644     case DRV_TLV_CRC_ERROR_2_TIMESTAMP:
0645     case DRV_TLV_CRC_ERROR_3_TIMESTAMP:
0646     case DRV_TLV_CRC_ERROR_4_TIMESTAMP:
0647     case DRV_TLV_CRC_ERROR_5_TIMESTAMP:
0648         idx = (p_tlv->tlv_type - DRV_TLV_CRC_ERROR_1_TIMESTAMP) / 2;
0649 
0650         return qed_mfw_get_tlv_time_value(&p_drv_buf->crc_err[idx],
0651                           p_buf);
0652     case DRV_TLV_LOSS_OF_SYNC_ERROR_COUNT:
0653         if (p_drv_buf->losync_err_set) {
0654             p_buf->p_val = &p_drv_buf->losync_err;
0655             return sizeof(p_drv_buf->losync_err);
0656         }
0657         break;
0658     case DRV_TLV_LOSS_OF_SIGNAL_ERRORS:
0659         if (p_drv_buf->losig_err_set) {
0660             p_buf->p_val = &p_drv_buf->losig_err;
0661             return sizeof(p_drv_buf->losig_err);
0662         }
0663         break;
0664     case DRV_TLV_PRIMITIVE_SEQUENCE_PROTOCOL_ERROR_COUNT:
0665         if (p_drv_buf->primtive_err_set) {
0666             p_buf->p_val = &p_drv_buf->primtive_err;
0667             return sizeof(p_drv_buf->primtive_err);
0668         }
0669         break;
0670     case DRV_TLV_DISPARITY_ERROR_COUNT:
0671         if (p_drv_buf->disparity_err_set) {
0672             p_buf->p_val = &p_drv_buf->disparity_err;
0673             return sizeof(p_drv_buf->disparity_err);
0674         }
0675         break;
0676     case DRV_TLV_CODE_VIOLATION_ERROR_COUNT:
0677         if (p_drv_buf->code_violation_err_set) {
0678             p_buf->p_val = &p_drv_buf->code_violation_err;
0679             return sizeof(p_drv_buf->code_violation_err);
0680         }
0681         break;
0682     case DRV_TLV_LAST_FLOGI_ISSUED_COMMON_PARAMETERS_WORD_1:
0683     case DRV_TLV_LAST_FLOGI_ISSUED_COMMON_PARAMETERS_WORD_2:
0684     case DRV_TLV_LAST_FLOGI_ISSUED_COMMON_PARAMETERS_WORD_3:
0685     case DRV_TLV_LAST_FLOGI_ISSUED_COMMON_PARAMETERS_WORD_4:
0686         idx = p_tlv->tlv_type -
0687             DRV_TLV_LAST_FLOGI_ISSUED_COMMON_PARAMETERS_WORD_1;
0688         if (p_drv_buf->flogi_param_set[idx]) {
0689             p_buf->p_val = &p_drv_buf->flogi_param[idx];
0690             return sizeof(p_drv_buf->flogi_param[idx]);
0691         }
0692         break;
0693     case DRV_TLV_LAST_FLOGI_TIMESTAMP:
0694         return qed_mfw_get_tlv_time_value(&p_drv_buf->flogi_tstamp,
0695                           p_buf);
0696     case DRV_TLV_LAST_FLOGI_ACC_COMMON_PARAMETERS_WORD_1:
0697     case DRV_TLV_LAST_FLOGI_ACC_COMMON_PARAMETERS_WORD_2:
0698     case DRV_TLV_LAST_FLOGI_ACC_COMMON_PARAMETERS_WORD_3:
0699     case DRV_TLV_LAST_FLOGI_ACC_COMMON_PARAMETERS_WORD_4:
0700         idx = p_tlv->tlv_type -
0701             DRV_TLV_LAST_FLOGI_ACC_COMMON_PARAMETERS_WORD_1;
0702 
0703         if (p_drv_buf->flogi_acc_param_set[idx]) {
0704             p_buf->p_val = &p_drv_buf->flogi_acc_param[idx];
0705             return sizeof(p_drv_buf->flogi_acc_param[idx]);
0706         }
0707         break;
0708     case DRV_TLV_LAST_FLOGI_ACC_TIMESTAMP:
0709         return qed_mfw_get_tlv_time_value(&p_drv_buf->flogi_acc_tstamp,
0710                           p_buf);
0711     case DRV_TLV_LAST_FLOGI_RJT:
0712         if (p_drv_buf->flogi_rjt_set) {
0713             p_buf->p_val = &p_drv_buf->flogi_rjt;
0714             return sizeof(p_drv_buf->flogi_rjt);
0715         }
0716         break;
0717     case DRV_TLV_LAST_FLOGI_RJT_TIMESTAMP:
0718         return qed_mfw_get_tlv_time_value(&p_drv_buf->flogi_rjt_tstamp,
0719                           p_buf);
0720     case DRV_TLV_FDISCS_SENT_COUNT:
0721         if (p_drv_buf->fdiscs_set) {
0722             p_buf->p_val = &p_drv_buf->fdiscs;
0723             return sizeof(p_drv_buf->fdiscs);
0724         }
0725         break;
0726     case DRV_TLV_FDISC_ACCS_RECEIVED:
0727         if (p_drv_buf->fdisc_acc_set) {
0728             p_buf->p_val = &p_drv_buf->fdisc_acc;
0729             return sizeof(p_drv_buf->fdisc_acc);
0730         }
0731         break;
0732     case DRV_TLV_FDISC_RJTS_RECEIVED:
0733         if (p_drv_buf->fdisc_rjt_set) {
0734             p_buf->p_val = &p_drv_buf->fdisc_rjt;
0735             return sizeof(p_drv_buf->fdisc_rjt);
0736         }
0737         break;
0738     case DRV_TLV_PLOGI_SENT_COUNT:
0739         if (p_drv_buf->plogi_set) {
0740             p_buf->p_val = &p_drv_buf->plogi;
0741             return sizeof(p_drv_buf->plogi);
0742         }
0743         break;
0744     case DRV_TLV_PLOGI_ACCS_RECEIVED:
0745         if (p_drv_buf->plogi_acc_set) {
0746             p_buf->p_val = &p_drv_buf->plogi_acc;
0747             return sizeof(p_drv_buf->plogi_acc);
0748         }
0749         break;
0750     case DRV_TLV_PLOGI_RJTS_RECEIVED:
0751         if (p_drv_buf->plogi_rjt_set) {
0752             p_buf->p_val = &p_drv_buf->plogi_rjt;
0753             return sizeof(p_drv_buf->plogi_rjt);
0754         }
0755         break;
0756     case DRV_TLV_PLOGI_1_SENT_DESTINATION_FC_ID:
0757     case DRV_TLV_PLOGI_2_SENT_DESTINATION_FC_ID:
0758     case DRV_TLV_PLOGI_3_SENT_DESTINATION_FC_ID:
0759     case DRV_TLV_PLOGI_4_SENT_DESTINATION_FC_ID:
0760     case DRV_TLV_PLOGI_5_SENT_DESTINATION_FC_ID:
0761         idx = (p_tlv->tlv_type -
0762                DRV_TLV_PLOGI_1_SENT_DESTINATION_FC_ID) / 2;
0763 
0764         if (p_drv_buf->plogi_dst_fcid_set[idx]) {
0765             p_buf->p_val = &p_drv_buf->plogi_dst_fcid[idx];
0766             return sizeof(p_drv_buf->plogi_dst_fcid[idx]);
0767         }
0768         break;
0769     case DRV_TLV_PLOGI_1_TIMESTAMP:
0770     case DRV_TLV_PLOGI_2_TIMESTAMP:
0771     case DRV_TLV_PLOGI_3_TIMESTAMP:
0772     case DRV_TLV_PLOGI_4_TIMESTAMP:
0773     case DRV_TLV_PLOGI_5_TIMESTAMP:
0774         idx = (p_tlv->tlv_type - DRV_TLV_PLOGI_1_TIMESTAMP) / 2;
0775 
0776         return qed_mfw_get_tlv_time_value(&p_drv_buf->plogi_tstamp[idx],
0777                           p_buf);
0778     case DRV_TLV_PLOGI_1_ACC_RECEIVED_SOURCE_FC_ID:
0779     case DRV_TLV_PLOGI_2_ACC_RECEIVED_SOURCE_FC_ID:
0780     case DRV_TLV_PLOGI_3_ACC_RECEIVED_SOURCE_FC_ID:
0781     case DRV_TLV_PLOGI_4_ACC_RECEIVED_SOURCE_FC_ID:
0782     case DRV_TLV_PLOGI_5_ACC_RECEIVED_SOURCE_FC_ID:
0783         idx = (p_tlv->tlv_type -
0784                DRV_TLV_PLOGI_1_ACC_RECEIVED_SOURCE_FC_ID) / 2;
0785 
0786         if (p_drv_buf->plogi_acc_src_fcid_set[idx]) {
0787             p_buf->p_val = &p_drv_buf->plogi_acc_src_fcid[idx];
0788             return sizeof(p_drv_buf->plogi_acc_src_fcid[idx]);
0789         }
0790         break;
0791     case DRV_TLV_PLOGI_1_ACC_TIMESTAMP:
0792     case DRV_TLV_PLOGI_2_ACC_TIMESTAMP:
0793     case DRV_TLV_PLOGI_3_ACC_TIMESTAMP:
0794     case DRV_TLV_PLOGI_4_ACC_TIMESTAMP:
0795     case DRV_TLV_PLOGI_5_ACC_TIMESTAMP:
0796         idx = (p_tlv->tlv_type - DRV_TLV_PLOGI_1_ACC_TIMESTAMP) / 2;
0797         p_time = &p_drv_buf->plogi_acc_tstamp[idx];
0798 
0799         return qed_mfw_get_tlv_time_value(p_time, p_buf);
0800     case DRV_TLV_LOGOS_ISSUED:
0801         if (p_drv_buf->tx_plogos_set) {
0802             p_buf->p_val = &p_drv_buf->tx_plogos;
0803             return sizeof(p_drv_buf->tx_plogos);
0804         }
0805         break;
0806     case DRV_TLV_LOGO_ACCS_RECEIVED:
0807         if (p_drv_buf->plogo_acc_set) {
0808             p_buf->p_val = &p_drv_buf->plogo_acc;
0809             return sizeof(p_drv_buf->plogo_acc);
0810         }
0811         break;
0812     case DRV_TLV_LOGO_RJTS_RECEIVED:
0813         if (p_drv_buf->plogo_rjt_set) {
0814             p_buf->p_val = &p_drv_buf->plogo_rjt;
0815             return sizeof(p_drv_buf->plogo_rjt);
0816         }
0817         break;
0818     case DRV_TLV_LOGO_1_RECEIVED_SOURCE_FC_ID:
0819     case DRV_TLV_LOGO_2_RECEIVED_SOURCE_FC_ID:
0820     case DRV_TLV_LOGO_3_RECEIVED_SOURCE_FC_ID:
0821     case DRV_TLV_LOGO_4_RECEIVED_SOURCE_FC_ID:
0822     case DRV_TLV_LOGO_5_RECEIVED_SOURCE_FC_ID:
0823         idx = (p_tlv->tlv_type - DRV_TLV_LOGO_1_RECEIVED_SOURCE_FC_ID) /
0824             2;
0825 
0826         if (p_drv_buf->plogo_src_fcid_set[idx]) {
0827             p_buf->p_val = &p_drv_buf->plogo_src_fcid[idx];
0828             return sizeof(p_drv_buf->plogo_src_fcid[idx]);
0829         }
0830         break;
0831     case DRV_TLV_LOGO_1_TIMESTAMP:
0832     case DRV_TLV_LOGO_2_TIMESTAMP:
0833     case DRV_TLV_LOGO_3_TIMESTAMP:
0834     case DRV_TLV_LOGO_4_TIMESTAMP:
0835     case DRV_TLV_LOGO_5_TIMESTAMP:
0836         idx = (p_tlv->tlv_type - DRV_TLV_LOGO_1_TIMESTAMP) / 2;
0837 
0838         return qed_mfw_get_tlv_time_value(&p_drv_buf->plogo_tstamp[idx],
0839                           p_buf);
0840     case DRV_TLV_LOGOS_RECEIVED:
0841         if (p_drv_buf->rx_logos_set) {
0842             p_buf->p_val = &p_drv_buf->rx_logos;
0843             return sizeof(p_drv_buf->rx_logos);
0844         }
0845         break;
0846     case DRV_TLV_ACCS_ISSUED:
0847         if (p_drv_buf->tx_accs_set) {
0848             p_buf->p_val = &p_drv_buf->tx_accs;
0849             return sizeof(p_drv_buf->tx_accs);
0850         }
0851         break;
0852     case DRV_TLV_PRLIS_ISSUED:
0853         if (p_drv_buf->tx_prlis_set) {
0854             p_buf->p_val = &p_drv_buf->tx_prlis;
0855             return sizeof(p_drv_buf->tx_prlis);
0856         }
0857         break;
0858     case DRV_TLV_ACCS_RECEIVED:
0859         if (p_drv_buf->rx_accs_set) {
0860             p_buf->p_val = &p_drv_buf->rx_accs;
0861             return sizeof(p_drv_buf->rx_accs);
0862         }
0863         break;
0864     case DRV_TLV_ABTS_SENT_COUNT:
0865         if (p_drv_buf->tx_abts_set) {
0866             p_buf->p_val = &p_drv_buf->tx_abts;
0867             return sizeof(p_drv_buf->tx_abts);
0868         }
0869         break;
0870     case DRV_TLV_ABTS_ACCS_RECEIVED:
0871         if (p_drv_buf->rx_abts_acc_set) {
0872             p_buf->p_val = &p_drv_buf->rx_abts_acc;
0873             return sizeof(p_drv_buf->rx_abts_acc);
0874         }
0875         break;
0876     case DRV_TLV_ABTS_RJTS_RECEIVED:
0877         if (p_drv_buf->rx_abts_rjt_set) {
0878             p_buf->p_val = &p_drv_buf->rx_abts_rjt;
0879             return sizeof(p_drv_buf->rx_abts_rjt);
0880         }
0881         break;
0882     case DRV_TLV_ABTS_1_SENT_DESTINATION_FC_ID:
0883     case DRV_TLV_ABTS_2_SENT_DESTINATION_FC_ID:
0884     case DRV_TLV_ABTS_3_SENT_DESTINATION_FC_ID:
0885     case DRV_TLV_ABTS_4_SENT_DESTINATION_FC_ID:
0886     case DRV_TLV_ABTS_5_SENT_DESTINATION_FC_ID:
0887         idx = (p_tlv->tlv_type -
0888                DRV_TLV_ABTS_1_SENT_DESTINATION_FC_ID) / 2;
0889 
0890         if (p_drv_buf->abts_dst_fcid_set[idx]) {
0891             p_buf->p_val = &p_drv_buf->abts_dst_fcid[idx];
0892             return sizeof(p_drv_buf->abts_dst_fcid[idx]);
0893         }
0894         break;
0895     case DRV_TLV_ABTS_1_TIMESTAMP:
0896     case DRV_TLV_ABTS_2_TIMESTAMP:
0897     case DRV_TLV_ABTS_3_TIMESTAMP:
0898     case DRV_TLV_ABTS_4_TIMESTAMP:
0899     case DRV_TLV_ABTS_5_TIMESTAMP:
0900         idx = (p_tlv->tlv_type - DRV_TLV_ABTS_1_TIMESTAMP) / 2;
0901 
0902         return qed_mfw_get_tlv_time_value(&p_drv_buf->abts_tstamp[idx],
0903                           p_buf);
0904     case DRV_TLV_RSCNS_RECEIVED:
0905         if (p_drv_buf->rx_rscn_set) {
0906             p_buf->p_val = &p_drv_buf->rx_rscn;
0907             return sizeof(p_drv_buf->rx_rscn);
0908         }
0909         break;
0910     case DRV_TLV_LAST_RSCN_RECEIVED_N_PORT_1:
0911     case DRV_TLV_LAST_RSCN_RECEIVED_N_PORT_2:
0912     case DRV_TLV_LAST_RSCN_RECEIVED_N_PORT_3:
0913     case DRV_TLV_LAST_RSCN_RECEIVED_N_PORT_4:
0914         idx = p_tlv->tlv_type - DRV_TLV_LAST_RSCN_RECEIVED_N_PORT_1;
0915 
0916         if (p_drv_buf->rx_rscn_nport_set[idx]) {
0917             p_buf->p_val = &p_drv_buf->rx_rscn_nport[idx];
0918             return sizeof(p_drv_buf->rx_rscn_nport[idx]);
0919         }
0920         break;
0921     case DRV_TLV_LUN_RESETS_ISSUED:
0922         if (p_drv_buf->tx_lun_rst_set) {
0923             p_buf->p_val = &p_drv_buf->tx_lun_rst;
0924             return sizeof(p_drv_buf->tx_lun_rst);
0925         }
0926         break;
0927     case DRV_TLV_ABORT_TASK_SETS_ISSUED:
0928         if (p_drv_buf->abort_task_sets_set) {
0929             p_buf->p_val = &p_drv_buf->abort_task_sets;
0930             return sizeof(p_drv_buf->abort_task_sets);
0931         }
0932         break;
0933     case DRV_TLV_TPRLOS_SENT:
0934         if (p_drv_buf->tx_tprlos_set) {
0935             p_buf->p_val = &p_drv_buf->tx_tprlos;
0936             return sizeof(p_drv_buf->tx_tprlos);
0937         }
0938         break;
0939     case DRV_TLV_NOS_SENT_COUNT:
0940         if (p_drv_buf->tx_nos_set) {
0941             p_buf->p_val = &p_drv_buf->tx_nos;
0942             return sizeof(p_drv_buf->tx_nos);
0943         }
0944         break;
0945     case DRV_TLV_NOS_RECEIVED_COUNT:
0946         if (p_drv_buf->rx_nos_set) {
0947             p_buf->p_val = &p_drv_buf->rx_nos;
0948             return sizeof(p_drv_buf->rx_nos);
0949         }
0950         break;
0951     case DRV_TLV_OLS_COUNT:
0952         if (p_drv_buf->ols_set) {
0953             p_buf->p_val = &p_drv_buf->ols;
0954             return sizeof(p_drv_buf->ols);
0955         }
0956         break;
0957     case DRV_TLV_LR_COUNT:
0958         if (p_drv_buf->lr_set) {
0959             p_buf->p_val = &p_drv_buf->lr;
0960             return sizeof(p_drv_buf->lr);
0961         }
0962         break;
0963     case DRV_TLV_LRR_COUNT:
0964         if (p_drv_buf->lrr_set) {
0965             p_buf->p_val = &p_drv_buf->lrr;
0966             return sizeof(p_drv_buf->lrr);
0967         }
0968         break;
0969     case DRV_TLV_LIP_SENT_COUNT:
0970         if (p_drv_buf->tx_lip_set) {
0971             p_buf->p_val = &p_drv_buf->tx_lip;
0972             return sizeof(p_drv_buf->tx_lip);
0973         }
0974         break;
0975     case DRV_TLV_LIP_RECEIVED_COUNT:
0976         if (p_drv_buf->rx_lip_set) {
0977             p_buf->p_val = &p_drv_buf->rx_lip;
0978             return sizeof(p_drv_buf->rx_lip);
0979         }
0980         break;
0981     case DRV_TLV_EOFA_COUNT:
0982         if (p_drv_buf->eofa_set) {
0983             p_buf->p_val = &p_drv_buf->eofa;
0984             return sizeof(p_drv_buf->eofa);
0985         }
0986         break;
0987     case DRV_TLV_EOFNI_COUNT:
0988         if (p_drv_buf->eofni_set) {
0989             p_buf->p_val = &p_drv_buf->eofni;
0990             return sizeof(p_drv_buf->eofni);
0991         }
0992         break;
0993     case DRV_TLV_SCSI_STATUS_CHECK_CONDITION_COUNT:
0994         if (p_drv_buf->scsi_chks_set) {
0995             p_buf->p_val = &p_drv_buf->scsi_chks;
0996             return sizeof(p_drv_buf->scsi_chks);
0997         }
0998         break;
0999     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 
1076 static int
1077 qed_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 
1179 static 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 
1244 int 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 
1333 drv_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 }