.. | .. |
---|
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/rtnetlink.h> |
---|
35 | 5 | #include <net/devlink.h> |
---|
36 | 6 | |
---|
| 7 | +#include "nfpcore/nfp.h" |
---|
37 | 8 | #include "nfpcore/nfp_nsp.h" |
---|
38 | 9 | #include "nfp_app.h" |
---|
39 | 10 | #include "nfp_main.h" |
---|
.. | .. |
---|
99 | 70 | unsigned int lanes; |
---|
100 | 71 | int ret; |
---|
101 | 72 | |
---|
102 | | - if (count < 2) |
---|
103 | | - return -EINVAL; |
---|
104 | | - |
---|
105 | 73 | mutex_lock(&pf->lock); |
---|
106 | 74 | |
---|
107 | 75 | rtnl_lock(); |
---|
.. | .. |
---|
110 | 78 | if (ret) |
---|
111 | 79 | goto out; |
---|
112 | 80 | |
---|
113 | | - if (eth_port.is_split || eth_port.port_lanes % count) { |
---|
| 81 | + if (eth_port.port_lanes % count) { |
---|
114 | 82 | ret = -EINVAL; |
---|
115 | 83 | goto out; |
---|
116 | 84 | } |
---|
.. | .. |
---|
173 | 141 | static int |
---|
174 | 142 | nfp_devlink_sb_pool_set(struct devlink *devlink, unsigned int sb_index, |
---|
175 | 143 | u16 pool_index, |
---|
176 | | - u32 size, enum devlink_sb_threshold_type threshold_type) |
---|
| 144 | + u32 size, enum devlink_sb_threshold_type threshold_type, |
---|
| 145 | + struct netlink_ext_ack *extack) |
---|
177 | 146 | { |
---|
178 | 147 | struct nfp_pf *pf = devlink_priv(devlink); |
---|
179 | 148 | |
---|
.. | .. |
---|
188 | 157 | return nfp_app_eswitch_mode_get(pf->app, mode); |
---|
189 | 158 | } |
---|
190 | 159 | |
---|
191 | | -static int nfp_devlink_eswitch_mode_set(struct devlink *devlink, u16 mode) |
---|
| 160 | +static int nfp_devlink_eswitch_mode_set(struct devlink *devlink, u16 mode, |
---|
| 161 | + struct netlink_ext_ack *extack) |
---|
192 | 162 | { |
---|
193 | 163 | struct nfp_pf *pf = devlink_priv(devlink); |
---|
194 | 164 | int ret; |
---|
.. | .. |
---|
200 | 170 | return ret; |
---|
201 | 171 | } |
---|
202 | 172 | |
---|
| 173 | +static const struct nfp_devlink_versions_simple { |
---|
| 174 | + const char *key; |
---|
| 175 | + const char *hwinfo; |
---|
| 176 | +} nfp_devlink_versions_hwinfo[] = { |
---|
| 177 | + { DEVLINK_INFO_VERSION_GENERIC_BOARD_ID, "assembly.partno", }, |
---|
| 178 | + { DEVLINK_INFO_VERSION_GENERIC_BOARD_REV, "assembly.revision", }, |
---|
| 179 | + { DEVLINK_INFO_VERSION_GENERIC_BOARD_MANUFACTURE, "assembly.vendor", }, |
---|
| 180 | + { "board.model", /* code name */ "assembly.model", }, |
---|
| 181 | +}; |
---|
| 182 | + |
---|
| 183 | +static int |
---|
| 184 | +nfp_devlink_versions_get_hwinfo(struct nfp_pf *pf, struct devlink_info_req *req) |
---|
| 185 | +{ |
---|
| 186 | + unsigned int i; |
---|
| 187 | + int err; |
---|
| 188 | + |
---|
| 189 | + for (i = 0; i < ARRAY_SIZE(nfp_devlink_versions_hwinfo); i++) { |
---|
| 190 | + const struct nfp_devlink_versions_simple *info; |
---|
| 191 | + const char *val; |
---|
| 192 | + |
---|
| 193 | + info = &nfp_devlink_versions_hwinfo[i]; |
---|
| 194 | + |
---|
| 195 | + val = nfp_hwinfo_lookup(pf->hwinfo, info->hwinfo); |
---|
| 196 | + if (!val) |
---|
| 197 | + continue; |
---|
| 198 | + |
---|
| 199 | + err = devlink_info_version_fixed_put(req, info->key, val); |
---|
| 200 | + if (err) |
---|
| 201 | + return err; |
---|
| 202 | + } |
---|
| 203 | + |
---|
| 204 | + return 0; |
---|
| 205 | +} |
---|
| 206 | + |
---|
| 207 | +static const struct nfp_devlink_versions { |
---|
| 208 | + enum nfp_nsp_versions id; |
---|
| 209 | + const char *key; |
---|
| 210 | +} nfp_devlink_versions_nsp[] = { |
---|
| 211 | + { NFP_VERSIONS_BUNDLE, DEVLINK_INFO_VERSION_GENERIC_FW_BUNDLE_ID, }, |
---|
| 212 | + { NFP_VERSIONS_BSP, DEVLINK_INFO_VERSION_GENERIC_FW_MGMT, }, |
---|
| 213 | + { NFP_VERSIONS_CPLD, "fw.cpld", }, |
---|
| 214 | + { NFP_VERSIONS_APP, DEVLINK_INFO_VERSION_GENERIC_FW_APP, }, |
---|
| 215 | + { NFP_VERSIONS_UNDI, DEVLINK_INFO_VERSION_GENERIC_FW_UNDI, }, |
---|
| 216 | + { NFP_VERSIONS_NCSI, DEVLINK_INFO_VERSION_GENERIC_FW_NCSI, }, |
---|
| 217 | + { NFP_VERSIONS_CFGR, "chip.init", }, |
---|
| 218 | +}; |
---|
| 219 | + |
---|
| 220 | +static int |
---|
| 221 | +nfp_devlink_versions_get_nsp(struct devlink_info_req *req, bool flash, |
---|
| 222 | + const u8 *buf, unsigned int size) |
---|
| 223 | +{ |
---|
| 224 | + unsigned int i; |
---|
| 225 | + int err; |
---|
| 226 | + |
---|
| 227 | + for (i = 0; i < ARRAY_SIZE(nfp_devlink_versions_nsp); i++) { |
---|
| 228 | + const struct nfp_devlink_versions *info; |
---|
| 229 | + const char *version; |
---|
| 230 | + |
---|
| 231 | + info = &nfp_devlink_versions_nsp[i]; |
---|
| 232 | + |
---|
| 233 | + version = nfp_nsp_versions_get(info->id, flash, buf, size); |
---|
| 234 | + if (IS_ERR(version)) { |
---|
| 235 | + if (PTR_ERR(version) == -ENOENT) |
---|
| 236 | + continue; |
---|
| 237 | + else |
---|
| 238 | + return PTR_ERR(version); |
---|
| 239 | + } |
---|
| 240 | + |
---|
| 241 | + if (flash) |
---|
| 242 | + err = devlink_info_version_stored_put(req, info->key, |
---|
| 243 | + version); |
---|
| 244 | + else |
---|
| 245 | + err = devlink_info_version_running_put(req, info->key, |
---|
| 246 | + version); |
---|
| 247 | + if (err) |
---|
| 248 | + return err; |
---|
| 249 | + } |
---|
| 250 | + |
---|
| 251 | + return 0; |
---|
| 252 | +} |
---|
| 253 | + |
---|
| 254 | +static int |
---|
| 255 | +nfp_devlink_info_get(struct devlink *devlink, struct devlink_info_req *req, |
---|
| 256 | + struct netlink_ext_ack *extack) |
---|
| 257 | +{ |
---|
| 258 | + struct nfp_pf *pf = devlink_priv(devlink); |
---|
| 259 | + const char *sn, *vendor, *part; |
---|
| 260 | + struct nfp_nsp *nsp; |
---|
| 261 | + char *buf = NULL; |
---|
| 262 | + int err; |
---|
| 263 | + |
---|
| 264 | + err = devlink_info_driver_name_put(req, "nfp"); |
---|
| 265 | + if (err) |
---|
| 266 | + return err; |
---|
| 267 | + |
---|
| 268 | + vendor = nfp_hwinfo_lookup(pf->hwinfo, "assembly.vendor"); |
---|
| 269 | + part = nfp_hwinfo_lookup(pf->hwinfo, "assembly.partno"); |
---|
| 270 | + sn = nfp_hwinfo_lookup(pf->hwinfo, "assembly.serial"); |
---|
| 271 | + if (vendor && part && sn) { |
---|
| 272 | + char *buf; |
---|
| 273 | + |
---|
| 274 | + buf = kmalloc(strlen(vendor) + strlen(part) + strlen(sn) + 1, |
---|
| 275 | + GFP_KERNEL); |
---|
| 276 | + if (!buf) |
---|
| 277 | + return -ENOMEM; |
---|
| 278 | + |
---|
| 279 | + buf[0] = '\0'; |
---|
| 280 | + strcat(buf, vendor); |
---|
| 281 | + strcat(buf, part); |
---|
| 282 | + strcat(buf, sn); |
---|
| 283 | + |
---|
| 284 | + err = devlink_info_serial_number_put(req, buf); |
---|
| 285 | + kfree(buf); |
---|
| 286 | + if (err) |
---|
| 287 | + return err; |
---|
| 288 | + } |
---|
| 289 | + |
---|
| 290 | + nsp = nfp_nsp_open(pf->cpp); |
---|
| 291 | + if (IS_ERR(nsp)) { |
---|
| 292 | + NL_SET_ERR_MSG_MOD(extack, "can't access NSP"); |
---|
| 293 | + return PTR_ERR(nsp); |
---|
| 294 | + } |
---|
| 295 | + |
---|
| 296 | + if (nfp_nsp_has_versions(nsp)) { |
---|
| 297 | + buf = kzalloc(NFP_NSP_VERSION_BUFSZ, GFP_KERNEL); |
---|
| 298 | + if (!buf) { |
---|
| 299 | + err = -ENOMEM; |
---|
| 300 | + goto err_close_nsp; |
---|
| 301 | + } |
---|
| 302 | + |
---|
| 303 | + err = nfp_nsp_versions(nsp, buf, NFP_NSP_VERSION_BUFSZ); |
---|
| 304 | + if (err) |
---|
| 305 | + goto err_free_buf; |
---|
| 306 | + |
---|
| 307 | + err = nfp_devlink_versions_get_nsp(req, false, |
---|
| 308 | + buf, NFP_NSP_VERSION_BUFSZ); |
---|
| 309 | + if (err) |
---|
| 310 | + goto err_free_buf; |
---|
| 311 | + |
---|
| 312 | + err = nfp_devlink_versions_get_nsp(req, true, |
---|
| 313 | + buf, NFP_NSP_VERSION_BUFSZ); |
---|
| 314 | + if (err) |
---|
| 315 | + goto err_free_buf; |
---|
| 316 | + |
---|
| 317 | + kfree(buf); |
---|
| 318 | + } |
---|
| 319 | + |
---|
| 320 | + nfp_nsp_close(nsp); |
---|
| 321 | + |
---|
| 322 | + return nfp_devlink_versions_get_hwinfo(pf, req); |
---|
| 323 | + |
---|
| 324 | +err_free_buf: |
---|
| 325 | + kfree(buf); |
---|
| 326 | +err_close_nsp: |
---|
| 327 | + nfp_nsp_close(nsp); |
---|
| 328 | + return err; |
---|
| 329 | +} |
---|
| 330 | + |
---|
| 331 | +static int |
---|
| 332 | +nfp_devlink_flash_update(struct devlink *devlink, |
---|
| 333 | + struct devlink_flash_update_params *params, |
---|
| 334 | + struct netlink_ext_ack *extack) |
---|
| 335 | +{ |
---|
| 336 | + return nfp_flash_update_common(devlink_priv(devlink), params->file_name, extack); |
---|
| 337 | +} |
---|
| 338 | + |
---|
203 | 339 | const struct devlink_ops nfp_devlink_ops = { |
---|
204 | 340 | .port_split = nfp_devlink_port_split, |
---|
205 | 341 | .port_unsplit = nfp_devlink_port_unsplit, |
---|
.. | .. |
---|
207 | 343 | .sb_pool_set = nfp_devlink_sb_pool_set, |
---|
208 | 344 | .eswitch_mode_get = nfp_devlink_eswitch_mode_get, |
---|
209 | 345 | .eswitch_mode_set = nfp_devlink_eswitch_mode_set, |
---|
| 346 | + .info_get = nfp_devlink_info_get, |
---|
| 347 | + .flash_update = nfp_devlink_flash_update, |
---|
210 | 348 | }; |
---|
211 | 349 | |
---|
212 | 350 | int nfp_devlink_port_register(struct nfp_app *app, struct nfp_port *port) |
---|
213 | 351 | { |
---|
| 352 | + struct devlink_port_attrs attrs = {}; |
---|
214 | 353 | struct nfp_eth_table_port eth_port; |
---|
215 | 354 | struct devlink *devlink; |
---|
| 355 | + const u8 *serial; |
---|
| 356 | + int serial_len; |
---|
216 | 357 | int ret; |
---|
217 | 358 | |
---|
218 | 359 | rtnl_lock(); |
---|
.. | .. |
---|
221 | 362 | if (ret) |
---|
222 | 363 | return ret; |
---|
223 | 364 | |
---|
224 | | - devlink_port_type_eth_set(&port->dl_port, port->netdev); |
---|
225 | | - devlink_port_attrs_set(&port->dl_port, DEVLINK_PORT_FLAVOUR_PHYSICAL, |
---|
226 | | - eth_port.label_port, eth_port.is_split, |
---|
227 | | - eth_port.label_subport); |
---|
| 365 | + attrs.split = eth_port.is_split; |
---|
| 366 | + attrs.splittable = eth_port.port_lanes > 1 && !attrs.split; |
---|
| 367 | + attrs.lanes = eth_port.port_lanes; |
---|
| 368 | + attrs.flavour = DEVLINK_PORT_FLAVOUR_PHYSICAL; |
---|
| 369 | + attrs.phys.port_number = eth_port.label_port; |
---|
| 370 | + attrs.phys.split_subport_number = eth_port.label_subport; |
---|
| 371 | + serial_len = nfp_cpp_serial(port->app->cpp, &serial); |
---|
| 372 | + memcpy(attrs.switch_id.id, serial, serial_len); |
---|
| 373 | + attrs.switch_id.id_len = serial_len; |
---|
| 374 | + devlink_port_attrs_set(&port->dl_port, &attrs); |
---|
228 | 375 | |
---|
229 | 376 | devlink = priv_to_devlink(app->pf); |
---|
230 | 377 | |
---|
.. | .. |
---|
235 | 382 | { |
---|
236 | 383 | devlink_port_unregister(&port->dl_port); |
---|
237 | 384 | } |
---|
| 385 | + |
---|
| 386 | +void nfp_devlink_port_type_eth_set(struct nfp_port *port) |
---|
| 387 | +{ |
---|
| 388 | + devlink_port_type_eth_set(&port->dl_port, port->netdev); |
---|
| 389 | +} |
---|
| 390 | + |
---|
| 391 | +void nfp_devlink_port_type_clear(struct nfp_port *port) |
---|
| 392 | +{ |
---|
| 393 | + devlink_port_type_clear(&port->dl_port); |
---|
| 394 | +} |
---|
| 395 | + |
---|
| 396 | +struct devlink_port *nfp_devlink_get_devlink_port(struct net_device *netdev) |
---|
| 397 | +{ |
---|
| 398 | + struct nfp_port *port; |
---|
| 399 | + |
---|
| 400 | + port = nfp_port_from_netdev(netdev); |
---|
| 401 | + if (!port) |
---|
| 402 | + return NULL; |
---|
| 403 | + |
---|
| 404 | + return &port->dl_port; |
---|
| 405 | +} |
---|