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