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_tlv.h"
12
13 #define FBNIC_SN_STR_LEN 24
14
fbnic_version_running_put(struct devlink_info_req * req,struct fbnic_fw_ver * fw_ver,char * ver_name)15 static int fbnic_version_running_put(struct devlink_info_req *req,
16 struct fbnic_fw_ver *fw_ver,
17 char *ver_name)
18 {
19 char running_ver[FBNIC_FW_VER_MAX_SIZE];
20 int err;
21
22 fbnic_mk_fw_ver_str(fw_ver->version, running_ver);
23 err = devlink_info_version_running_put(req, ver_name, running_ver);
24 if (err)
25 return err;
26
27 if (strlen(fw_ver->commit) > 0) {
28 char commit_name[FBNIC_SN_STR_LEN];
29
30 snprintf(commit_name, FBNIC_SN_STR_LEN, "%s.commit", ver_name);
31 err = devlink_info_version_running_put(req, commit_name,
32 fw_ver->commit);
33 if (err)
34 return err;
35 }
36
37 return 0;
38 }
39
fbnic_version_stored_put(struct devlink_info_req * req,struct fbnic_fw_ver * fw_ver,char * ver_name)40 static int fbnic_version_stored_put(struct devlink_info_req *req,
41 struct fbnic_fw_ver *fw_ver,
42 char *ver_name)
43 {
44 char stored_ver[FBNIC_FW_VER_MAX_SIZE];
45 int err;
46
47 fbnic_mk_fw_ver_str(fw_ver->version, stored_ver);
48 err = devlink_info_version_stored_put(req, ver_name, stored_ver);
49 if (err)
50 return err;
51
52 if (strlen(fw_ver->commit) > 0) {
53 char commit_name[FBNIC_SN_STR_LEN];
54
55 snprintf(commit_name, FBNIC_SN_STR_LEN, "%s.commit", ver_name);
56 err = devlink_info_version_stored_put(req, commit_name,
57 fw_ver->commit);
58 if (err)
59 return err;
60 }
61
62 return 0;
63 }
64
fbnic_devlink_info_get(struct devlink * devlink,struct devlink_info_req * req,struct netlink_ext_ack * extack)65 static int fbnic_devlink_info_get(struct devlink *devlink,
66 struct devlink_info_req *req,
67 struct netlink_ext_ack *extack)
68 {
69 struct fbnic_dev *fbd = devlink_priv(devlink);
70 int err;
71
72 err = fbnic_version_running_put(req, &fbd->fw_cap.running.mgmt,
73 DEVLINK_INFO_VERSION_GENERIC_FW);
74 if (err)
75 return err;
76
77 err = fbnic_version_running_put(req, &fbd->fw_cap.running.bootloader,
78 DEVLINK_INFO_VERSION_GENERIC_FW_BOOTLOADER);
79 if (err)
80 return err;
81
82 err = fbnic_version_stored_put(req, &fbd->fw_cap.stored.mgmt,
83 DEVLINK_INFO_VERSION_GENERIC_FW);
84 if (err)
85 return err;
86
87 err = fbnic_version_stored_put(req, &fbd->fw_cap.stored.bootloader,
88 DEVLINK_INFO_VERSION_GENERIC_FW_BOOTLOADER);
89 if (err)
90 return err;
91
92 err = fbnic_version_stored_put(req, &fbd->fw_cap.stored.undi,
93 DEVLINK_INFO_VERSION_GENERIC_FW_UNDI);
94 if (err)
95 return err;
96
97 if (fbd->dsn) {
98 unsigned char serial[FBNIC_SN_STR_LEN];
99 u8 dsn[8];
100
101 put_unaligned_be64(fbd->dsn, dsn);
102 err = snprintf(serial, FBNIC_SN_STR_LEN, "%8phD", dsn);
103 if (err < 0)
104 return err;
105
106 err = devlink_info_serial_number_put(req, serial);
107 if (err)
108 return err;
109 }
110
111 return 0;
112 }
113
114 static bool
fbnic_pldm_match_record(struct pldmfw * context,struct pldmfw_record * record)115 fbnic_pldm_match_record(struct pldmfw *context, struct pldmfw_record *record)
116 {
117 struct pldmfw_desc_tlv *desc;
118 u32 anti_rollback_ver = 0;
119 struct devlink *devlink;
120 struct fbnic_dev *fbd;
121 struct pci_dev *pdev;
122
123 /* First, use the standard PCI matching function */
124 if (!pldmfw_op_pci_match_record(context, record))
125 return false;
126
127 pdev = to_pci_dev(context->dev);
128 fbd = pci_get_drvdata(pdev);
129 devlink = priv_to_devlink(fbd);
130
131 /* If PCI match is successful, check for vendor-specific descriptors */
132 list_for_each_entry(desc, &record->descs, entry) {
133 if (desc->type != PLDM_DESC_ID_VENDOR_DEFINED)
134 continue;
135
136 if (desc->size < 21 || desc->data[0] != 1 ||
137 desc->data[1] != 15)
138 continue;
139
140 if (memcmp(desc->data + 2, "AntiRollbackVer", 15) != 0)
141 continue;
142
143 anti_rollback_ver = get_unaligned_le32(desc->data + 17);
144 break;
145 }
146
147 /* Compare versions and return error if they do not match */
148 if (anti_rollback_ver < fbd->fw_cap.anti_rollback_version) {
149 char buf[128];
150
151 snprintf(buf, sizeof(buf),
152 "New firmware anti-rollback version (0x%x) is older than device version (0x%x)!",
153 anti_rollback_ver, fbd->fw_cap.anti_rollback_version);
154 devlink_flash_update_status_notify(devlink, buf,
155 "Anti-Rollback", 0, 0);
156
157 return false;
158 }
159
160 return true;
161 }
162
163 static int
fbnic_flash_start(struct fbnic_dev * fbd,struct pldmfw_component * component)164 fbnic_flash_start(struct fbnic_dev *fbd, struct pldmfw_component *component)
165 {
166 struct fbnic_fw_completion *cmpl;
167 int err;
168
169 cmpl = fbnic_fw_alloc_cmpl(FBNIC_TLV_MSG_ID_FW_START_UPGRADE_REQ);
170 if (!cmpl)
171 return -ENOMEM;
172
173 err = fbnic_fw_xmit_fw_start_upgrade(fbd, cmpl,
174 component->identifier,
175 component->component_size);
176 if (err)
177 goto cmpl_free;
178
179 /* Wait for firmware to ack firmware upgrade start */
180 if (wait_for_completion_timeout(&cmpl->done, 10 * HZ))
181 err = cmpl->result;
182 else
183 err = -ETIMEDOUT;
184
185 fbnic_mbx_clear_cmpl(fbd, cmpl);
186 cmpl_free:
187 fbnic_fw_put_cmpl(cmpl);
188
189 return err;
190 }
191
192 static int
fbnic_flash_component(struct pldmfw * context,struct pldmfw_component * component)193 fbnic_flash_component(struct pldmfw *context,
194 struct pldmfw_component *component)
195 {
196 const u8 *data = component->component_data;
197 const u32 size = component->component_size;
198 struct fbnic_fw_completion *cmpl;
199 const char *component_name;
200 struct devlink *devlink;
201 struct fbnic_dev *fbd;
202 struct pci_dev *pdev;
203 u32 offset = 0;
204 u32 length = 0;
205 char buf[32];
206 int err;
207
208 pdev = to_pci_dev(context->dev);
209 fbd = pci_get_drvdata(pdev);
210 devlink = priv_to_devlink(fbd);
211
212 switch (component->identifier) {
213 case QSPI_SECTION_CMRT:
214 component_name = "boot1";
215 break;
216 case QSPI_SECTION_CONTROL_FW:
217 component_name = "boot2";
218 break;
219 case QSPI_SECTION_OPTION_ROM:
220 component_name = "option-rom";
221 break;
222 default:
223 snprintf(buf, sizeof(buf), "Unknown component ID %u!",
224 component->identifier);
225 devlink_flash_update_status_notify(devlink, buf, NULL, 0,
226 size);
227 return -EINVAL;
228 }
229
230 /* Once firmware receives the request to start upgrading it responds
231 * with two messages:
232 * 1. An ACK that it received the message and possible error code
233 * indicating that an upgrade is not currently possible.
234 * 2. A request for the first chunk of data
235 *
236 * Setup completions for write before issuing the start message so
237 * the driver can catch both messages.
238 */
239 cmpl = fbnic_fw_alloc_cmpl(FBNIC_TLV_MSG_ID_FW_WRITE_CHUNK_REQ);
240 if (!cmpl)
241 return -ENOMEM;
242
243 err = fbnic_mbx_set_cmpl(fbd, cmpl);
244 if (err)
245 goto cmpl_free;
246
247 devlink_flash_update_timeout_notify(devlink, "Initializing",
248 component_name, 15);
249 err = fbnic_flash_start(fbd, component);
250 if (err)
251 goto err_no_msg;
252
253 while (offset < size) {
254 if (!wait_for_completion_timeout(&cmpl->done, 15 * HZ)) {
255 err = -ETIMEDOUT;
256 break;
257 }
258
259 err = cmpl->result;
260 if (err)
261 break;
262
263 /* Verify firmware is requesting the next chunk in the seq. */
264 if (cmpl->u.fw_update.offset != offset + length) {
265 err = -EFAULT;
266 break;
267 }
268
269 offset = cmpl->u.fw_update.offset;
270 length = cmpl->u.fw_update.length;
271
272 if (length > TLV_MAX_DATA || offset + length > size) {
273 err = -EFAULT;
274 break;
275 }
276
277 devlink_flash_update_status_notify(devlink, "Flashing",
278 component_name,
279 offset, size);
280
281 /* Mailbox will set length to 0 once it receives the finish
282 * message.
283 */
284 if (!length)
285 continue;
286
287 reinit_completion(&cmpl->done);
288 err = fbnic_fw_xmit_fw_write_chunk(fbd, data, offset, length,
289 0);
290 if (err)
291 break;
292 }
293
294 if (err) {
295 fbnic_fw_xmit_fw_write_chunk(fbd, NULL, 0, 0, err);
296 err_no_msg:
297 snprintf(buf, sizeof(buf), "Mailbox encountered error %d!",
298 err);
299 devlink_flash_update_status_notify(devlink, buf,
300 component_name, 0, 0);
301 }
302
303 fbnic_mbx_clear_cmpl(fbd, cmpl);
304 cmpl_free:
305 fbnic_fw_put_cmpl(cmpl);
306
307 return err;
308 }
309
310 static const struct pldmfw_ops fbnic_pldmfw_ops = {
311 .match_record = fbnic_pldm_match_record,
312 .flash_component = fbnic_flash_component,
313 };
314
315 static int
fbnic_devlink_flash_update(struct devlink * devlink,struct devlink_flash_update_params * params,struct netlink_ext_ack * extack)316 fbnic_devlink_flash_update(struct devlink *devlink,
317 struct devlink_flash_update_params *params,
318 struct netlink_ext_ack *extack)
319 {
320 struct fbnic_dev *fbd = devlink_priv(devlink);
321 const struct firmware *fw = params->fw;
322 struct device *dev = fbd->dev;
323 struct pldmfw context;
324 char *err_msg;
325 int err;
326
327 context.ops = &fbnic_pldmfw_ops;
328 context.dev = dev;
329
330 err = pldmfw_flash_image(&context, fw);
331 if (err) {
332 switch (err) {
333 case -EINVAL:
334 err_msg = "Invalid image";
335 break;
336 case -EOPNOTSUPP:
337 err_msg = "Unsupported image";
338 break;
339 case -ENOMEM:
340 err_msg = "Out of memory";
341 break;
342 case -EFAULT:
343 err_msg = "Invalid header";
344 break;
345 case -ENOENT:
346 err_msg = "No matching record";
347 break;
348 case -ENODEV:
349 err_msg = "No matching device";
350 break;
351 case -ETIMEDOUT:
352 err_msg = "Timed out waiting for reply";
353 break;
354 default:
355 err_msg = "Unknown error";
356 break;
357 }
358
359 NL_SET_ERR_MSG_FMT_MOD(extack,
360 "Failed to flash PLDM Image: %s (error: %d)",
361 err_msg, err);
362 }
363
364 return err;
365 }
366
367 static const struct devlink_ops fbnic_devlink_ops = {
368 .info_get = fbnic_devlink_info_get,
369 .flash_update = fbnic_devlink_flash_update,
370 };
371
fbnic_devlink_free(struct fbnic_dev * fbd)372 void fbnic_devlink_free(struct fbnic_dev *fbd)
373 {
374 struct devlink *devlink = priv_to_devlink(fbd);
375
376 devlink_free(devlink);
377 }
378
fbnic_devlink_alloc(struct pci_dev * pdev)379 struct fbnic_dev *fbnic_devlink_alloc(struct pci_dev *pdev)
380 {
381 void __iomem * const *iomap_table;
382 struct devlink *devlink;
383 struct fbnic_dev *fbd;
384
385 devlink = devlink_alloc(&fbnic_devlink_ops, sizeof(struct fbnic_dev),
386 &pdev->dev);
387 if (!devlink)
388 return NULL;
389
390 fbd = devlink_priv(devlink);
391 pci_set_drvdata(pdev, fbd);
392 fbd->dev = &pdev->dev;
393
394 iomap_table = pcim_iomap_table(pdev);
395 fbd->uc_addr0 = iomap_table[0];
396 fbd->uc_addr4 = iomap_table[4];
397
398 fbd->dsn = pci_get_dsn(pdev);
399 fbd->mps = pcie_get_mps(pdev);
400 fbd->readrq = pcie_get_readrq(pdev);
401
402 fbd->mac_addr_boundary = FBNIC_RPC_TCAM_MACDA_DEFAULT_BOUNDARY;
403
404 return fbd;
405 }
406
fbnic_devlink_register(struct fbnic_dev * fbd)407 void fbnic_devlink_register(struct fbnic_dev *fbd)
408 {
409 struct devlink *devlink = priv_to_devlink(fbd);
410
411 devlink_register(devlink);
412 }
413
fbnic_devlink_unregister(struct fbnic_dev * fbd)414 void fbnic_devlink_unregister(struct fbnic_dev *fbd)
415 {
416 struct devlink *devlink = priv_to_devlink(fbd);
417
418 devlink_unregister(devlink);
419 }
420