0001
0002
0003
0004 #include <linux/etherdevice.h>
0005 #include <linux/lockdep.h>
0006 #include <linux/pci.h>
0007 #include <linux/skbuff.h>
0008 #include <linux/vmalloc.h>
0009 #include <net/devlink.h>
0010 #include <net/dst_metadata.h>
0011
0012 #include "main.h"
0013 #include "../nfpcore/nfp_cpp.h"
0014 #include "../nfpcore/nfp_nffw.h"
0015 #include "../nfpcore/nfp_nsp.h"
0016 #include "../nfp_app.h"
0017 #include "../nfp_main.h"
0018 #include "../nfp_net.h"
0019 #include "../nfp_net_repr.h"
0020 #include "../nfp_port.h"
0021 #include "./cmsg.h"
0022
0023 #define NFP_FLOWER_ALLOWED_VER 0x0001000000010000UL
0024
0025 #define NFP_MIN_INT_PORT_ID 1
0026 #define NFP_MAX_INT_PORT_ID 256
0027
0028 static const char *nfp_flower_extra_cap(struct nfp_app *app, struct nfp_net *nn)
0029 {
0030 return "FLOWER";
0031 }
0032
0033 static enum devlink_eswitch_mode eswitch_mode_get(struct nfp_app *app)
0034 {
0035 return DEVLINK_ESWITCH_MODE_SWITCHDEV;
0036 }
0037
0038 static int
0039 nfp_flower_lookup_internal_port_id(struct nfp_flower_priv *priv,
0040 struct net_device *netdev)
0041 {
0042 struct net_device *entry;
0043 int i, id = 0;
0044
0045 rcu_read_lock();
0046 idr_for_each_entry(&priv->internal_ports.port_ids, entry, i)
0047 if (entry == netdev) {
0048 id = i;
0049 break;
0050 }
0051 rcu_read_unlock();
0052
0053 return id;
0054 }
0055
0056 static int
0057 nfp_flower_get_internal_port_id(struct nfp_app *app, struct net_device *netdev)
0058 {
0059 struct nfp_flower_priv *priv = app->priv;
0060 int id;
0061
0062 id = nfp_flower_lookup_internal_port_id(priv, netdev);
0063 if (id > 0)
0064 return id;
0065
0066 idr_preload(GFP_ATOMIC);
0067 spin_lock_bh(&priv->internal_ports.lock);
0068 id = idr_alloc(&priv->internal_ports.port_ids, netdev,
0069 NFP_MIN_INT_PORT_ID, NFP_MAX_INT_PORT_ID, GFP_ATOMIC);
0070 spin_unlock_bh(&priv->internal_ports.lock);
0071 idr_preload_end();
0072
0073 return id;
0074 }
0075
0076 u32 nfp_flower_get_port_id_from_netdev(struct nfp_app *app,
0077 struct net_device *netdev)
0078 {
0079 int ext_port;
0080
0081 if (nfp_netdev_is_nfp_repr(netdev)) {
0082 return nfp_repr_get_port_id(netdev);
0083 } else if (nfp_flower_internal_port_can_offload(app, netdev)) {
0084 ext_port = nfp_flower_get_internal_port_id(app, netdev);
0085 if (ext_port < 0)
0086 return 0;
0087
0088 return nfp_flower_internal_port_get_port_id(ext_port);
0089 }
0090
0091 return 0;
0092 }
0093
0094 static struct net_device *
0095 nfp_flower_get_netdev_from_internal_port_id(struct nfp_app *app, int port_id)
0096 {
0097 struct nfp_flower_priv *priv = app->priv;
0098 struct net_device *netdev;
0099
0100 rcu_read_lock();
0101 netdev = idr_find(&priv->internal_ports.port_ids, port_id);
0102 rcu_read_unlock();
0103
0104 return netdev;
0105 }
0106
0107 static void
0108 nfp_flower_free_internal_port_id(struct nfp_app *app, struct net_device *netdev)
0109 {
0110 struct nfp_flower_priv *priv = app->priv;
0111 int id;
0112
0113 id = nfp_flower_lookup_internal_port_id(priv, netdev);
0114 if (!id)
0115 return;
0116
0117 spin_lock_bh(&priv->internal_ports.lock);
0118 idr_remove(&priv->internal_ports.port_ids, id);
0119 spin_unlock_bh(&priv->internal_ports.lock);
0120 }
0121
0122 static int
0123 nfp_flower_internal_port_event_handler(struct nfp_app *app,
0124 struct net_device *netdev,
0125 unsigned long event)
0126 {
0127 if (event == NETDEV_UNREGISTER &&
0128 nfp_flower_internal_port_can_offload(app, netdev))
0129 nfp_flower_free_internal_port_id(app, netdev);
0130
0131 return NOTIFY_OK;
0132 }
0133
0134 static void nfp_flower_internal_port_init(struct nfp_flower_priv *priv)
0135 {
0136 spin_lock_init(&priv->internal_ports.lock);
0137 idr_init(&priv->internal_ports.port_ids);
0138 }
0139
0140 static void nfp_flower_internal_port_cleanup(struct nfp_flower_priv *priv)
0141 {
0142 idr_destroy(&priv->internal_ports.port_ids);
0143 }
0144
0145 static struct nfp_flower_non_repr_priv *
0146 nfp_flower_non_repr_priv_lookup(struct nfp_app *app, struct net_device *netdev)
0147 {
0148 struct nfp_flower_priv *priv = app->priv;
0149 struct nfp_flower_non_repr_priv *entry;
0150
0151 ASSERT_RTNL();
0152
0153 list_for_each_entry(entry, &priv->non_repr_priv, list)
0154 if (entry->netdev == netdev)
0155 return entry;
0156
0157 return NULL;
0158 }
0159
0160 void
0161 __nfp_flower_non_repr_priv_get(struct nfp_flower_non_repr_priv *non_repr_priv)
0162 {
0163 non_repr_priv->ref_count++;
0164 }
0165
0166 struct nfp_flower_non_repr_priv *
0167 nfp_flower_non_repr_priv_get(struct nfp_app *app, struct net_device *netdev)
0168 {
0169 struct nfp_flower_priv *priv = app->priv;
0170 struct nfp_flower_non_repr_priv *entry;
0171
0172 entry = nfp_flower_non_repr_priv_lookup(app, netdev);
0173 if (entry)
0174 goto inc_ref;
0175
0176 entry = kzalloc(sizeof(*entry), GFP_KERNEL);
0177 if (!entry)
0178 return NULL;
0179
0180 entry->netdev = netdev;
0181 list_add(&entry->list, &priv->non_repr_priv);
0182
0183 inc_ref:
0184 __nfp_flower_non_repr_priv_get(entry);
0185 return entry;
0186 }
0187
0188 void
0189 __nfp_flower_non_repr_priv_put(struct nfp_flower_non_repr_priv *non_repr_priv)
0190 {
0191 if (--non_repr_priv->ref_count)
0192 return;
0193
0194 list_del(&non_repr_priv->list);
0195 kfree(non_repr_priv);
0196 }
0197
0198 void
0199 nfp_flower_non_repr_priv_put(struct nfp_app *app, struct net_device *netdev)
0200 {
0201 struct nfp_flower_non_repr_priv *entry;
0202
0203 entry = nfp_flower_non_repr_priv_lookup(app, netdev);
0204 if (!entry)
0205 return;
0206
0207 __nfp_flower_non_repr_priv_put(entry);
0208 }
0209
0210 static enum nfp_repr_type
0211 nfp_flower_repr_get_type_and_port(struct nfp_app *app, u32 port_id, u8 *port)
0212 {
0213 switch (FIELD_GET(NFP_FLOWER_CMSG_PORT_TYPE, port_id)) {
0214 case NFP_FLOWER_CMSG_PORT_TYPE_PHYS_PORT:
0215 *port = FIELD_GET(NFP_FLOWER_CMSG_PORT_PHYS_PORT_NUM,
0216 port_id);
0217 return NFP_REPR_TYPE_PHYS_PORT;
0218
0219 case NFP_FLOWER_CMSG_PORT_TYPE_PCIE_PORT:
0220 *port = FIELD_GET(NFP_FLOWER_CMSG_PORT_VNIC, port_id);
0221 if (FIELD_GET(NFP_FLOWER_CMSG_PORT_VNIC_TYPE, port_id) ==
0222 NFP_FLOWER_CMSG_PORT_VNIC_TYPE_PF)
0223 return NFP_REPR_TYPE_PF;
0224 else
0225 return NFP_REPR_TYPE_VF;
0226 }
0227
0228 return __NFP_REPR_TYPE_MAX;
0229 }
0230
0231 static struct net_device *
0232 nfp_flower_dev_get(struct nfp_app *app, u32 port_id, bool *redir_egress)
0233 {
0234 enum nfp_repr_type repr_type;
0235 struct nfp_reprs *reprs;
0236 u8 port = 0;
0237
0238
0239 if (FIELD_GET(NFP_FLOWER_CMSG_PORT_TYPE, port_id) ==
0240 NFP_FLOWER_CMSG_PORT_TYPE_OTHER_PORT) {
0241 if (redir_egress)
0242 *redir_egress = true;
0243 port = FIELD_GET(NFP_FLOWER_CMSG_PORT_PHYS_PORT_NUM, port_id);
0244 return nfp_flower_get_netdev_from_internal_port_id(app, port);
0245 }
0246
0247 repr_type = nfp_flower_repr_get_type_and_port(app, port_id, &port);
0248 if (repr_type > NFP_REPR_TYPE_MAX)
0249 return NULL;
0250
0251 reprs = rcu_dereference(app->reprs[repr_type]);
0252 if (!reprs)
0253 return NULL;
0254
0255 if (port >= reprs->num_reprs)
0256 return NULL;
0257
0258 return rcu_dereference(reprs->reprs[port]);
0259 }
0260
0261 static int
0262 nfp_flower_reprs_reify(struct nfp_app *app, enum nfp_repr_type type,
0263 bool exists)
0264 {
0265 struct nfp_reprs *reprs;
0266 int i, err, count = 0;
0267
0268 reprs = rcu_dereference_protected(app->reprs[type],
0269 nfp_app_is_locked(app));
0270 if (!reprs)
0271 return 0;
0272
0273 for (i = 0; i < reprs->num_reprs; i++) {
0274 struct net_device *netdev;
0275
0276 netdev = nfp_repr_get_locked(app, reprs, i);
0277 if (netdev) {
0278 struct nfp_repr *repr = netdev_priv(netdev);
0279
0280 err = nfp_flower_cmsg_portreify(repr, exists);
0281 if (err)
0282 return err;
0283 count++;
0284 }
0285 }
0286
0287 return count;
0288 }
0289
0290 static int
0291 nfp_flower_wait_repr_reify(struct nfp_app *app, atomic_t *replies, int tot_repl)
0292 {
0293 struct nfp_flower_priv *priv = app->priv;
0294
0295 if (!tot_repl)
0296 return 0;
0297
0298 assert_nfp_app_locked(app);
0299 if (!wait_event_timeout(priv->reify_wait_queue,
0300 atomic_read(replies) >= tot_repl,
0301 NFP_FL_REPLY_TIMEOUT)) {
0302 nfp_warn(app->cpp, "Not all reprs responded to reify\n");
0303 return -EIO;
0304 }
0305
0306 return 0;
0307 }
0308
0309 static int
0310 nfp_flower_repr_netdev_open(struct nfp_app *app, struct nfp_repr *repr)
0311 {
0312 int err;
0313
0314 err = nfp_flower_cmsg_portmod(repr, true, repr->netdev->mtu, false);
0315 if (err)
0316 return err;
0317
0318 netif_tx_wake_all_queues(repr->netdev);
0319
0320 return 0;
0321 }
0322
0323 static int
0324 nfp_flower_repr_netdev_stop(struct nfp_app *app, struct nfp_repr *repr)
0325 {
0326 netif_tx_disable(repr->netdev);
0327
0328 return nfp_flower_cmsg_portmod(repr, false, repr->netdev->mtu, false);
0329 }
0330
0331 static void
0332 nfp_flower_repr_netdev_clean(struct nfp_app *app, struct net_device *netdev)
0333 {
0334 struct nfp_repr *repr = netdev_priv(netdev);
0335
0336 kfree(repr->app_priv);
0337 }
0338
0339 static void
0340 nfp_flower_repr_netdev_preclean(struct nfp_app *app, struct net_device *netdev)
0341 {
0342 struct nfp_repr *repr = netdev_priv(netdev);
0343 struct nfp_flower_priv *priv = app->priv;
0344 atomic_t *replies = &priv->reify_replies;
0345 int err;
0346
0347 atomic_set(replies, 0);
0348 err = nfp_flower_cmsg_portreify(repr, false);
0349 if (err) {
0350 nfp_warn(app->cpp, "Failed to notify firmware about repr destruction\n");
0351 return;
0352 }
0353
0354 nfp_flower_wait_repr_reify(app, replies, 1);
0355 }
0356
0357 static void nfp_flower_sriov_disable(struct nfp_app *app)
0358 {
0359 struct nfp_flower_priv *priv = app->priv;
0360
0361 if (!priv->nn)
0362 return;
0363
0364 nfp_reprs_clean_and_free_by_type(app, NFP_REPR_TYPE_VF);
0365 }
0366
0367 static int
0368 nfp_flower_spawn_vnic_reprs(struct nfp_app *app,
0369 enum nfp_flower_cmsg_port_vnic_type vnic_type,
0370 enum nfp_repr_type repr_type, unsigned int cnt)
0371 {
0372 u8 nfp_pcie = nfp_cppcore_pcie_unit(app->pf->cpp);
0373 struct nfp_flower_priv *priv = app->priv;
0374 atomic_t *replies = &priv->reify_replies;
0375 struct nfp_flower_repr_priv *repr_priv;
0376 enum nfp_port_type port_type;
0377 struct nfp_repr *nfp_repr;
0378 struct nfp_reprs *reprs;
0379 int i, err, reify_cnt;
0380 const u8 queue = 0;
0381
0382 port_type = repr_type == NFP_REPR_TYPE_PF ? NFP_PORT_PF_PORT :
0383 NFP_PORT_VF_PORT;
0384
0385 reprs = nfp_reprs_alloc(cnt);
0386 if (!reprs)
0387 return -ENOMEM;
0388
0389 for (i = 0; i < cnt; i++) {
0390 struct net_device *repr;
0391 struct nfp_port *port;
0392 u32 port_id;
0393
0394 repr = nfp_repr_alloc(app);
0395 if (!repr) {
0396 err = -ENOMEM;
0397 goto err_reprs_clean;
0398 }
0399
0400 repr_priv = kzalloc(sizeof(*repr_priv), GFP_KERNEL);
0401 if (!repr_priv) {
0402 err = -ENOMEM;
0403 nfp_repr_free(repr);
0404 goto err_reprs_clean;
0405 }
0406
0407 nfp_repr = netdev_priv(repr);
0408 nfp_repr->app_priv = repr_priv;
0409 repr_priv->nfp_repr = nfp_repr;
0410
0411
0412 WARN_ON(repr_type == NFP_REPR_TYPE_PF && i);
0413
0414 port = nfp_port_alloc(app, port_type, repr);
0415 if (IS_ERR(port)) {
0416 err = PTR_ERR(port);
0417 kfree(repr_priv);
0418 nfp_repr_free(repr);
0419 goto err_reprs_clean;
0420 }
0421 if (repr_type == NFP_REPR_TYPE_PF) {
0422 port->pf_id = i;
0423 port->vnic = priv->nn->dp.ctrl_bar;
0424 } else {
0425 port->pf_id = 0;
0426 port->vf_id = i;
0427 port->vnic =
0428 app->pf->vf_cfg_mem + i * NFP_NET_CFG_BAR_SZ;
0429 }
0430
0431 eth_hw_addr_random(repr);
0432
0433 port_id = nfp_flower_cmsg_pcie_port(nfp_pcie, vnic_type,
0434 i, queue);
0435 err = nfp_repr_init(app, repr,
0436 port_id, port, priv->nn->dp.netdev);
0437 if (err) {
0438 kfree(repr_priv);
0439 nfp_port_free(port);
0440 nfp_repr_free(repr);
0441 goto err_reprs_clean;
0442 }
0443
0444 RCU_INIT_POINTER(reprs->reprs[i], repr);
0445 nfp_info(app->cpp, "%s%d Representor(%s) created\n",
0446 repr_type == NFP_REPR_TYPE_PF ? "PF" : "VF", i,
0447 repr->name);
0448 }
0449
0450 nfp_app_reprs_set(app, repr_type, reprs);
0451
0452 atomic_set(replies, 0);
0453 reify_cnt = nfp_flower_reprs_reify(app, repr_type, true);
0454 if (reify_cnt < 0) {
0455 err = reify_cnt;
0456 nfp_warn(app->cpp, "Failed to notify firmware about repr creation\n");
0457 goto err_reprs_remove;
0458 }
0459
0460 err = nfp_flower_wait_repr_reify(app, replies, reify_cnt);
0461 if (err)
0462 goto err_reprs_remove;
0463
0464 return 0;
0465 err_reprs_remove:
0466 reprs = nfp_app_reprs_set(app, repr_type, NULL);
0467 err_reprs_clean:
0468 nfp_reprs_clean_and_free(app, reprs);
0469 return err;
0470 }
0471
0472 static int nfp_flower_sriov_enable(struct nfp_app *app, int num_vfs)
0473 {
0474 struct nfp_flower_priv *priv = app->priv;
0475
0476 if (!priv->nn)
0477 return 0;
0478
0479 return nfp_flower_spawn_vnic_reprs(app,
0480 NFP_FLOWER_CMSG_PORT_VNIC_TYPE_VF,
0481 NFP_REPR_TYPE_VF, num_vfs);
0482 }
0483
0484 static int
0485 nfp_flower_spawn_phy_reprs(struct nfp_app *app, struct nfp_flower_priv *priv)
0486 {
0487 struct nfp_eth_table *eth_tbl = app->pf->eth_tbl;
0488 atomic_t *replies = &priv->reify_replies;
0489 struct nfp_flower_repr_priv *repr_priv;
0490 struct nfp_repr *nfp_repr;
0491 struct sk_buff *ctrl_skb;
0492 struct nfp_reprs *reprs;
0493 int err, reify_cnt;
0494 unsigned int i;
0495
0496 ctrl_skb = nfp_flower_cmsg_mac_repr_start(app, eth_tbl->count);
0497 if (!ctrl_skb)
0498 return -ENOMEM;
0499
0500 reprs = nfp_reprs_alloc(eth_tbl->max_index + 1);
0501 if (!reprs) {
0502 err = -ENOMEM;
0503 goto err_free_ctrl_skb;
0504 }
0505
0506 for (i = 0; i < eth_tbl->count; i++) {
0507 unsigned int phys_port = eth_tbl->ports[i].index;
0508 struct net_device *repr;
0509 struct nfp_port *port;
0510 u32 cmsg_port_id;
0511
0512 repr = nfp_repr_alloc(app);
0513 if (!repr) {
0514 err = -ENOMEM;
0515 goto err_reprs_clean;
0516 }
0517
0518 repr_priv = kzalloc(sizeof(*repr_priv), GFP_KERNEL);
0519 if (!repr_priv) {
0520 err = -ENOMEM;
0521 nfp_repr_free(repr);
0522 goto err_reprs_clean;
0523 }
0524
0525 nfp_repr = netdev_priv(repr);
0526 nfp_repr->app_priv = repr_priv;
0527 repr_priv->nfp_repr = nfp_repr;
0528
0529 port = nfp_port_alloc(app, NFP_PORT_PHYS_PORT, repr);
0530 if (IS_ERR(port)) {
0531 err = PTR_ERR(port);
0532 kfree(repr_priv);
0533 nfp_repr_free(repr);
0534 goto err_reprs_clean;
0535 }
0536 err = nfp_port_init_phy_port(app->pf, app, port, i);
0537 if (err) {
0538 kfree(repr_priv);
0539 nfp_port_free(port);
0540 nfp_repr_free(repr);
0541 goto err_reprs_clean;
0542 }
0543
0544 SET_NETDEV_DEV(repr, &priv->nn->pdev->dev);
0545 nfp_net_get_mac_addr(app->pf, repr, port);
0546
0547 cmsg_port_id = nfp_flower_cmsg_phys_port(phys_port);
0548 err = nfp_repr_init(app, repr,
0549 cmsg_port_id, port, priv->nn->dp.netdev);
0550 if (err) {
0551 kfree(repr_priv);
0552 nfp_port_free(port);
0553 nfp_repr_free(repr);
0554 goto err_reprs_clean;
0555 }
0556
0557 nfp_flower_cmsg_mac_repr_add(ctrl_skb, i,
0558 eth_tbl->ports[i].nbi,
0559 eth_tbl->ports[i].base,
0560 phys_port);
0561
0562 RCU_INIT_POINTER(reprs->reprs[phys_port], repr);
0563 nfp_info(app->cpp, "Phys Port %d Representor(%s) created\n",
0564 phys_port, repr->name);
0565 }
0566
0567 nfp_app_reprs_set(app, NFP_REPR_TYPE_PHYS_PORT, reprs);
0568
0569
0570
0571
0572
0573
0574
0575
0576 atomic_set(replies, 0);
0577 reify_cnt = nfp_flower_reprs_reify(app, NFP_REPR_TYPE_PHYS_PORT, true);
0578 if (reify_cnt < 0) {
0579 err = reify_cnt;
0580 nfp_warn(app->cpp, "Failed to notify firmware about repr creation\n");
0581 goto err_reprs_remove;
0582 }
0583
0584 err = nfp_flower_wait_repr_reify(app, replies, reify_cnt);
0585 if (err)
0586 goto err_reprs_remove;
0587
0588 nfp_ctrl_tx(app->ctrl, ctrl_skb);
0589
0590 return 0;
0591 err_reprs_remove:
0592 reprs = nfp_app_reprs_set(app, NFP_REPR_TYPE_PHYS_PORT, NULL);
0593 err_reprs_clean:
0594 nfp_reprs_clean_and_free(app, reprs);
0595 err_free_ctrl_skb:
0596 kfree_skb(ctrl_skb);
0597 return err;
0598 }
0599
0600 static int nfp_flower_vnic_alloc(struct nfp_app *app, struct nfp_net *nn,
0601 unsigned int id)
0602 {
0603 if (id > 0) {
0604 nfp_warn(app->cpp, "FlowerNIC doesn't support more than one data vNIC\n");
0605 goto err_invalid_port;
0606 }
0607
0608 eth_hw_addr_random(nn->dp.netdev);
0609 netif_keep_dst(nn->dp.netdev);
0610 nn->vnic_no_name = true;
0611
0612 return 0;
0613
0614 err_invalid_port:
0615 nn->port = nfp_port_alloc(app, NFP_PORT_INVALID, nn->dp.netdev);
0616 return PTR_ERR_OR_ZERO(nn->port);
0617 }
0618
0619 static void nfp_flower_vnic_clean(struct nfp_app *app, struct nfp_net *nn)
0620 {
0621 struct nfp_flower_priv *priv = app->priv;
0622
0623 if (app->pf->num_vfs)
0624 nfp_reprs_clean_and_free_by_type(app, NFP_REPR_TYPE_VF);
0625 nfp_reprs_clean_and_free_by_type(app, NFP_REPR_TYPE_PF);
0626 nfp_reprs_clean_and_free_by_type(app, NFP_REPR_TYPE_PHYS_PORT);
0627
0628 priv->nn = NULL;
0629 }
0630
0631 static int nfp_flower_vnic_init(struct nfp_app *app, struct nfp_net *nn)
0632 {
0633 struct nfp_flower_priv *priv = app->priv;
0634 int err;
0635
0636 priv->nn = nn;
0637
0638 err = nfp_flower_spawn_phy_reprs(app, app->priv);
0639 if (err)
0640 goto err_clear_nn;
0641
0642 err = nfp_flower_spawn_vnic_reprs(app,
0643 NFP_FLOWER_CMSG_PORT_VNIC_TYPE_PF,
0644 NFP_REPR_TYPE_PF, 1);
0645 if (err)
0646 goto err_destroy_reprs_phy;
0647
0648 if (app->pf->num_vfs) {
0649 err = nfp_flower_spawn_vnic_reprs(app,
0650 NFP_FLOWER_CMSG_PORT_VNIC_TYPE_VF,
0651 NFP_REPR_TYPE_VF,
0652 app->pf->num_vfs);
0653 if (err)
0654 goto err_destroy_reprs_pf;
0655 }
0656
0657 return 0;
0658
0659 err_destroy_reprs_pf:
0660 nfp_reprs_clean_and_free_by_type(app, NFP_REPR_TYPE_PF);
0661 err_destroy_reprs_phy:
0662 nfp_reprs_clean_and_free_by_type(app, NFP_REPR_TYPE_PHYS_PORT);
0663 err_clear_nn:
0664 priv->nn = NULL;
0665 return err;
0666 }
0667
0668 static void nfp_flower_wait_host_bit(struct nfp_app *app)
0669 {
0670 unsigned long err_at;
0671 u64 feat;
0672 int err;
0673
0674
0675 err_at = jiffies + msecs_to_jiffies(100);
0676 do {
0677 feat = nfp_rtsym_read_le(app->pf->rtbl,
0678 "_abi_flower_combined_features_global",
0679 &err);
0680 if (time_is_before_eq_jiffies(err_at)) {
0681 nfp_warn(app->cpp,
0682 "HOST_ACK bit not propagated in FW.\n");
0683 break;
0684 }
0685 usleep_range(1000, 2000);
0686 } while (!err && !(feat & NFP_FL_FEATS_HOST_ACK));
0687
0688 if (err)
0689 nfp_warn(app->cpp,
0690 "Could not read global features entry from FW\n");
0691 }
0692
0693 static int nfp_flower_sync_feature_bits(struct nfp_app *app)
0694 {
0695 struct nfp_flower_priv *app_priv = app->priv;
0696 int err;
0697
0698
0699 err = nfp_rtsym_write_le(app->pf->rtbl, "_abi_flower_host_mask",
0700 app_priv->flower_ext_feats |
0701 NFP_FL_FEATS_HOST_ACK);
0702 if (!err)
0703 nfp_flower_wait_host_bit(app);
0704 else if (err != -ENOENT)
0705 return err;
0706
0707
0708 err = nfp_rtsym_write_le(app->pf->rtbl,
0709 "_abi_flower_balance_sync_enable", 1);
0710 if (!err) {
0711 app_priv->flower_en_feats |= NFP_FL_ENABLE_LAG;
0712 nfp_flower_lag_init(&app_priv->nfp_lag);
0713 } else if (err == -ENOENT) {
0714 nfp_warn(app->cpp, "LAG not supported by FW.\n");
0715 } else {
0716 return err;
0717 }
0718
0719 if (app_priv->flower_ext_feats & NFP_FL_FEATS_FLOW_MOD) {
0720
0721 err = nfp_rtsym_write_le(app->pf->rtbl,
0722 "_abi_flower_merge_hint_enable", 1);
0723 if (!err) {
0724 app_priv->flower_en_feats |= NFP_FL_ENABLE_FLOW_MERGE;
0725 nfp_flower_internal_port_init(app_priv);
0726 } else if (err == -ENOENT) {
0727 nfp_warn(app->cpp,
0728 "Flow merge not supported by FW.\n");
0729 } else {
0730 return err;
0731 }
0732 } else {
0733 nfp_warn(app->cpp, "Flow mod/merge not supported by FW.\n");
0734 }
0735
0736 return 0;
0737 }
0738
0739 static int nfp_flower_init(struct nfp_app *app)
0740 {
0741 u64 version, features, ctx_count, num_mems;
0742 const struct nfp_pf *pf = app->pf;
0743 struct nfp_flower_priv *app_priv;
0744 int err;
0745
0746 if (!pf->eth_tbl) {
0747 nfp_warn(app->cpp, "FlowerNIC requires eth table\n");
0748 return -EINVAL;
0749 }
0750
0751 if (!pf->mac_stats_bar) {
0752 nfp_warn(app->cpp, "FlowerNIC requires mac_stats BAR\n");
0753 return -EINVAL;
0754 }
0755
0756 if (!pf->vf_cfg_bar) {
0757 nfp_warn(app->cpp, "FlowerNIC requires vf_cfg BAR\n");
0758 return -EINVAL;
0759 }
0760
0761 version = nfp_rtsym_read_le(app->pf->rtbl, "hw_flower_version", &err);
0762 if (err) {
0763 nfp_warn(app->cpp, "FlowerNIC requires hw_flower_version memory symbol\n");
0764 return err;
0765 }
0766
0767 num_mems = nfp_rtsym_read_le(app->pf->rtbl, "CONFIG_FC_HOST_CTX_SPLIT",
0768 &err);
0769 if (err) {
0770 nfp_warn(app->cpp,
0771 "FlowerNIC: unsupported host context memory: %d\n",
0772 err);
0773 err = 0;
0774 num_mems = 1;
0775 }
0776
0777 if (!FIELD_FIT(NFP_FL_STAT_ID_MU_NUM, num_mems) || !num_mems) {
0778 nfp_warn(app->cpp,
0779 "FlowerNIC: invalid host context memory: %llu\n",
0780 num_mems);
0781 return -EINVAL;
0782 }
0783
0784 ctx_count = nfp_rtsym_read_le(app->pf->rtbl, "CONFIG_FC_HOST_CTX_COUNT",
0785 &err);
0786 if (err) {
0787 nfp_warn(app->cpp,
0788 "FlowerNIC: unsupported host context count: %d\n",
0789 err);
0790 err = 0;
0791 ctx_count = BIT(17);
0792 }
0793
0794
0795 if (version != NFP_FLOWER_ALLOWED_VER) {
0796 nfp_warn(app->cpp, "FlowerNIC: unsupported firmware version\n");
0797 return -EINVAL;
0798 }
0799
0800 app_priv = vzalloc(sizeof(struct nfp_flower_priv));
0801 if (!app_priv)
0802 return -ENOMEM;
0803
0804 app_priv->total_mem_units = num_mems;
0805 app_priv->active_mem_unit = 0;
0806 app_priv->stats_ring_size = roundup_pow_of_two(ctx_count);
0807 app->priv = app_priv;
0808 app_priv->app = app;
0809 skb_queue_head_init(&app_priv->cmsg_skbs_high);
0810 skb_queue_head_init(&app_priv->cmsg_skbs_low);
0811 INIT_WORK(&app_priv->cmsg_work, nfp_flower_cmsg_process_rx);
0812 init_waitqueue_head(&app_priv->reify_wait_queue);
0813
0814 init_waitqueue_head(&app_priv->mtu_conf.wait_q);
0815 spin_lock_init(&app_priv->mtu_conf.lock);
0816
0817 err = nfp_flower_metadata_init(app, ctx_count, num_mems);
0818 if (err)
0819 goto err_free_app_priv;
0820
0821
0822 features = nfp_rtsym_read_le(app->pf->rtbl,
0823 "_abi_flower_extra_features", &err);
0824 if (err)
0825 app_priv->flower_ext_feats = 0;
0826 else
0827 app_priv->flower_ext_feats = features & NFP_FL_FEATS_HOST;
0828
0829 err = nfp_flower_sync_feature_bits(app);
0830 if (err)
0831 goto err_cleanup;
0832
0833 if (app_priv->flower_ext_feats & NFP_FL_FEATS_VF_RLIM)
0834 nfp_flower_qos_init(app);
0835
0836 INIT_LIST_HEAD(&app_priv->indr_block_cb_priv);
0837 INIT_LIST_HEAD(&app_priv->non_repr_priv);
0838 app_priv->pre_tun_rule_cnt = 0;
0839
0840 return 0;
0841
0842 err_cleanup:
0843 if (app_priv->flower_en_feats & NFP_FL_ENABLE_LAG)
0844 nfp_flower_lag_cleanup(&app_priv->nfp_lag);
0845 nfp_flower_metadata_cleanup(app);
0846 err_free_app_priv:
0847 vfree(app->priv);
0848 return err;
0849 }
0850
0851 static void nfp_flower_clean(struct nfp_app *app)
0852 {
0853 struct nfp_flower_priv *app_priv = app->priv;
0854
0855 skb_queue_purge(&app_priv->cmsg_skbs_high);
0856 skb_queue_purge(&app_priv->cmsg_skbs_low);
0857 flush_work(&app_priv->cmsg_work);
0858
0859 if (app_priv->flower_ext_feats & NFP_FL_FEATS_VF_RLIM)
0860 nfp_flower_qos_cleanup(app);
0861
0862 if (app_priv->flower_en_feats & NFP_FL_ENABLE_LAG)
0863 nfp_flower_lag_cleanup(&app_priv->nfp_lag);
0864
0865 if (app_priv->flower_en_feats & NFP_FL_ENABLE_FLOW_MERGE)
0866 nfp_flower_internal_port_cleanup(app_priv);
0867
0868 nfp_flower_metadata_cleanup(app);
0869 vfree(app->priv);
0870 app->priv = NULL;
0871 }
0872
0873 static bool nfp_flower_check_ack(struct nfp_flower_priv *app_priv)
0874 {
0875 bool ret;
0876
0877 spin_lock_bh(&app_priv->mtu_conf.lock);
0878 ret = app_priv->mtu_conf.ack;
0879 spin_unlock_bh(&app_priv->mtu_conf.lock);
0880
0881 return ret;
0882 }
0883
0884 static int
0885 nfp_flower_repr_change_mtu(struct nfp_app *app, struct net_device *netdev,
0886 int new_mtu)
0887 {
0888 struct nfp_flower_priv *app_priv = app->priv;
0889 struct nfp_repr *repr = netdev_priv(netdev);
0890 int err;
0891
0892
0893 if (repr->port->type != NFP_PORT_PHYS_PORT)
0894 return 0;
0895
0896 if (!(app_priv->flower_ext_feats & NFP_FL_NBI_MTU_SETTING)) {
0897 nfp_err(app->cpp, "Physical port MTU setting not supported\n");
0898 return -EINVAL;
0899 }
0900
0901 spin_lock_bh(&app_priv->mtu_conf.lock);
0902 app_priv->mtu_conf.ack = false;
0903 app_priv->mtu_conf.requested_val = new_mtu;
0904 app_priv->mtu_conf.portnum = repr->dst->u.port_info.port_id;
0905 spin_unlock_bh(&app_priv->mtu_conf.lock);
0906
0907 err = nfp_flower_cmsg_portmod(repr, netif_carrier_ok(netdev), new_mtu,
0908 true);
0909 if (err) {
0910 spin_lock_bh(&app_priv->mtu_conf.lock);
0911 app_priv->mtu_conf.requested_val = 0;
0912 spin_unlock_bh(&app_priv->mtu_conf.lock);
0913 return err;
0914 }
0915
0916
0917 if (!wait_event_timeout(app_priv->mtu_conf.wait_q,
0918 nfp_flower_check_ack(app_priv),
0919 NFP_FL_REPLY_TIMEOUT)) {
0920 spin_lock_bh(&app_priv->mtu_conf.lock);
0921 app_priv->mtu_conf.requested_val = 0;
0922 spin_unlock_bh(&app_priv->mtu_conf.lock);
0923 nfp_warn(app->cpp, "MTU change not verified with fw\n");
0924 return -EIO;
0925 }
0926
0927 return 0;
0928 }
0929
0930 static int nfp_flower_start(struct nfp_app *app)
0931 {
0932 struct nfp_flower_priv *app_priv = app->priv;
0933 int err;
0934
0935 if (app_priv->flower_en_feats & NFP_FL_ENABLE_LAG) {
0936 err = nfp_flower_lag_reset(&app_priv->nfp_lag);
0937 if (err)
0938 return err;
0939 }
0940
0941 err = flow_indr_dev_register(nfp_flower_indr_setup_tc_cb, app);
0942 if (err)
0943 return err;
0944
0945 err = nfp_tunnel_config_start(app);
0946 if (err)
0947 goto err_tunnel_config;
0948
0949 return 0;
0950
0951 err_tunnel_config:
0952 flow_indr_dev_unregister(nfp_flower_indr_setup_tc_cb, app,
0953 nfp_flower_setup_indr_tc_release);
0954 return err;
0955 }
0956
0957 static void nfp_flower_stop(struct nfp_app *app)
0958 {
0959 nfp_tunnel_config_stop(app);
0960
0961 flow_indr_dev_unregister(nfp_flower_indr_setup_tc_cb, app,
0962 nfp_flower_setup_indr_tc_release);
0963 }
0964
0965 static int
0966 nfp_flower_netdev_event(struct nfp_app *app, struct net_device *netdev,
0967 unsigned long event, void *ptr)
0968 {
0969 struct nfp_flower_priv *app_priv = app->priv;
0970 int ret;
0971
0972 if (app_priv->flower_en_feats & NFP_FL_ENABLE_LAG) {
0973 ret = nfp_flower_lag_netdev_event(app_priv, netdev, event, ptr);
0974 if (ret & NOTIFY_STOP_MASK)
0975 return ret;
0976 }
0977
0978 ret = nfp_flower_internal_port_event_handler(app, netdev, event);
0979 if (ret & NOTIFY_STOP_MASK)
0980 return ret;
0981
0982 return nfp_tunnel_mac_event_handler(app, netdev, event, ptr);
0983 }
0984
0985 const struct nfp_app_type app_flower = {
0986 .id = NFP_APP_FLOWER_NIC,
0987 .name = "flower",
0988
0989 .ctrl_cap_mask = ~0U,
0990 .ctrl_has_meta = true,
0991
0992 .extra_cap = nfp_flower_extra_cap,
0993
0994 .init = nfp_flower_init,
0995 .clean = nfp_flower_clean,
0996
0997 .repr_change_mtu = nfp_flower_repr_change_mtu,
0998
0999 .vnic_alloc = nfp_flower_vnic_alloc,
1000 .vnic_init = nfp_flower_vnic_init,
1001 .vnic_clean = nfp_flower_vnic_clean,
1002
1003 .repr_preclean = nfp_flower_repr_netdev_preclean,
1004 .repr_clean = nfp_flower_repr_netdev_clean,
1005
1006 .repr_open = nfp_flower_repr_netdev_open,
1007 .repr_stop = nfp_flower_repr_netdev_stop,
1008
1009 .start = nfp_flower_start,
1010 .stop = nfp_flower_stop,
1011
1012 .netdev_event = nfp_flower_netdev_event,
1013
1014 .ctrl_msg_rx = nfp_flower_cmsg_rx,
1015
1016 .sriov_enable = nfp_flower_sriov_enable,
1017 .sriov_disable = nfp_flower_sriov_disable,
1018
1019 .eswitch_mode_get = eswitch_mode_get,
1020 .dev_get = nfp_flower_dev_get,
1021
1022 .setup_tc = nfp_flower_setup_tc,
1023 };