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)
20 struct 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 
28 static 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. */
243 static int
244 qed_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 
305 static int
306 qed_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 
408 static int
409 qed_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 
439 static int
440 qed_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 
1074 static int
1075 qed_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 
1177 static 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 
1242 int 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 
1330 drv_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