836 lines · c
1// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)2/* Copyright (C) 2015-2018 Netronome Systems, Inc. */3 4/*5 * nfp_net_main.c6 * Netronome network device driver: Main entry point7 * Authors: Jakub Kicinski <jakub.kicinski@netronome.com>8 * Alejandro Lucero <alejandro.lucero@netronome.com>9 * Jason McMullan <jason.mcmullan@netronome.com>10 * Rolf Neugebauer <rolf.neugebauer@netronome.com>11 */12 13#include <linux/etherdevice.h>14#include <linux/kernel.h>15#include <linux/init.h>16#include <linux/lockdep.h>17#include <linux/pci.h>18#include <linux/pci_regs.h>19#include <linux/random.h>20#include <linux/rtnetlink.h>21 22#include "nfpcore/nfp.h"23#include "nfpcore/nfp_cpp.h"24#include "nfpcore/nfp_dev.h"25#include "nfpcore/nfp_nffw.h"26#include "nfpcore/nfp_nsp.h"27#include "nfpcore/nfp6000_pcie.h"28#include "nfp_app.h"29#include "nfp_net_ctrl.h"30#include "nfp_net_sriov.h"31#include "nfp_net.h"32#include "nfp_main.h"33#include "nfp_port.h"34 35#define NFP_PF_CSR_SLICE_SIZE (32 * 1024)36 37/**38 * nfp_net_get_mac_addr() - Get the MAC address.39 * @pf: NFP PF handle40 * @netdev: net_device to set MAC address on41 * @port: NFP port structure42 *43 * First try to get the MAC address from NSP ETH table. If that44 * fails generate a random address.45 */46void47nfp_net_get_mac_addr(struct nfp_pf *pf, struct net_device *netdev,48 struct nfp_port *port)49{50 struct nfp_eth_table_port *eth_port;51 52 eth_port = __nfp_port_get_eth_port(port);53 if (!eth_port) {54 eth_hw_addr_random(netdev);55 return;56 }57 58 eth_hw_addr_set(netdev, eth_port->mac_addr);59 ether_addr_copy(netdev->perm_addr, eth_port->mac_addr);60}61 62static struct nfp_eth_table_port *63nfp_net_find_port(struct nfp_eth_table *eth_tbl, unsigned int index)64{65 int i;66 67 for (i = 0; eth_tbl && i < eth_tbl->count; i++)68 if (eth_tbl->ports[i].index == index)69 return ð_tbl->ports[i];70 71 return NULL;72}73 74static int nfp_net_pf_get_num_ports(struct nfp_pf *pf)75{76 return nfp_pf_rtsym_read_optional(pf, "nfd_cfg_pf%u_num_ports", 1);77}78 79static void nfp_net_pf_free_vnic(struct nfp_pf *pf, struct nfp_net *nn)80{81 if (nfp_net_is_data_vnic(nn))82 nfp_app_vnic_free(pf->app, nn);83 nfp_port_free(nn->port);84 list_del(&nn->vnic_list);85 pf->num_vnics--;86 nfp_net_free(nn);87}88 89static void nfp_net_pf_free_vnics(struct nfp_pf *pf)90{91 struct nfp_net *nn, *next;92 93 list_for_each_entry_safe(nn, next, &pf->vnics, vnic_list)94 if (nfp_net_is_data_vnic(nn))95 nfp_net_pf_free_vnic(pf, nn);96}97 98static struct nfp_net *99nfp_net_pf_alloc_vnic(struct nfp_pf *pf, bool needs_netdev,100 void __iomem *ctrl_bar, void __iomem *qc_bar,101 int stride, unsigned int id)102{103 u32 tx_base, rx_base, n_tx_rings, n_rx_rings;104 struct nfp_net *nn;105 int err;106 107 tx_base = readl(ctrl_bar + NFP_NET_CFG_START_TXQ);108 rx_base = readl(ctrl_bar + NFP_NET_CFG_START_RXQ);109 n_tx_rings = readl(ctrl_bar + NFP_NET_CFG_MAX_TXRINGS);110 n_rx_rings = readl(ctrl_bar + NFP_NET_CFG_MAX_RXRINGS);111 112 /* Allocate and initialise the vNIC */113 nn = nfp_net_alloc(pf->pdev, pf->dev_info, ctrl_bar, needs_netdev,114 n_tx_rings, n_rx_rings);115 if (IS_ERR(nn))116 return nn;117 118 nn->app = pf->app;119 nn->tx_bar = qc_bar + tx_base * NFP_QCP_QUEUE_ADDR_SZ;120 nn->rx_bar = qc_bar + rx_base * NFP_QCP_QUEUE_ADDR_SZ;121 nn->dp.is_vf = 0;122 nn->stride_rx = stride;123 nn->stride_tx = stride;124 125 if (needs_netdev) {126 err = nfp_app_vnic_alloc(pf->app, nn, id);127 if (err) {128 nfp_net_free(nn);129 return ERR_PTR(err);130 }131 }132 133 pf->num_vnics++;134 list_add_tail(&nn->vnic_list, &pf->vnics);135 136 return nn;137}138 139static int140nfp_net_pf_init_vnic(struct nfp_pf *pf, struct nfp_net *nn, unsigned int id)141{142 int err;143 144 nn->id = id;145 146 if (nn->port) {147 err = nfp_devlink_port_register(pf->app, nn->port);148 if (err)149 return err;150 }151 152 err = nfp_net_init(nn);153 if (err)154 goto err_devlink_port_clean;155 156 nfp_net_debugfs_vnic_add(nn, pf->ddir);157 158 nfp_net_info(nn);159 160 if (nfp_net_is_data_vnic(nn)) {161 err = nfp_app_vnic_init(pf->app, nn);162 if (err)163 goto err_debugfs_vnic_clean;164 }165 166 return 0;167 168err_debugfs_vnic_clean:169 nfp_net_debugfs_dir_clean(&nn->debugfs_dir);170 nfp_net_clean(nn);171err_devlink_port_clean:172 if (nn->port)173 nfp_devlink_port_unregister(nn->port);174 return err;175}176 177static int178nfp_net_pf_alloc_vnics(struct nfp_pf *pf, void __iomem *ctrl_bar,179 void __iomem *qc_bar, int stride)180{181 struct nfp_net *nn;182 unsigned int i;183 int err;184 185 for (i = 0; i < pf->max_data_vnics; i++) {186 nn = nfp_net_pf_alloc_vnic(pf, true, ctrl_bar, qc_bar,187 stride, i);188 if (IS_ERR(nn)) {189 err = PTR_ERR(nn);190 goto err_free_prev;191 }192 193 if (nn->port)194 nn->port->link_cb = nfp_net_refresh_port_table;195 196 ctrl_bar += NFP_PF_CSR_SLICE_SIZE;197 198 /* Kill the vNIC if app init marked it as invalid */199 if (nn->port && nn->port->type == NFP_PORT_INVALID)200 nfp_net_pf_free_vnic(pf, nn);201 }202 203 if (list_empty(&pf->vnics))204 return -ENODEV;205 206 return 0;207 208err_free_prev:209 nfp_net_pf_free_vnics(pf);210 return err;211}212 213static void nfp_net_pf_clean_vnic(struct nfp_pf *pf, struct nfp_net *nn)214{215 if (nfp_net_is_data_vnic(nn))216 nfp_app_vnic_clean(pf->app, nn);217 nfp_net_debugfs_dir_clean(&nn->debugfs_dir);218 nfp_net_clean(nn);219 if (nn->port)220 nfp_devlink_port_unregister(nn->port);221}222 223static int nfp_net_pf_alloc_irqs(struct nfp_pf *pf)224{225 unsigned int wanted_irqs, num_irqs, vnics_left, irqs_left;226 struct nfp_net *nn;227 228 /* Get MSI-X vectors */229 wanted_irqs = 0;230 list_for_each_entry(nn, &pf->vnics, vnic_list)231 wanted_irqs += NFP_NET_NON_Q_VECTORS + nn->dp.num_r_vecs;232 pf->irq_entries = kcalloc(wanted_irqs, sizeof(*pf->irq_entries),233 GFP_KERNEL);234 if (!pf->irq_entries)235 return -ENOMEM;236 237 num_irqs = nfp_net_irqs_alloc(pf->pdev, pf->irq_entries,238 NFP_NET_MIN_VNIC_IRQS * pf->num_vnics,239 wanted_irqs);240 if (!num_irqs) {241 nfp_warn(pf->cpp, "Unable to allocate MSI-X vectors\n");242 kfree(pf->irq_entries);243 return -ENOMEM;244 }245 246 /* Distribute IRQs to vNICs */247 irqs_left = num_irqs;248 vnics_left = pf->num_vnics;249 list_for_each_entry(nn, &pf->vnics, vnic_list) {250 unsigned int n;251 252 n = min(NFP_NET_NON_Q_VECTORS + nn->dp.num_r_vecs,253 DIV_ROUND_UP(irqs_left, vnics_left));254 nfp_net_irqs_assign(nn, &pf->irq_entries[num_irqs - irqs_left],255 n);256 irqs_left -= n;257 vnics_left--;258 }259 260 return 0;261}262 263static void nfp_net_pf_free_irqs(struct nfp_pf *pf)264{265 nfp_net_irqs_disable(pf->pdev);266 kfree(pf->irq_entries);267}268 269static int nfp_net_pf_init_vnics(struct nfp_pf *pf)270{271 struct nfp_net *nn;272 unsigned int id;273 int err;274 275 /* Finish vNIC init and register */276 id = 0;277 list_for_each_entry(nn, &pf->vnics, vnic_list) {278 if (!nfp_net_is_data_vnic(nn))279 continue;280 err = nfp_net_pf_init_vnic(pf, nn, id);281 if (err)282 goto err_prev_deinit;283 284 id++;285 }286 287 return 0;288 289err_prev_deinit:290 list_for_each_entry_continue_reverse(nn, &pf->vnics, vnic_list)291 if (nfp_net_is_data_vnic(nn))292 nfp_net_pf_clean_vnic(pf, nn);293 return err;294}295 296static int297nfp_net_pf_app_init(struct nfp_pf *pf, u8 __iomem *qc_bar, unsigned int stride)298{299 struct devlink *devlink = priv_to_devlink(pf);300 u8 __iomem *ctrl_bar;301 int err;302 303 pf->app = nfp_app_alloc(pf, nfp_net_pf_get_app_id(pf));304 if (IS_ERR(pf->app))305 return PTR_ERR(pf->app);306 307 devl_lock(devlink);308 err = nfp_app_init(pf->app);309 devl_unlock(devlink);310 if (err)311 goto err_free;312 313 if (!nfp_app_needs_ctrl_vnic(pf->app))314 return 0;315 316 ctrl_bar = nfp_pf_map_rtsym(pf, "net.ctrl", "_pf%u_net_ctrl_bar",317 NFP_PF_CSR_SLICE_SIZE, &pf->ctrl_vnic_bar);318 if (IS_ERR(ctrl_bar)) {319 nfp_err(pf->cpp, "Failed to find ctrl vNIC memory symbol\n");320 err = PTR_ERR(ctrl_bar);321 goto err_app_clean;322 }323 324 pf->ctrl_vnic = nfp_net_pf_alloc_vnic(pf, false, ctrl_bar, qc_bar,325 stride, 0);326 if (IS_ERR(pf->ctrl_vnic)) {327 err = PTR_ERR(pf->ctrl_vnic);328 goto err_unmap;329 }330 331 return 0;332 333err_unmap:334 nfp_cpp_area_release_free(pf->ctrl_vnic_bar);335err_app_clean:336 devl_lock(devlink);337 nfp_app_clean(pf->app);338 devl_unlock(devlink);339err_free:340 nfp_app_free(pf->app);341 pf->app = NULL;342 return err;343}344 345static void nfp_net_pf_app_clean(struct nfp_pf *pf)346{347 struct devlink *devlink = priv_to_devlink(pf);348 349 if (pf->ctrl_vnic) {350 nfp_net_pf_free_vnic(pf, pf->ctrl_vnic);351 nfp_cpp_area_release_free(pf->ctrl_vnic_bar);352 }353 354 devl_lock(devlink);355 nfp_app_clean(pf->app);356 devl_unlock(devlink);357 358 nfp_app_free(pf->app);359 pf->app = NULL;360}361 362static int nfp_net_pf_app_start_ctrl(struct nfp_pf *pf)363{364 int err;365 366 if (!pf->ctrl_vnic)367 return 0;368 err = nfp_net_pf_init_vnic(pf, pf->ctrl_vnic, 0);369 if (err)370 return err;371 372 err = nfp_ctrl_open(pf->ctrl_vnic);373 if (err)374 goto err_clean_ctrl;375 376 return 0;377 378err_clean_ctrl:379 nfp_net_pf_clean_vnic(pf, pf->ctrl_vnic);380 return err;381}382 383static void nfp_net_pf_app_stop_ctrl(struct nfp_pf *pf)384{385 if (!pf->ctrl_vnic)386 return;387 nfp_ctrl_close(pf->ctrl_vnic);388 nfp_net_pf_clean_vnic(pf, pf->ctrl_vnic);389}390 391static int nfp_net_pf_app_start(struct nfp_pf *pf)392{393 int err;394 395 err = nfp_net_pf_app_start_ctrl(pf);396 if (err)397 return err;398 399 err = nfp_app_start(pf->app, pf->ctrl_vnic);400 if (err)401 goto err_ctrl_stop;402 403 if (pf->num_vfs) {404 err = nfp_app_sriov_enable(pf->app, pf->num_vfs);405 if (err)406 goto err_app_stop;407 }408 409 return 0;410 411err_app_stop:412 nfp_app_stop(pf->app);413err_ctrl_stop:414 nfp_net_pf_app_stop_ctrl(pf);415 return err;416}417 418static void nfp_net_pf_app_stop(struct nfp_pf *pf)419{420 if (pf->num_vfs)421 nfp_app_sriov_disable(pf->app);422 nfp_app_stop(pf->app);423 nfp_net_pf_app_stop_ctrl(pf);424}425 426static void nfp_net_pci_unmap_mem(struct nfp_pf *pf)427{428 if (pf->vfcfg_tbl2_area)429 nfp_cpp_area_release_free(pf->vfcfg_tbl2_area);430 if (pf->vf_cfg_bar)431 nfp_cpp_area_release_free(pf->vf_cfg_bar);432 if (pf->mac_stats_bar)433 nfp_cpp_area_release_free(pf->mac_stats_bar);434 nfp_cpp_area_release_free(pf->qc_area);435 nfp_cpp_area_release_free(pf->data_vnic_bar);436}437 438static int nfp_net_pci_map_mem(struct nfp_pf *pf)439{440 u32 min_size, cpp_id;441 u8 __iomem *mem;442 int err;443 444 min_size = pf->max_data_vnics * NFP_PF_CSR_SLICE_SIZE;445 mem = nfp_pf_map_rtsym(pf, "net.bar0", "_pf%d_net_bar0",446 min_size, &pf->data_vnic_bar);447 if (IS_ERR(mem)) {448 nfp_err(pf->cpp, "Failed to find data vNIC memory symbol\n");449 return PTR_ERR(mem);450 }451 452 if (pf->eth_tbl) {453 min_size = NFP_MAC_STATS_SIZE * (pf->eth_tbl->max_index + 1);454 pf->mac_stats_mem = nfp_rtsym_map(pf->rtbl, "_mac_stats",455 "net.macstats", min_size,456 &pf->mac_stats_bar);457 if (IS_ERR(pf->mac_stats_mem)) {458 if (PTR_ERR(pf->mac_stats_mem) != -ENOENT) {459 err = PTR_ERR(pf->mac_stats_mem);460 goto err_unmap_ctrl;461 }462 pf->mac_stats_mem = NULL;463 }464 }465 466 pf->vf_cfg_mem = nfp_pf_map_rtsym(pf, "net.vfcfg", "_pf%d_net_vf_bar",467 NFP_NET_CFG_BAR_SZ * pf->limit_vfs,468 &pf->vf_cfg_bar);469 if (IS_ERR(pf->vf_cfg_mem)) {470 if (PTR_ERR(pf->vf_cfg_mem) != -ENOENT) {471 err = PTR_ERR(pf->vf_cfg_mem);472 goto err_unmap_mac_stats;473 }474 pf->vf_cfg_mem = NULL;475 }476 477 min_size = NFP_NET_VF_CFG_SZ * pf->limit_vfs + NFP_NET_VF_CFG_MB_SZ;478 pf->vfcfg_tbl2 = nfp_pf_map_rtsym(pf, "net.vfcfg_tbl2",479 "_pf%d_net_vf_cfg2",480 min_size, &pf->vfcfg_tbl2_area);481 if (IS_ERR(pf->vfcfg_tbl2)) {482 if (PTR_ERR(pf->vfcfg_tbl2) != -ENOENT) {483 err = PTR_ERR(pf->vfcfg_tbl2);484 goto err_unmap_vf_cfg;485 }486 pf->vfcfg_tbl2 = NULL;487 }488 489 cpp_id = NFP_CPP_ISLAND_ID(0, NFP_CPP_ACTION_RW, 0, 0);490 mem = nfp_cpp_map_area(pf->cpp, "net.qc", cpp_id,491 nfp_qcp_queue_offset(pf->dev_info, 0),492 pf->dev_info->qc_area_sz, &pf->qc_area);493 if (IS_ERR(mem)) {494 nfp_err(pf->cpp, "Failed to map Queue Controller area.\n");495 err = PTR_ERR(mem);496 goto err_unmap_vfcfg_tbl2;497 }498 499 return 0;500 501err_unmap_vfcfg_tbl2:502 if (pf->vfcfg_tbl2_area)503 nfp_cpp_area_release_free(pf->vfcfg_tbl2_area);504err_unmap_vf_cfg:505 if (pf->vf_cfg_bar)506 nfp_cpp_area_release_free(pf->vf_cfg_bar);507err_unmap_mac_stats:508 if (pf->mac_stats_bar)509 nfp_cpp_area_release_free(pf->mac_stats_bar);510err_unmap_ctrl:511 nfp_cpp_area_release_free(pf->data_vnic_bar);512 return err;513}514 515static const unsigned int lr_to_speed[] = {516 [NFP_NET_CFG_STS_LINK_RATE_UNSUPPORTED] = 0,517 [NFP_NET_CFG_STS_LINK_RATE_UNKNOWN] = SPEED_UNKNOWN,518 [NFP_NET_CFG_STS_LINK_RATE_1G] = SPEED_1000,519 [NFP_NET_CFG_STS_LINK_RATE_10G] = SPEED_10000,520 [NFP_NET_CFG_STS_LINK_RATE_25G] = SPEED_25000,521 [NFP_NET_CFG_STS_LINK_RATE_40G] = SPEED_40000,522 [NFP_NET_CFG_STS_LINK_RATE_50G] = SPEED_50000,523 [NFP_NET_CFG_STS_LINK_RATE_100G] = SPEED_100000,524};525 526unsigned int nfp_net_lr2speed(unsigned int linkrate)527{528 if (linkrate < ARRAY_SIZE(lr_to_speed))529 return lr_to_speed[linkrate];530 531 return SPEED_UNKNOWN;532}533 534unsigned int nfp_net_speed2lr(unsigned int speed)535{536 int i;537 538 for (i = 0; i < ARRAY_SIZE(lr_to_speed); i++) {539 if (speed == lr_to_speed[i])540 return i;541 }542 543 return NFP_NET_CFG_STS_LINK_RATE_UNKNOWN;544}545 546static void nfp_net_notify_port_speed(struct nfp_port *port)547{548 struct net_device *netdev = port->netdev;549 struct nfp_net *nn;550 u16 sts;551 552 if (!nfp_netdev_is_nfp_net(netdev))553 return;554 555 nn = netdev_priv(netdev);556 sts = nn_readw(nn, NFP_NET_CFG_STS);557 558 if (!(sts & NFP_NET_CFG_STS_LINK)) {559 nn_writew(nn, NFP_NET_CFG_STS_NSP_LINK_RATE, NFP_NET_CFG_STS_LINK_RATE_UNKNOWN);560 return;561 }562 563 nn_writew(nn, NFP_NET_CFG_STS_NSP_LINK_RATE, nfp_net_speed2lr(port->eth_port->speed));564}565 566static int567nfp_net_eth_port_update(struct nfp_cpp *cpp, struct nfp_port *port,568 struct nfp_eth_table *eth_table)569{570 struct nfp_eth_table_port *eth_port;571 572 ASSERT_RTNL();573 574 eth_port = nfp_net_find_port(eth_table, port->eth_id);575 if (!eth_port) {576 set_bit(NFP_PORT_CHANGED, &port->flags);577 nfp_warn(cpp, "Warning: port #%d not present after reconfig\n",578 port->eth_id);579 return -EIO;580 }581 if (eth_port->override_changed) {582 nfp_warn(cpp, "Port #%d config changed, unregistering. Driver reload required before port will be operational again.\n", port->eth_id);583 port->type = NFP_PORT_INVALID;584 }585 586 memcpy(port->eth_port, eth_port, sizeof(*eth_port));587 nfp_net_notify_port_speed(port);588 589 return 0;590}591 592int nfp_net_refresh_port_table_sync(struct nfp_pf *pf)593{594 struct devlink *devlink = priv_to_devlink(pf);595 struct nfp_eth_table *eth_table;596 struct nfp_net *nn, *next;597 struct nfp_port *port;598 int err;599 600 devl_assert_locked(devlink);601 602 /* Check for nfp_net_pci_remove() racing against us */603 if (list_empty(&pf->vnics))604 return 0;605 606 /* Update state of all ports */607 rtnl_lock();608 list_for_each_entry(port, &pf->ports, port_list)609 clear_bit(NFP_PORT_CHANGED, &port->flags);610 611 eth_table = nfp_eth_read_ports(pf->cpp);612 if (!eth_table) {613 list_for_each_entry(port, &pf->ports, port_list)614 if (__nfp_port_get_eth_port(port))615 set_bit(NFP_PORT_CHANGED, &port->flags);616 rtnl_unlock();617 nfp_err(pf->cpp, "Error refreshing port config!\n");618 return -EIO;619 }620 621 list_for_each_entry(port, &pf->ports, port_list)622 if (__nfp_port_get_eth_port(port))623 nfp_net_eth_port_update(pf->cpp, port, eth_table);624 rtnl_unlock();625 626 kfree(eth_table);627 628 /* Resync repr state. This may cause reprs to be removed. */629 err = nfp_reprs_resync_phys_ports(pf->app);630 if (err)631 return err;632 633 /* Shoot off the ports which became invalid */634 list_for_each_entry_safe(nn, next, &pf->vnics, vnic_list) {635 if (!nn->port || nn->port->type != NFP_PORT_INVALID)636 continue;637 638 nfp_net_pf_clean_vnic(pf, nn);639 nfp_net_pf_free_vnic(pf, nn);640 }641 642 return 0;643}644 645static void nfp_net_refresh_vnics(struct work_struct *work)646{647 struct nfp_pf *pf = container_of(work, struct nfp_pf,648 port_refresh_work);649 struct devlink *devlink = priv_to_devlink(pf);650 651 devl_lock(devlink);652 nfp_net_refresh_port_table_sync(pf);653 devl_unlock(devlink);654}655 656void nfp_net_refresh_port_table(struct nfp_port *port)657{658 struct nfp_pf *pf = port->app->pf;659 660 set_bit(NFP_PORT_CHANGED, &port->flags);661 662 queue_work(pf->wq, &pf->port_refresh_work);663}664 665int nfp_net_refresh_eth_port(struct nfp_port *port)666{667 struct nfp_cpp *cpp = port->app->cpp;668 struct nfp_eth_table *eth_table;669 int ret;670 671 clear_bit(NFP_PORT_CHANGED, &port->flags);672 673 eth_table = nfp_eth_read_ports(cpp);674 if (!eth_table) {675 set_bit(NFP_PORT_CHANGED, &port->flags);676 nfp_err(cpp, "Error refreshing port state table!\n");677 return -EIO;678 }679 680 ret = nfp_net_eth_port_update(cpp, port, eth_table);681 682 kfree(eth_table);683 684 return ret;685}686 687/*688 * PCI device functions689 */690int nfp_net_pci_probe(struct nfp_pf *pf)691{692 struct devlink *devlink = priv_to_devlink(pf);693 struct nfp_net_fw_version fw_ver;694 u8 __iomem *ctrl_bar, *qc_bar;695 int stride;696 int err;697 698 INIT_WORK(&pf->port_refresh_work, nfp_net_refresh_vnics);699 700 if (!pf->rtbl) {701 nfp_err(pf->cpp, "No %s, giving up.\n",702 pf->fw_loaded ? "symbol table" : "firmware found");703 return -EINVAL;704 }705 706 pf->max_data_vnics = nfp_net_pf_get_num_ports(pf);707 if ((int)pf->max_data_vnics < 0)708 return pf->max_data_vnics;709 710 err = nfp_net_pci_map_mem(pf);711 if (err)712 return err;713 714 ctrl_bar = nfp_cpp_area_iomem(pf->data_vnic_bar);715 qc_bar = nfp_cpp_area_iomem(pf->qc_area);716 if (!ctrl_bar || !qc_bar) {717 err = -EIO;718 goto err_unmap;719 }720 721 nfp_net_get_fw_version(&fw_ver, ctrl_bar);722 if (fw_ver.extend & NFP_NET_CFG_VERSION_RESERVED_MASK ||723 fw_ver.class != NFP_NET_CFG_VERSION_CLASS_GENERIC) {724 nfp_err(pf->cpp, "Unknown Firmware ABI %d.%d.%d.%d\n",725 fw_ver.extend, fw_ver.class,726 fw_ver.major, fw_ver.minor);727 err = -EINVAL;728 goto err_unmap;729 }730 731 /* Determine stride */732 if (nfp_net_fw_ver_eq(&fw_ver, 0, 0, 0, 1)) {733 stride = 2;734 nfp_warn(pf->cpp, "OBSOLETE Firmware detected - VF isolation not available\n");735 } else {736 switch (fw_ver.major) {737 case 1 ... 5:738 stride = 4;739 break;740 default:741 nfp_err(pf->cpp, "Unsupported Firmware ABI %d.%d.%d.%d\n",742 fw_ver.extend, fw_ver.class,743 fw_ver.major, fw_ver.minor);744 err = -EINVAL;745 goto err_unmap;746 }747 }748 749 err = nfp_net_pf_app_init(pf, qc_bar, stride);750 if (err)751 goto err_unmap;752 753 err = nfp_shared_buf_register(pf);754 if (err)755 goto err_devlink_unreg;756 757 devl_lock(devlink);758 err = nfp_devlink_params_register(pf);759 if (err)760 goto err_shared_buf_unreg;761 762 pf->ddir = nfp_net_debugfs_device_add(pf->pdev);763 764 /* Allocate the vnics and do basic init */765 err = nfp_net_pf_alloc_vnics(pf, ctrl_bar, qc_bar, stride);766 if (err)767 goto err_clean_ddir;768 769 err = nfp_net_pf_alloc_irqs(pf);770 if (err)771 goto err_free_vnics;772 773 err = nfp_net_pf_app_start(pf);774 if (err)775 goto err_free_irqs;776 777 err = nfp_net_pf_init_vnics(pf);778 if (err)779 goto err_stop_app;780 781 devl_unlock(devlink);782 devlink_register(devlink);783 784 return 0;785 786err_stop_app:787 nfp_net_pf_app_stop(pf);788err_free_irqs:789 nfp_net_pf_free_irqs(pf);790err_free_vnics:791 nfp_net_pf_free_vnics(pf);792err_clean_ddir:793 nfp_net_debugfs_dir_clean(&pf->ddir);794 nfp_devlink_params_unregister(pf);795err_shared_buf_unreg:796 devl_unlock(devlink);797 nfp_shared_buf_unregister(pf);798err_devlink_unreg:799 cancel_work_sync(&pf->port_refresh_work);800 nfp_net_pf_app_clean(pf);801err_unmap:802 nfp_net_pci_unmap_mem(pf);803 return err;804}805 806void nfp_net_pci_remove(struct nfp_pf *pf)807{808 struct devlink *devlink = priv_to_devlink(pf);809 struct nfp_net *nn, *next;810 811 devlink_unregister(priv_to_devlink(pf));812 devl_lock(devlink);813 list_for_each_entry_safe(nn, next, &pf->vnics, vnic_list) {814 if (!nfp_net_is_data_vnic(nn))815 continue;816 nfp_net_pf_clean_vnic(pf, nn);817 nfp_net_pf_free_vnic(pf, nn);818 }819 820 nfp_net_pf_app_stop(pf);821 /* stop app first, to avoid double free of ctrl vNIC's ddir */822 nfp_net_debugfs_dir_clean(&pf->ddir);823 824 nfp_devlink_params_unregister(pf);825 826 devl_unlock(devlink);827 828 nfp_shared_buf_unregister(pf);829 830 nfp_net_pf_free_irqs(pf);831 nfp_net_pf_app_clean(pf);832 nfp_net_pci_unmap_mem(pf);833 834 cancel_work_sync(&pf->port_refresh_work);835}836