xref: /linux/drivers/net/ethernet/meta/fbnic/fbnic_devlink.c (revision 566ab427f827b0256d3e8ce0235d088e6a9c28bd)
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/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_version_running_put(struct devlink_info_req *req,
14 				     struct fbnic_fw_ver *fw_ver,
15 				     char *ver_name)
16 {
17 	char running_ver[FBNIC_FW_VER_MAX_SIZE];
18 	int err;
19 
20 	fbnic_mk_fw_ver_str(fw_ver->version, running_ver);
21 	err = devlink_info_version_running_put(req, ver_name, running_ver);
22 	if (err)
23 		return err;
24 
25 	if (strlen(fw_ver->commit) > 0) {
26 		char commit_name[FBNIC_SN_STR_LEN];
27 
28 		snprintf(commit_name, FBNIC_SN_STR_LEN, "%s.commit", ver_name);
29 		err = devlink_info_version_running_put(req, commit_name,
30 						       fw_ver->commit);
31 		if (err)
32 			return err;
33 	}
34 
35 	return 0;
36 }
37 
38 static int fbnic_version_stored_put(struct devlink_info_req *req,
39 				    struct fbnic_fw_ver *fw_ver,
40 				    char *ver_name)
41 {
42 	char stored_ver[FBNIC_FW_VER_MAX_SIZE];
43 	int err;
44 
45 	fbnic_mk_fw_ver_str(fw_ver->version, stored_ver);
46 	err = devlink_info_version_stored_put(req, ver_name, stored_ver);
47 	if (err)
48 		return err;
49 
50 	if (strlen(fw_ver->commit) > 0) {
51 		char commit_name[FBNIC_SN_STR_LEN];
52 
53 		snprintf(commit_name, FBNIC_SN_STR_LEN, "%s.commit", ver_name);
54 		err = devlink_info_version_stored_put(req, commit_name,
55 						      fw_ver->commit);
56 		if (err)
57 			return err;
58 	}
59 
60 	return 0;
61 }
62 
63 static int fbnic_devlink_info_get(struct devlink *devlink,
64 				  struct devlink_info_req *req,
65 				  struct netlink_ext_ack *extack)
66 {
67 	struct fbnic_dev *fbd = devlink_priv(devlink);
68 	int err;
69 
70 	err = fbnic_version_running_put(req, &fbd->fw_cap.running.mgmt,
71 					DEVLINK_INFO_VERSION_GENERIC_FW);
72 	if (err)
73 		return err;
74 
75 	err = fbnic_version_running_put(req, &fbd->fw_cap.running.bootloader,
76 					DEVLINK_INFO_VERSION_GENERIC_FW_BOOTLOADER);
77 	if (err)
78 		return err;
79 
80 	err = fbnic_version_stored_put(req, &fbd->fw_cap.stored.mgmt,
81 				       DEVLINK_INFO_VERSION_GENERIC_FW);
82 	if (err)
83 		return err;
84 
85 	err = fbnic_version_stored_put(req, &fbd->fw_cap.stored.bootloader,
86 				       DEVLINK_INFO_VERSION_GENERIC_FW_BOOTLOADER);
87 	if (err)
88 		return err;
89 
90 	err = fbnic_version_stored_put(req, &fbd->fw_cap.stored.undi,
91 				       DEVLINK_INFO_VERSION_GENERIC_FW_UNDI);
92 	if (err)
93 		return err;
94 
95 	if (fbd->dsn) {
96 		unsigned char serial[FBNIC_SN_STR_LEN];
97 		u8 dsn[8];
98 
99 		put_unaligned_be64(fbd->dsn, dsn);
100 		err = snprintf(serial, FBNIC_SN_STR_LEN, "%8phD", dsn);
101 		if (err < 0)
102 			return err;
103 
104 		err = devlink_info_serial_number_put(req, serial);
105 		if (err)
106 			return err;
107 	}
108 
109 	return 0;
110 }
111 
112 static const struct devlink_ops fbnic_devlink_ops = {
113 	.info_get = fbnic_devlink_info_get,
114 };
115 
116 void fbnic_devlink_free(struct fbnic_dev *fbd)
117 {
118 	struct devlink *devlink = priv_to_devlink(fbd);
119 
120 	devlink_free(devlink);
121 }
122 
123 struct fbnic_dev *fbnic_devlink_alloc(struct pci_dev *pdev)
124 {
125 	void __iomem * const *iomap_table;
126 	struct devlink *devlink;
127 	struct fbnic_dev *fbd;
128 
129 	devlink = devlink_alloc(&fbnic_devlink_ops, sizeof(struct fbnic_dev),
130 				&pdev->dev);
131 	if (!devlink)
132 		return NULL;
133 
134 	fbd = devlink_priv(devlink);
135 	pci_set_drvdata(pdev, fbd);
136 	fbd->dev = &pdev->dev;
137 
138 	iomap_table = pcim_iomap_table(pdev);
139 	fbd->uc_addr0 = iomap_table[0];
140 	fbd->uc_addr4 = iomap_table[4];
141 
142 	fbd->dsn = pci_get_dsn(pdev);
143 	fbd->mps = pcie_get_mps(pdev);
144 	fbd->readrq = pcie_get_readrq(pdev);
145 
146 	fbd->mac_addr_boundary = FBNIC_RPC_TCAM_MACDA_DEFAULT_BOUNDARY;
147 
148 	return fbd;
149 }
150 
151 void fbnic_devlink_register(struct fbnic_dev *fbd)
152 {
153 	struct devlink *devlink = priv_to_devlink(fbd);
154 
155 	devlink_register(devlink);
156 }
157 
158 void fbnic_devlink_unregister(struct fbnic_dev *fbd)
159 {
160 	struct devlink *devlink = priv_to_devlink(fbd);
161 
162 	devlink_unregister(devlink);
163 }
164