1// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
2/* Copyright (c) 2019-2020 Marvell International Ltd. */
3
4#include <linux/types.h>
5#include <asm/byteorder.h>
6#include <linux/bug.h>
7#include <linux/errno.h>
8#include <linux/kernel.h>
9#include <linux/slab.h>
10#include <linux/string.h>
11#include <linux/vmalloc.h>
12#include "qed.h"
13#include "qed_hw.h"
14#include "qed_mcp.h"
15#include "qed_reg_addr.h"
16
17#define TLV_TYPE(p) (p[0])
18#define TLV_LENGTH(p) (p[1])
19#define TLV_FLAGS(p) (p[3])
20
21#define QED_TLV_DATA_MAX (14)
22struct qed_tlv_parsed_buf {
23 /* To be filled with the address to set in Value field */
24 void *p_val;
25
26 /* To be used internally in case the value has to be modified */
27 u8 data[QED_TLV_DATA_MAX];
28};
29
30static int qed_mfw_get_tlv_group(u8 tlv_type, u8 *tlv_group)
31{
32 switch (tlv_type) {
33 case DRV_TLV_FEATURE_FLAGS:
34 case DRV_TLV_LOCAL_ADMIN_ADDR:
35 case DRV_TLV_ADDITIONAL_MAC_ADDR_1:
36 case DRV_TLV_ADDITIONAL_MAC_ADDR_2:
37 case DRV_TLV_OS_DRIVER_STATES:
38 case DRV_TLV_PXE_BOOT_PROGRESS:
39 case DRV_TLV_RX_FRAMES_RECEIVED:
40 case DRV_TLV_RX_BYTES_RECEIVED:
41 case DRV_TLV_TX_FRAMES_SENT:
42 case DRV_TLV_TX_BYTES_SENT:
43 case DRV_TLV_NPIV_ENABLED:
44 case DRV_TLV_PCIE_BUS_RX_UTILIZATION:
45 case DRV_TLV_PCIE_BUS_TX_UTILIZATION:
46 case DRV_TLV_DEVICE_CPU_CORES_UTILIZATION:
47 case DRV_TLV_LAST_VALID_DCC_TLV_RECEIVED:
48 case DRV_TLV_NCSI_RX_BYTES_RECEIVED:
49 case DRV_TLV_NCSI_TX_BYTES_SENT:
50 *tlv_group |= QED_MFW_TLV_GENERIC;
51 break;
52 case DRV_TLV_LSO_MAX_OFFLOAD_SIZE:
53 case DRV_TLV_LSO_MIN_SEGMENT_COUNT:
54 case DRV_TLV_PROMISCUOUS_MODE:
55 case DRV_TLV_TX_DESCRIPTORS_QUEUE_SIZE:
56 case DRV_TLV_RX_DESCRIPTORS_QUEUE_SIZE:
57 case DRV_TLV_NUM_OF_NET_QUEUE_VMQ_CFG:
58 case DRV_TLV_NUM_OFFLOADED_CONNECTIONS_TCP_IPV4:
59 case DRV_TLV_NUM_OFFLOADED_CONNECTIONS_TCP_IPV6:
60 case DRV_TLV_TX_DESCRIPTOR_QUEUE_AVG_DEPTH:
61 case DRV_TLV_RX_DESCRIPTORS_QUEUE_AVG_DEPTH:
62 case DRV_TLV_IOV_OFFLOAD:
63 case DRV_TLV_TX_QUEUES_EMPTY:
64 case DRV_TLV_RX_QUEUES_EMPTY:
65 case DRV_TLV_TX_QUEUES_FULL:
66 case DRV_TLV_RX_QUEUES_FULL:
67 *tlv_group |= QED_MFW_TLV_ETH;
68 break;
69 case DRV_TLV_SCSI_TO:
70 case DRV_TLV_R_T_TOV:
71 case DRV_TLV_R_A_TOV:
72 case DRV_TLV_E_D_TOV:
73 case DRV_TLV_CR_TOV:
74 case DRV_TLV_BOOT_TYPE:
75 case DRV_TLV_NPIV_STATE:
76 case DRV_TLV_NUM_OF_NPIV_IDS:
77 case DRV_TLV_SWITCH_NAME:
78 case DRV_TLV_SWITCH_PORT_NUM:
79 case DRV_TLV_SWITCH_PORT_ID:
80 case DRV_TLV_VENDOR_NAME:
81 case DRV_TLV_SWITCH_MODEL:
82 case DRV_TLV_SWITCH_FW_VER:
83 case DRV_TLV_QOS_PRIORITY_PER_802_1P:
84 case DRV_TLV_PORT_ALIAS:
85 case DRV_TLV_PORT_STATE:
86 case DRV_TLV_FIP_TX_DESCRIPTORS_QUEUE_SIZE:
87 case DRV_TLV_FCOE_RX_DESCRIPTORS_QUEUE_SIZE:
88 case DRV_TLV_LINK_FAILURE_COUNT:
89 case DRV_TLV_FCOE_BOOT_PROGRESS:
90 case DRV_TLV_RX_BROADCAST_PACKETS:
91 case DRV_TLV_TX_BROADCAST_PACKETS:
92 case DRV_TLV_FCOE_TX_DESCRIPTOR_QUEUE_AVG_DEPTH:
93 case DRV_TLV_FCOE_RX_DESCRIPTORS_QUEUE_AVG_DEPTH:
94 case DRV_TLV_FCOE_RX_FRAMES_RECEIVED:
95 case DRV_TLV_FCOE_RX_BYTES_RECEIVED:
96 case DRV_TLV_FCOE_TX_FRAMES_SENT:
97 case DRV_TLV_FCOE_TX_BYTES_SENT:
98 case DRV_TLV_CRC_ERROR_COUNT:
99 case DRV_TLV_CRC_ERROR_1_RECEIVED_SOURCE_FC_ID:
100 case DRV_TLV_CRC_ERROR_1_TIMESTAMP:
101 case DRV_TLV_CRC_ERROR_2_RECEIVED_SOURCE_FC_ID:
102 case DRV_TLV_CRC_ERROR_2_TIMESTAMP:
103 case DRV_TLV_CRC_ERROR_3_RECEIVED_SOURCE_FC_ID:
104 case DRV_TLV_CRC_ERROR_3_TIMESTAMP:
105 case DRV_TLV_CRC_ERROR_4_RECEIVED_SOURCE_FC_ID:
106 case DRV_TLV_CRC_ERROR_4_TIMESTAMP:
107 case DRV_TLV_CRC_ERROR_5_RECEIVED_SOURCE_FC_ID:
108 case DRV_TLV_CRC_ERROR_5_TIMESTAMP:
109 case DRV_TLV_LOSS_OF_SYNC_ERROR_COUNT:
110 case DRV_TLV_LOSS_OF_SIGNAL_ERRORS:
111 case DRV_TLV_PRIMITIVE_SEQUENCE_PROTOCOL_ERROR_COUNT:
112 case DRV_TLV_DISPARITY_ERROR_COUNT:
113 case DRV_TLV_CODE_VIOLATION_ERROR_COUNT:
114 case DRV_TLV_LAST_FLOGI_ISSUED_COMMON_PARAMETERS_WORD_1:
115 case DRV_TLV_LAST_FLOGI_ISSUED_COMMON_PARAMETERS_WORD_2:
116 case DRV_TLV_LAST_FLOGI_ISSUED_COMMON_PARAMETERS_WORD_3:
117 case DRV_TLV_LAST_FLOGI_ISSUED_COMMON_PARAMETERS_WORD_4:
118 case DRV_TLV_LAST_FLOGI_TIMESTAMP:
119 case DRV_TLV_LAST_FLOGI_ACC_COMMON_PARAMETERS_WORD_1:
120 case DRV_TLV_LAST_FLOGI_ACC_COMMON_PARAMETERS_WORD_2:
121 case DRV_TLV_LAST_FLOGI_ACC_COMMON_PARAMETERS_WORD_3:
122 case DRV_TLV_LAST_FLOGI_ACC_COMMON_PARAMETERS_WORD_4:
123 case DRV_TLV_LAST_FLOGI_ACC_TIMESTAMP:
124 case DRV_TLV_LAST_FLOGI_RJT:
125 case DRV_TLV_LAST_FLOGI_RJT_TIMESTAMP:
126 case DRV_TLV_FDISCS_SENT_COUNT:
127 case DRV_TLV_FDISC_ACCS_RECEIVED:
128 case DRV_TLV_FDISC_RJTS_RECEIVED:
129 case DRV_TLV_PLOGI_SENT_COUNT:
130 case DRV_TLV_PLOGI_ACCS_RECEIVED:
131 case DRV_TLV_PLOGI_RJTS_RECEIVED:
132 case DRV_TLV_PLOGI_1_SENT_DESTINATION_FC_ID:
133 case DRV_TLV_PLOGI_1_TIMESTAMP:
134 case DRV_TLV_PLOGI_2_SENT_DESTINATION_FC_ID:
135 case DRV_TLV_PLOGI_2_TIMESTAMP:
136 case DRV_TLV_PLOGI_3_SENT_DESTINATION_FC_ID:
137 case DRV_TLV_PLOGI_3_TIMESTAMP:
138 case DRV_TLV_PLOGI_4_SENT_DESTINATION_FC_ID:
139 case DRV_TLV_PLOGI_4_TIMESTAMP:
140 case DRV_TLV_PLOGI_5_SENT_DESTINATION_FC_ID:
141 case DRV_TLV_PLOGI_5_TIMESTAMP:
142 case DRV_TLV_PLOGI_1_ACC_RECEIVED_SOURCE_FC_ID:
143 case DRV_TLV_PLOGI_1_ACC_TIMESTAMP:
144 case DRV_TLV_PLOGI_2_ACC_RECEIVED_SOURCE_FC_ID:
145 case DRV_TLV_PLOGI_2_ACC_TIMESTAMP:
146 case DRV_TLV_PLOGI_3_ACC_RECEIVED_SOURCE_FC_ID:
147 case DRV_TLV_PLOGI_3_ACC_TIMESTAMP:
148 case DRV_TLV_PLOGI_4_ACC_RECEIVED_SOURCE_FC_ID:
149 case DRV_TLV_PLOGI_4_ACC_TIMESTAMP:
150 case DRV_TLV_PLOGI_5_ACC_RECEIVED_SOURCE_FC_ID:
151 case DRV_TLV_PLOGI_5_ACC_TIMESTAMP:
152 case DRV_TLV_LOGOS_ISSUED:
153 case DRV_TLV_LOGO_ACCS_RECEIVED:
154 case DRV_TLV_LOGO_RJTS_RECEIVED:
155 case DRV_TLV_LOGO_1_RECEIVED_SOURCE_FC_ID:
156 case DRV_TLV_LOGO_1_TIMESTAMP:
157 case DRV_TLV_LOGO_2_RECEIVED_SOURCE_FC_ID:
158 case DRV_TLV_LOGO_2_TIMESTAMP:
159 case DRV_TLV_LOGO_3_RECEIVED_SOURCE_FC_ID:
160 case DRV_TLV_LOGO_3_TIMESTAMP:
161 case DRV_TLV_LOGO_4_RECEIVED_SOURCE_FC_ID:
162 case DRV_TLV_LOGO_4_TIMESTAMP:
163 case DRV_TLV_LOGO_5_RECEIVED_SOURCE_FC_ID:
164 case DRV_TLV_LOGO_5_TIMESTAMP:
165 case DRV_TLV_LOGOS_RECEIVED:
166 case DRV_TLV_ACCS_ISSUED:
167 case DRV_TLV_PRLIS_ISSUED:
168 case DRV_TLV_ACCS_RECEIVED:
169 case DRV_TLV_ABTS_SENT_COUNT:
170 case DRV_TLV_ABTS_ACCS_RECEIVED:
171 case DRV_TLV_ABTS_RJTS_RECEIVED:
172 case DRV_TLV_ABTS_1_SENT_DESTINATION_FC_ID:
173 case DRV_TLV_ABTS_1_TIMESTAMP:
174 case DRV_TLV_ABTS_2_SENT_DESTINATION_FC_ID:
175 case DRV_TLV_ABTS_2_TIMESTAMP:
176 case DRV_TLV_ABTS_3_SENT_DESTINATION_FC_ID:
177 case DRV_TLV_ABTS_3_TIMESTAMP:
178 case DRV_TLV_ABTS_4_SENT_DESTINATION_FC_ID:
179 case DRV_TLV_ABTS_4_TIMESTAMP:
180 case DRV_TLV_ABTS_5_SENT_DESTINATION_FC_ID:
181 case DRV_TLV_ABTS_5_TIMESTAMP:
182 case DRV_TLV_RSCNS_RECEIVED:
183 case DRV_TLV_LAST_RSCN_RECEIVED_N_PORT_1:
184 case DRV_TLV_LAST_RSCN_RECEIVED_N_PORT_2:
185 case DRV_TLV_LAST_RSCN_RECEIVED_N_PORT_3:
186 case DRV_TLV_LAST_RSCN_RECEIVED_N_PORT_4:
187 case DRV_TLV_LUN_RESETS_ISSUED:
188 case DRV_TLV_ABORT_TASK_SETS_ISSUED:
189 case DRV_TLV_TPRLOS_SENT:
190 case DRV_TLV_NOS_SENT_COUNT:
191 case DRV_TLV_NOS_RECEIVED_COUNT:
192 case DRV_TLV_OLS_COUNT:
193 case DRV_TLV_LR_COUNT:
194 case DRV_TLV_LRR_COUNT:
195 case DRV_TLV_LIP_SENT_COUNT:
196 case DRV_TLV_LIP_RECEIVED_COUNT:
197 case DRV_TLV_EOFA_COUNT:
198 case DRV_TLV_EOFNI_COUNT:
199 case DRV_TLV_SCSI_STATUS_CHECK_CONDITION_COUNT:
200 case DRV_TLV_SCSI_STATUS_CONDITION_MET_COUNT:
201 case DRV_TLV_SCSI_STATUS_BUSY_COUNT:
202 case DRV_TLV_SCSI_STATUS_INTERMEDIATE_COUNT:
203 case DRV_TLV_SCSI_STATUS_INTERMEDIATE_CONDITION_MET_COUNT:
204 case DRV_TLV_SCSI_STATUS_RESERVATION_CONFLICT_COUNT:
205 case DRV_TLV_SCSI_STATUS_TASK_SET_FULL_COUNT:
206 case DRV_TLV_SCSI_STATUS_ACA_ACTIVE_COUNT:
207 case DRV_TLV_SCSI_STATUS_TASK_ABORTED_COUNT:
208 case DRV_TLV_SCSI_CHECK_CONDITION_1_RECEIVED_SK_ASC_ASCQ:
209 case DRV_TLV_SCSI_CHECK_1_TIMESTAMP:
210 case DRV_TLV_SCSI_CHECK_CONDITION_2_RECEIVED_SK_ASC_ASCQ:
211 case DRV_TLV_SCSI_CHECK_2_TIMESTAMP:
212 case DRV_TLV_SCSI_CHECK_CONDITION_3_RECEIVED_SK_ASC_ASCQ:
213 case DRV_TLV_SCSI_CHECK_3_TIMESTAMP:
214 case DRV_TLV_SCSI_CHECK_CONDITION_4_RECEIVED_SK_ASC_ASCQ:
215 case DRV_TLV_SCSI_CHECK_4_TIMESTAMP:
216 case DRV_TLV_SCSI_CHECK_CONDITION_5_RECEIVED_SK_ASC_ASCQ:
217 case DRV_TLV_SCSI_CHECK_5_TIMESTAMP:
218 *tlv_group = QED_MFW_TLV_FCOE;
219 break;
220 case DRV_TLV_TARGET_LLMNR_ENABLED:
221 case DRV_TLV_HEADER_DIGEST_FLAG_ENABLED:
222 case DRV_TLV_DATA_DIGEST_FLAG_ENABLED:
223 case DRV_TLV_AUTHENTICATION_METHOD:
224 case DRV_TLV_ISCSI_BOOT_TARGET_PORTAL:
225 case DRV_TLV_MAX_FRAME_SIZE:
226 case DRV_TLV_PDU_TX_DESCRIPTORS_QUEUE_SIZE:
227 case DRV_TLV_PDU_RX_DESCRIPTORS_QUEUE_SIZE:
228 case DRV_TLV_ISCSI_BOOT_PROGRESS:
229 case DRV_TLV_PDU_TX_DESCRIPTOR_QUEUE_AVG_DEPTH:
230 case DRV_TLV_PDU_RX_DESCRIPTORS_QUEUE_AVG_DEPTH:
231 case DRV_TLV_ISCSI_PDU_RX_FRAMES_RECEIVED:
232 case DRV_TLV_ISCSI_PDU_RX_BYTES_RECEIVED:
233 case DRV_TLV_ISCSI_PDU_TX_FRAMES_SENT:
234 case DRV_TLV_ISCSI_PDU_TX_BYTES_SENT:
235 *tlv_group |= QED_MFW_TLV_ISCSI;
236 break;
237 default:
238 return -EINVAL;
239 }
240
241 return 0;
242}
243
244/* Returns size of the data buffer or, -1 in case TLV data is not available. */
245static int
246qed_mfw_get_gen_tlv_value(struct qed_drv_tlv_hdr *p_tlv,
247 struct qed_mfw_tlv_generic *p_drv_buf,
248 struct qed_tlv_parsed_buf *p_buf)
249{
250 switch (p_tlv->tlv_type) {
251 case DRV_TLV_FEATURE_FLAGS:
252 if (p_drv_buf->flags.b_set) {
253 memset(p_buf->data, 0, sizeof(u8) * QED_TLV_DATA_MAX);
254 p_buf->data[0] = p_drv_buf->flags.ipv4_csum_offload ?
255 1 : 0;
256 p_buf->data[0] |= (p_drv_buf->flags.lso_supported ?
257 1 : 0) << 1;
258 p_buf->p_val = p_buf->data;
259 return QED_MFW_TLV_FLAGS_SIZE;
260 }
261 break;
262
263 case DRV_TLV_LOCAL_ADMIN_ADDR:
264 case DRV_TLV_ADDITIONAL_MAC_ADDR_1:
265 case DRV_TLV_ADDITIONAL_MAC_ADDR_2:
266 {
267 int idx = p_tlv->tlv_type - DRV_TLV_LOCAL_ADMIN_ADDR;
268
269 if (p_drv_buf->mac_set[idx]) {
270 p_buf->p_val = p_drv_buf->mac[idx];
271 return ETH_ALEN;
272 }
273 break;
274 }
275
276 case DRV_TLV_RX_FRAMES_RECEIVED:
277 if (p_drv_buf->rx_frames_set) {
278 p_buf->p_val = &p_drv_buf->rx_frames;
279 return sizeof(p_drv_buf->rx_frames);
280 }
281 break;
282 case DRV_TLV_RX_BYTES_RECEIVED:
283 if (p_drv_buf->rx_bytes_set) {
284 p_buf->p_val = &p_drv_buf->rx_bytes;
285 return sizeof(p_drv_buf->rx_bytes);
286 }
287 break;
288 case DRV_TLV_TX_FRAMES_SENT:
289 if (p_drv_buf->tx_frames_set) {
290 p_buf->p_val = &p_drv_buf->tx_frames;
291 return sizeof(p_drv_buf->tx_frames);
292 }
293 break;
294 case DRV_TLV_TX_BYTES_SENT:
295 if (p_drv_buf->tx_bytes_set) {
296 p_buf->p_val = &p_drv_buf->tx_bytes;
297 return sizeof(p_drv_buf->tx_bytes);
298 }
299 break;
300 default:
301 break;
302 }
303
304 return -1;
305}
306
307static int
308qed_mfw_get_eth_tlv_value(struct qed_drv_tlv_hdr *p_tlv,
309 struct qed_mfw_tlv_eth *p_drv_buf,
310 struct qed_tlv_parsed_buf *p_buf)
311{
312 switch (p_tlv->tlv_type) {
313 case DRV_TLV_LSO_MAX_OFFLOAD_SIZE:
314 if (p_drv_buf->lso_maxoff_size_set) {
315 p_buf->p_val = &p_drv_buf->lso_maxoff_size;
316 return sizeof(p_drv_buf->lso_maxoff_size);
317 }
318 break;
319 case DRV_TLV_LSO_MIN_SEGMENT_COUNT:
320 if (p_drv_buf->lso_minseg_size_set) {
321 p_buf->p_val = &p_drv_buf->lso_minseg_size;
322 return sizeof(p_drv_buf->lso_minseg_size);
323 }
324 break;
325 case DRV_TLV_PROMISCUOUS_MODE:
326 if (p_drv_buf->prom_mode_set) {
327 p_buf->p_val = &p_drv_buf->prom_mode;
328 return sizeof(p_drv_buf->prom_mode);
329 }
330 break;
331 case DRV_TLV_TX_DESCRIPTORS_QUEUE_SIZE:
332 if (p_drv_buf->tx_descr_size_set) {
333 p_buf->p_val = &p_drv_buf->tx_descr_size;
334 return sizeof(p_drv_buf->tx_descr_size);
335 }
336 break;
337 case DRV_TLV_RX_DESCRIPTORS_QUEUE_SIZE:
338 if (p_drv_buf->rx_descr_size_set) {
339 p_buf->p_val = &p_drv_buf->rx_descr_size;
340 return sizeof(p_drv_buf->rx_descr_size);
341 }
342 break;
343 case DRV_TLV_NUM_OF_NET_QUEUE_VMQ_CFG:
344 if (p_drv_buf->netq_count_set) {
345 p_buf->p_val = &p_drv_buf->netq_count;
346 return sizeof(p_drv_buf->netq_count);
347 }
348 break;
349 case DRV_TLV_NUM_OFFLOADED_CONNECTIONS_TCP_IPV4:
350 if (p_drv_buf->tcp4_offloads_set) {
351 p_buf->p_val = &p_drv_buf->tcp4_offloads;
352 return sizeof(p_drv_buf->tcp4_offloads);
353 }
354 break;
355 case DRV_TLV_NUM_OFFLOADED_CONNECTIONS_TCP_IPV6:
356 if (p_drv_buf->tcp6_offloads_set) {
357 p_buf->p_val = &p_drv_buf->tcp6_offloads;
358 return sizeof(p_drv_buf->tcp6_offloads);
359 }
360 break;
361 case DRV_TLV_TX_DESCRIPTOR_QUEUE_AVG_DEPTH:
362 if (p_drv_buf->tx_descr_qdepth_set) {
363 p_buf->p_val = &p_drv_buf->tx_descr_qdepth;
364 return sizeof(p_drv_buf->tx_descr_qdepth);
365 }
366 break;
367 case DRV_TLV_RX_DESCRIPTORS_QUEUE_AVG_DEPTH:
368 if (p_drv_buf->rx_descr_qdepth_set) {
369 p_buf->p_val = &p_drv_buf->rx_descr_qdepth;
370 return sizeof(p_drv_buf->rx_descr_qdepth);
371 }
372 break;
373 case DRV_TLV_IOV_OFFLOAD:
374 if (p_drv_buf->iov_offload_set) {
375 p_buf->p_val = &p_drv_buf->iov_offload;
376 return sizeof(p_drv_buf->iov_offload);
377 }
378 break;
379 case DRV_TLV_TX_QUEUES_EMPTY:
380 if (p_drv_buf->txqs_empty_set) {
381 p_buf->p_val = &p_drv_buf->txqs_empty;
382 return sizeof(p_drv_buf->txqs_empty);
383 }
384 break;
385 case DRV_TLV_RX_QUEUES_EMPTY:
386 if (p_drv_buf->rxqs_empty_set) {
387 p_buf->p_val = &p_drv_buf->rxqs_empty;
388 return sizeof(p_drv_buf->rxqs_empty);
389 }
390 break;
391 case DRV_TLV_TX_QUEUES_FULL:
392 if (p_drv_buf->num_txqs_full_set) {
393 p_buf->p_val = &p_drv_buf->num_txqs_full;
394 return sizeof(p_drv_buf->num_txqs_full);
395 }
396 break;
397 case DRV_TLV_RX_QUEUES_FULL:
398 if (p_drv_buf->num_rxqs_full_set) {
399 p_buf->p_val = &p_drv_buf->num_rxqs_full;
400 return sizeof(p_drv_buf->num_rxqs_full);
401 }
402 break;
403 default:
404 break;
405 }
406
407 return -1;
408}
409
410static int
411qed_mfw_get_tlv_time_value(struct qed_mfw_tlv_time *p_time,
412 struct qed_tlv_parsed_buf *p_buf)
413{
414 if (!p_time->b_set)
415 return -1;
416
417 /* Validate numbers */
418 if (p_time->month > 12)
419 p_time->month = 0;
420 if (p_time->day > 31)
421 p_time->day = 0;
422 if (p_time->hour > 23)
423 p_time->hour = 0;
424 if (p_time->min > 59)
425 p_time->min = 0;
426 if (p_time->msec > 999)
427 p_time->msec = 0;
428 if (p_time->usec > 999)
429 p_time->usec = 0;
430
431 memset(p_buf->data, 0, sizeof(u8) * QED_TLV_DATA_MAX);
432 snprintf(buf: p_buf->data, size: 14, fmt: "%d%d%d%d%d%d",
433 p_time->month, p_time->day,
434 p_time->hour, p_time->min, p_time->msec, p_time->usec);
435
436 p_buf->p_val = p_buf->data;
437
438 return QED_MFW_TLV_TIME_SIZE;
439}
440
441static int
442qed_mfw_get_fcoe_tlv_value(struct qed_drv_tlv_hdr *p_tlv,
443 struct qed_mfw_tlv_fcoe *p_drv_buf,
444 struct qed_tlv_parsed_buf *p_buf)
445{
446 struct qed_mfw_tlv_time *p_time;
447 u8 idx;
448
449 switch (p_tlv->tlv_type) {
450 case DRV_TLV_SCSI_TO:
451 if (p_drv_buf->scsi_timeout_set) {
452 p_buf->p_val = &p_drv_buf->scsi_timeout;
453 return sizeof(p_drv_buf->scsi_timeout);
454 }
455 break;
456 case DRV_TLV_R_T_TOV:
457 if (p_drv_buf->rt_tov_set) {
458 p_buf->p_val = &p_drv_buf->rt_tov;
459 return sizeof(p_drv_buf->rt_tov);
460 }
461 break;
462 case DRV_TLV_R_A_TOV:
463 if (p_drv_buf->ra_tov_set) {
464 p_buf->p_val = &p_drv_buf->ra_tov;
465 return sizeof(p_drv_buf->ra_tov);
466 }
467 break;
468 case DRV_TLV_E_D_TOV:
469 if (p_drv_buf->ed_tov_set) {
470 p_buf->p_val = &p_drv_buf->ed_tov;
471 return sizeof(p_drv_buf->ed_tov);
472 }
473 break;
474 case DRV_TLV_CR_TOV:
475 if (p_drv_buf->cr_tov_set) {
476 p_buf->p_val = &p_drv_buf->cr_tov;
477 return sizeof(p_drv_buf->cr_tov);
478 }
479 break;
480 case DRV_TLV_BOOT_TYPE:
481 if (p_drv_buf->boot_type_set) {
482 p_buf->p_val = &p_drv_buf->boot_type;
483 return sizeof(p_drv_buf->boot_type);
484 }
485 break;
486 case DRV_TLV_NPIV_STATE:
487 if (p_drv_buf->npiv_state_set) {
488 p_buf->p_val = &p_drv_buf->npiv_state;
489 return sizeof(p_drv_buf->npiv_state);
490 }
491 break;
492 case DRV_TLV_NUM_OF_NPIV_IDS:
493 if (p_drv_buf->num_npiv_ids_set) {
494 p_buf->p_val = &p_drv_buf->num_npiv_ids;
495 return sizeof(p_drv_buf->num_npiv_ids);
496 }
497 break;
498 case DRV_TLV_SWITCH_NAME:
499 if (p_drv_buf->switch_name_set) {
500 p_buf->p_val = &p_drv_buf->switch_name;
501 return sizeof(p_drv_buf->switch_name);
502 }
503 break;
504 case DRV_TLV_SWITCH_PORT_NUM:
505 if (p_drv_buf->switch_portnum_set) {
506 p_buf->p_val = &p_drv_buf->switch_portnum;
507 return sizeof(p_drv_buf->switch_portnum);
508 }
509 break;
510 case DRV_TLV_SWITCH_PORT_ID:
511 if (p_drv_buf->switch_portid_set) {
512 p_buf->p_val = &p_drv_buf->switch_portid;
513 return sizeof(p_drv_buf->switch_portid);
514 }
515 break;
516 case DRV_TLV_VENDOR_NAME:
517 if (p_drv_buf->vendor_name_set) {
518 p_buf->p_val = &p_drv_buf->vendor_name;
519 return sizeof(p_drv_buf->vendor_name);
520 }
521 break;
522 case DRV_TLV_SWITCH_MODEL:
523 if (p_drv_buf->switch_model_set) {
524 p_buf->p_val = &p_drv_buf->switch_model;
525 return sizeof(p_drv_buf->switch_model);
526 }
527 break;
528 case DRV_TLV_SWITCH_FW_VER:
529 if (p_drv_buf->switch_fw_version_set) {
530 p_buf->p_val = &p_drv_buf->switch_fw_version;
531 return sizeof(p_drv_buf->switch_fw_version);
532 }
533 break;
534 case DRV_TLV_QOS_PRIORITY_PER_802_1P:
535 if (p_drv_buf->qos_pri_set) {
536 p_buf->p_val = &p_drv_buf->qos_pri;
537 return sizeof(p_drv_buf->qos_pri);
538 }
539 break;
540 case DRV_TLV_PORT_ALIAS:
541 if (p_drv_buf->port_alias_set) {
542 p_buf->p_val = &p_drv_buf->port_alias;
543 return sizeof(p_drv_buf->port_alias);
544 }
545 break;
546 case DRV_TLV_PORT_STATE:
547 if (p_drv_buf->port_state_set) {
548 p_buf->p_val = &p_drv_buf->port_state;
549 return sizeof(p_drv_buf->port_state);
550 }
551 break;
552 case DRV_TLV_FIP_TX_DESCRIPTORS_QUEUE_SIZE:
553 if (p_drv_buf->fip_tx_descr_size_set) {
554 p_buf->p_val = &p_drv_buf->fip_tx_descr_size;
555 return sizeof(p_drv_buf->fip_tx_descr_size);
556 }
557 break;
558 case DRV_TLV_FCOE_RX_DESCRIPTORS_QUEUE_SIZE:
559 if (p_drv_buf->fip_rx_descr_size_set) {
560 p_buf->p_val = &p_drv_buf->fip_rx_descr_size;
561 return sizeof(p_drv_buf->fip_rx_descr_size);
562 }
563 break;
564 case DRV_TLV_LINK_FAILURE_COUNT:
565 if (p_drv_buf->link_failures_set) {
566 p_buf->p_val = &p_drv_buf->link_failures;
567 return sizeof(p_drv_buf->link_failures);
568 }
569 break;
570 case DRV_TLV_FCOE_BOOT_PROGRESS:
571 if (p_drv_buf->fcoe_boot_progress_set) {
572 p_buf->p_val = &p_drv_buf->fcoe_boot_progress;
573 return sizeof(p_drv_buf->fcoe_boot_progress);
574 }
575 break;
576 case DRV_TLV_RX_BROADCAST_PACKETS:
577 if (p_drv_buf->rx_bcast_set) {
578 p_buf->p_val = &p_drv_buf->rx_bcast;
579 return sizeof(p_drv_buf->rx_bcast);
580 }
581 break;
582 case DRV_TLV_TX_BROADCAST_PACKETS:
583 if (p_drv_buf->tx_bcast_set) {
584 p_buf->p_val = &p_drv_buf->tx_bcast;
585 return sizeof(p_drv_buf->tx_bcast);
586 }
587 break;
588 case DRV_TLV_FCOE_TX_DESCRIPTOR_QUEUE_AVG_DEPTH:
589 if (p_drv_buf->fcoe_txq_depth_set) {
590 p_buf->p_val = &p_drv_buf->fcoe_txq_depth;
591 return sizeof(p_drv_buf->fcoe_txq_depth);
592 }
593 break;
594 case DRV_TLV_FCOE_RX_DESCRIPTORS_QUEUE_AVG_DEPTH:
595 if (p_drv_buf->fcoe_rxq_depth_set) {
596 p_buf->p_val = &p_drv_buf->fcoe_rxq_depth;
597 return sizeof(p_drv_buf->fcoe_rxq_depth);
598 }
599 break;
600 case DRV_TLV_FCOE_RX_FRAMES_RECEIVED:
601 if (p_drv_buf->fcoe_rx_frames_set) {
602 p_buf->p_val = &p_drv_buf->fcoe_rx_frames;
603 return sizeof(p_drv_buf->fcoe_rx_frames);
604 }
605 break;
606 case DRV_TLV_FCOE_RX_BYTES_RECEIVED:
607 if (p_drv_buf->fcoe_rx_bytes_set) {
608 p_buf->p_val = &p_drv_buf->fcoe_rx_bytes;
609 return sizeof(p_drv_buf->fcoe_rx_bytes);
610 }
611 break;
612 case DRV_TLV_FCOE_TX_FRAMES_SENT:
613 if (p_drv_buf->fcoe_tx_frames_set) {
614 p_buf->p_val = &p_drv_buf->fcoe_tx_frames;
615 return sizeof(p_drv_buf->fcoe_tx_frames);
616 }
617 break;
618 case DRV_TLV_FCOE_TX_BYTES_SENT:
619 if (p_drv_buf->fcoe_tx_bytes_set) {
620 p_buf->p_val = &p_drv_buf->fcoe_tx_bytes;
621 return sizeof(p_drv_buf->fcoe_tx_bytes);
622 }
623 break;
624 case DRV_TLV_CRC_ERROR_COUNT:
625 if (p_drv_buf->crc_count_set) {
626 p_buf->p_val = &p_drv_buf->crc_count;
627 return sizeof(p_drv_buf->crc_count);
628 }
629 break;
630 case DRV_TLV_CRC_ERROR_1_RECEIVED_SOURCE_FC_ID:
631 case DRV_TLV_CRC_ERROR_2_RECEIVED_SOURCE_FC_ID:
632 case DRV_TLV_CRC_ERROR_3_RECEIVED_SOURCE_FC_ID:
633 case DRV_TLV_CRC_ERROR_4_RECEIVED_SOURCE_FC_ID:
634 case DRV_TLV_CRC_ERROR_5_RECEIVED_SOURCE_FC_ID:
635 idx = (p_tlv->tlv_type -
636 DRV_TLV_CRC_ERROR_1_RECEIVED_SOURCE_FC_ID) / 2;
637
638 if (p_drv_buf->crc_err_src_fcid_set[idx]) {
639 p_buf->p_val = &p_drv_buf->crc_err_src_fcid[idx];
640 return sizeof(p_drv_buf->crc_err_src_fcid[idx]);
641 }
642 break;
643 case DRV_TLV_CRC_ERROR_1_TIMESTAMP:
644 case DRV_TLV_CRC_ERROR_2_TIMESTAMP:
645 case DRV_TLV_CRC_ERROR_3_TIMESTAMP:
646 case DRV_TLV_CRC_ERROR_4_TIMESTAMP:
647 case DRV_TLV_CRC_ERROR_5_TIMESTAMP:
648 idx = (p_tlv->tlv_type - DRV_TLV_CRC_ERROR_1_TIMESTAMP) / 2;
649
650 return qed_mfw_get_tlv_time_value(p_time: &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_time: &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_time: &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_time: &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_time: &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_time: &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_time: &p_drv_buf->abts_tstamp[idx],
903 p_buf);
904 case DRV_TLV_RSCNS_RECEIVED:
905 if (p_drv_buf->rx_rscn_set) {
906 p_buf->p_val = &p_drv_buf->rx_rscn;
907 return sizeof(p_drv_buf->rx_rscn);
908 }
909 break;
910 case DRV_TLV_LAST_RSCN_RECEIVED_N_PORT_1:
911 case DRV_TLV_LAST_RSCN_RECEIVED_N_PORT_2:
912 case DRV_TLV_LAST_RSCN_RECEIVED_N_PORT_3:
913 case DRV_TLV_LAST_RSCN_RECEIVED_N_PORT_4:
914 idx = p_tlv->tlv_type - DRV_TLV_LAST_RSCN_RECEIVED_N_PORT_1;
915
916 if (p_drv_buf->rx_rscn_nport_set[idx]) {
917 p_buf->p_val = &p_drv_buf->rx_rscn_nport[idx];
918 return sizeof(p_drv_buf->rx_rscn_nport[idx]);
919 }
920 break;
921 case DRV_TLV_LUN_RESETS_ISSUED:
922 if (p_drv_buf->tx_lun_rst_set) {
923 p_buf->p_val = &p_drv_buf->tx_lun_rst;
924 return sizeof(p_drv_buf->tx_lun_rst);
925 }
926 break;
927 case DRV_TLV_ABORT_TASK_SETS_ISSUED:
928 if (p_drv_buf->abort_task_sets_set) {
929 p_buf->p_val = &p_drv_buf->abort_task_sets;
930 return sizeof(p_drv_buf->abort_task_sets);
931 }
932 break;
933 case DRV_TLV_TPRLOS_SENT:
934 if (p_drv_buf->tx_tprlos_set) {
935 p_buf->p_val = &p_drv_buf->tx_tprlos;
936 return sizeof(p_drv_buf->tx_tprlos);
937 }
938 break;
939 case DRV_TLV_NOS_SENT_COUNT:
940 if (p_drv_buf->tx_nos_set) {
941 p_buf->p_val = &p_drv_buf->tx_nos;
942 return sizeof(p_drv_buf->tx_nos);
943 }
944 break;
945 case DRV_TLV_NOS_RECEIVED_COUNT:
946 if (p_drv_buf->rx_nos_set) {
947 p_buf->p_val = &p_drv_buf->rx_nos;
948 return sizeof(p_drv_buf->rx_nos);
949 }
950 break;
951 case DRV_TLV_OLS_COUNT:
952 if (p_drv_buf->ols_set) {
953 p_buf->p_val = &p_drv_buf->ols;
954 return sizeof(p_drv_buf->ols);
955 }
956 break;
957 case DRV_TLV_LR_COUNT:
958 if (p_drv_buf->lr_set) {
959 p_buf->p_val = &p_drv_buf->lr;
960 return sizeof(p_drv_buf->lr);
961 }
962 break;
963 case DRV_TLV_LRR_COUNT:
964 if (p_drv_buf->lrr_set) {
965 p_buf->p_val = &p_drv_buf->lrr;
966 return sizeof(p_drv_buf->lrr);
967 }
968 break;
969 case DRV_TLV_LIP_SENT_COUNT:
970 if (p_drv_buf->tx_lip_set) {
971 p_buf->p_val = &p_drv_buf->tx_lip;
972 return sizeof(p_drv_buf->tx_lip);
973 }
974 break;
975 case DRV_TLV_LIP_RECEIVED_COUNT:
976 if (p_drv_buf->rx_lip_set) {
977 p_buf->p_val = &p_drv_buf->rx_lip;
978 return sizeof(p_drv_buf->rx_lip);
979 }
980 break;
981 case DRV_TLV_EOFA_COUNT:
982 if (p_drv_buf->eofa_set) {
983 p_buf->p_val = &p_drv_buf->eofa;
984 return sizeof(p_drv_buf->eofa);
985 }
986 break;
987 case DRV_TLV_EOFNI_COUNT:
988 if (p_drv_buf->eofni_set) {
989 p_buf->p_val = &p_drv_buf->eofni;
990 return sizeof(p_drv_buf->eofni);
991 }
992 break;
993 case DRV_TLV_SCSI_STATUS_CHECK_CONDITION_COUNT:
994 if (p_drv_buf->scsi_chks_set) {
995 p_buf->p_val = &p_drv_buf->scsi_chks;
996 return sizeof(p_drv_buf->scsi_chks);
997 }
998 break;
999 case DRV_TLV_SCSI_STATUS_CONDITION_MET_COUNT:
1000 if (p_drv_buf->scsi_cond_met_set) {
1001 p_buf->p_val = &p_drv_buf->scsi_cond_met;
1002 return sizeof(p_drv_buf->scsi_cond_met);
1003 }
1004 break;
1005 case DRV_TLV_SCSI_STATUS_BUSY_COUNT:
1006 if (p_drv_buf->scsi_busy_set) {
1007 p_buf->p_val = &p_drv_buf->scsi_busy;
1008 return sizeof(p_drv_buf->scsi_busy);
1009 }
1010 break;
1011 case DRV_TLV_SCSI_STATUS_INTERMEDIATE_COUNT:
1012 if (p_drv_buf->scsi_inter_set) {
1013 p_buf->p_val = &p_drv_buf->scsi_inter;
1014 return sizeof(p_drv_buf->scsi_inter);
1015 }
1016 break;
1017 case DRV_TLV_SCSI_STATUS_INTERMEDIATE_CONDITION_MET_COUNT:
1018 if (p_drv_buf->scsi_inter_cond_met_set) {
1019 p_buf->p_val = &p_drv_buf->scsi_inter_cond_met;
1020 return sizeof(p_drv_buf->scsi_inter_cond_met);
1021 }
1022 break;
1023 case DRV_TLV_SCSI_STATUS_RESERVATION_CONFLICT_COUNT:
1024 if (p_drv_buf->scsi_rsv_conflicts_set) {
1025 p_buf->p_val = &p_drv_buf->scsi_rsv_conflicts;
1026 return sizeof(p_drv_buf->scsi_rsv_conflicts);
1027 }
1028 break;
1029 case DRV_TLV_SCSI_STATUS_TASK_SET_FULL_COUNT:
1030 if (p_drv_buf->scsi_tsk_full_set) {
1031 p_buf->p_val = &p_drv_buf->scsi_tsk_full;
1032 return sizeof(p_drv_buf->scsi_tsk_full);
1033 }
1034 break;
1035 case DRV_TLV_SCSI_STATUS_ACA_ACTIVE_COUNT:
1036 if (p_drv_buf->scsi_aca_active_set) {
1037 p_buf->p_val = &p_drv_buf->scsi_aca_active;
1038 return sizeof(p_drv_buf->scsi_aca_active);
1039 }
1040 break;
1041 case DRV_TLV_SCSI_STATUS_TASK_ABORTED_COUNT:
1042 if (p_drv_buf->scsi_tsk_abort_set) {
1043 p_buf->p_val = &p_drv_buf->scsi_tsk_abort;
1044 return sizeof(p_drv_buf->scsi_tsk_abort);
1045 }
1046 break;
1047 case DRV_TLV_SCSI_CHECK_CONDITION_1_RECEIVED_SK_ASC_ASCQ:
1048 case DRV_TLV_SCSI_CHECK_CONDITION_2_RECEIVED_SK_ASC_ASCQ:
1049 case DRV_TLV_SCSI_CHECK_CONDITION_3_RECEIVED_SK_ASC_ASCQ:
1050 case DRV_TLV_SCSI_CHECK_CONDITION_4_RECEIVED_SK_ASC_ASCQ:
1051 case DRV_TLV_SCSI_CHECK_CONDITION_5_RECEIVED_SK_ASC_ASCQ:
1052 idx = (p_tlv->tlv_type -
1053 DRV_TLV_SCSI_CHECK_CONDITION_1_RECEIVED_SK_ASC_ASCQ) / 2;
1054
1055 if (p_drv_buf->scsi_rx_chk_set[idx]) {
1056 p_buf->p_val = &p_drv_buf->scsi_rx_chk[idx];
1057 return sizeof(p_drv_buf->scsi_rx_chk[idx]);
1058 }
1059 break;
1060 case DRV_TLV_SCSI_CHECK_1_TIMESTAMP:
1061 case DRV_TLV_SCSI_CHECK_2_TIMESTAMP:
1062 case DRV_TLV_SCSI_CHECK_3_TIMESTAMP:
1063 case DRV_TLV_SCSI_CHECK_4_TIMESTAMP:
1064 case DRV_TLV_SCSI_CHECK_5_TIMESTAMP:
1065 idx = (p_tlv->tlv_type - DRV_TLV_SCSI_CHECK_1_TIMESTAMP) / 2;
1066 p_time = &p_drv_buf->scsi_chk_tstamp[idx];
1067
1068 return qed_mfw_get_tlv_time_value(p_time, p_buf);
1069 default:
1070 break;
1071 }
1072
1073 return -1;
1074}
1075
1076static int
1077qed_mfw_get_iscsi_tlv_value(struct qed_drv_tlv_hdr *p_tlv,
1078 struct qed_mfw_tlv_iscsi *p_drv_buf,
1079 struct qed_tlv_parsed_buf *p_buf)
1080{
1081 switch (p_tlv->tlv_type) {
1082 case DRV_TLV_TARGET_LLMNR_ENABLED:
1083 if (p_drv_buf->target_llmnr_set) {
1084 p_buf->p_val = &p_drv_buf->target_llmnr;
1085 return sizeof(p_drv_buf->target_llmnr);
1086 }
1087 break;
1088 case DRV_TLV_HEADER_DIGEST_FLAG_ENABLED:
1089 if (p_drv_buf->header_digest_set) {
1090 p_buf->p_val = &p_drv_buf->header_digest;
1091 return sizeof(p_drv_buf->header_digest);
1092 }
1093 break;
1094 case DRV_TLV_DATA_DIGEST_FLAG_ENABLED:
1095 if (p_drv_buf->data_digest_set) {
1096 p_buf->p_val = &p_drv_buf->data_digest;
1097 return sizeof(p_drv_buf->data_digest);
1098 }
1099 break;
1100 case DRV_TLV_AUTHENTICATION_METHOD:
1101 if (p_drv_buf->auth_method_set) {
1102 p_buf->p_val = &p_drv_buf->auth_method;
1103 return sizeof(p_drv_buf->auth_method);
1104 }
1105 break;
1106 case DRV_TLV_ISCSI_BOOT_TARGET_PORTAL:
1107 if (p_drv_buf->boot_taget_portal_set) {
1108 p_buf->p_val = &p_drv_buf->boot_taget_portal;
1109 return sizeof(p_drv_buf->boot_taget_portal);
1110 }
1111 break;
1112 case DRV_TLV_MAX_FRAME_SIZE:
1113 if (p_drv_buf->frame_size_set) {
1114 p_buf->p_val = &p_drv_buf->frame_size;
1115 return sizeof(p_drv_buf->frame_size);
1116 }
1117 break;
1118 case DRV_TLV_PDU_TX_DESCRIPTORS_QUEUE_SIZE:
1119 if (p_drv_buf->tx_desc_size_set) {
1120 p_buf->p_val = &p_drv_buf->tx_desc_size;
1121 return sizeof(p_drv_buf->tx_desc_size);
1122 }
1123 break;
1124 case DRV_TLV_PDU_RX_DESCRIPTORS_QUEUE_SIZE:
1125 if (p_drv_buf->rx_desc_size_set) {
1126 p_buf->p_val = &p_drv_buf->rx_desc_size;
1127 return sizeof(p_drv_buf->rx_desc_size);
1128 }
1129 break;
1130 case DRV_TLV_ISCSI_BOOT_PROGRESS:
1131 if (p_drv_buf->boot_progress_set) {
1132 p_buf->p_val = &p_drv_buf->boot_progress;
1133 return sizeof(p_drv_buf->boot_progress);
1134 }
1135 break;
1136 case DRV_TLV_PDU_TX_DESCRIPTOR_QUEUE_AVG_DEPTH:
1137 if (p_drv_buf->tx_desc_qdepth_set) {
1138 p_buf->p_val = &p_drv_buf->tx_desc_qdepth;
1139 return sizeof(p_drv_buf->tx_desc_qdepth);
1140 }
1141 break;
1142 case DRV_TLV_PDU_RX_DESCRIPTORS_QUEUE_AVG_DEPTH:
1143 if (p_drv_buf->rx_desc_qdepth_set) {
1144 p_buf->p_val = &p_drv_buf->rx_desc_qdepth;
1145 return sizeof(p_drv_buf->rx_desc_qdepth);
1146 }
1147 break;
1148 case DRV_TLV_ISCSI_PDU_RX_FRAMES_RECEIVED:
1149 if (p_drv_buf->rx_frames_set) {
1150 p_buf->p_val = &p_drv_buf->rx_frames;
1151 return sizeof(p_drv_buf->rx_frames);
1152 }
1153 break;
1154 case DRV_TLV_ISCSI_PDU_RX_BYTES_RECEIVED:
1155 if (p_drv_buf->rx_bytes_set) {
1156 p_buf->p_val = &p_drv_buf->rx_bytes;
1157 return sizeof(p_drv_buf->rx_bytes);
1158 }
1159 break;
1160 case DRV_TLV_ISCSI_PDU_TX_FRAMES_SENT:
1161 if (p_drv_buf->tx_frames_set) {
1162 p_buf->p_val = &p_drv_buf->tx_frames;
1163 return sizeof(p_drv_buf->tx_frames);
1164 }
1165 break;
1166 case DRV_TLV_ISCSI_PDU_TX_BYTES_SENT:
1167 if (p_drv_buf->tx_bytes_set) {
1168 p_buf->p_val = &p_drv_buf->tx_bytes;
1169 return sizeof(p_drv_buf->tx_bytes);
1170 }
1171 break;
1172 default:
1173 break;
1174 }
1175
1176 return -1;
1177}
1178
1179static int qed_mfw_update_tlvs(struct qed_hwfn *p_hwfn,
1180 u8 tlv_group, u8 *p_mfw_buf, u32 size)
1181{
1182 union qed_mfw_tlv_data *p_tlv_data;
1183 struct qed_tlv_parsed_buf buffer;
1184 struct qed_drv_tlv_hdr tlv;
1185 int len = 0;
1186 u32 offset;
1187 u8 *p_tlv;
1188
1189 p_tlv_data = vzalloc(size: sizeof(*p_tlv_data));
1190 if (!p_tlv_data)
1191 return -ENOMEM;
1192
1193 if (qed_mfw_fill_tlv_data(hwfn: p_hwfn, type: tlv_group, tlv_data: p_tlv_data)) {
1194 vfree(addr: 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(p_tlv: &tlv,
1212 p_drv_buf: &p_tlv_data->generic,
1213 p_buf: &buffer);
1214 else if (tlv_group == QED_MFW_TLV_ETH)
1215 len = qed_mfw_get_eth_tlv_value(p_tlv: &tlv,
1216 p_drv_buf: &p_tlv_data->eth,
1217 p_buf: &buffer);
1218 else if (tlv_group == QED_MFW_TLV_FCOE)
1219 len = qed_mfw_get_fcoe_tlv_value(p_tlv: &tlv,
1220 p_drv_buf: &p_tlv_data->fcoe,
1221 p_buf: &buffer);
1222 else
1223 len = qed_mfw_get_iscsi_tlv_value(p_tlv: &tlv,
1224 p_drv_buf: &p_tlv_data->iscsi,
1225 p_buf: &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(addr: p_tlv_data);
1240
1241 return 0;
1242}
1243
1244int qed_mfw_process_tlv_req(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt)
1245{
1246 u32 addr, size, offset, resp, param, val, global_offsize, global_addr;
1247 u8 tlv_group = 0, id, *p_mfw_buf = NULL, *p_temp;
1248 struct qed_drv_tlv_hdr tlv;
1249 int rc;
1250
1251 addr = SECTION_OFFSIZE_ADDR(p_hwfn->mcp_info->public_base,
1252 PUBLIC_GLOBAL);
1253 global_offsize = qed_rd(p_hwfn, p_ptt, hw_addr: 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, hw_addr: addr);
1257 size = qed_rd(p_hwfn, p_ptt, hw_addr: 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, hw_addr: 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_type: tlv.tlv_type, tlv_group: &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, tlv_group: 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, hw_addr: addr + offset, val);
1331 }
1332
1333drv_done:
1334 rc = qed_mcp_cmd(p_hwfn, p_ptt, cmd: DRV_MSG_CODE_GET_TLV_DONE, param: 0, o_mcp_resp: &resp,
1335 o_mcp_param: &param);
1336
1337 vfree(addr: p_mfw_buf);
1338
1339 return rc;
1340}
1341

source code of linux/drivers/net/ethernet/qlogic/qed/qed_mng_tlv.c