blob: 1985e58ab0db0a0a1c9a67b6663cfc2554e99bd9 [file] [log] [blame]
Jakub Kicinskic4c8f392018-05-21 22:12:47 -07001// SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
2/*
3 * Copyright (C) 2018 Netronome Systems, Inc.
4 *
5 * This software is dual licensed under the GNU General License Version 2,
6 * June 1991 as shown in the file COPYING in the top-level directory of this
7 * source tree or the BSD 2-Clause License provided below. You have the
8 * option to license this software under the complete terms of either license.
9 *
10 * The BSD 2-Clause License:
11 *
12 * Redistribution and use in source and binary forms, with or
13 * without modification, are permitted provided that the following
14 * conditions are met:
15 *
16 * 1. Redistributions of source code must retain the above
17 * copyright notice, this list of conditions and the following
18 * disclaimer.
19 *
20 * 2. Redistributions in binary form must reproduce the above
21 * copyright notice, this list of conditions and the following
22 * disclaimer in the documentation and/or other materials
23 * provided with the distribution.
24 *
25 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
29 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
30 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
31 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
32 * SOFTWARE.
33 */
34
Jakub Kicinskicc54dc22018-05-21 22:12:48 -070035#include <linux/etherdevice.h>
36
37#include "../nfpcore/nfp.h"
Jakub Kicinskic4c8f392018-05-21 22:12:47 -070038#include "../nfpcore/nfp_cpp.h"
39#include "../nfpcore/nfp_nsp.h"
40#include "../nfp_app.h"
41#include "../nfp_main.h"
Jakub Kicinskicc54dc22018-05-21 22:12:48 -070042#include "../nfp_net.h"
43#include "../nfp_port.h"
Jakub Kicinskic4c8f392018-05-21 22:12:47 -070044#include "main.h"
45
Jakub Kicinskicc54dc22018-05-21 22:12:48 -070046static void
47nfp_abm_vnic_set_mac(struct nfp_pf *pf, struct nfp_abm *abm, struct nfp_net *nn,
48 unsigned int id)
49{
50 struct nfp_eth_table_port *eth_port = &pf->eth_tbl->ports[id];
51 u8 mac_addr[ETH_ALEN];
52 const char *mac_str;
53 char name[32];
54
55 if (id > pf->eth_tbl->count) {
56 nfp_warn(pf->cpp, "No entry for persistent MAC address\n");
57 eth_hw_addr_random(nn->dp.netdev);
58 return;
59 }
60
61 snprintf(name, sizeof(name), "eth%u.mac.pf%u",
62 eth_port->eth_index, abm->pf_id);
63
64 mac_str = nfp_hwinfo_lookup(pf->hwinfo, name);
65 if (!mac_str) {
66 nfp_warn(pf->cpp, "Can't lookup persistent MAC address (%s)\n",
67 name);
68 eth_hw_addr_random(nn->dp.netdev);
69 return;
70 }
71
72 if (sscanf(mac_str, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
73 &mac_addr[0], &mac_addr[1], &mac_addr[2],
74 &mac_addr[3], &mac_addr[4], &mac_addr[5]) != 6) {
75 nfp_warn(pf->cpp, "Can't parse persistent MAC address (%s)\n",
76 mac_str);
77 eth_hw_addr_random(nn->dp.netdev);
78 return;
79 }
80
81 ether_addr_copy(nn->dp.netdev->dev_addr, mac_addr);
82 ether_addr_copy(nn->dp.netdev->perm_addr, mac_addr);
83}
84
85static int
86nfp_abm_vnic_alloc(struct nfp_app *app, struct nfp_net *nn, unsigned int id)
87{
88 struct nfp_abm *abm = app->priv;
89 struct nfp_abm_link *alink;
90 int err;
91
92 alink = kzalloc(sizeof(*alink), GFP_KERNEL);
93 if (!alink)
94 return -ENOMEM;
95 nn->app_priv = alink;
96 alink->abm = abm;
97 alink->vnic = nn;
98 alink->id = id;
99
100 nn->port = nfp_port_alloc(app, NFP_PORT_PHYS_PORT, nn->dp.netdev);
101 if (IS_ERR(nn->port)) {
102 err = PTR_ERR(nn->port);
103 goto err_free_alink;
104 }
105
106 err = nfp_app_nic_vnic_init_phy_port(app->pf, app, nn, id);
107 if (err < 0)
108 goto err_free_port;
109 if (nn->port->type == NFP_PORT_INVALID)
110 /* core will kill this vNIC */
111 return 0;
112
113 nfp_abm_vnic_set_mac(app->pf, abm, nn, id);
114 nfp_abm_ctrl_read_params(alink);
115
116 return 0;
117
118err_free_port:
119 nfp_port_free(nn->port);
120err_free_alink:
121 kfree(alink);
122 return err;
123}
124
125static void nfp_abm_vnic_free(struct nfp_app *app, struct nfp_net *nn)
126{
127 struct nfp_abm_link *alink = nn->app_priv;
128
129 kfree(alink);
130}
131
Jakub Kicinskic4c8f392018-05-21 22:12:47 -0700132static int nfp_abm_init(struct nfp_app *app)
133{
134 struct nfp_pf *pf = app->pf;
135 struct nfp_abm *abm;
Jakub Kicinskicc54dc22018-05-21 22:12:48 -0700136 int err;
Jakub Kicinskic4c8f392018-05-21 22:12:47 -0700137
138 if (!pf->eth_tbl) {
139 nfp_err(pf->cpp, "ABM NIC requires ETH table\n");
140 return -EINVAL;
141 }
142 if (pf->max_data_vnics != pf->eth_tbl->count) {
143 nfp_err(pf->cpp, "ETH entries don't match vNICs (%d vs %d)\n",
144 pf->max_data_vnics, pf->eth_tbl->count);
145 return -EINVAL;
146 }
147 if (!pf->mac_stats_bar) {
148 nfp_warn(app->cpp, "ABM NIC requires mac_stats symbol\n");
149 return -EINVAL;
150 }
151
152 abm = kzalloc(sizeof(*abm), GFP_KERNEL);
153 if (!abm)
154 return -ENOMEM;
155 app->priv = abm;
156 abm->app = app;
157
Jakub Kicinskicc54dc22018-05-21 22:12:48 -0700158 err = nfp_abm_ctrl_find_addrs(abm);
159 if (err)
160 goto err_free_abm;
161
Jakub Kicinskic4c8f392018-05-21 22:12:47 -0700162 return 0;
Jakub Kicinskicc54dc22018-05-21 22:12:48 -0700163
164err_free_abm:
165 kfree(abm);
166 app->priv = NULL;
167 return err;
Jakub Kicinskic4c8f392018-05-21 22:12:47 -0700168}
169
170static void nfp_abm_clean(struct nfp_app *app)
171{
172 struct nfp_abm *abm = app->priv;
173
174 kfree(abm);
175 app->priv = NULL;
176}
177
178const struct nfp_app_type app_abm = {
179 .id = NFP_APP_ACTIVE_BUFFER_MGMT_NIC,
180 .name = "abm",
181
182 .init = nfp_abm_init,
183 .clean = nfp_abm_clean,
184
Jakub Kicinskicc54dc22018-05-21 22:12:48 -0700185 .vnic_alloc = nfp_abm_vnic_alloc,
186 .vnic_free = nfp_abm_vnic_free,
Jakub Kicinskic4c8f392018-05-21 22:12:47 -0700187};