xref: /linux/drivers/net/ethernet/meta/fbnic/fbnic_devlink.c (revision 55a42f78ffd386e01a5404419f8c5ded7db70a21)
1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright (c) Meta Platforms, Inc. and affiliates. */
3 
4 #include <linux/unaligned.h>
5 #include <linux/pci.h>
6 #include <linux/pldmfw.h>
7 #include <linux/types.h>
8 #include <net/devlink.h>
9 
10 #include "fbnic.h"
11 #include "fbnic_fw.h"
12 #include "fbnic_tlv.h"
13 
14 #define FBNIC_SN_STR_LEN	24
15 
16 static int fbnic_version_running_put(struct devlink_info_req *req,
17 				     struct fbnic_fw_ver *fw_ver,
18 				     char *ver_name)
19 {
20 	char running_ver[FBNIC_FW_VER_MAX_SIZE];
21 	int err;
22 
23 	fbnic_mk_fw_ver_str(fw_ver->version, running_ver);
24 	err = devlink_info_version_running_put(req, ver_name, running_ver);
25 	if (err)
26 		return err;
27 
28 	if (strlen(fw_ver->commit) > 0) {
29 		char commit_name[FBNIC_SN_STR_LEN];
30 
31 		snprintf(commit_name, FBNIC_SN_STR_LEN, "%s.commit", ver_name);
32 		err = devlink_info_version_running_put(req, commit_name,
33 						       fw_ver->commit);
34 		if (err)
35 			return err;
36 	}
37 
38 	return 0;
39 }
40 
41 static int fbnic_version_stored_put(struct devlink_info_req *req,
42 				    struct fbnic_fw_ver *fw_ver,
43 				    char *ver_name)
44 {
45 	char stored_ver[FBNIC_FW_VER_MAX_SIZE];
46 	int err;
47 
48 	fbnic_mk_fw_ver_str(fw_ver->version, stored_ver);
49 	err = devlink_info_version_stored_put(req, ver_name, stored_ver);
50 	if (err)
51 		return err;
52 
53 	if (strlen(fw_ver->commit) > 0) {
54 		char commit_name[FBNIC_SN_STR_LEN];
55 
56 		snprintf(commit_name, FBNIC_SN_STR_LEN, "%s.commit", ver_name);
57 		err = devlink_info_version_stored_put(req, commit_name,
58 						      fw_ver->commit);
59 		if (err)
60 			return err;
61 	}
62 
63 	return 0;
64 }
65 
66 static int fbnic_devlink_info_get(struct devlink *devlink,
67 				  struct devlink_info_req *req,
68 				  struct netlink_ext_ack *extack)
69 {
70 	struct fbnic_dev *fbd = devlink_priv(devlink);
71 	int err;
72 
73 	err = fbnic_version_running_put(req, &fbd->fw_cap.running.mgmt,
74 					DEVLINK_INFO_VERSION_GENERIC_FW);
75 	if (err)
76 		return err;
77 
78 	err = fbnic_version_running_put(req, &fbd->fw_cap.running.bootloader,
79 					DEVLINK_INFO_VERSION_GENERIC_FW_BOOTLOADER);
80 	if (err)
81 		return err;
82 
83 	err = fbnic_version_stored_put(req, &fbd->fw_cap.stored.mgmt,
84 				       DEVLINK_INFO_VERSION_GENERIC_FW);
85 	if (err)
86 		return err;
87 
88 	err = fbnic_version_stored_put(req, &fbd->fw_cap.stored.bootloader,
89 				       DEVLINK_INFO_VERSION_GENERIC_FW_BOOTLOADER);
90 	if (err)
91 		return err;
92 
93 	err = fbnic_version_stored_put(req, &fbd->fw_cap.stored.undi,
94 				       DEVLINK_INFO_VERSION_GENERIC_FW_UNDI);
95 	if (err)
96 		return err;
97 
98 	if (fbd->dsn) {
99 		unsigned char serial[FBNIC_SN_STR_LEN];
100 		u8 dsn[8];
101 
102 		put_unaligned_be64(fbd->dsn, dsn);
103 		err = snprintf(serial, FBNIC_SN_STR_LEN, "%8phD", dsn);
104 		if (err < 0)
105 			return err;
106 
107 		err = devlink_info_serial_number_put(req, serial);
108 		if (err)
109 			return err;
110 	}
111 
112 	return 0;
113 }
114 
115 static bool
116 fbnic_pldm_match_record(struct pldmfw *context, struct pldmfw_record *record)
117 {
118 	struct pldmfw_desc_tlv *desc;
119 	u32 anti_rollback_ver = 0;
120 	struct devlink *devlink;
121 	struct fbnic_dev *fbd;
122 	struct pci_dev *pdev;
123 
124 	/* First, use the standard PCI matching function */
125 	if (!pldmfw_op_pci_match_record(context, record))
126 		return false;
127 
128 	pdev = to_pci_dev(context->dev);
129 	fbd = pci_get_drvdata(pdev);
130 	devlink = priv_to_devlink(fbd);
131 
132 	/* If PCI match is successful, check for vendor-specific descriptors */
133 	list_for_each_entry(desc, &record->descs, entry) {
134 		if (desc->type != PLDM_DESC_ID_VENDOR_DEFINED)
135 			continue;
136 
137 		if (desc->size < 21 || desc->data[0] != 1 ||
138 		    desc->data[1] != 15)
139 			continue;
140 
141 		if (memcmp(desc->data + 2, "AntiRollbackVer", 15) != 0)
142 			continue;
143 
144 		anti_rollback_ver = get_unaligned_le32(desc->data + 17);
145 		break;
146 	}
147 
148 	/* Compare versions and return error if they do not match */
149 	if (anti_rollback_ver < fbd->fw_cap.anti_rollback_version) {
150 		char buf[128];
151 
152 		snprintf(buf, sizeof(buf),
153 			 "New firmware anti-rollback version (0x%x) is older than device version (0x%x)!",
154 			 anti_rollback_ver, fbd->fw_cap.anti_rollback_version);
155 		devlink_flash_update_status_notify(devlink, buf,
156 						   "Anti-Rollback", 0, 0);
157 
158 		return false;
159 	}
160 
161 	return true;
162 }
163 
164 static int
165 fbnic_flash_start(struct fbnic_dev *fbd, struct pldmfw_component *component)
166 {
167 	struct fbnic_fw_completion *cmpl;
168 	int err;
169 
170 	cmpl = fbnic_fw_alloc_cmpl(FBNIC_TLV_MSG_ID_FW_START_UPGRADE_REQ);
171 	if (!cmpl)
172 		return -ENOMEM;
173 
174 	err = fbnic_fw_xmit_fw_start_upgrade(fbd, cmpl,
175 					     component->identifier,
176 					     component->component_size);
177 	if (err)
178 		goto cmpl_free;
179 
180 	/* Wait for firmware to ack firmware upgrade start */
181 	if (wait_for_completion_timeout(&cmpl->done, 10 * HZ))
182 		err = cmpl->result;
183 	else
184 		err = -ETIMEDOUT;
185 
186 	fbnic_mbx_clear_cmpl(fbd, cmpl);
187 cmpl_free:
188 	fbnic_fw_put_cmpl(cmpl);
189 
190 	return err;
191 }
192 
193 static int
194 fbnic_flash_component(struct pldmfw *context,
195 		      struct pldmfw_component *component)
196 {
197 	const u8 *data = component->component_data;
198 	const u32 size = component->component_size;
199 	struct fbnic_fw_completion *cmpl;
200 	const char *component_name;
201 	struct devlink *devlink;
202 	struct fbnic_dev *fbd;
203 	struct pci_dev *pdev;
204 	u32 offset = 0;
205 	u32 length = 0;
206 	char buf[32];
207 	int err;
208 
209 	pdev = to_pci_dev(context->dev);
210 	fbd = pci_get_drvdata(pdev);
211 	devlink = priv_to_devlink(fbd);
212 
213 	switch (component->identifier) {
214 	case QSPI_SECTION_CMRT:
215 		component_name = "boot1";
216 		break;
217 	case QSPI_SECTION_CONTROL_FW:
218 		component_name = "boot2";
219 		break;
220 	case QSPI_SECTION_OPTION_ROM:
221 		component_name = "option-rom";
222 		break;
223 	default:
224 		snprintf(buf, sizeof(buf), "Unknown component ID %u!",
225 			 component->identifier);
226 		devlink_flash_update_status_notify(devlink, buf, NULL, 0,
227 						   size);
228 		return -EINVAL;
229 	}
230 
231 	/* Once firmware receives the request to start upgrading it responds
232 	 * with two messages:
233 	 * 1. An ACK that it received the message and possible error code
234 	 *    indicating that an upgrade is not currently possible.
235 	 * 2. A request for the first chunk of data
236 	 *
237 	 * Setup completions for write before issuing the start message so
238 	 * the driver can catch both messages.
239 	 */
240 	cmpl = fbnic_fw_alloc_cmpl(FBNIC_TLV_MSG_ID_FW_WRITE_CHUNK_REQ);
241 	if (!cmpl)
242 		return -ENOMEM;
243 
244 	err = fbnic_mbx_set_cmpl(fbd, cmpl);
245 	if (err)
246 		goto cmpl_free;
247 
248 	devlink_flash_update_timeout_notify(devlink, "Initializing",
249 					    component_name, 15);
250 	err = fbnic_flash_start(fbd, component);
251 	if (err)
252 		goto err_no_msg;
253 
254 	while (offset < size) {
255 		if (!wait_for_completion_timeout(&cmpl->done, 15 * HZ)) {
256 			err = -ETIMEDOUT;
257 			break;
258 		}
259 
260 		err = cmpl->result;
261 		if (err)
262 			break;
263 
264 		/* Verify firmware is requesting the next chunk in the seq. */
265 		if (cmpl->u.fw_update.offset != offset + length) {
266 			err = -EFAULT;
267 			break;
268 		}
269 
270 		offset = cmpl->u.fw_update.offset;
271 		length = cmpl->u.fw_update.length;
272 
273 		if (length > TLV_MAX_DATA || offset + length > size) {
274 			err = -EFAULT;
275 			break;
276 		}
277 
278 		devlink_flash_update_status_notify(devlink, "Flashing",
279 						   component_name,
280 						   offset, size);
281 
282 		/* Mailbox will set length to 0 once it receives the finish
283 		 * message.
284 		 */
285 		if (!length)
286 			continue;
287 
288 		reinit_completion(&cmpl->done);
289 		err = fbnic_fw_xmit_fw_write_chunk(fbd, data, offset, length,
290 						   0);
291 		if (err)
292 			break;
293 	}
294 
295 	if (err) {
296 		fbnic_fw_xmit_fw_write_chunk(fbd, NULL, 0, 0, err);
297 err_no_msg:
298 		snprintf(buf, sizeof(buf), "Mailbox encountered error %d!",
299 			 err);
300 		devlink_flash_update_status_notify(devlink, buf,
301 						   component_name, 0, 0);
302 	}
303 
304 	fbnic_mbx_clear_cmpl(fbd, cmpl);
305 cmpl_free:
306 	fbnic_fw_put_cmpl(cmpl);
307 
308 	return err;
309 }
310 
311 static const struct pldmfw_ops fbnic_pldmfw_ops = {
312 	.match_record = fbnic_pldm_match_record,
313 	.flash_component = fbnic_flash_component,
314 };
315 
316 static int
317 fbnic_devlink_flash_update(struct devlink *devlink,
318 			   struct devlink_flash_update_params *params,
319 			   struct netlink_ext_ack *extack)
320 {
321 	struct fbnic_dev *fbd = devlink_priv(devlink);
322 	const struct firmware *fw = params->fw;
323 	struct device *dev = fbd->dev;
324 	struct pldmfw context;
325 	char *err_msg;
326 	int err;
327 
328 	context.ops = &fbnic_pldmfw_ops;
329 	context.dev = dev;
330 
331 	err = pldmfw_flash_image(&context, fw);
332 	if (err) {
333 		switch (err) {
334 		case -EINVAL:
335 			err_msg = "Invalid image";
336 			break;
337 		case -EOPNOTSUPP:
338 			err_msg = "Unsupported image";
339 			break;
340 		case -ENOMEM:
341 			err_msg = "Out of memory";
342 			break;
343 		case -EFAULT:
344 			err_msg = "Invalid header";
345 			break;
346 		case -ENOENT:
347 			err_msg = "No matching record";
348 			break;
349 		case -ENODEV:
350 			err_msg = "No matching device";
351 			break;
352 		case -ETIMEDOUT:
353 			err_msg = "Timed out waiting for reply";
354 			break;
355 		default:
356 			err_msg = "Unknown error";
357 			break;
358 		}
359 
360 		NL_SET_ERR_MSG_FMT_MOD(extack,
361 				       "Failed to flash PLDM Image: %s (error: %d)",
362 				       err_msg, err);
363 	}
364 
365 	return err;
366 }
367 
368 static const struct devlink_ops fbnic_devlink_ops = {
369 	.info_get	= fbnic_devlink_info_get,
370 	.flash_update	= fbnic_devlink_flash_update,
371 };
372 
373 static int fbnic_fw_reporter_dump(struct devlink_health_reporter *reporter,
374 				  struct devlink_fmsg *fmsg, void *priv_ctx,
375 				  struct netlink_ext_ack *extack)
376 {
377 	struct fbnic_dev *fbd = devlink_health_reporter_priv(reporter);
378 	u32 offset, index, index_count, length, size;
379 	struct fbnic_fw_completion *fw_cmpl;
380 	u8 *dump_data, **data;
381 	int err;
382 
383 	fw_cmpl = fbnic_fw_alloc_cmpl(FBNIC_TLV_MSG_ID_COREDUMP_GET_INFO_RESP);
384 	if (!fw_cmpl)
385 		return -ENOMEM;
386 
387 	err = fbnic_fw_xmit_coredump_info_msg(fbd, fw_cmpl, true);
388 	if (err) {
389 		NL_SET_ERR_MSG_MOD(extack,
390 				   "Failed to transmit core dump info msg");
391 		goto cmpl_free;
392 	}
393 	if (!wait_for_completion_timeout(&fw_cmpl->done, 2 * HZ)) {
394 		NL_SET_ERR_MSG_MOD(extack,
395 				   "Timed out waiting on core dump info");
396 		err = -ETIMEDOUT;
397 		goto cmpl_cleanup;
398 	}
399 
400 	size = fw_cmpl->u.coredump_info.size;
401 	err = fw_cmpl->result;
402 
403 	fbnic_mbx_clear_cmpl(fbd, fw_cmpl);
404 	fbnic_fw_put_cmpl(fw_cmpl);
405 
406 	/* Handle error returned by firmware */
407 	if (err) {
408 		NL_SET_ERR_MSG_MOD(extack, "Firmware core dump returned error");
409 		return err;
410 	}
411 	if (!size) {
412 		NL_SET_ERR_MSG_MOD(extack,
413 				   "Firmware core dump returned size 0");
414 		return -EIO;
415 	}
416 
417 	/* Read the dump, we can only transfer TLV_MAX_DATA at a time */
418 	index_count = DIV_ROUND_UP(size, TLV_MAX_DATA);
419 
420 	fw_cmpl = __fbnic_fw_alloc_cmpl(FBNIC_TLV_MSG_ID_COREDUMP_READ_RESP,
421 					sizeof(void *) * index_count + size);
422 	if (!fw_cmpl)
423 		return -ENOMEM;
424 
425 	/* Populate pointer table w/ pointer offsets */
426 	dump_data = (void *)&fw_cmpl->u.coredump.data[index_count];
427 	data = fw_cmpl->u.coredump.data;
428 	fw_cmpl->u.coredump.size = size;
429 	fw_cmpl->u.coredump.stride = TLV_MAX_DATA;
430 
431 	for (index = 0; index < index_count; index++) {
432 		/* First iteration installs completion */
433 		struct fbnic_fw_completion *cmpl_arg = index ? NULL : fw_cmpl;
434 
435 		offset = index * TLV_MAX_DATA;
436 		length = min(size - offset, TLV_MAX_DATA);
437 
438 		data[index] = dump_data + offset;
439 		err = fbnic_fw_xmit_coredump_read_msg(fbd, cmpl_arg,
440 						      offset, length);
441 		if (err) {
442 			NL_SET_ERR_MSG_MOD(extack,
443 					   "Failed to transmit core dump msg");
444 			if (cmpl_arg)
445 				goto cmpl_free;
446 			else
447 				goto cmpl_cleanup;
448 		}
449 
450 		if (wait_for_completion_timeout(&fw_cmpl->done, 2 * HZ)) {
451 			reinit_completion(&fw_cmpl->done);
452 		} else {
453 			NL_SET_ERR_MSG_FMT_MOD(extack,
454 					       "Timed out waiting on core dump (%d/%d)",
455 					       index + 1, index_count);
456 			err = -ETIMEDOUT;
457 			goto cmpl_cleanup;
458 		}
459 
460 		/* If we didn't see the reply record as incomplete */
461 		if (fw_cmpl->u.coredump.data[index]) {
462 			NL_SET_ERR_MSG_FMT_MOD(extack,
463 					       "No data for core dump chunk (%d/%d)",
464 					       index + 1, index_count);
465 			err = -EIO;
466 			goto cmpl_cleanup;
467 		}
468 	}
469 
470 	devlink_fmsg_binary_pair_nest_start(fmsg, "FW coredump");
471 
472 	for (offset = 0; offset < size; offset += length) {
473 		length = min_t(u32, size - offset, TLV_MAX_DATA);
474 
475 		devlink_fmsg_binary_put(fmsg, dump_data + offset, length);
476 	}
477 
478 	devlink_fmsg_binary_pair_nest_end(fmsg);
479 
480 cmpl_cleanup:
481 	fbnic_mbx_clear_cmpl(fbd, fw_cmpl);
482 cmpl_free:
483 	fbnic_fw_put_cmpl(fw_cmpl);
484 
485 	return err;
486 }
487 
488 static int
489 fbnic_fw_reporter_diagnose(struct devlink_health_reporter *reporter,
490 			   struct devlink_fmsg *fmsg,
491 			   struct netlink_ext_ack *extack)
492 {
493 	struct fbnic_dev *fbd = devlink_health_reporter_priv(reporter);
494 	u32 sec, msec;
495 
496 	/* Device is most likely down, we're not exchanging heartbeats */
497 	if (!fbd->prev_firmware_time)
498 		return 0;
499 
500 	sec = div_u64_rem(fbd->firmware_time, MSEC_PER_SEC, &msec);
501 
502 	devlink_fmsg_pair_nest_start(fmsg, "last_heartbeat");
503 	devlink_fmsg_obj_nest_start(fmsg);
504 	devlink_fmsg_pair_nest_start(fmsg, "fw_uptime");
505 	devlink_fmsg_obj_nest_start(fmsg);
506 	devlink_fmsg_u32_pair_put(fmsg, "sec", sec);
507 	devlink_fmsg_u32_pair_put(fmsg, "msec", msec);
508 	devlink_fmsg_obj_nest_end(fmsg);
509 	devlink_fmsg_pair_nest_end(fmsg);
510 	devlink_fmsg_obj_nest_end(fmsg);
511 	devlink_fmsg_pair_nest_end(fmsg);
512 
513 	return 0;
514 }
515 
516 void __printf(2, 3)
517 fbnic_devlink_fw_report(struct fbnic_dev *fbd, const char *format, ...)
518 {
519 	char msg[FBNIC_FW_LOG_MAX_SIZE];
520 	va_list args;
521 
522 	va_start(args, format);
523 	vsnprintf(msg, FBNIC_FW_LOG_MAX_SIZE, format, args);
524 	va_end(args);
525 
526 	devlink_health_report(fbd->fw_reporter, msg, fbd);
527 	if (fbnic_fw_log_ready(fbd))
528 		fbnic_fw_log_write(fbd, 0, fbd->firmware_time, msg);
529 }
530 
531 static const struct devlink_health_reporter_ops fbnic_fw_ops = {
532 	.name = "fw",
533 	.dump = fbnic_fw_reporter_dump,
534 	.diagnose = fbnic_fw_reporter_diagnose,
535 };
536 
537 static u32 fbnic_read_otp_status(struct fbnic_dev *fbd)
538 {
539 	return fbnic_fw_rd32(fbd, FBNIC_NS_OTP_STATUS);
540 }
541 
542 static int
543 fbnic_otp_reporter_dump(struct devlink_health_reporter *reporter,
544 			struct devlink_fmsg *fmsg, void *priv_ctx,
545 			struct netlink_ext_ack *extack)
546 {
547 	struct fbnic_dev *fbd = devlink_health_reporter_priv(reporter);
548 	u32 otp_status, otp_write_status, m;
549 
550 	otp_status = fbnic_read_otp_status(fbd);
551 	otp_write_status = fbnic_fw_rd32(fbd, FBNIC_NS_OTP_WRITE_STATUS);
552 
553 	/* Dump OTP status */
554 	devlink_fmsg_pair_nest_start(fmsg, "OTP");
555 	devlink_fmsg_obj_nest_start(fmsg);
556 
557 	devlink_fmsg_u32_pair_put(fmsg, "Status", otp_status);
558 
559 	/* Extract OTP Write Data status */
560 	m = FBNIC_NS_OTP_WRITE_DATA_STATUS_MASK;
561 	devlink_fmsg_u32_pair_put(fmsg, "Data",
562 				  FIELD_GET(m, otp_write_status));
563 
564 	/* Extract OTP Write ECC status */
565 	m = FBNIC_NS_OTP_WRITE_ECC_STATUS_MASK;
566 	devlink_fmsg_u32_pair_put(fmsg, "ECC",
567 				  FIELD_GET(m, otp_write_status));
568 
569 	devlink_fmsg_obj_nest_end(fmsg);
570 	devlink_fmsg_pair_nest_end(fmsg);
571 
572 	return 0;
573 }
574 
575 void fbnic_devlink_otp_check(struct fbnic_dev *fbd, const char *msg)
576 {
577 	/* Check if there is anything to report */
578 	if (!fbnic_read_otp_status(fbd))
579 		return;
580 
581 	devlink_health_report(fbd->otp_reporter, msg, fbd);
582 	if (fbnic_fw_log_ready(fbd))
583 		fbnic_fw_log_write(fbd, 0, fbd->firmware_time, msg);
584 }
585 
586 static const struct devlink_health_reporter_ops fbnic_otp_ops = {
587 	.name = "otp",
588 	.dump = fbnic_otp_reporter_dump,
589 };
590 
591 int fbnic_devlink_health_create(struct fbnic_dev *fbd)
592 {
593 	fbd->fw_reporter = devlink_health_reporter_create(priv_to_devlink(fbd),
594 							  &fbnic_fw_ops, fbd);
595 	if (IS_ERR(fbd->fw_reporter)) {
596 		dev_warn(fbd->dev,
597 			 "Failed to create FW fault reporter: %pe\n",
598 			 fbd->fw_reporter);
599 		return PTR_ERR(fbd->fw_reporter);
600 	}
601 
602 	fbd->otp_reporter = devlink_health_reporter_create(priv_to_devlink(fbd),
603 							   &fbnic_otp_ops, fbd);
604 	if (IS_ERR(fbd->otp_reporter)) {
605 		devlink_health_reporter_destroy(fbd->fw_reporter);
606 		dev_warn(fbd->dev,
607 			 "Failed to create OTP fault reporter: %pe\n",
608 			 fbd->otp_reporter);
609 		return PTR_ERR(fbd->otp_reporter);
610 	}
611 
612 	return 0;
613 }
614 
615 void fbnic_devlink_health_destroy(struct fbnic_dev *fbd)
616 {
617 	devlink_health_reporter_destroy(fbd->otp_reporter);
618 	devlink_health_reporter_destroy(fbd->fw_reporter);
619 }
620 
621 void fbnic_devlink_free(struct fbnic_dev *fbd)
622 {
623 	struct devlink *devlink = priv_to_devlink(fbd);
624 
625 	devlink_free(devlink);
626 }
627 
628 struct fbnic_dev *fbnic_devlink_alloc(struct pci_dev *pdev)
629 {
630 	void __iomem * const *iomap_table;
631 	struct devlink *devlink;
632 	struct fbnic_dev *fbd;
633 
634 	devlink = devlink_alloc(&fbnic_devlink_ops, sizeof(struct fbnic_dev),
635 				&pdev->dev);
636 	if (!devlink)
637 		return NULL;
638 
639 	fbd = devlink_priv(devlink);
640 	pci_set_drvdata(pdev, fbd);
641 	fbd->dev = &pdev->dev;
642 
643 	iomap_table = pcim_iomap_table(pdev);
644 	fbd->uc_addr0 = iomap_table[0];
645 	fbd->uc_addr4 = iomap_table[4];
646 
647 	fbd->dsn = pci_get_dsn(pdev);
648 	fbd->mps = pcie_get_mps(pdev);
649 	fbd->readrq = pcie_get_readrq(pdev);
650 
651 	fbd->mac_addr_boundary = FBNIC_RPC_TCAM_MACDA_DEFAULT_BOUNDARY;
652 
653 	return fbd;
654 }
655 
656 void fbnic_devlink_register(struct fbnic_dev *fbd)
657 {
658 	struct devlink *devlink = priv_to_devlink(fbd);
659 
660 	devlink_register(devlink);
661 }
662 
663 void fbnic_devlink_unregister(struct fbnic_dev *fbd)
664 {
665 	struct devlink *devlink = priv_to_devlink(fbd);
666 
667 	devlink_unregister(devlink);
668 }
669