.. | .. |
---|
1 | | -/* |
---|
2 | | - * Copyright (C) 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) 2017-2018 Netronome Systems, Inc. */ |
---|
33 | 3 | |
---|
34 | 4 | #include <linux/etherdevice.h> |
---|
35 | 5 | #include <linux/lockdep.h> |
---|
.. | .. |
---|
52 | 22 | |
---|
53 | 23 | #define NFP_FLOWER_ALLOWED_VER 0x0001000000010000UL |
---|
54 | 24 | |
---|
| 25 | +#define NFP_MIN_INT_PORT_ID 1 |
---|
| 26 | +#define NFP_MAX_INT_PORT_ID 256 |
---|
| 27 | + |
---|
55 | 28 | static const char *nfp_flower_extra_cap(struct nfp_app *app, struct nfp_net *nn) |
---|
56 | 29 | { |
---|
57 | 30 | return "FLOWER"; |
---|
.. | .. |
---|
60 | 33 | static enum devlink_eswitch_mode eswitch_mode_get(struct nfp_app *app) |
---|
61 | 34 | { |
---|
62 | 35 | return DEVLINK_ESWITCH_MODE_SWITCHDEV; |
---|
| 36 | +} |
---|
| 37 | + |
---|
| 38 | +static int |
---|
| 39 | +nfp_flower_lookup_internal_port_id(struct nfp_flower_priv *priv, |
---|
| 40 | + struct net_device *netdev) |
---|
| 41 | +{ |
---|
| 42 | + struct net_device *entry; |
---|
| 43 | + int i, id = 0; |
---|
| 44 | + |
---|
| 45 | + rcu_read_lock(); |
---|
| 46 | + idr_for_each_entry(&priv->internal_ports.port_ids, entry, i) |
---|
| 47 | + if (entry == netdev) { |
---|
| 48 | + id = i; |
---|
| 49 | + break; |
---|
| 50 | + } |
---|
| 51 | + rcu_read_unlock(); |
---|
| 52 | + |
---|
| 53 | + return id; |
---|
| 54 | +} |
---|
| 55 | + |
---|
| 56 | +static int |
---|
| 57 | +nfp_flower_get_internal_port_id(struct nfp_app *app, struct net_device *netdev) |
---|
| 58 | +{ |
---|
| 59 | + struct nfp_flower_priv *priv = app->priv; |
---|
| 60 | + int id; |
---|
| 61 | + |
---|
| 62 | + id = nfp_flower_lookup_internal_port_id(priv, netdev); |
---|
| 63 | + if (id > 0) |
---|
| 64 | + return id; |
---|
| 65 | + |
---|
| 66 | + idr_preload(GFP_ATOMIC); |
---|
| 67 | + spin_lock_bh(&priv->internal_ports.lock); |
---|
| 68 | + id = idr_alloc(&priv->internal_ports.port_ids, netdev, |
---|
| 69 | + NFP_MIN_INT_PORT_ID, NFP_MAX_INT_PORT_ID, GFP_ATOMIC); |
---|
| 70 | + spin_unlock_bh(&priv->internal_ports.lock); |
---|
| 71 | + idr_preload_end(); |
---|
| 72 | + |
---|
| 73 | + return id; |
---|
| 74 | +} |
---|
| 75 | + |
---|
| 76 | +u32 nfp_flower_get_port_id_from_netdev(struct nfp_app *app, |
---|
| 77 | + struct net_device *netdev) |
---|
| 78 | +{ |
---|
| 79 | + int ext_port; |
---|
| 80 | + |
---|
| 81 | + if (nfp_netdev_is_nfp_repr(netdev)) { |
---|
| 82 | + return nfp_repr_get_port_id(netdev); |
---|
| 83 | + } else if (nfp_flower_internal_port_can_offload(app, netdev)) { |
---|
| 84 | + ext_port = nfp_flower_get_internal_port_id(app, netdev); |
---|
| 85 | + if (ext_port < 0) |
---|
| 86 | + return 0; |
---|
| 87 | + |
---|
| 88 | + return nfp_flower_internal_port_get_port_id(ext_port); |
---|
| 89 | + } |
---|
| 90 | + |
---|
| 91 | + return 0; |
---|
| 92 | +} |
---|
| 93 | + |
---|
| 94 | +static struct net_device * |
---|
| 95 | +nfp_flower_get_netdev_from_internal_port_id(struct nfp_app *app, int port_id) |
---|
| 96 | +{ |
---|
| 97 | + struct nfp_flower_priv *priv = app->priv; |
---|
| 98 | + struct net_device *netdev; |
---|
| 99 | + |
---|
| 100 | + rcu_read_lock(); |
---|
| 101 | + netdev = idr_find(&priv->internal_ports.port_ids, port_id); |
---|
| 102 | + rcu_read_unlock(); |
---|
| 103 | + |
---|
| 104 | + return netdev; |
---|
| 105 | +} |
---|
| 106 | + |
---|
| 107 | +static void |
---|
| 108 | +nfp_flower_free_internal_port_id(struct nfp_app *app, struct net_device *netdev) |
---|
| 109 | +{ |
---|
| 110 | + struct nfp_flower_priv *priv = app->priv; |
---|
| 111 | + int id; |
---|
| 112 | + |
---|
| 113 | + id = nfp_flower_lookup_internal_port_id(priv, netdev); |
---|
| 114 | + if (!id) |
---|
| 115 | + return; |
---|
| 116 | + |
---|
| 117 | + spin_lock_bh(&priv->internal_ports.lock); |
---|
| 118 | + idr_remove(&priv->internal_ports.port_ids, id); |
---|
| 119 | + spin_unlock_bh(&priv->internal_ports.lock); |
---|
| 120 | +} |
---|
| 121 | + |
---|
| 122 | +static int |
---|
| 123 | +nfp_flower_internal_port_event_handler(struct nfp_app *app, |
---|
| 124 | + struct net_device *netdev, |
---|
| 125 | + unsigned long event) |
---|
| 126 | +{ |
---|
| 127 | + if (event == NETDEV_UNREGISTER && |
---|
| 128 | + nfp_flower_internal_port_can_offload(app, netdev)) |
---|
| 129 | + nfp_flower_free_internal_port_id(app, netdev); |
---|
| 130 | + |
---|
| 131 | + return NOTIFY_OK; |
---|
| 132 | +} |
---|
| 133 | + |
---|
| 134 | +static void nfp_flower_internal_port_init(struct nfp_flower_priv *priv) |
---|
| 135 | +{ |
---|
| 136 | + spin_lock_init(&priv->internal_ports.lock); |
---|
| 137 | + idr_init(&priv->internal_ports.port_ids); |
---|
| 138 | +} |
---|
| 139 | + |
---|
| 140 | +static void nfp_flower_internal_port_cleanup(struct nfp_flower_priv *priv) |
---|
| 141 | +{ |
---|
| 142 | + idr_destroy(&priv->internal_ports.port_ids); |
---|
| 143 | +} |
---|
| 144 | + |
---|
| 145 | +static struct nfp_flower_non_repr_priv * |
---|
| 146 | +nfp_flower_non_repr_priv_lookup(struct nfp_app *app, struct net_device *netdev) |
---|
| 147 | +{ |
---|
| 148 | + struct nfp_flower_priv *priv = app->priv; |
---|
| 149 | + struct nfp_flower_non_repr_priv *entry; |
---|
| 150 | + |
---|
| 151 | + ASSERT_RTNL(); |
---|
| 152 | + |
---|
| 153 | + list_for_each_entry(entry, &priv->non_repr_priv, list) |
---|
| 154 | + if (entry->netdev == netdev) |
---|
| 155 | + return entry; |
---|
| 156 | + |
---|
| 157 | + return NULL; |
---|
| 158 | +} |
---|
| 159 | + |
---|
| 160 | +void |
---|
| 161 | +__nfp_flower_non_repr_priv_get(struct nfp_flower_non_repr_priv *non_repr_priv) |
---|
| 162 | +{ |
---|
| 163 | + non_repr_priv->ref_count++; |
---|
| 164 | +} |
---|
| 165 | + |
---|
| 166 | +struct nfp_flower_non_repr_priv * |
---|
| 167 | +nfp_flower_non_repr_priv_get(struct nfp_app *app, struct net_device *netdev) |
---|
| 168 | +{ |
---|
| 169 | + struct nfp_flower_priv *priv = app->priv; |
---|
| 170 | + struct nfp_flower_non_repr_priv *entry; |
---|
| 171 | + |
---|
| 172 | + entry = nfp_flower_non_repr_priv_lookup(app, netdev); |
---|
| 173 | + if (entry) |
---|
| 174 | + goto inc_ref; |
---|
| 175 | + |
---|
| 176 | + entry = kzalloc(sizeof(*entry), GFP_KERNEL); |
---|
| 177 | + if (!entry) |
---|
| 178 | + return NULL; |
---|
| 179 | + |
---|
| 180 | + entry->netdev = netdev; |
---|
| 181 | + list_add(&entry->list, &priv->non_repr_priv); |
---|
| 182 | + |
---|
| 183 | +inc_ref: |
---|
| 184 | + __nfp_flower_non_repr_priv_get(entry); |
---|
| 185 | + return entry; |
---|
| 186 | +} |
---|
| 187 | + |
---|
| 188 | +void |
---|
| 189 | +__nfp_flower_non_repr_priv_put(struct nfp_flower_non_repr_priv *non_repr_priv) |
---|
| 190 | +{ |
---|
| 191 | + if (--non_repr_priv->ref_count) |
---|
| 192 | + return; |
---|
| 193 | + |
---|
| 194 | + list_del(&non_repr_priv->list); |
---|
| 195 | + kfree(non_repr_priv); |
---|
| 196 | +} |
---|
| 197 | + |
---|
| 198 | +void |
---|
| 199 | +nfp_flower_non_repr_priv_put(struct nfp_app *app, struct net_device *netdev) |
---|
| 200 | +{ |
---|
| 201 | + struct nfp_flower_non_repr_priv *entry; |
---|
| 202 | + |
---|
| 203 | + entry = nfp_flower_non_repr_priv_lookup(app, netdev); |
---|
| 204 | + if (!entry) |
---|
| 205 | + return; |
---|
| 206 | + |
---|
| 207 | + __nfp_flower_non_repr_priv_put(entry); |
---|
63 | 208 | } |
---|
64 | 209 | |
---|
65 | 210 | static enum nfp_repr_type |
---|
.. | .. |
---|
84 | 229 | } |
---|
85 | 230 | |
---|
86 | 231 | static struct net_device * |
---|
87 | | -nfp_flower_repr_get(struct nfp_app *app, u32 port_id) |
---|
| 232 | +nfp_flower_dev_get(struct nfp_app *app, u32 port_id, bool *redir_egress) |
---|
88 | 233 | { |
---|
89 | 234 | enum nfp_repr_type repr_type; |
---|
90 | 235 | struct nfp_reprs *reprs; |
---|
91 | 236 | u8 port = 0; |
---|
| 237 | + |
---|
| 238 | + /* Check if the port is internal. */ |
---|
| 239 | + if (FIELD_GET(NFP_FLOWER_CMSG_PORT_TYPE, port_id) == |
---|
| 240 | + NFP_FLOWER_CMSG_PORT_TYPE_OTHER_PORT) { |
---|
| 241 | + if (redir_egress) |
---|
| 242 | + *redir_egress = true; |
---|
| 243 | + port = FIELD_GET(NFP_FLOWER_CMSG_PORT_PHYS_PORT_NUM, port_id); |
---|
| 244 | + return nfp_flower_get_netdev_from_internal_port_id(app, port); |
---|
| 245 | + } |
---|
92 | 246 | |
---|
93 | 247 | repr_type = nfp_flower_repr_get_type_and_port(app, port_id, &port); |
---|
94 | 248 | if (repr_type > NFP_REPR_TYPE_MAX) |
---|
.. | .. |
---|
137 | 291 | nfp_flower_wait_repr_reify(struct nfp_app *app, atomic_t *replies, int tot_repl) |
---|
138 | 292 | { |
---|
139 | 293 | struct nfp_flower_priv *priv = app->priv; |
---|
140 | | - int err; |
---|
141 | 294 | |
---|
142 | 295 | if (!tot_repl) |
---|
143 | 296 | return 0; |
---|
144 | 297 | |
---|
145 | 298 | lockdep_assert_held(&app->pf->lock); |
---|
146 | | - err = wait_event_interruptible_timeout(priv->reify_wait_queue, |
---|
147 | | - atomic_read(replies) >= tot_repl, |
---|
148 | | - msecs_to_jiffies(10)); |
---|
149 | | - if (err <= 0) { |
---|
| 299 | + if (!wait_event_timeout(priv->reify_wait_queue, |
---|
| 300 | + atomic_read(replies) >= tot_repl, |
---|
| 301 | + NFP_FL_REPLY_TIMEOUT)) { |
---|
150 | 302 | nfp_warn(app->cpp, "Not all reprs responded to reify\n"); |
---|
151 | 303 | return -EIO; |
---|
152 | 304 | } |
---|
.. | .. |
---|
176 | 328 | return nfp_flower_cmsg_portmod(repr, false, repr->netdev->mtu, false); |
---|
177 | 329 | } |
---|
178 | 330 | |
---|
179 | | -static int |
---|
180 | | -nfp_flower_repr_netdev_init(struct nfp_app *app, struct net_device *netdev) |
---|
181 | | -{ |
---|
182 | | - return tc_setup_cb_egdev_register(netdev, |
---|
183 | | - nfp_flower_setup_tc_egress_cb, |
---|
184 | | - netdev_priv(netdev)); |
---|
185 | | -} |
---|
186 | | - |
---|
187 | 331 | static void |
---|
188 | 332 | nfp_flower_repr_netdev_clean(struct nfp_app *app, struct net_device *netdev) |
---|
189 | 333 | { |
---|
190 | 334 | struct nfp_repr *repr = netdev_priv(netdev); |
---|
191 | 335 | |
---|
192 | 336 | kfree(repr->app_priv); |
---|
193 | | - |
---|
194 | | - tc_setup_cb_egdev_unregister(netdev, nfp_flower_setup_tc_egress_cb, |
---|
195 | | - netdev_priv(netdev)); |
---|
196 | 337 | } |
---|
197 | 338 | |
---|
198 | 339 | static void |
---|
.. | .. |
---|
265 | 406 | |
---|
266 | 407 | nfp_repr = netdev_priv(repr); |
---|
267 | 408 | nfp_repr->app_priv = repr_priv; |
---|
| 409 | + repr_priv->nfp_repr = nfp_repr; |
---|
268 | 410 | |
---|
269 | 411 | /* For now we only support 1 PF */ |
---|
270 | 412 | WARN_ON(repr_type == NFP_REPR_TYPE_PF && i); |
---|
.. | .. |
---|
382 | 524 | |
---|
383 | 525 | nfp_repr = netdev_priv(repr); |
---|
384 | 526 | nfp_repr->app_priv = repr_priv; |
---|
| 527 | + repr_priv->nfp_repr = nfp_repr; |
---|
385 | 528 | |
---|
386 | 529 | port = nfp_port_alloc(app, NFP_PORT_PHYS_PORT, repr); |
---|
387 | 530 | if (IS_ERR(port)) { |
---|
.. | .. |
---|
522 | 665 | return err; |
---|
523 | 666 | } |
---|
524 | 667 | |
---|
| 668 | +static void nfp_flower_wait_host_bit(struct nfp_app *app) |
---|
| 669 | +{ |
---|
| 670 | + unsigned long err_at; |
---|
| 671 | + u64 feat; |
---|
| 672 | + int err; |
---|
| 673 | + |
---|
| 674 | + /* Wait for HOST_ACK flag bit to propagate */ |
---|
| 675 | + err_at = jiffies + msecs_to_jiffies(100); |
---|
| 676 | + do { |
---|
| 677 | + feat = nfp_rtsym_read_le(app->pf->rtbl, |
---|
| 678 | + "_abi_flower_combined_features_global", |
---|
| 679 | + &err); |
---|
| 680 | + if (time_is_before_eq_jiffies(err_at)) { |
---|
| 681 | + nfp_warn(app->cpp, |
---|
| 682 | + "HOST_ACK bit not propagated in FW.\n"); |
---|
| 683 | + break; |
---|
| 684 | + } |
---|
| 685 | + usleep_range(1000, 2000); |
---|
| 686 | + } while (!err && !(feat & NFP_FL_FEATS_HOST_ACK)); |
---|
| 687 | + |
---|
| 688 | + if (err) |
---|
| 689 | + nfp_warn(app->cpp, |
---|
| 690 | + "Could not read global features entry from FW\n"); |
---|
| 691 | +} |
---|
| 692 | + |
---|
| 693 | +static int nfp_flower_sync_feature_bits(struct nfp_app *app) |
---|
| 694 | +{ |
---|
| 695 | + struct nfp_flower_priv *app_priv = app->priv; |
---|
| 696 | + int err; |
---|
| 697 | + |
---|
| 698 | + /* Tell the firmware of the host supported features. */ |
---|
| 699 | + err = nfp_rtsym_write_le(app->pf->rtbl, "_abi_flower_host_mask", |
---|
| 700 | + app_priv->flower_ext_feats | |
---|
| 701 | + NFP_FL_FEATS_HOST_ACK); |
---|
| 702 | + if (!err) |
---|
| 703 | + nfp_flower_wait_host_bit(app); |
---|
| 704 | + else if (err != -ENOENT) |
---|
| 705 | + return err; |
---|
| 706 | + |
---|
| 707 | + /* Tell the firmware that the driver supports lag. */ |
---|
| 708 | + err = nfp_rtsym_write_le(app->pf->rtbl, |
---|
| 709 | + "_abi_flower_balance_sync_enable", 1); |
---|
| 710 | + if (!err) { |
---|
| 711 | + app_priv->flower_en_feats |= NFP_FL_ENABLE_LAG; |
---|
| 712 | + nfp_flower_lag_init(&app_priv->nfp_lag); |
---|
| 713 | + } else if (err == -ENOENT) { |
---|
| 714 | + nfp_warn(app->cpp, "LAG not supported by FW.\n"); |
---|
| 715 | + } else { |
---|
| 716 | + return err; |
---|
| 717 | + } |
---|
| 718 | + |
---|
| 719 | + if (app_priv->flower_ext_feats & NFP_FL_FEATS_FLOW_MOD) { |
---|
| 720 | + /* Tell the firmware that the driver supports flow merging. */ |
---|
| 721 | + err = nfp_rtsym_write_le(app->pf->rtbl, |
---|
| 722 | + "_abi_flower_merge_hint_enable", 1); |
---|
| 723 | + if (!err) { |
---|
| 724 | + app_priv->flower_en_feats |= NFP_FL_ENABLE_FLOW_MERGE; |
---|
| 725 | + nfp_flower_internal_port_init(app_priv); |
---|
| 726 | + } else if (err == -ENOENT) { |
---|
| 727 | + nfp_warn(app->cpp, |
---|
| 728 | + "Flow merge not supported by FW.\n"); |
---|
| 729 | + } else { |
---|
| 730 | + return err; |
---|
| 731 | + } |
---|
| 732 | + } else { |
---|
| 733 | + nfp_warn(app->cpp, "Flow mod/merge not supported by FW.\n"); |
---|
| 734 | + } |
---|
| 735 | + |
---|
| 736 | + return 0; |
---|
| 737 | +} |
---|
| 738 | + |
---|
525 | 739 | static int nfp_flower_init(struct nfp_app *app) |
---|
526 | 740 | { |
---|
| 741 | + u64 version, features, ctx_count, num_mems; |
---|
527 | 742 | const struct nfp_pf *pf = app->pf; |
---|
528 | 743 | struct nfp_flower_priv *app_priv; |
---|
529 | | - u64 version, features; |
---|
530 | 744 | int err; |
---|
531 | 745 | |
---|
532 | 746 | if (!pf->eth_tbl) { |
---|
.. | .. |
---|
550 | 764 | return err; |
---|
551 | 765 | } |
---|
552 | 766 | |
---|
| 767 | + num_mems = nfp_rtsym_read_le(app->pf->rtbl, "CONFIG_FC_HOST_CTX_SPLIT", |
---|
| 768 | + &err); |
---|
| 769 | + if (err) { |
---|
| 770 | + nfp_warn(app->cpp, |
---|
| 771 | + "FlowerNIC: unsupported host context memory: %d\n", |
---|
| 772 | + err); |
---|
| 773 | + err = 0; |
---|
| 774 | + num_mems = 1; |
---|
| 775 | + } |
---|
| 776 | + |
---|
| 777 | + if (!FIELD_FIT(NFP_FL_STAT_ID_MU_NUM, num_mems) || !num_mems) { |
---|
| 778 | + nfp_warn(app->cpp, |
---|
| 779 | + "FlowerNIC: invalid host context memory: %llu\n", |
---|
| 780 | + num_mems); |
---|
| 781 | + return -EINVAL; |
---|
| 782 | + } |
---|
| 783 | + |
---|
| 784 | + ctx_count = nfp_rtsym_read_le(app->pf->rtbl, "CONFIG_FC_HOST_CTX_COUNT", |
---|
| 785 | + &err); |
---|
| 786 | + if (err) { |
---|
| 787 | + nfp_warn(app->cpp, |
---|
| 788 | + "FlowerNIC: unsupported host context count: %d\n", |
---|
| 789 | + err); |
---|
| 790 | + err = 0; |
---|
| 791 | + ctx_count = BIT(17); |
---|
| 792 | + } |
---|
| 793 | + |
---|
553 | 794 | /* We need to ensure hardware has enough flower capabilities. */ |
---|
554 | 795 | if (version != NFP_FLOWER_ALLOWED_VER) { |
---|
555 | 796 | nfp_warn(app->cpp, "FlowerNIC: unsupported firmware version\n"); |
---|
.. | .. |
---|
560 | 801 | if (!app_priv) |
---|
561 | 802 | return -ENOMEM; |
---|
562 | 803 | |
---|
| 804 | + app_priv->total_mem_units = num_mems; |
---|
| 805 | + app_priv->active_mem_unit = 0; |
---|
| 806 | + app_priv->stats_ring_size = roundup_pow_of_two(ctx_count); |
---|
563 | 807 | app->priv = app_priv; |
---|
564 | 808 | app_priv->app = app; |
---|
565 | 809 | skb_queue_head_init(&app_priv->cmsg_skbs_high); |
---|
.. | .. |
---|
570 | 814 | init_waitqueue_head(&app_priv->mtu_conf.wait_q); |
---|
571 | 815 | spin_lock_init(&app_priv->mtu_conf.lock); |
---|
572 | 816 | |
---|
573 | | - err = nfp_flower_metadata_init(app); |
---|
| 817 | + err = nfp_flower_metadata_init(app, ctx_count, num_mems); |
---|
574 | 818 | if (err) |
---|
575 | 819 | goto err_free_app_priv; |
---|
576 | 820 | |
---|
.. | .. |
---|
580 | 824 | if (err) |
---|
581 | 825 | app_priv->flower_ext_feats = 0; |
---|
582 | 826 | else |
---|
583 | | - app_priv->flower_ext_feats = features; |
---|
| 827 | + app_priv->flower_ext_feats = features & NFP_FL_FEATS_HOST; |
---|
584 | 828 | |
---|
585 | | - /* Tell the firmware that the driver supports lag. */ |
---|
586 | | - err = nfp_rtsym_write_le(app->pf->rtbl, |
---|
587 | | - "_abi_flower_balance_sync_enable", 1); |
---|
588 | | - if (!err) { |
---|
589 | | - app_priv->flower_ext_feats |= NFP_FL_FEATS_LAG; |
---|
590 | | - nfp_flower_lag_init(&app_priv->nfp_lag); |
---|
591 | | - } else if (err == -ENOENT) { |
---|
592 | | - nfp_warn(app->cpp, "LAG not supported by FW.\n"); |
---|
593 | | - } else { |
---|
594 | | - goto err_cleanup_metadata; |
---|
595 | | - } |
---|
| 829 | + err = nfp_flower_sync_feature_bits(app); |
---|
| 830 | + if (err) |
---|
| 831 | + goto err_cleanup; |
---|
| 832 | + |
---|
| 833 | + if (app_priv->flower_ext_feats & NFP_FL_FEATS_VF_RLIM) |
---|
| 834 | + nfp_flower_qos_init(app); |
---|
| 835 | + |
---|
| 836 | + INIT_LIST_HEAD(&app_priv->indr_block_cb_priv); |
---|
| 837 | + INIT_LIST_HEAD(&app_priv->non_repr_priv); |
---|
| 838 | + app_priv->pre_tun_rule_cnt = 0; |
---|
596 | 839 | |
---|
597 | 840 | return 0; |
---|
598 | 841 | |
---|
599 | | -err_cleanup_metadata: |
---|
| 842 | +err_cleanup: |
---|
| 843 | + if (app_priv->flower_en_feats & NFP_FL_ENABLE_LAG) |
---|
| 844 | + nfp_flower_lag_cleanup(&app_priv->nfp_lag); |
---|
600 | 845 | nfp_flower_metadata_cleanup(app); |
---|
601 | 846 | err_free_app_priv: |
---|
602 | 847 | vfree(app->priv); |
---|
.. | .. |
---|
611 | 856 | skb_queue_purge(&app_priv->cmsg_skbs_low); |
---|
612 | 857 | flush_work(&app_priv->cmsg_work); |
---|
613 | 858 | |
---|
614 | | - if (app_priv->flower_ext_feats & NFP_FL_FEATS_LAG) |
---|
| 859 | + if (app_priv->flower_ext_feats & NFP_FL_FEATS_VF_RLIM) |
---|
| 860 | + nfp_flower_qos_cleanup(app); |
---|
| 861 | + |
---|
| 862 | + if (app_priv->flower_en_feats & NFP_FL_ENABLE_LAG) |
---|
615 | 863 | nfp_flower_lag_cleanup(&app_priv->nfp_lag); |
---|
| 864 | + |
---|
| 865 | + if (app_priv->flower_en_feats & NFP_FL_ENABLE_FLOW_MERGE) |
---|
| 866 | + nfp_flower_internal_port_cleanup(app_priv); |
---|
616 | 867 | |
---|
617 | 868 | nfp_flower_metadata_cleanup(app); |
---|
618 | 869 | vfree(app->priv); |
---|
.. | .. |
---|
636 | 887 | { |
---|
637 | 888 | struct nfp_flower_priv *app_priv = app->priv; |
---|
638 | 889 | struct nfp_repr *repr = netdev_priv(netdev); |
---|
639 | | - int err, ack; |
---|
| 890 | + int err; |
---|
640 | 891 | |
---|
641 | 892 | /* Only need to config FW for physical port MTU change. */ |
---|
642 | 893 | if (repr->port->type != NFP_PORT_PHYS_PORT) |
---|
.. | .. |
---|
663 | 914 | } |
---|
664 | 915 | |
---|
665 | 916 | /* Wait for fw to ack the change. */ |
---|
666 | | - ack = wait_event_timeout(app_priv->mtu_conf.wait_q, |
---|
667 | | - nfp_flower_check_ack(app_priv), |
---|
668 | | - msecs_to_jiffies(10)); |
---|
669 | | - |
---|
670 | | - if (!ack) { |
---|
| 917 | + if (!wait_event_timeout(app_priv->mtu_conf.wait_q, |
---|
| 918 | + nfp_flower_check_ack(app_priv), |
---|
| 919 | + NFP_FL_REPLY_TIMEOUT)) { |
---|
671 | 920 | spin_lock_bh(&app_priv->mtu_conf.lock); |
---|
672 | 921 | app_priv->mtu_conf.requested_val = 0; |
---|
673 | 922 | spin_unlock_bh(&app_priv->mtu_conf.lock); |
---|
.. | .. |
---|
683 | 932 | struct nfp_flower_priv *app_priv = app->priv; |
---|
684 | 933 | int err; |
---|
685 | 934 | |
---|
686 | | - if (app_priv->flower_ext_feats & NFP_FL_FEATS_LAG) { |
---|
| 935 | + if (app_priv->flower_en_feats & NFP_FL_ENABLE_LAG) { |
---|
687 | 936 | err = nfp_flower_lag_reset(&app_priv->nfp_lag); |
---|
688 | | - if (err) |
---|
689 | | - return err; |
---|
690 | | - |
---|
691 | | - err = register_netdevice_notifier(&app_priv->nfp_lag.lag_nb); |
---|
692 | 937 | if (err) |
---|
693 | 938 | return err; |
---|
694 | 939 | } |
---|
695 | 940 | |
---|
696 | | - return nfp_tunnel_config_start(app); |
---|
| 941 | + err = flow_indr_dev_register(nfp_flower_indr_setup_tc_cb, app); |
---|
| 942 | + if (err) |
---|
| 943 | + return err; |
---|
| 944 | + |
---|
| 945 | + err = nfp_tunnel_config_start(app); |
---|
| 946 | + if (err) |
---|
| 947 | + goto err_tunnel_config; |
---|
| 948 | + |
---|
| 949 | + return 0; |
---|
| 950 | + |
---|
| 951 | +err_tunnel_config: |
---|
| 952 | + flow_indr_dev_unregister(nfp_flower_indr_setup_tc_cb, app, |
---|
| 953 | + nfp_flower_setup_indr_tc_release); |
---|
| 954 | + return err; |
---|
697 | 955 | } |
---|
698 | 956 | |
---|
699 | 957 | static void nfp_flower_stop(struct nfp_app *app) |
---|
700 | 958 | { |
---|
701 | | - struct nfp_flower_priv *app_priv = app->priv; |
---|
702 | | - |
---|
703 | | - if (app_priv->flower_ext_feats & NFP_FL_FEATS_LAG) |
---|
704 | | - unregister_netdevice_notifier(&app_priv->nfp_lag.lag_nb); |
---|
705 | | - |
---|
706 | 959 | nfp_tunnel_config_stop(app); |
---|
| 960 | + |
---|
| 961 | + flow_indr_dev_unregister(nfp_flower_indr_setup_tc_cb, app, |
---|
| 962 | + nfp_flower_setup_indr_tc_release); |
---|
| 963 | +} |
---|
| 964 | + |
---|
| 965 | +static int |
---|
| 966 | +nfp_flower_netdev_event(struct nfp_app *app, struct net_device *netdev, |
---|
| 967 | + unsigned long event, void *ptr) |
---|
| 968 | +{ |
---|
| 969 | + struct nfp_flower_priv *app_priv = app->priv; |
---|
| 970 | + int ret; |
---|
| 971 | + |
---|
| 972 | + if (app_priv->flower_en_feats & NFP_FL_ENABLE_LAG) { |
---|
| 973 | + ret = nfp_flower_lag_netdev_event(app_priv, netdev, event, ptr); |
---|
| 974 | + if (ret & NOTIFY_STOP_MASK) |
---|
| 975 | + return ret; |
---|
| 976 | + } |
---|
| 977 | + |
---|
| 978 | + ret = nfp_flower_internal_port_event_handler(app, netdev, event); |
---|
| 979 | + if (ret & NOTIFY_STOP_MASK) |
---|
| 980 | + return ret; |
---|
| 981 | + |
---|
| 982 | + return nfp_tunnel_mac_event_handler(app, netdev, event, ptr); |
---|
707 | 983 | } |
---|
708 | 984 | |
---|
709 | 985 | const struct nfp_app_type app_flower = { |
---|
.. | .. |
---|
724 | 1000 | .vnic_init = nfp_flower_vnic_init, |
---|
725 | 1001 | .vnic_clean = nfp_flower_vnic_clean, |
---|
726 | 1002 | |
---|
727 | | - .repr_init = nfp_flower_repr_netdev_init, |
---|
728 | 1003 | .repr_preclean = nfp_flower_repr_netdev_preclean, |
---|
729 | 1004 | .repr_clean = nfp_flower_repr_netdev_clean, |
---|
730 | 1005 | |
---|
.. | .. |
---|
734 | 1009 | .start = nfp_flower_start, |
---|
735 | 1010 | .stop = nfp_flower_stop, |
---|
736 | 1011 | |
---|
| 1012 | + .netdev_event = nfp_flower_netdev_event, |
---|
| 1013 | + |
---|
737 | 1014 | .ctrl_msg_rx = nfp_flower_cmsg_rx, |
---|
738 | 1015 | |
---|
739 | 1016 | .sriov_enable = nfp_flower_sriov_enable, |
---|
740 | 1017 | .sriov_disable = nfp_flower_sriov_disable, |
---|
741 | 1018 | |
---|
742 | 1019 | .eswitch_mode_get = eswitch_mode_get, |
---|
743 | | - .repr_get = nfp_flower_repr_get, |
---|
| 1020 | + .dev_get = nfp_flower_dev_get, |
---|
744 | 1021 | |
---|
745 | 1022 | .setup_tc = nfp_flower_setup_tc, |
---|
746 | 1023 | }; |
---|