Commit | Line | Data |
---|---|---|
39651abd SRK |
1 | /* QLogic qed NIC Driver |
2 | * Copyright (c) 2015 QLogic Corporation | |
3 | * | |
4 | * This software is available under the terms of the GNU General Public License | |
5 | * (GPL) Version 2, available from the file COPYING in the main directory of | |
6 | * this source tree. | |
7 | */ | |
8 | ||
9 | #include <linux/types.h> | |
10 | #include <asm/byteorder.h> | |
11 | #include <linux/bitops.h> | |
12 | #include <linux/errno.h> | |
13 | #include <linux/kernel.h> | |
14 | #include <linux/slab.h> | |
15 | #include <linux/string.h> | |
16 | #include "qed.h" | |
17 | #include "qed_cxt.h" | |
18 | #include "qed_dcbx.h" | |
19 | #include "qed_hsi.h" | |
20 | #include "qed_sp.h" | |
21 | ||
22 | #define QED_DCBX_MAX_MIB_READ_TRY (100) | |
23 | #define QED_ETH_TYPE_DEFAULT (0) | |
24 | #define QED_ETH_TYPE_ROCE (0x8915) | |
25 | #define QED_UDP_PORT_TYPE_ROCE_V2 (0x12B7) | |
26 | #define QED_ETH_TYPE_FCOE (0x8906) | |
27 | #define QED_TCP_PORT_ISCSI (0xCBC) | |
28 | ||
29 | #define QED_DCBX_INVALID_PRIORITY 0xFF | |
30 | ||
31 | /* Get Traffic Class from priority traffic class table, 4 bits represent | |
32 | * the traffic class corresponding to the priority. | |
33 | */ | |
34 | #define QED_DCBX_PRIO2TC(prio_tc_tbl, prio) \ | |
35 | ((u32)(prio_tc_tbl >> ((7 - prio) * 4)) & 0x7) | |
36 | ||
37 | static const struct qed_dcbx_app_metadata qed_dcbx_app_update[] = { | |
38 | {DCBX_PROTOCOL_ISCSI, "ISCSI", QED_PCI_DEFAULT}, | |
39 | {DCBX_PROTOCOL_FCOE, "FCOE", QED_PCI_DEFAULT}, | |
40 | {DCBX_PROTOCOL_ROCE, "ROCE", QED_PCI_DEFAULT}, | |
41 | {DCBX_PROTOCOL_ROCE_V2, "ROCE_V2", QED_PCI_DEFAULT}, | |
42 | {DCBX_PROTOCOL_ETH, "ETH", QED_PCI_ETH} | |
43 | }; | |
44 | ||
45 | static bool qed_dcbx_app_ethtype(u32 app_info_bitmap) | |
46 | { | |
47 | return !!(QED_MFW_GET_FIELD(app_info_bitmap, DCBX_APP_SF) == | |
48 | DCBX_APP_SF_ETHTYPE); | |
49 | } | |
50 | ||
51 | static bool qed_dcbx_app_port(u32 app_info_bitmap) | |
52 | { | |
53 | return !!(QED_MFW_GET_FIELD(app_info_bitmap, DCBX_APP_SF) == | |
54 | DCBX_APP_SF_PORT); | |
55 | } | |
56 | ||
57 | static bool qed_dcbx_default_tlv(u32 app_info_bitmap, u16 proto_id) | |
58 | { | |
59 | return !!(qed_dcbx_app_ethtype(app_info_bitmap) && | |
60 | proto_id == QED_ETH_TYPE_DEFAULT); | |
61 | } | |
62 | ||
63 | static bool qed_dcbx_iscsi_tlv(u32 app_info_bitmap, u16 proto_id) | |
64 | { | |
65 | return !!(qed_dcbx_app_port(app_info_bitmap) && | |
66 | proto_id == QED_TCP_PORT_ISCSI); | |
67 | } | |
68 | ||
69 | static bool qed_dcbx_fcoe_tlv(u32 app_info_bitmap, u16 proto_id) | |
70 | { | |
71 | return !!(qed_dcbx_app_ethtype(app_info_bitmap) && | |
72 | proto_id == QED_ETH_TYPE_FCOE); | |
73 | } | |
74 | ||
75 | static bool qed_dcbx_roce_tlv(u32 app_info_bitmap, u16 proto_id) | |
76 | { | |
77 | return !!(qed_dcbx_app_ethtype(app_info_bitmap) && | |
78 | proto_id == QED_ETH_TYPE_ROCE); | |
79 | } | |
80 | ||
81 | static bool qed_dcbx_roce_v2_tlv(u32 app_info_bitmap, u16 proto_id) | |
82 | { | |
83 | return !!(qed_dcbx_app_port(app_info_bitmap) && | |
84 | proto_id == QED_UDP_PORT_TYPE_ROCE_V2); | |
85 | } | |
86 | ||
87 | static void | |
88 | qed_dcbx_dp_protocol(struct qed_hwfn *p_hwfn, struct qed_dcbx_results *p_data) | |
89 | { | |
90 | enum dcbx_protocol_type id; | |
91 | int i; | |
92 | ||
93 | DP_VERBOSE(p_hwfn, QED_MSG_DCB, "DCBX negotiated: %d\n", | |
94 | p_data->dcbx_enabled); | |
95 | ||
96 | for (i = 0; i < ARRAY_SIZE(qed_dcbx_app_update); i++) { | |
97 | id = qed_dcbx_app_update[i].id; | |
98 | ||
99 | DP_VERBOSE(p_hwfn, QED_MSG_DCB, | |
100 | "%s info: update %d, enable %d, prio %d, tc %d, num_tc %d\n", | |
101 | qed_dcbx_app_update[i].name, p_data->arr[id].update, | |
102 | p_data->arr[id].enable, p_data->arr[id].priority, | |
103 | p_data->arr[id].tc, p_hwfn->hw_info.num_tc); | |
104 | } | |
105 | } | |
106 | ||
107 | static void | |
108 | qed_dcbx_set_params(struct qed_dcbx_results *p_data, | |
109 | struct qed_hw_info *p_info, | |
110 | bool enable, | |
111 | bool update, | |
112 | u8 prio, | |
113 | u8 tc, | |
114 | enum dcbx_protocol_type type, | |
115 | enum qed_pci_personality personality) | |
116 | { | |
117 | /* PF update ramrod data */ | |
118 | p_data->arr[type].update = update; | |
119 | p_data->arr[type].enable = enable; | |
120 | p_data->arr[type].priority = prio; | |
121 | p_data->arr[type].tc = tc; | |
122 | ||
123 | /* QM reconf data */ | |
124 | if (p_info->personality == personality) { | |
125 | if (personality == QED_PCI_ETH) | |
126 | p_info->non_offload_tc = tc; | |
127 | else | |
128 | p_info->offload_tc = tc; | |
129 | } | |
130 | } | |
131 | ||
132 | /* Update app protocol data and hw_info fields with the TLV info */ | |
133 | static void | |
134 | qed_dcbx_update_app_info(struct qed_dcbx_results *p_data, | |
135 | struct qed_hwfn *p_hwfn, | |
136 | bool enable, | |
137 | bool update, | |
138 | u8 prio, u8 tc, enum dcbx_protocol_type type) | |
139 | { | |
140 | struct qed_hw_info *p_info = &p_hwfn->hw_info; | |
141 | enum qed_pci_personality personality; | |
142 | enum dcbx_protocol_type id; | |
143 | char *name; | |
144 | int i; | |
145 | ||
146 | for (i = 0; i < ARRAY_SIZE(qed_dcbx_app_update); i++) { | |
147 | id = qed_dcbx_app_update[i].id; | |
148 | ||
149 | if (type != id) | |
150 | continue; | |
151 | ||
152 | personality = qed_dcbx_app_update[i].personality; | |
153 | name = qed_dcbx_app_update[i].name; | |
154 | ||
155 | qed_dcbx_set_params(p_data, p_info, enable, update, | |
156 | prio, tc, type, personality); | |
157 | } | |
158 | } | |
159 | ||
160 | static bool | |
161 | qed_dcbx_get_app_protocol_type(struct qed_hwfn *p_hwfn, | |
162 | u32 app_prio_bitmap, | |
163 | u16 id, enum dcbx_protocol_type *type) | |
164 | { | |
165 | if (qed_dcbx_fcoe_tlv(app_prio_bitmap, id)) { | |
166 | *type = DCBX_PROTOCOL_FCOE; | |
167 | } else if (qed_dcbx_roce_tlv(app_prio_bitmap, id)) { | |
168 | *type = DCBX_PROTOCOL_ROCE; | |
169 | } else if (qed_dcbx_iscsi_tlv(app_prio_bitmap, id)) { | |
170 | *type = DCBX_PROTOCOL_ISCSI; | |
171 | } else if (qed_dcbx_default_tlv(app_prio_bitmap, id)) { | |
172 | *type = DCBX_PROTOCOL_ETH; | |
173 | } else if (qed_dcbx_roce_v2_tlv(app_prio_bitmap, id)) { | |
174 | *type = DCBX_PROTOCOL_ROCE_V2; | |
175 | } else { | |
176 | *type = DCBX_MAX_PROTOCOL_TYPE; | |
177 | DP_ERR(p_hwfn, | |
178 | "No action required, App TLV id = 0x%x app_prio_bitmap = 0x%x\n", | |
179 | id, app_prio_bitmap); | |
180 | return false; | |
181 | } | |
182 | ||
183 | return true; | |
184 | } | |
185 | ||
186 | /* Parse app TLV's to update TC information in hw_info structure for | |
187 | * reconfiguring QM. Get protocol specific data for PF update ramrod command. | |
188 | */ | |
189 | static int | |
190 | qed_dcbx_process_tlv(struct qed_hwfn *p_hwfn, | |
191 | struct qed_dcbx_results *p_data, | |
192 | struct dcbx_app_priority_entry *p_tbl, | |
193 | u32 pri_tc_tbl, int count, bool dcbx_enabled) | |
194 | { | |
54b9430f | 195 | u8 tc, priority_map; |
39651abd SRK |
196 | enum dcbx_protocol_type type; |
197 | u16 protocol_id; | |
54b9430f | 198 | int priority; |
39651abd SRK |
199 | bool enable; |
200 | int i; | |
201 | ||
202 | DP_VERBOSE(p_hwfn, QED_MSG_DCB, "Num APP entries = %d\n", count); | |
203 | ||
204 | /* Parse APP TLV */ | |
205 | for (i = 0; i < count; i++) { | |
206 | protocol_id = QED_MFW_GET_FIELD(p_tbl[i].entry, | |
207 | DCBX_APP_PROTOCOL_ID); | |
208 | priority_map = QED_MFW_GET_FIELD(p_tbl[i].entry, | |
209 | DCBX_APP_PRI_MAP); | |
210 | priority = ffs(priority_map) - 1; | |
211 | if (priority < 0) { | |
212 | DP_ERR(p_hwfn, "Invalid priority\n"); | |
213 | return -EINVAL; | |
214 | } | |
215 | ||
216 | tc = QED_DCBX_PRIO2TC(pri_tc_tbl, priority); | |
217 | if (qed_dcbx_get_app_protocol_type(p_hwfn, p_tbl[i].entry, | |
218 | protocol_id, &type)) { | |
219 | /* ETH always have the enable bit reset, as it gets | |
220 | * vlan information per packet. For other protocols, | |
221 | * should be set according to the dcbx_enabled | |
222 | * indication, but we only got here if there was an | |
223 | * app tlv for the protocol, so dcbx must be enabled. | |
224 | */ | |
ec7c7f5c | 225 | enable = !(type == DCBX_PROTOCOL_ETH); |
39651abd SRK |
226 | |
227 | qed_dcbx_update_app_info(p_data, p_hwfn, enable, true, | |
228 | priority, tc, type); | |
229 | } | |
230 | } | |
231 | ||
232 | /* If RoCE-V2 TLV is not detected, driver need to use RoCE app | |
233 | * data for RoCE-v2 not the default app data. | |
234 | */ | |
235 | if (!p_data->arr[DCBX_PROTOCOL_ROCE_V2].update && | |
236 | p_data->arr[DCBX_PROTOCOL_ROCE].update) { | |
237 | tc = p_data->arr[DCBX_PROTOCOL_ROCE].tc; | |
238 | priority = p_data->arr[DCBX_PROTOCOL_ROCE].priority; | |
239 | qed_dcbx_update_app_info(p_data, p_hwfn, true, true, | |
240 | priority, tc, DCBX_PROTOCOL_ROCE_V2); | |
241 | } | |
242 | ||
243 | /* Update ramrod protocol data and hw_info fields | |
244 | * with default info when corresponding APP TLV's are not detected. | |
245 | * The enabled field has a different logic for ethernet as only for | |
246 | * ethernet dcb should disabled by default, as the information arrives | |
247 | * from the OS (unless an explicit app tlv was present). | |
248 | */ | |
249 | tc = p_data->arr[DCBX_PROTOCOL_ETH].tc; | |
250 | priority = p_data->arr[DCBX_PROTOCOL_ETH].priority; | |
251 | for (type = 0; type < DCBX_MAX_PROTOCOL_TYPE; type++) { | |
252 | if (p_data->arr[type].update) | |
253 | continue; | |
254 | ||
255 | enable = (type == DCBX_PROTOCOL_ETH) ? false : dcbx_enabled; | |
256 | qed_dcbx_update_app_info(p_data, p_hwfn, enable, true, | |
257 | priority, tc, type); | |
258 | } | |
259 | ||
260 | return 0; | |
261 | } | |
262 | ||
263 | /* Parse app TLV's to update TC information in hw_info structure for | |
264 | * reconfiguring QM. Get protocol specific data for PF update ramrod command. | |
265 | */ | |
266 | static int qed_dcbx_process_mib_info(struct qed_hwfn *p_hwfn) | |
267 | { | |
268 | struct dcbx_app_priority_feature *p_app; | |
269 | struct dcbx_app_priority_entry *p_tbl; | |
270 | struct qed_dcbx_results data = { 0 }; | |
271 | struct dcbx_ets_feature *p_ets; | |
272 | struct qed_hw_info *p_info; | |
273 | u32 pri_tc_tbl, flags; | |
274 | bool dcbx_enabled; | |
275 | int num_entries; | |
276 | int rc = 0; | |
277 | ||
278 | /* If DCBx version is non zero, then negotiation was | |
279 | * successfuly performed | |
280 | */ | |
281 | flags = p_hwfn->p_dcbx_info->operational.flags; | |
282 | dcbx_enabled = !!QED_MFW_GET_FIELD(flags, DCBX_CONFIG_VERSION); | |
283 | ||
284 | p_app = &p_hwfn->p_dcbx_info->operational.features.app; | |
285 | p_tbl = p_app->app_pri_tbl; | |
286 | ||
287 | p_ets = &p_hwfn->p_dcbx_info->operational.features.ets; | |
288 | pri_tc_tbl = p_ets->pri_tc_tbl[0]; | |
289 | ||
290 | p_info = &p_hwfn->hw_info; | |
291 | num_entries = QED_MFW_GET_FIELD(p_app->flags, DCBX_APP_NUM_ENTRIES); | |
292 | ||
293 | rc = qed_dcbx_process_tlv(p_hwfn, &data, p_tbl, pri_tc_tbl, | |
294 | num_entries, dcbx_enabled); | |
295 | if (rc) | |
296 | return rc; | |
297 | ||
298 | p_info->num_tc = QED_MFW_GET_FIELD(p_ets->flags, DCBX_ETS_MAX_TCS); | |
299 | data.pf_id = p_hwfn->rel_pf_id; | |
300 | data.dcbx_enabled = dcbx_enabled; | |
301 | ||
302 | qed_dcbx_dp_protocol(p_hwfn, &data); | |
303 | ||
304 | memcpy(&p_hwfn->p_dcbx_info->results, &data, | |
305 | sizeof(struct qed_dcbx_results)); | |
306 | ||
307 | return 0; | |
308 | } | |
309 | ||
310 | static int | |
311 | qed_dcbx_copy_mib(struct qed_hwfn *p_hwfn, | |
312 | struct qed_ptt *p_ptt, | |
313 | struct qed_dcbx_mib_meta_data *p_data, | |
314 | enum qed_mib_read_type type) | |
315 | { | |
316 | u32 prefix_seq_num, suffix_seq_num; | |
317 | int read_count = 0; | |
318 | int rc = 0; | |
319 | ||
320 | /* The data is considered to be valid only if both sequence numbers are | |
321 | * the same. | |
322 | */ | |
323 | do { | |
324 | if (type == QED_DCBX_REMOTE_LLDP_MIB) { | |
325 | qed_memcpy_from(p_hwfn, p_ptt, p_data->lldp_remote, | |
326 | p_data->addr, p_data->size); | |
327 | prefix_seq_num = p_data->lldp_remote->prefix_seq_num; | |
328 | suffix_seq_num = p_data->lldp_remote->suffix_seq_num; | |
329 | } else { | |
330 | qed_memcpy_from(p_hwfn, p_ptt, p_data->mib, | |
331 | p_data->addr, p_data->size); | |
332 | prefix_seq_num = p_data->mib->prefix_seq_num; | |
333 | suffix_seq_num = p_data->mib->suffix_seq_num; | |
334 | } | |
335 | read_count++; | |
336 | ||
337 | DP_VERBOSE(p_hwfn, | |
338 | QED_MSG_DCB, | |
339 | "mib type = %d, try count = %d prefix seq num = %d suffix seq num = %d\n", | |
340 | type, read_count, prefix_seq_num, suffix_seq_num); | |
341 | } while ((prefix_seq_num != suffix_seq_num) && | |
342 | (read_count < QED_DCBX_MAX_MIB_READ_TRY)); | |
343 | ||
344 | if (read_count >= QED_DCBX_MAX_MIB_READ_TRY) { | |
345 | DP_ERR(p_hwfn, | |
346 | "MIB read err, mib type = %d, try count = %d prefix seq num = %d suffix seq num = %d\n", | |
347 | type, read_count, prefix_seq_num, suffix_seq_num); | |
348 | rc = -EIO; | |
349 | } | |
350 | ||
351 | return rc; | |
352 | } | |
353 | ||
354 | static int | |
355 | qed_dcbx_read_local_lldp_mib(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt) | |
356 | { | |
357 | struct qed_dcbx_mib_meta_data data; | |
358 | int rc = 0; | |
359 | ||
360 | memset(&data, 0, sizeof(data)); | |
361 | data.addr = p_hwfn->mcp_info->port_addr + offsetof(struct public_port, | |
362 | lldp_config_params); | |
363 | data.lldp_local = p_hwfn->p_dcbx_info->lldp_local; | |
364 | data.size = sizeof(struct lldp_config_params_s); | |
365 | qed_memcpy_from(p_hwfn, p_ptt, data.lldp_local, data.addr, data.size); | |
366 | ||
367 | return rc; | |
368 | } | |
369 | ||
370 | static int | |
371 | qed_dcbx_read_remote_lldp_mib(struct qed_hwfn *p_hwfn, | |
372 | struct qed_ptt *p_ptt, | |
373 | enum qed_mib_read_type type) | |
374 | { | |
375 | struct qed_dcbx_mib_meta_data data; | |
376 | int rc = 0; | |
377 | ||
378 | memset(&data, 0, sizeof(data)); | |
379 | data.addr = p_hwfn->mcp_info->port_addr + offsetof(struct public_port, | |
380 | lldp_status_params); | |
381 | data.lldp_remote = p_hwfn->p_dcbx_info->lldp_remote; | |
382 | data.size = sizeof(struct lldp_status_params_s); | |
383 | rc = qed_dcbx_copy_mib(p_hwfn, p_ptt, &data, type); | |
384 | ||
385 | return rc; | |
386 | } | |
387 | ||
388 | static int | |
389 | qed_dcbx_read_operational_mib(struct qed_hwfn *p_hwfn, | |
390 | struct qed_ptt *p_ptt, | |
391 | enum qed_mib_read_type type) | |
392 | { | |
393 | struct qed_dcbx_mib_meta_data data; | |
394 | int rc = 0; | |
395 | ||
396 | memset(&data, 0, sizeof(data)); | |
397 | data.addr = p_hwfn->mcp_info->port_addr + | |
398 | offsetof(struct public_port, operational_dcbx_mib); | |
399 | data.mib = &p_hwfn->p_dcbx_info->operational; | |
400 | data.size = sizeof(struct dcbx_mib); | |
401 | rc = qed_dcbx_copy_mib(p_hwfn, p_ptt, &data, type); | |
402 | ||
403 | return rc; | |
404 | } | |
405 | ||
406 | static int | |
407 | qed_dcbx_read_remote_mib(struct qed_hwfn *p_hwfn, | |
408 | struct qed_ptt *p_ptt, enum qed_mib_read_type type) | |
409 | { | |
410 | struct qed_dcbx_mib_meta_data data; | |
411 | int rc = 0; | |
412 | ||
413 | memset(&data, 0, sizeof(data)); | |
414 | data.addr = p_hwfn->mcp_info->port_addr + | |
415 | offsetof(struct public_port, remote_dcbx_mib); | |
416 | data.mib = &p_hwfn->p_dcbx_info->remote; | |
417 | data.size = sizeof(struct dcbx_mib); | |
418 | rc = qed_dcbx_copy_mib(p_hwfn, p_ptt, &data, type); | |
419 | ||
420 | return rc; | |
421 | } | |
422 | ||
423 | static int | |
424 | qed_dcbx_read_local_mib(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt) | |
425 | { | |
426 | struct qed_dcbx_mib_meta_data data; | |
427 | int rc = 0; | |
428 | ||
429 | memset(&data, 0, sizeof(data)); | |
430 | data.addr = p_hwfn->mcp_info->port_addr + | |
431 | offsetof(struct public_port, local_admin_dcbx_mib); | |
432 | data.local_admin = &p_hwfn->p_dcbx_info->local_admin; | |
433 | data.size = sizeof(struct dcbx_local_params); | |
434 | qed_memcpy_from(p_hwfn, p_ptt, data.local_admin, data.addr, data.size); | |
435 | ||
436 | return rc; | |
437 | } | |
438 | ||
439 | static int qed_dcbx_read_mib(struct qed_hwfn *p_hwfn, | |
440 | struct qed_ptt *p_ptt, enum qed_mib_read_type type) | |
441 | { | |
442 | int rc = -EINVAL; | |
443 | ||
444 | switch (type) { | |
445 | case QED_DCBX_OPERATIONAL_MIB: | |
446 | rc = qed_dcbx_read_operational_mib(p_hwfn, p_ptt, type); | |
447 | break; | |
448 | case QED_DCBX_REMOTE_MIB: | |
449 | rc = qed_dcbx_read_remote_mib(p_hwfn, p_ptt, type); | |
450 | break; | |
451 | case QED_DCBX_LOCAL_MIB: | |
452 | rc = qed_dcbx_read_local_mib(p_hwfn, p_ptt); | |
453 | break; | |
454 | case QED_DCBX_REMOTE_LLDP_MIB: | |
455 | rc = qed_dcbx_read_remote_lldp_mib(p_hwfn, p_ptt, type); | |
456 | break; | |
457 | case QED_DCBX_LOCAL_LLDP_MIB: | |
458 | rc = qed_dcbx_read_local_lldp_mib(p_hwfn, p_ptt); | |
459 | break; | |
460 | default: | |
461 | DP_ERR(p_hwfn, "MIB read err, unknown mib type %d\n", type); | |
462 | } | |
463 | ||
464 | return rc; | |
465 | } | |
466 | ||
467 | /* Read updated MIB. | |
468 | * Reconfigure QM and invoke PF update ramrod command if operational MIB | |
469 | * change is detected. | |
470 | */ | |
471 | int | |
472 | qed_dcbx_mib_update_event(struct qed_hwfn *p_hwfn, | |
473 | struct qed_ptt *p_ptt, enum qed_mib_read_type type) | |
474 | { | |
475 | int rc = 0; | |
476 | ||
477 | rc = qed_dcbx_read_mib(p_hwfn, p_ptt, type); | |
478 | if (rc) | |
479 | return rc; | |
480 | ||
481 | if (type == QED_DCBX_OPERATIONAL_MIB) { | |
482 | rc = qed_dcbx_process_mib_info(p_hwfn); | |
483 | if (!rc) { | |
484 | /* reconfigure tcs of QM queues according | |
485 | * to negotiation results | |
486 | */ | |
487 | qed_qm_reconf(p_hwfn, p_ptt); | |
488 | ||
489 | /* update storm FW with negotiation results */ | |
490 | qed_sp_pf_update(p_hwfn); | |
491 | } | |
492 | } | |
493 | ||
494 | return rc; | |
495 | } | |
496 | ||
497 | int qed_dcbx_info_alloc(struct qed_hwfn *p_hwfn) | |
498 | { | |
499 | int rc = 0; | |
500 | ||
501 | p_hwfn->p_dcbx_info = kzalloc(sizeof(*p_hwfn->p_dcbx_info), GFP_KERNEL); | |
502 | if (!p_hwfn->p_dcbx_info) { | |
503 | DP_NOTICE(p_hwfn, | |
504 | "Failed to allocate 'struct qed_dcbx_info'\n"); | |
505 | rc = -ENOMEM; | |
506 | } | |
507 | ||
508 | return rc; | |
509 | } | |
510 | ||
511 | void qed_dcbx_info_free(struct qed_hwfn *p_hwfn, | |
512 | struct qed_dcbx_info *p_dcbx_info) | |
513 | { | |
514 | kfree(p_hwfn->p_dcbx_info); | |
515 | } | |
516 | ||
517 | static void qed_dcbx_update_protocol_data(struct protocol_dcb_data *p_data, | |
518 | struct qed_dcbx_results *p_src, | |
519 | enum dcbx_protocol_type type) | |
520 | { | |
521 | p_data->dcb_enable_flag = p_src->arr[type].enable; | |
522 | p_data->dcb_priority = p_src->arr[type].priority; | |
523 | p_data->dcb_tc = p_src->arr[type].tc; | |
524 | } | |
525 | ||
526 | /* Set pf update ramrod command params */ | |
527 | void qed_dcbx_set_pf_update_params(struct qed_dcbx_results *p_src, | |
528 | struct pf_update_ramrod_data *p_dest) | |
529 | { | |
530 | struct protocol_dcb_data *p_dcb_data; | |
531 | bool update_flag = false; | |
532 | ||
533 | p_dest->pf_id = p_src->pf_id; | |
534 | ||
535 | update_flag = p_src->arr[DCBX_PROTOCOL_FCOE].update; | |
536 | p_dest->update_fcoe_dcb_data_flag = update_flag; | |
537 | ||
538 | update_flag = p_src->arr[DCBX_PROTOCOL_ROCE].update; | |
539 | p_dest->update_roce_dcb_data_flag = update_flag; | |
540 | update_flag = p_src->arr[DCBX_PROTOCOL_ROCE_V2].update; | |
541 | p_dest->update_roce_dcb_data_flag = update_flag; | |
542 | ||
543 | update_flag = p_src->arr[DCBX_PROTOCOL_ISCSI].update; | |
544 | p_dest->update_iscsi_dcb_data_flag = update_flag; | |
545 | update_flag = p_src->arr[DCBX_PROTOCOL_ETH].update; | |
546 | p_dest->update_eth_dcb_data_flag = update_flag; | |
547 | ||
548 | p_dcb_data = &p_dest->fcoe_dcb_data; | |
549 | qed_dcbx_update_protocol_data(p_dcb_data, p_src, DCBX_PROTOCOL_FCOE); | |
550 | p_dcb_data = &p_dest->roce_dcb_data; | |
551 | ||
552 | if (p_src->arr[DCBX_PROTOCOL_ROCE].update) | |
553 | qed_dcbx_update_protocol_data(p_dcb_data, p_src, | |
554 | DCBX_PROTOCOL_ROCE); | |
555 | if (p_src->arr[DCBX_PROTOCOL_ROCE_V2].update) | |
556 | qed_dcbx_update_protocol_data(p_dcb_data, p_src, | |
557 | DCBX_PROTOCOL_ROCE_V2); | |
558 | ||
559 | p_dcb_data = &p_dest->iscsi_dcb_data; | |
560 | qed_dcbx_update_protocol_data(p_dcb_data, p_src, DCBX_PROTOCOL_ISCSI); | |
561 | p_dcb_data = &p_dest->eth_dcb_data; | |
562 | qed_dcbx_update_protocol_data(p_dcb_data, p_src, DCBX_PROTOCOL_ETH); | |
563 | } |