xref: /linux/drivers/net/ethernet/meta/fbnic/fbnic_devlink.c (revision fa8a4d3659d0c1ad73d5f59b2e0a6d408de5b317)
1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright (c) Meta Platforms, Inc. and affiliates. */
3 
4 #include <asm/unaligned.h>
5 #include <linux/pci.h>
6 #include <linux/types.h>
7 #include <net/devlink.h>
8 
9 #include "fbnic.h"
10 
11 #define FBNIC_SN_STR_LEN	24
12 
13 static int fbnic_devlink_info_get(struct devlink *devlink,
14 				  struct devlink_info_req *req,
15 				  struct netlink_ext_ack *extack)
16 {
17 	struct fbnic_dev *fbd = devlink_priv(devlink);
18 	int err;
19 
20 	if (fbd->dsn) {
21 		unsigned char serial[FBNIC_SN_STR_LEN];
22 		u8 dsn[8];
23 
24 		put_unaligned_be64(fbd->dsn, dsn);
25 		err = snprintf(serial, FBNIC_SN_STR_LEN, "%8phD", dsn);
26 		if (err < 0)
27 			return err;
28 
29 		err = devlink_info_serial_number_put(req, serial);
30 		if (err)
31 			return err;
32 	}
33 
34 	return 0;
35 }
36 
37 static const struct devlink_ops fbnic_devlink_ops = {
38 	.info_get = fbnic_devlink_info_get,
39 };
40 
41 void fbnic_devlink_free(struct fbnic_dev *fbd)
42 {
43 	struct devlink *devlink = priv_to_devlink(fbd);
44 
45 	devlink_free(devlink);
46 }
47 
48 struct fbnic_dev *fbnic_devlink_alloc(struct pci_dev *pdev)
49 {
50 	void __iomem * const *iomap_table;
51 	struct devlink *devlink;
52 	struct fbnic_dev *fbd;
53 
54 	devlink = devlink_alloc(&fbnic_devlink_ops, sizeof(struct fbnic_dev),
55 				&pdev->dev);
56 	if (!devlink)
57 		return NULL;
58 
59 	fbd = devlink_priv(devlink);
60 	pci_set_drvdata(pdev, fbd);
61 	fbd->dev = &pdev->dev;
62 
63 	iomap_table = pcim_iomap_table(pdev);
64 	fbd->uc_addr0 = iomap_table[0];
65 	fbd->uc_addr4 = iomap_table[4];
66 
67 	fbd->dsn = pci_get_dsn(pdev);
68 	fbd->mps = pcie_get_mps(pdev);
69 	fbd->readrq = pcie_get_readrq(pdev);
70 
71 	fbd->mac_addr_boundary = FBNIC_RPC_TCAM_MACDA_DEFAULT_BOUNDARY;
72 
73 	return fbd;
74 }
75 
76 void fbnic_devlink_register(struct fbnic_dev *fbd)
77 {
78 	struct devlink *devlink = priv_to_devlink(fbd);
79 
80 	devlink_register(devlink);
81 }
82 
83 void fbnic_devlink_unregister(struct fbnic_dev *fbd)
84 {
85 	struct devlink *devlink = priv_to_devlink(fbd);
86 
87 	devlink_unregister(devlink);
88 }
89