OSDN Git Service

qed: Add support for processing fcoe tlv request.
[uclinux-h8/linux.git] / drivers / net / ethernet / qlogic / qed / qed_mng_tlv.c
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         default:
219                 return -EINVAL;
220         }
221
222         return 0;
223 }
224
225 /* Returns size of the data buffer or, -1 in case TLV data is not available. */
226 static int
227 qed_mfw_get_gen_tlv_value(struct qed_drv_tlv_hdr *p_tlv,
228                           struct qed_mfw_tlv_generic *p_drv_buf,
229                           struct qed_tlv_parsed_buf *p_buf)
230 {
231         switch (p_tlv->tlv_type) {
232         case DRV_TLV_FEATURE_FLAGS:
233                 if (p_drv_buf->flags.b_set) {
234                         memset(p_buf->data, 0, sizeof(u8) * QED_TLV_DATA_MAX);
235                         p_buf->data[0] = p_drv_buf->flags.ipv4_csum_offload ?
236                             1 : 0;
237                         p_buf->data[0] |= (p_drv_buf->flags.lso_supported ?
238                                            1 : 0) << 1;
239                         p_buf->p_val = p_buf->data;
240                         return QED_MFW_TLV_FLAGS_SIZE;
241                 }
242                 break;
243
244         case DRV_TLV_LOCAL_ADMIN_ADDR:
245         case DRV_TLV_ADDITIONAL_MAC_ADDR_1:
246         case DRV_TLV_ADDITIONAL_MAC_ADDR_2:
247                 {
248                         int idx = p_tlv->tlv_type - DRV_TLV_LOCAL_ADMIN_ADDR;
249
250                         if (p_drv_buf->mac_set[idx]) {
251                                 p_buf->p_val = p_drv_buf->mac[idx];
252                                 return ETH_ALEN;
253                         }
254                         break;
255                 }
256
257         case DRV_TLV_RX_FRAMES_RECEIVED:
258                 if (p_drv_buf->rx_frames_set) {
259                         p_buf->p_val = &p_drv_buf->rx_frames;
260                         return sizeof(p_drv_buf->rx_frames);
261                 }
262                 break;
263         case DRV_TLV_RX_BYTES_RECEIVED:
264                 if (p_drv_buf->rx_bytes_set) {
265                         p_buf->p_val = &p_drv_buf->rx_bytes;
266                         return sizeof(p_drv_buf->rx_bytes);
267                 }
268                 break;
269         case DRV_TLV_TX_FRAMES_SENT:
270                 if (p_drv_buf->tx_frames_set) {
271                         p_buf->p_val = &p_drv_buf->tx_frames;
272                         return sizeof(p_drv_buf->tx_frames);
273                 }
274                 break;
275         case DRV_TLV_TX_BYTES_SENT:
276                 if (p_drv_buf->tx_bytes_set) {
277                         p_buf->p_val = &p_drv_buf->tx_bytes;
278                         return sizeof(p_drv_buf->tx_bytes);
279                 }
280                 break;
281         default:
282                 break;
283         }
284
285         return -1;
286 }
287
288 static int
289 qed_mfw_get_eth_tlv_value(struct qed_drv_tlv_hdr *p_tlv,
290                           struct qed_mfw_tlv_eth *p_drv_buf,
291                           struct qed_tlv_parsed_buf *p_buf)
292 {
293         switch (p_tlv->tlv_type) {
294         case DRV_TLV_LSO_MAX_OFFLOAD_SIZE:
295                 if (p_drv_buf->lso_maxoff_size_set) {
296                         p_buf->p_val = &p_drv_buf->lso_maxoff_size;
297                         return sizeof(p_drv_buf->lso_maxoff_size);
298                 }
299                 break;
300         case DRV_TLV_LSO_MIN_SEGMENT_COUNT:
301                 if (p_drv_buf->lso_minseg_size_set) {
302                         p_buf->p_val = &p_drv_buf->lso_minseg_size;
303                         return sizeof(p_drv_buf->lso_minseg_size);
304                 }
305                 break;
306         case DRV_TLV_PROMISCUOUS_MODE:
307                 if (p_drv_buf->prom_mode_set) {
308                         p_buf->p_val = &p_drv_buf->prom_mode;
309                         return sizeof(p_drv_buf->prom_mode);
310                 }
311                 break;
312         case DRV_TLV_TX_DESCRIPTORS_QUEUE_SIZE:
313                 if (p_drv_buf->tx_descr_size_set) {
314                         p_buf->p_val = &p_drv_buf->tx_descr_size;
315                         return sizeof(p_drv_buf->tx_descr_size);
316                 }
317                 break;
318         case DRV_TLV_RX_DESCRIPTORS_QUEUE_SIZE:
319                 if (p_drv_buf->rx_descr_size_set) {
320                         p_buf->p_val = &p_drv_buf->rx_descr_size;
321                         return sizeof(p_drv_buf->rx_descr_size);
322                 }
323                 break;
324         case DRV_TLV_NUM_OF_NET_QUEUE_VMQ_CFG:
325                 if (p_drv_buf->netq_count_set) {
326                         p_buf->p_val = &p_drv_buf->netq_count;
327                         return sizeof(p_drv_buf->netq_count);
328                 }
329                 break;
330         case DRV_TLV_NUM_OFFLOADED_CONNECTIONS_TCP_IPV4:
331                 if (p_drv_buf->tcp4_offloads_set) {
332                         p_buf->p_val = &p_drv_buf->tcp4_offloads;
333                         return sizeof(p_drv_buf->tcp4_offloads);
334                 }
335                 break;
336         case DRV_TLV_NUM_OFFLOADED_CONNECTIONS_TCP_IPV6:
337                 if (p_drv_buf->tcp6_offloads_set) {
338                         p_buf->p_val = &p_drv_buf->tcp6_offloads;
339                         return sizeof(p_drv_buf->tcp6_offloads);
340                 }
341                 break;
342         case DRV_TLV_TX_DESCRIPTOR_QUEUE_AVG_DEPTH:
343                 if (p_drv_buf->tx_descr_qdepth_set) {
344                         p_buf->p_val = &p_drv_buf->tx_descr_qdepth;
345                         return sizeof(p_drv_buf->tx_descr_qdepth);
346                 }
347                 break;
348         case DRV_TLV_RX_DESCRIPTORS_QUEUE_AVG_DEPTH:
349                 if (p_drv_buf->rx_descr_qdepth_set) {
350                         p_buf->p_val = &p_drv_buf->rx_descr_qdepth;
351                         return sizeof(p_drv_buf->rx_descr_qdepth);
352                 }
353                 break;
354         case DRV_TLV_IOV_OFFLOAD:
355                 if (p_drv_buf->iov_offload_set) {
356                         p_buf->p_val = &p_drv_buf->iov_offload;
357                         return sizeof(p_drv_buf->iov_offload);
358                 }
359                 break;
360         case DRV_TLV_TX_QUEUES_EMPTY:
361                 if (p_drv_buf->txqs_empty_set) {
362                         p_buf->p_val = &p_drv_buf->txqs_empty;
363                         return sizeof(p_drv_buf->txqs_empty);
364                 }
365                 break;
366         case DRV_TLV_RX_QUEUES_EMPTY:
367                 if (p_drv_buf->rxqs_empty_set) {
368                         p_buf->p_val = &p_drv_buf->rxqs_empty;
369                         return sizeof(p_drv_buf->rxqs_empty);
370                 }
371                 break;
372         case DRV_TLV_TX_QUEUES_FULL:
373                 if (p_drv_buf->num_txqs_full_set) {
374                         p_buf->p_val = &p_drv_buf->num_txqs_full;
375                         return sizeof(p_drv_buf->num_txqs_full);
376                 }
377                 break;
378         case DRV_TLV_RX_QUEUES_FULL:
379                 if (p_drv_buf->num_rxqs_full_set) {
380                         p_buf->p_val = &p_drv_buf->num_rxqs_full;
381                         return sizeof(p_drv_buf->num_rxqs_full);
382                 }
383                 break;
384         default:
385                 break;
386         }
387
388         return -1;
389 }
390
391 static int
392 qed_mfw_get_tlv_time_value(struct qed_mfw_tlv_time *p_time,
393                            struct qed_tlv_parsed_buf *p_buf)
394 {
395         if (!p_time->b_set)
396                 return -1;
397
398         /* Validate numbers */
399         if (p_time->month > 12)
400                 p_time->month = 0;
401         if (p_time->day > 31)
402                 p_time->day = 0;
403         if (p_time->hour > 23)
404                 p_time->hour = 0;
405         if (p_time->min > 59)
406                 p_time->hour = 0;
407         if (p_time->msec > 999)
408                 p_time->msec = 0;
409         if (p_time->usec > 999)
410                 p_time->usec = 0;
411
412         memset(p_buf->data, 0, sizeof(u8) * QED_TLV_DATA_MAX);
413         snprintf(p_buf->data, 14, "%d%d%d%d%d%d",
414                  p_time->month, p_time->day,
415                  p_time->hour, p_time->min, p_time->msec, p_time->usec);
416
417         p_buf->p_val = p_buf->data;
418
419         return QED_MFW_TLV_TIME_SIZE;
420 }
421
422 static int
423 qed_mfw_get_fcoe_tlv_value(struct qed_drv_tlv_hdr *p_tlv,
424                            struct qed_mfw_tlv_fcoe *p_drv_buf,
425                            struct qed_tlv_parsed_buf *p_buf)
426 {
427         struct qed_mfw_tlv_time *p_time;
428         u8 idx;
429
430         switch (p_tlv->tlv_type) {
431         case DRV_TLV_SCSI_TO:
432                 if (p_drv_buf->scsi_timeout_set) {
433                         p_buf->p_val = &p_drv_buf->scsi_timeout;
434                         return sizeof(p_drv_buf->scsi_timeout);
435                 }
436                 break;
437         case DRV_TLV_R_T_TOV:
438                 if (p_drv_buf->rt_tov_set) {
439                         p_buf->p_val = &p_drv_buf->rt_tov;
440                         return sizeof(p_drv_buf->rt_tov);
441                 }
442                 break;
443         case DRV_TLV_R_A_TOV:
444                 if (p_drv_buf->ra_tov_set) {
445                         p_buf->p_val = &p_drv_buf->ra_tov;
446                         return sizeof(p_drv_buf->ra_tov);
447                 }
448                 break;
449         case DRV_TLV_E_D_TOV:
450                 if (p_drv_buf->ed_tov_set) {
451                         p_buf->p_val = &p_drv_buf->ed_tov;
452                         return sizeof(p_drv_buf->ed_tov);
453                 }
454                 break;
455         case DRV_TLV_CR_TOV:
456                 if (p_drv_buf->cr_tov_set) {
457                         p_buf->p_val = &p_drv_buf->cr_tov;
458                         return sizeof(p_drv_buf->cr_tov);
459                 }
460                 break;
461         case DRV_TLV_BOOT_TYPE:
462                 if (p_drv_buf->boot_type_set) {
463                         p_buf->p_val = &p_drv_buf->boot_type;
464                         return sizeof(p_drv_buf->boot_type);
465                 }
466                 break;
467         case DRV_TLV_NPIV_STATE:
468                 if (p_drv_buf->npiv_state_set) {
469                         p_buf->p_val = &p_drv_buf->npiv_state;
470                         return sizeof(p_drv_buf->npiv_state);
471                 }
472                 break;
473         case DRV_TLV_NUM_OF_NPIV_IDS:
474                 if (p_drv_buf->num_npiv_ids_set) {
475                         p_buf->p_val = &p_drv_buf->num_npiv_ids;
476                         return sizeof(p_drv_buf->num_npiv_ids);
477                 }
478                 break;
479         case DRV_TLV_SWITCH_NAME:
480                 if (p_drv_buf->switch_name_set) {
481                         p_buf->p_val = &p_drv_buf->switch_name;
482                         return sizeof(p_drv_buf->switch_name);
483                 }
484                 break;
485         case DRV_TLV_SWITCH_PORT_NUM:
486                 if (p_drv_buf->switch_portnum_set) {
487                         p_buf->p_val = &p_drv_buf->switch_portnum;
488                         return sizeof(p_drv_buf->switch_portnum);
489                 }
490                 break;
491         case DRV_TLV_SWITCH_PORT_ID:
492                 if (p_drv_buf->switch_portid_set) {
493                         p_buf->p_val = &p_drv_buf->switch_portid;
494                         return sizeof(p_drv_buf->switch_portid);
495                 }
496                 break;
497         case DRV_TLV_VENDOR_NAME:
498                 if (p_drv_buf->vendor_name_set) {
499                         p_buf->p_val = &p_drv_buf->vendor_name;
500                         return sizeof(p_drv_buf->vendor_name);
501                 }
502                 break;
503         case DRV_TLV_SWITCH_MODEL:
504                 if (p_drv_buf->switch_model_set) {
505                         p_buf->p_val = &p_drv_buf->switch_model;
506                         return sizeof(p_drv_buf->switch_model);
507                 }
508                 break;
509         case DRV_TLV_SWITCH_FW_VER:
510                 if (p_drv_buf->switch_fw_version_set) {
511                         p_buf->p_val = &p_drv_buf->switch_fw_version;
512                         return sizeof(p_drv_buf->switch_fw_version);
513                 }
514                 break;
515         case DRV_TLV_QOS_PRIORITY_PER_802_1P:
516                 if (p_drv_buf->qos_pri_set) {
517                         p_buf->p_val = &p_drv_buf->qos_pri;
518                         return sizeof(p_drv_buf->qos_pri);
519                 }
520                 break;
521         case DRV_TLV_PORT_ALIAS:
522                 if (p_drv_buf->port_alias_set) {
523                         p_buf->p_val = &p_drv_buf->port_alias;
524                         return sizeof(p_drv_buf->port_alias);
525                 }
526                 break;
527         case DRV_TLV_PORT_STATE:
528                 if (p_drv_buf->port_state_set) {
529                         p_buf->p_val = &p_drv_buf->port_state;
530                         return sizeof(p_drv_buf->port_state);
531                 }
532                 break;
533         case DRV_TLV_FIP_TX_DESCRIPTORS_QUEUE_SIZE:
534                 if (p_drv_buf->fip_tx_descr_size_set) {
535                         p_buf->p_val = &p_drv_buf->fip_tx_descr_size;
536                         return sizeof(p_drv_buf->fip_tx_descr_size);
537                 }
538                 break;
539         case DRV_TLV_FCOE_RX_DESCRIPTORS_QUEUE_SIZE:
540                 if (p_drv_buf->fip_rx_descr_size_set) {
541                         p_buf->p_val = &p_drv_buf->fip_rx_descr_size;
542                         return sizeof(p_drv_buf->fip_rx_descr_size);
543                 }
544                 break;
545         case DRV_TLV_LINK_FAILURE_COUNT:
546                 if (p_drv_buf->link_failures_set) {
547                         p_buf->p_val = &p_drv_buf->link_failures;
548                         return sizeof(p_drv_buf->link_failures);
549                 }
550                 break;
551         case DRV_TLV_FCOE_BOOT_PROGRESS:
552                 if (p_drv_buf->fcoe_boot_progress_set) {
553                         p_buf->p_val = &p_drv_buf->fcoe_boot_progress;
554                         return sizeof(p_drv_buf->fcoe_boot_progress);
555                 }
556                 break;
557         case DRV_TLV_RX_BROADCAST_PACKETS:
558                 if (p_drv_buf->rx_bcast_set) {
559                         p_buf->p_val = &p_drv_buf->rx_bcast;
560                         return sizeof(p_drv_buf->rx_bcast);
561                 }
562                 break;
563         case DRV_TLV_TX_BROADCAST_PACKETS:
564                 if (p_drv_buf->tx_bcast_set) {
565                         p_buf->p_val = &p_drv_buf->tx_bcast;
566                         return sizeof(p_drv_buf->tx_bcast);
567                 }
568                 break;
569         case DRV_TLV_FCOE_TX_DESCRIPTOR_QUEUE_AVG_DEPTH:
570                 if (p_drv_buf->fcoe_txq_depth_set) {
571                         p_buf->p_val = &p_drv_buf->fcoe_txq_depth;
572                         return sizeof(p_drv_buf->fcoe_txq_depth);
573                 }
574                 break;
575         case DRV_TLV_FCOE_RX_DESCRIPTORS_QUEUE_AVG_DEPTH:
576                 if (p_drv_buf->fcoe_rxq_depth_set) {
577                         p_buf->p_val = &p_drv_buf->fcoe_rxq_depth;
578                         return sizeof(p_drv_buf->fcoe_rxq_depth);
579                 }
580                 break;
581         case DRV_TLV_FCOE_RX_FRAMES_RECEIVED:
582                 if (p_drv_buf->fcoe_rx_frames_set) {
583                         p_buf->p_val = &p_drv_buf->fcoe_rx_frames;
584                         return sizeof(p_drv_buf->fcoe_rx_frames);
585                 }
586                 break;
587         case DRV_TLV_FCOE_RX_BYTES_RECEIVED:
588                 if (p_drv_buf->fcoe_rx_bytes_set) {
589                         p_buf->p_val = &p_drv_buf->fcoe_rx_bytes;
590                         return sizeof(p_drv_buf->fcoe_rx_bytes);
591                 }
592                 break;
593         case DRV_TLV_FCOE_TX_FRAMES_SENT:
594                 if (p_drv_buf->fcoe_tx_frames_set) {
595                         p_buf->p_val = &p_drv_buf->fcoe_tx_frames;
596                         return sizeof(p_drv_buf->fcoe_tx_frames);
597                 }
598                 break;
599         case DRV_TLV_FCOE_TX_BYTES_SENT:
600                 if (p_drv_buf->fcoe_tx_bytes_set) {
601                         p_buf->p_val = &p_drv_buf->fcoe_tx_bytes;
602                         return sizeof(p_drv_buf->fcoe_tx_bytes);
603                 }
604                 break;
605         case DRV_TLV_CRC_ERROR_COUNT:
606                 if (p_drv_buf->crc_count_set) {
607                         p_buf->p_val = &p_drv_buf->crc_count;
608                         return sizeof(p_drv_buf->crc_count);
609                 }
610                 break;
611         case DRV_TLV_CRC_ERROR_1_RECEIVED_SOURCE_FC_ID:
612         case DRV_TLV_CRC_ERROR_2_RECEIVED_SOURCE_FC_ID:
613         case DRV_TLV_CRC_ERROR_3_RECEIVED_SOURCE_FC_ID:
614         case DRV_TLV_CRC_ERROR_4_RECEIVED_SOURCE_FC_ID:
615         case DRV_TLV_CRC_ERROR_5_RECEIVED_SOURCE_FC_ID:
616                 idx = (p_tlv->tlv_type -
617                        DRV_TLV_CRC_ERROR_1_RECEIVED_SOURCE_FC_ID) / 2;
618
619                 if (p_drv_buf->crc_err_src_fcid_set[idx]) {
620                         p_buf->p_val = &p_drv_buf->crc_err_src_fcid[idx];
621                         return sizeof(p_drv_buf->crc_err_src_fcid[idx]);
622                 }
623                 break;
624         case DRV_TLV_CRC_ERROR_1_TIMESTAMP:
625         case DRV_TLV_CRC_ERROR_2_TIMESTAMP:
626         case DRV_TLV_CRC_ERROR_3_TIMESTAMP:
627         case DRV_TLV_CRC_ERROR_4_TIMESTAMP:
628         case DRV_TLV_CRC_ERROR_5_TIMESTAMP:
629                 idx = (p_tlv->tlv_type - DRV_TLV_CRC_ERROR_1_TIMESTAMP) / 2;
630
631                 return qed_mfw_get_tlv_time_value(&p_drv_buf->crc_err[idx],
632                                                   p_buf);
633         case DRV_TLV_LOSS_OF_SYNC_ERROR_COUNT:
634                 if (p_drv_buf->losync_err_set) {
635                         p_buf->p_val = &p_drv_buf->losync_err;
636                         return sizeof(p_drv_buf->losync_err);
637                 }
638                 break;
639         case DRV_TLV_LOSS_OF_SIGNAL_ERRORS:
640                 if (p_drv_buf->losig_err_set) {
641                         p_buf->p_val = &p_drv_buf->losig_err;
642                         return sizeof(p_drv_buf->losig_err);
643                 }
644                 break;
645         case DRV_TLV_PRIMITIVE_SEQUENCE_PROTOCOL_ERROR_COUNT:
646                 if (p_drv_buf->primtive_err_set) {
647                         p_buf->p_val = &p_drv_buf->primtive_err;
648                         return sizeof(p_drv_buf->primtive_err);
649                 }
650                 break;
651         case DRV_TLV_DISPARITY_ERROR_COUNT:
652                 if (p_drv_buf->disparity_err_set) {
653                         p_buf->p_val = &p_drv_buf->disparity_err;
654                         return sizeof(p_drv_buf->disparity_err);
655                 }
656                 break;
657         case DRV_TLV_CODE_VIOLATION_ERROR_COUNT:
658                 if (p_drv_buf->code_violation_err_set) {
659                         p_buf->p_val = &p_drv_buf->code_violation_err;
660                         return sizeof(p_drv_buf->code_violation_err);
661                 }
662                 break;
663         case DRV_TLV_LAST_FLOGI_ISSUED_COMMON_PARAMETERS_WORD_1:
664         case DRV_TLV_LAST_FLOGI_ISSUED_COMMON_PARAMETERS_WORD_2:
665         case DRV_TLV_LAST_FLOGI_ISSUED_COMMON_PARAMETERS_WORD_3:
666         case DRV_TLV_LAST_FLOGI_ISSUED_COMMON_PARAMETERS_WORD_4:
667                 idx = p_tlv->tlv_type -
668                         DRV_TLV_LAST_FLOGI_ISSUED_COMMON_PARAMETERS_WORD_1;
669                 if (p_drv_buf->flogi_param_set[idx]) {
670                         p_buf->p_val = &p_drv_buf->flogi_param[idx];
671                         return sizeof(p_drv_buf->flogi_param[idx]);
672                 }
673                 break;
674         case DRV_TLV_LAST_FLOGI_TIMESTAMP:
675                 return qed_mfw_get_tlv_time_value(&p_drv_buf->flogi_tstamp,
676                                                   p_buf);
677         case DRV_TLV_LAST_FLOGI_ACC_COMMON_PARAMETERS_WORD_1:
678         case DRV_TLV_LAST_FLOGI_ACC_COMMON_PARAMETERS_WORD_2:
679         case DRV_TLV_LAST_FLOGI_ACC_COMMON_PARAMETERS_WORD_3:
680         case DRV_TLV_LAST_FLOGI_ACC_COMMON_PARAMETERS_WORD_4:
681                 idx = p_tlv->tlv_type -
682                         DRV_TLV_LAST_FLOGI_ACC_COMMON_PARAMETERS_WORD_1;
683
684                 if (p_drv_buf->flogi_acc_param_set[idx]) {
685                         p_buf->p_val = &p_drv_buf->flogi_acc_param[idx];
686                         return sizeof(p_drv_buf->flogi_acc_param[idx]);
687                 }
688                 break;
689         case DRV_TLV_LAST_FLOGI_ACC_TIMESTAMP:
690                 return qed_mfw_get_tlv_time_value(&p_drv_buf->flogi_acc_tstamp,
691                                                   p_buf);
692         case DRV_TLV_LAST_FLOGI_RJT:
693                 if (p_drv_buf->flogi_rjt_set) {
694                         p_buf->p_val = &p_drv_buf->flogi_rjt;
695                         return sizeof(p_drv_buf->flogi_rjt);
696                 }
697                 break;
698         case DRV_TLV_LAST_FLOGI_RJT_TIMESTAMP:
699                 return qed_mfw_get_tlv_time_value(&p_drv_buf->flogi_rjt_tstamp,
700                                                   p_buf);
701         case DRV_TLV_FDISCS_SENT_COUNT:
702                 if (p_drv_buf->fdiscs_set) {
703                         p_buf->p_val = &p_drv_buf->fdiscs;
704                         return sizeof(p_drv_buf->fdiscs);
705                 }
706                 break;
707         case DRV_TLV_FDISC_ACCS_RECEIVED:
708                 if (p_drv_buf->fdisc_acc_set) {
709                         p_buf->p_val = &p_drv_buf->fdisc_acc;
710                         return sizeof(p_drv_buf->fdisc_acc);
711                 }
712                 break;
713         case DRV_TLV_FDISC_RJTS_RECEIVED:
714                 if (p_drv_buf->fdisc_rjt_set) {
715                         p_buf->p_val = &p_drv_buf->fdisc_rjt;
716                         return sizeof(p_drv_buf->fdisc_rjt);
717                 }
718                 break;
719         case DRV_TLV_PLOGI_SENT_COUNT:
720                 if (p_drv_buf->plogi_set) {
721                         p_buf->p_val = &p_drv_buf->plogi;
722                         return sizeof(p_drv_buf->plogi);
723                 }
724                 break;
725         case DRV_TLV_PLOGI_ACCS_RECEIVED:
726                 if (p_drv_buf->plogi_acc_set) {
727                         p_buf->p_val = &p_drv_buf->plogi_acc;
728                         return sizeof(p_drv_buf->plogi_acc);
729                 }
730                 break;
731         case DRV_TLV_PLOGI_RJTS_RECEIVED:
732                 if (p_drv_buf->plogi_rjt_set) {
733                         p_buf->p_val = &p_drv_buf->plogi_rjt;
734                         return sizeof(p_drv_buf->plogi_rjt);
735                 }
736                 break;
737         case DRV_TLV_PLOGI_1_SENT_DESTINATION_FC_ID:
738         case DRV_TLV_PLOGI_2_SENT_DESTINATION_FC_ID:
739         case DRV_TLV_PLOGI_3_SENT_DESTINATION_FC_ID:
740         case DRV_TLV_PLOGI_4_SENT_DESTINATION_FC_ID:
741         case DRV_TLV_PLOGI_5_SENT_DESTINATION_FC_ID:
742                 idx = (p_tlv->tlv_type -
743                        DRV_TLV_PLOGI_1_SENT_DESTINATION_FC_ID) / 2;
744
745                 if (p_drv_buf->plogi_dst_fcid_set[idx]) {
746                         p_buf->p_val = &p_drv_buf->plogi_dst_fcid[idx];
747                         return sizeof(p_drv_buf->plogi_dst_fcid[idx]);
748                 }
749                 break;
750         case DRV_TLV_PLOGI_1_TIMESTAMP:
751         case DRV_TLV_PLOGI_2_TIMESTAMP:
752         case DRV_TLV_PLOGI_3_TIMESTAMP:
753         case DRV_TLV_PLOGI_4_TIMESTAMP:
754         case DRV_TLV_PLOGI_5_TIMESTAMP:
755                 idx = (p_tlv->tlv_type - DRV_TLV_PLOGI_1_TIMESTAMP) / 2;
756
757                 return qed_mfw_get_tlv_time_value(&p_drv_buf->plogi_tstamp[idx],
758                                                   p_buf);
759         case DRV_TLV_PLOGI_1_ACC_RECEIVED_SOURCE_FC_ID:
760         case DRV_TLV_PLOGI_2_ACC_RECEIVED_SOURCE_FC_ID:
761         case DRV_TLV_PLOGI_3_ACC_RECEIVED_SOURCE_FC_ID:
762         case DRV_TLV_PLOGI_4_ACC_RECEIVED_SOURCE_FC_ID:
763         case DRV_TLV_PLOGI_5_ACC_RECEIVED_SOURCE_FC_ID:
764                 idx = (p_tlv->tlv_type -
765                        DRV_TLV_PLOGI_1_ACC_RECEIVED_SOURCE_FC_ID) / 2;
766
767                 if (p_drv_buf->plogi_acc_src_fcid_set[idx]) {
768                         p_buf->p_val = &p_drv_buf->plogi_acc_src_fcid[idx];
769                         return sizeof(p_drv_buf->plogi_acc_src_fcid[idx]);
770                 }
771                 break;
772         case DRV_TLV_PLOGI_1_ACC_TIMESTAMP:
773         case DRV_TLV_PLOGI_2_ACC_TIMESTAMP:
774         case DRV_TLV_PLOGI_3_ACC_TIMESTAMP:
775         case DRV_TLV_PLOGI_4_ACC_TIMESTAMP:
776         case DRV_TLV_PLOGI_5_ACC_TIMESTAMP:
777                 idx = (p_tlv->tlv_type - DRV_TLV_PLOGI_1_ACC_TIMESTAMP) / 2;
778                 p_time = &p_drv_buf->plogi_acc_tstamp[idx];
779
780                 return qed_mfw_get_tlv_time_value(p_time, p_buf);
781         case DRV_TLV_LOGOS_ISSUED:
782                 if (p_drv_buf->tx_plogos_set) {
783                         p_buf->p_val = &p_drv_buf->tx_plogos;
784                         return sizeof(p_drv_buf->tx_plogos);
785                 }
786                 break;
787         case DRV_TLV_LOGO_ACCS_RECEIVED:
788                 if (p_drv_buf->plogo_acc_set) {
789                         p_buf->p_val = &p_drv_buf->plogo_acc;
790                         return sizeof(p_drv_buf->plogo_acc);
791                 }
792                 break;
793         case DRV_TLV_LOGO_RJTS_RECEIVED:
794                 if (p_drv_buf->plogo_rjt_set) {
795                         p_buf->p_val = &p_drv_buf->plogo_rjt;
796                         return sizeof(p_drv_buf->plogo_rjt);
797                 }
798                 break;
799         case DRV_TLV_LOGO_1_RECEIVED_SOURCE_FC_ID:
800         case DRV_TLV_LOGO_2_RECEIVED_SOURCE_FC_ID:
801         case DRV_TLV_LOGO_3_RECEIVED_SOURCE_FC_ID:
802         case DRV_TLV_LOGO_4_RECEIVED_SOURCE_FC_ID:
803         case DRV_TLV_LOGO_5_RECEIVED_SOURCE_FC_ID:
804                 idx = (p_tlv->tlv_type - DRV_TLV_LOGO_1_RECEIVED_SOURCE_FC_ID) /
805                         2;
806
807                 if (p_drv_buf->plogo_src_fcid_set[idx]) {
808                         p_buf->p_val = &p_drv_buf->plogo_src_fcid[idx];
809                         return sizeof(p_drv_buf->plogo_src_fcid[idx]);
810                 }
811                 break;
812         case DRV_TLV_LOGO_1_TIMESTAMP:
813         case DRV_TLV_LOGO_2_TIMESTAMP:
814         case DRV_TLV_LOGO_3_TIMESTAMP:
815         case DRV_TLV_LOGO_4_TIMESTAMP:
816         case DRV_TLV_LOGO_5_TIMESTAMP:
817                 idx = (p_tlv->tlv_type - DRV_TLV_LOGO_1_TIMESTAMP) / 2;
818
819                 return qed_mfw_get_tlv_time_value(&p_drv_buf->plogo_tstamp[idx],
820                                                   p_buf);
821         case DRV_TLV_LOGOS_RECEIVED:
822                 if (p_drv_buf->rx_logos_set) {
823                         p_buf->p_val = &p_drv_buf->rx_logos;
824                         return sizeof(p_drv_buf->rx_logos);
825                 }
826                 break;
827         case DRV_TLV_ACCS_ISSUED:
828                 if (p_drv_buf->tx_accs_set) {
829                         p_buf->p_val = &p_drv_buf->tx_accs;
830                         return sizeof(p_drv_buf->tx_accs);
831                 }
832                 break;
833         case DRV_TLV_PRLIS_ISSUED:
834                 if (p_drv_buf->tx_prlis_set) {
835                         p_buf->p_val = &p_drv_buf->tx_prlis;
836                         return sizeof(p_drv_buf->tx_prlis);
837                 }
838                 break;
839         case DRV_TLV_ACCS_RECEIVED:
840                 if (p_drv_buf->rx_accs_set) {
841                         p_buf->p_val = &p_drv_buf->rx_accs;
842                         return sizeof(p_drv_buf->rx_accs);
843                 }
844                 break;
845         case DRV_TLV_ABTS_SENT_COUNT:
846                 if (p_drv_buf->tx_abts_set) {
847                         p_buf->p_val = &p_drv_buf->tx_abts;
848                         return sizeof(p_drv_buf->tx_abts);
849                 }
850                 break;
851         case DRV_TLV_ABTS_ACCS_RECEIVED:
852                 if (p_drv_buf->rx_abts_acc_set) {
853                         p_buf->p_val = &p_drv_buf->rx_abts_acc;
854                         return sizeof(p_drv_buf->rx_abts_acc);
855                 }
856                 break;
857         case DRV_TLV_ABTS_RJTS_RECEIVED:
858                 if (p_drv_buf->rx_abts_rjt_set) {
859                         p_buf->p_val = &p_drv_buf->rx_abts_rjt;
860                         return sizeof(p_drv_buf->rx_abts_rjt);
861                 }
862                 break;
863         case DRV_TLV_ABTS_1_SENT_DESTINATION_FC_ID:
864         case DRV_TLV_ABTS_2_SENT_DESTINATION_FC_ID:
865         case DRV_TLV_ABTS_3_SENT_DESTINATION_FC_ID:
866         case DRV_TLV_ABTS_4_SENT_DESTINATION_FC_ID:
867         case DRV_TLV_ABTS_5_SENT_DESTINATION_FC_ID:
868                 idx = (p_tlv->tlv_type -
869                        DRV_TLV_ABTS_1_SENT_DESTINATION_FC_ID) / 2;
870
871                 if (p_drv_buf->abts_dst_fcid_set[idx]) {
872                         p_buf->p_val = &p_drv_buf->abts_dst_fcid[idx];
873                         return sizeof(p_drv_buf->abts_dst_fcid[idx]);
874                 }
875                 break;
876         case DRV_TLV_ABTS_1_TIMESTAMP:
877         case DRV_TLV_ABTS_2_TIMESTAMP:
878         case DRV_TLV_ABTS_3_TIMESTAMP:
879         case DRV_TLV_ABTS_4_TIMESTAMP:
880         case DRV_TLV_ABTS_5_TIMESTAMP:
881                 idx = (p_tlv->tlv_type - DRV_TLV_ABTS_1_TIMESTAMP) / 2;
882
883                 return qed_mfw_get_tlv_time_value(&p_drv_buf->abts_tstamp[idx],
884                                                   p_buf);
885         case DRV_TLV_RSCNS_RECEIVED:
886                 if (p_drv_buf->rx_rscn_set) {
887                         p_buf->p_val = &p_drv_buf->rx_rscn;
888                         return sizeof(p_drv_buf->rx_rscn);
889                 }
890                 break;
891         case DRV_TLV_LAST_RSCN_RECEIVED_N_PORT_1:
892         case DRV_TLV_LAST_RSCN_RECEIVED_N_PORT_2:
893         case DRV_TLV_LAST_RSCN_RECEIVED_N_PORT_3:
894         case DRV_TLV_LAST_RSCN_RECEIVED_N_PORT_4:
895                 idx = p_tlv->tlv_type - DRV_TLV_LAST_RSCN_RECEIVED_N_PORT_1;
896
897                 if (p_drv_buf->rx_rscn_nport_set[idx]) {
898                         p_buf->p_val = &p_drv_buf->rx_rscn_nport[idx];
899                         return sizeof(p_drv_buf->rx_rscn_nport[idx]);
900                 }
901                 break;
902         case DRV_TLV_LUN_RESETS_ISSUED:
903                 if (p_drv_buf->tx_lun_rst_set) {
904                         p_buf->p_val = &p_drv_buf->tx_lun_rst;
905                         return sizeof(p_drv_buf->tx_lun_rst);
906                 }
907                 break;
908         case DRV_TLV_ABORT_TASK_SETS_ISSUED:
909                 if (p_drv_buf->abort_task_sets_set) {
910                         p_buf->p_val = &p_drv_buf->abort_task_sets;
911                         return sizeof(p_drv_buf->abort_task_sets);
912                 }
913                 break;
914         case DRV_TLV_TPRLOS_SENT:
915                 if (p_drv_buf->tx_tprlos_set) {
916                         p_buf->p_val = &p_drv_buf->tx_tprlos;
917                         return sizeof(p_drv_buf->tx_tprlos);
918                 }
919                 break;
920         case DRV_TLV_NOS_SENT_COUNT:
921                 if (p_drv_buf->tx_nos_set) {
922                         p_buf->p_val = &p_drv_buf->tx_nos;
923                         return sizeof(p_drv_buf->tx_nos);
924                 }
925                 break;
926         case DRV_TLV_NOS_RECEIVED_COUNT:
927                 if (p_drv_buf->rx_nos_set) {
928                         p_buf->p_val = &p_drv_buf->rx_nos;
929                         return sizeof(p_drv_buf->rx_nos);
930                 }
931                 break;
932         case DRV_TLV_OLS_COUNT:
933                 if (p_drv_buf->ols_set) {
934                         p_buf->p_val = &p_drv_buf->ols;
935                         return sizeof(p_drv_buf->ols);
936                 }
937                 break;
938         case DRV_TLV_LR_COUNT:
939                 if (p_drv_buf->lr_set) {
940                         p_buf->p_val = &p_drv_buf->lr;
941                         return sizeof(p_drv_buf->lr);
942                 }
943                 break;
944         case DRV_TLV_LRR_COUNT:
945                 if (p_drv_buf->lrr_set) {
946                         p_buf->p_val = &p_drv_buf->lrr;
947                         return sizeof(p_drv_buf->lrr);
948                 }
949                 break;
950         case DRV_TLV_LIP_SENT_COUNT:
951                 if (p_drv_buf->tx_lip_set) {
952                         p_buf->p_val = &p_drv_buf->tx_lip;
953                         return sizeof(p_drv_buf->tx_lip);
954                 }
955                 break;
956         case DRV_TLV_LIP_RECEIVED_COUNT:
957                 if (p_drv_buf->rx_lip_set) {
958                         p_buf->p_val = &p_drv_buf->rx_lip;
959                         return sizeof(p_drv_buf->rx_lip);
960                 }
961                 break;
962         case DRV_TLV_EOFA_COUNT:
963                 if (p_drv_buf->eofa_set) {
964                         p_buf->p_val = &p_drv_buf->eofa;
965                         return sizeof(p_drv_buf->eofa);
966                 }
967                 break;
968         case DRV_TLV_EOFNI_COUNT:
969                 if (p_drv_buf->eofni_set) {
970                         p_buf->p_val = &p_drv_buf->eofni;
971                         return sizeof(p_drv_buf->eofni);
972                 }
973                 break;
974         case DRV_TLV_SCSI_STATUS_CHECK_CONDITION_COUNT:
975                 if (p_drv_buf->scsi_chks_set) {
976                         p_buf->p_val = &p_drv_buf->scsi_chks;
977                         return sizeof(p_drv_buf->scsi_chks);
978                 }
979                 break;
980         case DRV_TLV_SCSI_STATUS_CONDITION_MET_COUNT:
981                 if (p_drv_buf->scsi_cond_met_set) {
982                         p_buf->p_val = &p_drv_buf->scsi_cond_met;
983                         return sizeof(p_drv_buf->scsi_cond_met);
984                 }
985                 break;
986         case DRV_TLV_SCSI_STATUS_BUSY_COUNT:
987                 if (p_drv_buf->scsi_busy_set) {
988                         p_buf->p_val = &p_drv_buf->scsi_busy;
989                         return sizeof(p_drv_buf->scsi_busy);
990                 }
991                 break;
992         case DRV_TLV_SCSI_STATUS_INTERMEDIATE_COUNT:
993                 if (p_drv_buf->scsi_inter_set) {
994                         p_buf->p_val = &p_drv_buf->scsi_inter;
995                         return sizeof(p_drv_buf->scsi_inter);
996                 }
997                 break;
998         case DRV_TLV_SCSI_STATUS_INTERMEDIATE_CONDITION_MET_COUNT:
999                 if (p_drv_buf->scsi_inter_cond_met_set) {
1000                         p_buf->p_val = &p_drv_buf->scsi_inter_cond_met;
1001                         return sizeof(p_drv_buf->scsi_inter_cond_met);
1002                 }
1003                 break;
1004         case DRV_TLV_SCSI_STATUS_RESERVATION_CONFLICT_COUNT:
1005                 if (p_drv_buf->scsi_rsv_conflicts_set) {
1006                         p_buf->p_val = &p_drv_buf->scsi_rsv_conflicts;
1007                         return sizeof(p_drv_buf->scsi_rsv_conflicts);
1008                 }
1009                 break;
1010         case DRV_TLV_SCSI_STATUS_TASK_SET_FULL_COUNT:
1011                 if (p_drv_buf->scsi_tsk_full_set) {
1012                         p_buf->p_val = &p_drv_buf->scsi_tsk_full;
1013                         return sizeof(p_drv_buf->scsi_tsk_full);
1014                 }
1015                 break;
1016         case DRV_TLV_SCSI_STATUS_ACA_ACTIVE_COUNT:
1017                 if (p_drv_buf->scsi_aca_active_set) {
1018                         p_buf->p_val = &p_drv_buf->scsi_aca_active;
1019                         return sizeof(p_drv_buf->scsi_aca_active);
1020                 }
1021                 break;
1022         case DRV_TLV_SCSI_STATUS_TASK_ABORTED_COUNT:
1023                 if (p_drv_buf->scsi_tsk_abort_set) {
1024                         p_buf->p_val = &p_drv_buf->scsi_tsk_abort;
1025                         return sizeof(p_drv_buf->scsi_tsk_abort);
1026                 }
1027                 break;
1028         case DRV_TLV_SCSI_CHECK_CONDITION_1_RECEIVED_SK_ASC_ASCQ:
1029         case DRV_TLV_SCSI_CHECK_CONDITION_2_RECEIVED_SK_ASC_ASCQ:
1030         case DRV_TLV_SCSI_CHECK_CONDITION_3_RECEIVED_SK_ASC_ASCQ:
1031         case DRV_TLV_SCSI_CHECK_CONDITION_4_RECEIVED_SK_ASC_ASCQ:
1032         case DRV_TLV_SCSI_CHECK_CONDITION_5_RECEIVED_SK_ASC_ASCQ:
1033                 idx = (p_tlv->tlv_type -
1034                        DRV_TLV_SCSI_CHECK_CONDITION_1_RECEIVED_SK_ASC_ASCQ) / 2;
1035
1036                 if (p_drv_buf->scsi_rx_chk_set[idx]) {
1037                         p_buf->p_val = &p_drv_buf->scsi_rx_chk[idx];
1038                         return sizeof(p_drv_buf->scsi_rx_chk[idx]);
1039                 }
1040                 break;
1041         case DRV_TLV_SCSI_CHECK_1_TIMESTAMP:
1042         case DRV_TLV_SCSI_CHECK_2_TIMESTAMP:
1043         case DRV_TLV_SCSI_CHECK_3_TIMESTAMP:
1044         case DRV_TLV_SCSI_CHECK_4_TIMESTAMP:
1045         case DRV_TLV_SCSI_CHECK_5_TIMESTAMP:
1046                 idx = (p_tlv->tlv_type - DRV_TLV_SCSI_CHECK_1_TIMESTAMP) / 2;
1047                 p_time = &p_drv_buf->scsi_chk_tstamp[idx];
1048
1049                 return qed_mfw_get_tlv_time_value(p_time, p_buf);
1050         default:
1051                 break;
1052         }
1053
1054         return -1;
1055 }
1056
1057 static int qed_mfw_update_tlvs(struct qed_hwfn *p_hwfn,
1058                                u8 tlv_group, u8 *p_mfw_buf, u32 size)
1059 {
1060         union qed_mfw_tlv_data *p_tlv_data;
1061         struct qed_tlv_parsed_buf buffer;
1062         struct qed_drv_tlv_hdr tlv;
1063         int len = 0;
1064         u32 offset;
1065         u8 *p_tlv;
1066
1067         p_tlv_data = vzalloc(sizeof(*p_tlv_data));
1068         if (!p_tlv_data)
1069                 return -ENOMEM;
1070
1071         if (qed_mfw_fill_tlv_data(p_hwfn, tlv_group, p_tlv_data)) {
1072                 vfree(p_tlv_data);
1073                 return -EINVAL;
1074         }
1075
1076         memset(&tlv, 0, sizeof(tlv));
1077         for (offset = 0; offset < size;
1078              offset += sizeof(tlv) + sizeof(u32) * tlv.tlv_length) {
1079                 p_tlv = &p_mfw_buf[offset];
1080                 tlv.tlv_type = TLV_TYPE(p_tlv);
1081                 tlv.tlv_length = TLV_LENGTH(p_tlv);
1082                 tlv.tlv_flags = TLV_FLAGS(p_tlv);
1083
1084                 DP_VERBOSE(p_hwfn, QED_MSG_SP,
1085                            "Type %d length = %d flags = 0x%x\n", tlv.tlv_type,
1086                            tlv.tlv_length, tlv.tlv_flags);
1087
1088                 if (tlv_group == QED_MFW_TLV_GENERIC)
1089                         len = qed_mfw_get_gen_tlv_value(&tlv,
1090                                                         &p_tlv_data->generic,
1091                                                         &buffer);
1092                 else if (tlv_group == QED_MFW_TLV_ETH)
1093                         len = qed_mfw_get_eth_tlv_value(&tlv,
1094                                                         &p_tlv_data->eth,
1095                                                         &buffer);
1096                 else if (tlv_group == QED_MFW_TLV_FCOE)
1097                         len = qed_mfw_get_fcoe_tlv_value(&tlv,
1098                                                          &p_tlv_data->fcoe,
1099                                                          &buffer);
1100
1101                 if (len > 0) {
1102                         WARN(len > 4 * tlv.tlv_length,
1103                              "Incorrect MFW TLV length %d, it shouldn't be greater than %d\n",
1104                              len, 4 * tlv.tlv_length);
1105                         len = min_t(int, len, 4 * tlv.tlv_length);
1106                         tlv.tlv_flags |= QED_DRV_TLV_FLAGS_CHANGED;
1107                         TLV_FLAGS(p_tlv) = tlv.tlv_flags;
1108                         memcpy(p_mfw_buf + offset + sizeof(tlv),
1109                                buffer.p_val, len);
1110                 }
1111         }
1112
1113         vfree(p_tlv_data);
1114
1115         return 0;
1116 }
1117
1118 int qed_mfw_process_tlv_req(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt)
1119 {
1120         u32 addr, size, offset, resp, param, val, global_offsize, global_addr;
1121         u8 tlv_group = 0, id, *p_mfw_buf = NULL, *p_temp;
1122         struct qed_drv_tlv_hdr tlv;
1123         int rc;
1124
1125         addr = SECTION_OFFSIZE_ADDR(p_hwfn->mcp_info->public_base,
1126                                     PUBLIC_GLOBAL);
1127         global_offsize = qed_rd(p_hwfn, p_ptt, addr);
1128         global_addr = SECTION_ADDR(global_offsize, 0);
1129         addr = global_addr + offsetof(struct public_global, data_ptr);
1130         addr = qed_rd(p_hwfn, p_ptt, addr);
1131         size = qed_rd(p_hwfn, p_ptt, global_addr +
1132                       offsetof(struct public_global, data_size));
1133
1134         if (!size) {
1135                 DP_NOTICE(p_hwfn, "Invalid TLV req size = %d\n", size);
1136                 goto drv_done;
1137         }
1138
1139         p_mfw_buf = vzalloc(size);
1140         if (!p_mfw_buf) {
1141                 DP_NOTICE(p_hwfn, "Failed allocate memory for p_mfw_buf\n");
1142                 goto drv_done;
1143         }
1144
1145         /* Read the TLV request to local buffer. MFW represents the TLV in
1146          * little endian format and mcp returns it bigendian format. Hence
1147          * driver need to convert data to little endian first and then do the
1148          * memcpy (casting) to preserve the MFW TLV format in the driver buffer.
1149          *
1150          */
1151         for (offset = 0; offset < size; offset += sizeof(u32)) {
1152                 val = qed_rd(p_hwfn, p_ptt, addr + offset);
1153                 val = be32_to_cpu(val);
1154                 memcpy(&p_mfw_buf[offset], &val, sizeof(u32));
1155         }
1156
1157         /* Parse the headers to enumerate the requested TLV groups */
1158         for (offset = 0; offset < size;
1159              offset += sizeof(tlv) + sizeof(u32) * tlv.tlv_length) {
1160                 p_temp = &p_mfw_buf[offset];
1161                 tlv.tlv_type = TLV_TYPE(p_temp);
1162                 tlv.tlv_length = TLV_LENGTH(p_temp);
1163                 if (qed_mfw_get_tlv_group(tlv.tlv_type, &tlv_group))
1164                         DP_VERBOSE(p_hwfn, NETIF_MSG_DRV,
1165                                    "Un recognized TLV %d\n", tlv.tlv_type);
1166         }
1167
1168         /* Sanitize the TLV groups according to personality */
1169         if ((tlv_group & QED_MFW_TLV_ETH) && !QED_IS_L2_PERSONALITY(p_hwfn)) {
1170                 DP_VERBOSE(p_hwfn, QED_MSG_SP,
1171                            "Skipping L2 TLVs for non-L2 function\n");
1172                 tlv_group &= ~QED_MFW_TLV_ETH;
1173         }
1174
1175         if ((tlv_group & QED_MFW_TLV_FCOE) &&
1176             p_hwfn->hw_info.personality != QED_PCI_FCOE) {
1177                 DP_VERBOSE(p_hwfn, QED_MSG_SP,
1178                            "Skipping FCoE TLVs for non-FCoE function\n");
1179                 tlv_group &= ~QED_MFW_TLV_FCOE;
1180         }
1181
1182         /* Update the TLV values in the local buffer */
1183         for (id = QED_MFW_TLV_GENERIC; id < QED_MFW_TLV_MAX; id <<= 1) {
1184                 if (tlv_group & id)
1185                         if (qed_mfw_update_tlvs(p_hwfn, id, p_mfw_buf, size))
1186                                 goto drv_done;
1187         }
1188
1189         /* Write the TLV data to shared memory. The stream of 4 bytes first need
1190          * to be mem-copied to u32 element to make it as LSB format. And then
1191          * converted to big endian as required by mcp-write.
1192          */
1193         for (offset = 0; offset < size; offset += sizeof(u32)) {
1194                 memcpy(&val, &p_mfw_buf[offset], sizeof(u32));
1195                 val = cpu_to_be32(val);
1196                 qed_wr(p_hwfn, p_ptt, addr + offset, val);
1197         }
1198
1199 drv_done:
1200         rc = qed_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_GET_TLV_DONE, 0, &resp,
1201                          &param);
1202
1203         vfree(p_mfw_buf);
1204
1205         return rc;
1206 }