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