.. | .. |
---|
1 | | -/* |
---|
2 | | - * Copyright (C) 2015-2017 Netronome Systems, Inc. |
---|
3 | | - * |
---|
4 | | - * This software is dual licensed under the GNU General License Version 2, |
---|
5 | | - * June 1991 as shown in the file COPYING in the top-level directory of this |
---|
6 | | - * source tree or the BSD 2-Clause License provided below. You have the |
---|
7 | | - * option to license this software under the complete terms of either license. |
---|
8 | | - * |
---|
9 | | - * The BSD 2-Clause License: |
---|
10 | | - * |
---|
11 | | - * Redistribution and use in source and binary forms, with or |
---|
12 | | - * without modification, are permitted provided that the following |
---|
13 | | - * conditions are met: |
---|
14 | | - * |
---|
15 | | - * 1. Redistributions of source code must retain the above |
---|
16 | | - * copyright notice, this list of conditions and the following |
---|
17 | | - * disclaimer. |
---|
18 | | - * |
---|
19 | | - * 2. Redistributions in binary form must reproduce the above |
---|
20 | | - * copyright notice, this list of conditions and the following |
---|
21 | | - * disclaimer in the documentation and/or other materials |
---|
22 | | - * provided with the distribution. |
---|
23 | | - * |
---|
24 | | - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
---|
25 | | - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
---|
26 | | - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
---|
27 | | - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS |
---|
28 | | - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN |
---|
29 | | - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN |
---|
30 | | - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
---|
31 | | - * SOFTWARE. |
---|
32 | | - */ |
---|
| 1 | +// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) |
---|
| 2 | +/* Copyright (C) 2015-2018 Netronome Systems, Inc. */ |
---|
33 | 3 | |
---|
34 | 4 | /* |
---|
35 | 5 | * nfp_main.c |
---|
.. | .. |
---|
44 | 14 | #include <linux/mutex.h> |
---|
45 | 15 | #include <linux/pci.h> |
---|
46 | 16 | #include <linux/firmware.h> |
---|
47 | | -#include <linux/vermagic.h> |
---|
48 | 17 | #include <linux/vmalloc.h> |
---|
49 | 18 | #include <net/devlink.h> |
---|
50 | 19 | |
---|
.. | .. |
---|
61 | 30 | #include "nfp_net.h" |
---|
62 | 31 | |
---|
63 | 32 | static const char nfp_driver_name[] = "nfp"; |
---|
64 | | -const char nfp_driver_version[] = VERMAGIC_STRING; |
---|
65 | 33 | |
---|
66 | 34 | static const struct pci_device_id nfp_pci_device_ids[] = { |
---|
67 | 35 | { PCI_VENDOR_ID_NETRONOME, PCI_DEVICE_ID_NETRONOME_NFP6000, |
---|
| 36 | + PCI_VENDOR_ID_NETRONOME, PCI_ANY_ID, |
---|
| 37 | + PCI_ANY_ID, 0, |
---|
| 38 | + }, |
---|
| 39 | + { PCI_VENDOR_ID_NETRONOME, PCI_DEVICE_ID_NETRONOME_NFP5000, |
---|
68 | 40 | PCI_VENDOR_ID_NETRONOME, PCI_ANY_ID, |
---|
69 | 41 | PCI_ANY_ID, 0, |
---|
70 | 42 | }, |
---|
.. | .. |
---|
112 | 84 | int nfp_mbox_cmd(struct nfp_pf *pf, u32 cmd, void *in_data, u64 in_length, |
---|
113 | 85 | void *out_data, u64 out_length) |
---|
114 | 86 | { |
---|
115 | | - unsigned long long addr; |
---|
116 | 87 | unsigned long err_at; |
---|
117 | 88 | u64 max_data_sz; |
---|
118 | 89 | u32 val = 0; |
---|
119 | | - u32 cpp_id; |
---|
120 | 90 | int n, err; |
---|
121 | 91 | |
---|
122 | 92 | if (!pf->mbox) |
---|
123 | 93 | return -EOPNOTSUPP; |
---|
124 | 94 | |
---|
125 | | - cpp_id = NFP_CPP_ISLAND_ID(pf->mbox->target, NFP_CPP_ACTION_RW, 0, |
---|
126 | | - pf->mbox->domain); |
---|
127 | | - addr = pf->mbox->addr; |
---|
128 | | - max_data_sz = pf->mbox->size - NFP_MBOX_SYM_MIN_SIZE; |
---|
| 95 | + max_data_sz = nfp_rtsym_size(pf->mbox) - NFP_MBOX_SYM_MIN_SIZE; |
---|
129 | 96 | |
---|
130 | 97 | /* Check if cmd field is clear */ |
---|
131 | | - err = nfp_cpp_readl(pf->cpp, cpp_id, addr + NFP_MBOX_CMD, &val); |
---|
| 98 | + err = nfp_rtsym_readl(pf->cpp, pf->mbox, NFP_MBOX_CMD, &val); |
---|
132 | 99 | if (err || val) { |
---|
133 | 100 | nfp_warn(pf->cpp, "failed to issue command (%u): %u, err: %d\n", |
---|
134 | 101 | cmd, val, err); |
---|
.. | .. |
---|
136 | 103 | } |
---|
137 | 104 | |
---|
138 | 105 | in_length = min(in_length, max_data_sz); |
---|
139 | | - n = nfp_cpp_write(pf->cpp, cpp_id, addr + NFP_MBOX_DATA, |
---|
140 | | - in_data, in_length); |
---|
| 106 | + n = nfp_rtsym_write(pf->cpp, pf->mbox, NFP_MBOX_DATA, in_data, |
---|
| 107 | + in_length); |
---|
141 | 108 | if (n != in_length) |
---|
142 | 109 | return -EIO; |
---|
143 | 110 | /* Write data_len and wipe reserved */ |
---|
144 | | - err = nfp_cpp_writeq(pf->cpp, cpp_id, addr + NFP_MBOX_DATA_LEN, |
---|
145 | | - in_length); |
---|
| 111 | + err = nfp_rtsym_writeq(pf->cpp, pf->mbox, NFP_MBOX_DATA_LEN, in_length); |
---|
146 | 112 | if (err) |
---|
147 | 113 | return err; |
---|
148 | 114 | |
---|
149 | 115 | /* Read back for ordering */ |
---|
150 | | - err = nfp_cpp_readl(pf->cpp, cpp_id, addr + NFP_MBOX_DATA_LEN, &val); |
---|
| 116 | + err = nfp_rtsym_readl(pf->cpp, pf->mbox, NFP_MBOX_DATA_LEN, &val); |
---|
151 | 117 | if (err) |
---|
152 | 118 | return err; |
---|
153 | 119 | |
---|
154 | 120 | /* Write cmd and wipe return value */ |
---|
155 | | - err = nfp_cpp_writeq(pf->cpp, cpp_id, addr + NFP_MBOX_CMD, cmd); |
---|
| 121 | + err = nfp_rtsym_writeq(pf->cpp, pf->mbox, NFP_MBOX_CMD, cmd); |
---|
156 | 122 | if (err) |
---|
157 | 123 | return err; |
---|
158 | 124 | |
---|
159 | 125 | err_at = jiffies + 5 * HZ; |
---|
160 | 126 | while (true) { |
---|
161 | 127 | /* Wait for command to go to 0 (NFP_MBOX_NO_CMD) */ |
---|
162 | | - err = nfp_cpp_readl(pf->cpp, cpp_id, addr + NFP_MBOX_CMD, &val); |
---|
| 128 | + err = nfp_rtsym_readl(pf->cpp, pf->mbox, NFP_MBOX_CMD, &val); |
---|
163 | 129 | if (err) |
---|
164 | 130 | return err; |
---|
165 | 131 | if (!val) |
---|
.. | .. |
---|
172 | 138 | } |
---|
173 | 139 | |
---|
174 | 140 | /* Copy output if any (could be error info, do it before reading ret) */ |
---|
175 | | - err = nfp_cpp_readl(pf->cpp, cpp_id, addr + NFP_MBOX_DATA_LEN, &val); |
---|
| 141 | + err = nfp_rtsym_readl(pf->cpp, pf->mbox, NFP_MBOX_DATA_LEN, &val); |
---|
176 | 142 | if (err) |
---|
177 | 143 | return err; |
---|
178 | 144 | |
---|
179 | 145 | out_length = min_t(u32, val, min(out_length, max_data_sz)); |
---|
180 | | - n = nfp_cpp_read(pf->cpp, cpp_id, addr + NFP_MBOX_DATA, |
---|
181 | | - out_data, out_length); |
---|
| 146 | + n = nfp_rtsym_read(pf->cpp, pf->mbox, NFP_MBOX_DATA, |
---|
| 147 | + out_data, out_length); |
---|
182 | 148 | if (n != out_length) |
---|
183 | 149 | return -EIO; |
---|
184 | 150 | |
---|
185 | 151 | /* Check if there is an error */ |
---|
186 | | - err = nfp_cpp_readl(pf->cpp, cpp_id, addr + NFP_MBOX_RET, &val); |
---|
| 152 | + err = nfp_rtsym_readl(pf->cpp, pf->mbox, NFP_MBOX_RET, &val); |
---|
187 | 153 | if (err) |
---|
188 | 154 | return err; |
---|
189 | 155 | if (val) |
---|
.. | .. |
---|
326 | 292 | |
---|
327 | 293 | static int nfp_pcie_sriov_configure(struct pci_dev *pdev, int num_vfs) |
---|
328 | 294 | { |
---|
| 295 | + if (!pci_get_drvdata(pdev)) |
---|
| 296 | + return -ENOENT; |
---|
| 297 | + |
---|
329 | 298 | if (num_vfs == 0) |
---|
330 | 299 | return nfp_pcie_sriov_disable(pdev); |
---|
331 | 300 | else |
---|
332 | 301 | return nfp_pcie_sriov_enable(pdev, num_vfs); |
---|
| 302 | +} |
---|
| 303 | + |
---|
| 304 | +int nfp_flash_update_common(struct nfp_pf *pf, const char *path, |
---|
| 305 | + struct netlink_ext_ack *extack) |
---|
| 306 | +{ |
---|
| 307 | + struct device *dev = &pf->pdev->dev; |
---|
| 308 | + const struct firmware *fw; |
---|
| 309 | + struct nfp_nsp *nsp; |
---|
| 310 | + int err; |
---|
| 311 | + |
---|
| 312 | + nsp = nfp_nsp_open(pf->cpp); |
---|
| 313 | + if (IS_ERR(nsp)) { |
---|
| 314 | + err = PTR_ERR(nsp); |
---|
| 315 | + if (extack) |
---|
| 316 | + NL_SET_ERR_MSG_MOD(extack, "can't access NSP"); |
---|
| 317 | + else |
---|
| 318 | + dev_err(dev, "Failed to access the NSP: %d\n", err); |
---|
| 319 | + return err; |
---|
| 320 | + } |
---|
| 321 | + |
---|
| 322 | + err = request_firmware_direct(&fw, path, dev); |
---|
| 323 | + if (err) { |
---|
| 324 | + NL_SET_ERR_MSG_MOD(extack, |
---|
| 325 | + "unable to read flash file from disk"); |
---|
| 326 | + goto exit_close_nsp; |
---|
| 327 | + } |
---|
| 328 | + |
---|
| 329 | + dev_info(dev, "Please be patient while writing flash image: %s\n", |
---|
| 330 | + path); |
---|
| 331 | + |
---|
| 332 | + err = nfp_nsp_write_flash(nsp, fw); |
---|
| 333 | + if (err < 0) |
---|
| 334 | + goto exit_release_fw; |
---|
| 335 | + dev_info(dev, "Finished writing flash image\n"); |
---|
| 336 | + err = 0; |
---|
| 337 | + |
---|
| 338 | +exit_release_fw: |
---|
| 339 | + release_firmware(fw); |
---|
| 340 | +exit_close_nsp: |
---|
| 341 | + nfp_nsp_close(nsp); |
---|
| 342 | + return err; |
---|
333 | 343 | } |
---|
334 | 344 | |
---|
335 | 345 | static const struct firmware * |
---|
.. | .. |
---|
340 | 350 | |
---|
341 | 351 | err = request_firmware_direct(&fw, name, &pdev->dev); |
---|
342 | 352 | nfp_info(pf->cpp, " %s: %s\n", |
---|
343 | | - name, err ? "not found" : "found, loading..."); |
---|
| 353 | + name, err ? "not found" : "found"); |
---|
344 | 354 | if (err) |
---|
345 | 355 | return NULL; |
---|
346 | 356 | |
---|
.. | .. |
---|
418 | 428 | return nfp_net_fw_request(pdev, pf, fw_name); |
---|
419 | 429 | } |
---|
420 | 430 | |
---|
| 431 | +static int |
---|
| 432 | +nfp_get_fw_policy_value(struct pci_dev *pdev, struct nfp_nsp *nsp, |
---|
| 433 | + const char *key, const char *default_val, int max_val, |
---|
| 434 | + int *value) |
---|
| 435 | +{ |
---|
| 436 | + char hwinfo[64]; |
---|
| 437 | + long hi_val; |
---|
| 438 | + int err; |
---|
| 439 | + |
---|
| 440 | + snprintf(hwinfo, sizeof(hwinfo), key); |
---|
| 441 | + err = nfp_nsp_hwinfo_lookup_optional(nsp, hwinfo, sizeof(hwinfo), |
---|
| 442 | + default_val); |
---|
| 443 | + if (err) |
---|
| 444 | + return err; |
---|
| 445 | + |
---|
| 446 | + err = kstrtol(hwinfo, 0, &hi_val); |
---|
| 447 | + if (err || hi_val < 0 || hi_val > max_val) { |
---|
| 448 | + dev_warn(&pdev->dev, |
---|
| 449 | + "Invalid value '%s' from '%s', ignoring\n", |
---|
| 450 | + hwinfo, key); |
---|
| 451 | + err = kstrtol(default_val, 0, &hi_val); |
---|
| 452 | + } |
---|
| 453 | + |
---|
| 454 | + *value = hi_val; |
---|
| 455 | + return err; |
---|
| 456 | +} |
---|
| 457 | + |
---|
421 | 458 | /** |
---|
422 | | - * nfp_net_fw_load() - Load the firmware image |
---|
| 459 | + * nfp_fw_load() - Load the firmware image |
---|
423 | 460 | * @pdev: PCI Device structure |
---|
424 | 461 | * @pf: NFP PF Device structure |
---|
425 | 462 | * @nsp: NFP SP handle |
---|
.. | .. |
---|
429 | 466 | static int |
---|
430 | 467 | nfp_fw_load(struct pci_dev *pdev, struct nfp_pf *pf, struct nfp_nsp *nsp) |
---|
431 | 468 | { |
---|
432 | | - const struct firmware *fw; |
---|
| 469 | + bool do_reset, fw_loaded = false; |
---|
| 470 | + const struct firmware *fw = NULL; |
---|
| 471 | + int err, reset, policy, ifcs = 0; |
---|
| 472 | + char *token, *ptr; |
---|
| 473 | + char hwinfo[64]; |
---|
433 | 474 | u16 interface; |
---|
434 | | - int err; |
---|
| 475 | + |
---|
| 476 | + snprintf(hwinfo, sizeof(hwinfo), "abi_drv_load_ifc"); |
---|
| 477 | + err = nfp_nsp_hwinfo_lookup_optional(nsp, hwinfo, sizeof(hwinfo), |
---|
| 478 | + NFP_NSP_DRV_LOAD_IFC_DEFAULT); |
---|
| 479 | + if (err) |
---|
| 480 | + return err; |
---|
435 | 481 | |
---|
436 | 482 | interface = nfp_cpp_interface(pf->cpp); |
---|
437 | | - if (NFP_CPP_INTERFACE_UNIT_of(interface) != 0) { |
---|
438 | | - /* Only Unit 0 should reset or load firmware */ |
---|
| 483 | + ptr = hwinfo; |
---|
| 484 | + while ((token = strsep(&ptr, ","))) { |
---|
| 485 | + unsigned long interface_hi; |
---|
| 486 | + |
---|
| 487 | + err = kstrtoul(token, 0, &interface_hi); |
---|
| 488 | + if (err) { |
---|
| 489 | + dev_err(&pdev->dev, |
---|
| 490 | + "Failed to parse interface '%s': %d\n", |
---|
| 491 | + token, err); |
---|
| 492 | + return err; |
---|
| 493 | + } |
---|
| 494 | + |
---|
| 495 | + ifcs++; |
---|
| 496 | + if (interface == interface_hi) |
---|
| 497 | + break; |
---|
| 498 | + } |
---|
| 499 | + |
---|
| 500 | + if (!token) { |
---|
439 | 501 | dev_info(&pdev->dev, "Firmware will be loaded by partner\n"); |
---|
440 | 502 | return 0; |
---|
441 | 503 | } |
---|
442 | 504 | |
---|
| 505 | + err = nfp_get_fw_policy_value(pdev, nsp, "abi_drv_reset", |
---|
| 506 | + NFP_NSP_DRV_RESET_DEFAULT, |
---|
| 507 | + NFP_NSP_DRV_RESET_NEVER, &reset); |
---|
| 508 | + if (err) |
---|
| 509 | + return err; |
---|
| 510 | + |
---|
| 511 | + err = nfp_get_fw_policy_value(pdev, nsp, "app_fw_from_flash", |
---|
| 512 | + NFP_NSP_APP_FW_LOAD_DEFAULT, |
---|
| 513 | + NFP_NSP_APP_FW_LOAD_PREF, &policy); |
---|
| 514 | + if (err) |
---|
| 515 | + return err; |
---|
| 516 | + |
---|
443 | 517 | fw = nfp_net_fw_find(pdev, pf); |
---|
444 | | - if (!fw) |
---|
445 | | - return 0; |
---|
| 518 | + do_reset = reset == NFP_NSP_DRV_RESET_ALWAYS || |
---|
| 519 | + (fw && reset == NFP_NSP_DRV_RESET_DISK); |
---|
446 | 520 | |
---|
447 | | - dev_info(&pdev->dev, "Soft-reset, loading FW image\n"); |
---|
448 | | - err = nfp_nsp_device_soft_reset(nsp); |
---|
449 | | - if (err < 0) { |
---|
450 | | - dev_err(&pdev->dev, "Failed to soft reset the NFP: %d\n", |
---|
451 | | - err); |
---|
452 | | - goto exit_release_fw; |
---|
| 521 | + if (do_reset) { |
---|
| 522 | + dev_info(&pdev->dev, "Soft-resetting the NFP\n"); |
---|
| 523 | + err = nfp_nsp_device_soft_reset(nsp); |
---|
| 524 | + if (err < 0) { |
---|
| 525 | + dev_err(&pdev->dev, |
---|
| 526 | + "Failed to soft reset the NFP: %d\n", err); |
---|
| 527 | + goto exit_release_fw; |
---|
| 528 | + } |
---|
453 | 529 | } |
---|
454 | 530 | |
---|
455 | | - err = nfp_nsp_load_fw(nsp, fw); |
---|
| 531 | + if (fw && policy != NFP_NSP_APP_FW_LOAD_FLASH) { |
---|
| 532 | + if (nfp_nsp_has_fw_loaded(nsp) && nfp_nsp_fw_loaded(nsp)) |
---|
| 533 | + goto exit_release_fw; |
---|
456 | 534 | |
---|
457 | | - if (err < 0) { |
---|
458 | | - dev_err(&pdev->dev, "FW loading failed: %d\n", err); |
---|
459 | | - goto exit_release_fw; |
---|
| 535 | + err = nfp_nsp_load_fw(nsp, fw); |
---|
| 536 | + if (err < 0) { |
---|
| 537 | + dev_err(&pdev->dev, "FW loading failed: %d\n", |
---|
| 538 | + err); |
---|
| 539 | + goto exit_release_fw; |
---|
| 540 | + } |
---|
| 541 | + dev_info(&pdev->dev, "Finished loading FW image\n"); |
---|
| 542 | + fw_loaded = true; |
---|
| 543 | + } else if (policy != NFP_NSP_APP_FW_LOAD_DISK && |
---|
| 544 | + nfp_nsp_has_stored_fw_load(nsp)) { |
---|
| 545 | + |
---|
| 546 | + /* Don't propagate this error to stick with legacy driver |
---|
| 547 | + * behavior, failure will be detected later during init. |
---|
| 548 | + */ |
---|
| 549 | + if (!nfp_nsp_load_stored_fw(nsp)) |
---|
| 550 | + dev_info(&pdev->dev, "Finished loading stored FW image\n"); |
---|
| 551 | + |
---|
| 552 | + /* Don't flag the fw_loaded in this case since other devices |
---|
| 553 | + * may reuse the firmware when configured this way |
---|
| 554 | + */ |
---|
| 555 | + } else { |
---|
| 556 | + dev_warn(&pdev->dev, "Didn't load firmware, please update flash or reconfigure card\n"); |
---|
460 | 557 | } |
---|
461 | | - |
---|
462 | | - dev_info(&pdev->dev, "Finished loading FW image\n"); |
---|
463 | 558 | |
---|
464 | 559 | exit_release_fw: |
---|
465 | 560 | release_firmware(fw); |
---|
466 | 561 | |
---|
467 | | - return err < 0 ? err : 1; |
---|
| 562 | + /* We don't want to unload firmware when other devices may still be |
---|
| 563 | + * dependent on it, which could be the case if there are multiple |
---|
| 564 | + * devices that could load firmware. |
---|
| 565 | + */ |
---|
| 566 | + if (fw_loaded && ifcs == 1) |
---|
| 567 | + pf->unload_fw_on_remove = true; |
---|
| 568 | + |
---|
| 569 | + return err < 0 ? err : fw_loaded; |
---|
468 | 570 | } |
---|
469 | 571 | |
---|
470 | 572 | static void |
---|
.. | .. |
---|
566 | 668 | /* Optional per-PCI PF mailbox */ |
---|
567 | 669 | snprintf(pf_symbol, sizeof(pf_symbol), NFP_MBOX_SYM_NAME, pf_id); |
---|
568 | 670 | pf->mbox = nfp_rtsym_lookup(pf->rtbl, pf_symbol); |
---|
569 | | - if (pf->mbox && pf->mbox->size < NFP_MBOX_SYM_MIN_SIZE) { |
---|
| 671 | + if (pf->mbox && nfp_rtsym_size(pf->mbox) < NFP_MBOX_SYM_MIN_SIZE) { |
---|
570 | 672 | nfp_err(pf->cpp, "PF mailbox symbol too small: %llu < %d\n", |
---|
571 | | - pf->mbox->size, NFP_MBOX_SYM_MIN_SIZE); |
---|
| 673 | + nfp_rtsym_size(pf->mbox), NFP_MBOX_SYM_MIN_SIZE); |
---|
572 | 674 | return -EINVAL; |
---|
573 | 675 | } |
---|
574 | 676 | |
---|
.. | .. |
---|
581 | 683 | struct devlink *devlink; |
---|
582 | 684 | struct nfp_pf *pf; |
---|
583 | 685 | int err; |
---|
| 686 | + |
---|
| 687 | + if (pdev->vendor == PCI_VENDOR_ID_NETRONOME && |
---|
| 688 | + pdev->device == PCI_DEVICE_ID_NETRONOME_NFP6000_VF) |
---|
| 689 | + dev_warn(&pdev->dev, "Binding NFP VF device to the NFP PF driver, the VF driver is called 'nfp_netvf'\n"); |
---|
584 | 690 | |
---|
585 | 691 | err = pci_enable_device(pdev); |
---|
586 | 692 | if (err < 0) |
---|
.. | .. |
---|
686 | 792 | err_fw_unload: |
---|
687 | 793 | kfree(pf->rtbl); |
---|
688 | 794 | nfp_mip_close(pf->mip); |
---|
689 | | - if (pf->fw_loaded) |
---|
| 795 | + if (pf->unload_fw_on_remove) |
---|
690 | 796 | nfp_fw_unload(pf); |
---|
691 | 797 | kfree(pf->eth_tbl); |
---|
692 | 798 | kfree(pf->nspi); |
---|
.. | .. |
---|
709 | 815 | return err; |
---|
710 | 816 | } |
---|
711 | 817 | |
---|
712 | | -static void nfp_pci_remove(struct pci_dev *pdev) |
---|
| 818 | +static void __nfp_pci_shutdown(struct pci_dev *pdev, bool unload_fw) |
---|
713 | 819 | { |
---|
714 | | - struct nfp_pf *pf = pci_get_drvdata(pdev); |
---|
| 820 | + struct nfp_pf *pf; |
---|
| 821 | + |
---|
| 822 | + pf = pci_get_drvdata(pdev); |
---|
| 823 | + if (!pf) |
---|
| 824 | + return; |
---|
715 | 825 | |
---|
716 | 826 | nfp_hwmon_unregister(pf); |
---|
717 | 827 | |
---|
.. | .. |
---|
722 | 832 | vfree(pf->dumpspec); |
---|
723 | 833 | kfree(pf->rtbl); |
---|
724 | 834 | nfp_mip_close(pf->mip); |
---|
725 | | - if (pf->fw_loaded) |
---|
| 835 | + if (unload_fw && pf->unload_fw_on_remove) |
---|
726 | 836 | nfp_fw_unload(pf); |
---|
727 | 837 | |
---|
728 | 838 | destroy_workqueue(pf->wq); |
---|
.. | .. |
---|
738 | 848 | pci_disable_device(pdev); |
---|
739 | 849 | } |
---|
740 | 850 | |
---|
| 851 | +static void nfp_pci_remove(struct pci_dev *pdev) |
---|
| 852 | +{ |
---|
| 853 | + __nfp_pci_shutdown(pdev, true); |
---|
| 854 | +} |
---|
| 855 | + |
---|
| 856 | +static void nfp_pci_shutdown(struct pci_dev *pdev) |
---|
| 857 | +{ |
---|
| 858 | + __nfp_pci_shutdown(pdev, false); |
---|
| 859 | +} |
---|
| 860 | + |
---|
741 | 861 | static struct pci_driver nfp_pci_driver = { |
---|
742 | 862 | .name = nfp_driver_name, |
---|
743 | 863 | .id_table = nfp_pci_device_ids, |
---|
744 | 864 | .probe = nfp_pci_probe, |
---|
745 | 865 | .remove = nfp_pci_remove, |
---|
| 866 | + .shutdown = nfp_pci_shutdown, |
---|
746 | 867 | .sriov_configure = nfp_pcie_sriov_configure, |
---|
747 | 868 | }; |
---|
748 | 869 | |
---|
.. | .. |
---|
782 | 903 | module_init(nfp_main_init); |
---|
783 | 904 | module_exit(nfp_main_exit); |
---|
784 | 905 | |
---|
| 906 | +MODULE_FIRMWARE("netronome/nic_AMDA0058-0011_2x40.nffw"); |
---|
| 907 | +MODULE_FIRMWARE("netronome/nic_AMDA0058-0012_2x40.nffw"); |
---|
785 | 908 | MODULE_FIRMWARE("netronome/nic_AMDA0081-0001_1x40.nffw"); |
---|
786 | 909 | MODULE_FIRMWARE("netronome/nic_AMDA0081-0001_4x10.nffw"); |
---|
787 | 910 | MODULE_FIRMWARE("netronome/nic_AMDA0096-0001_2x10.nffw"); |
---|
.. | .. |
---|
795 | 918 | MODULE_AUTHOR("Netronome Systems <oss-drivers@netronome.com>"); |
---|
796 | 919 | MODULE_LICENSE("GPL"); |
---|
797 | 920 | MODULE_DESCRIPTION("The Netronome Flow Processor (NFP) driver."); |
---|
798 | | -MODULE_VERSION(UTS_RELEASE); |
---|