root/drivers/net/ethernet/netronome/nfp/nfp_devlink.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. nfp_devlink_fill_eth_port
  2. nfp_devlink_fill_eth_port_from_id
  3. nfp_devlink_set_lanes
  4. nfp_devlink_port_split
  5. nfp_devlink_port_unsplit
  6. nfp_devlink_sb_pool_get
  7. nfp_devlink_sb_pool_set
  8. nfp_devlink_eswitch_mode_get
  9. nfp_devlink_eswitch_mode_set
  10. nfp_devlink_versions_get_hwinfo
  11. nfp_devlink_versions_get_nsp
  12. nfp_devlink_info_get
  13. nfp_devlink_flash_update
  14. nfp_devlink_port_register
  15. nfp_devlink_port_unregister
  16. nfp_devlink_port_type_eth_set
  17. nfp_devlink_port_type_clear
  18. nfp_devlink_get_devlink_port

   1 // SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
   2 /* Copyright (C) 2017-2018 Netronome Systems, Inc. */
   3 
   4 #include <linux/rtnetlink.h>
   5 #include <net/devlink.h>
   6 
   7 #include "nfpcore/nfp.h"
   8 #include "nfpcore/nfp_nsp.h"
   9 #include "nfp_app.h"
  10 #include "nfp_main.h"
  11 #include "nfp_port.h"
  12 
  13 static int
  14 nfp_devlink_fill_eth_port(struct nfp_port *port,
  15                           struct nfp_eth_table_port *copy)
  16 {
  17         struct nfp_eth_table_port *eth_port;
  18 
  19         eth_port = __nfp_port_get_eth_port(port);
  20         if (!eth_port)
  21                 return -EINVAL;
  22 
  23         memcpy(copy, eth_port, sizeof(*eth_port));
  24 
  25         return 0;
  26 }
  27 
  28 static int
  29 nfp_devlink_fill_eth_port_from_id(struct nfp_pf *pf, unsigned int port_index,
  30                                   struct nfp_eth_table_port *copy)
  31 {
  32         struct nfp_port *port;
  33 
  34         port = nfp_port_from_id(pf, NFP_PORT_PHYS_PORT, port_index);
  35 
  36         return nfp_devlink_fill_eth_port(port, copy);
  37 }
  38 
  39 static int
  40 nfp_devlink_set_lanes(struct nfp_pf *pf, unsigned int idx, unsigned int lanes)
  41 {
  42         struct nfp_nsp *nsp;
  43         int ret;
  44 
  45         nsp = nfp_eth_config_start(pf->cpp, idx);
  46         if (IS_ERR(nsp))
  47                 return PTR_ERR(nsp);
  48 
  49         ret = __nfp_eth_set_split(nsp, lanes);
  50         if (ret) {
  51                 nfp_eth_config_cleanup_end(nsp);
  52                 return ret;
  53         }
  54 
  55         ret = nfp_eth_config_commit_end(nsp);
  56         if (ret < 0)
  57                 return ret;
  58         if (ret) /* no change */
  59                 return 0;
  60 
  61         return nfp_net_refresh_port_table_sync(pf);
  62 }
  63 
  64 static int
  65 nfp_devlink_port_split(struct devlink *devlink, unsigned int port_index,
  66                        unsigned int count, struct netlink_ext_ack *extack)
  67 {
  68         struct nfp_pf *pf = devlink_priv(devlink);
  69         struct nfp_eth_table_port eth_port;
  70         unsigned int lanes;
  71         int ret;
  72 
  73         if (count < 2)
  74                 return -EINVAL;
  75 
  76         mutex_lock(&pf->lock);
  77 
  78         rtnl_lock();
  79         ret = nfp_devlink_fill_eth_port_from_id(pf, port_index, &eth_port);
  80         rtnl_unlock();
  81         if (ret)
  82                 goto out;
  83 
  84         if (eth_port.is_split || eth_port.port_lanes % count) {
  85                 ret = -EINVAL;
  86                 goto out;
  87         }
  88 
  89         /* Special case the 100G CXP -> 2x40G split */
  90         lanes = eth_port.port_lanes / count;
  91         if (eth_port.lanes == 10 && count == 2)
  92                 lanes = 8 / count;
  93 
  94         ret = nfp_devlink_set_lanes(pf, eth_port.index, lanes);
  95 out:
  96         mutex_unlock(&pf->lock);
  97 
  98         return ret;
  99 }
 100 
 101 static int
 102 nfp_devlink_port_unsplit(struct devlink *devlink, unsigned int port_index,
 103                          struct netlink_ext_ack *extack)
 104 {
 105         struct nfp_pf *pf = devlink_priv(devlink);
 106         struct nfp_eth_table_port eth_port;
 107         unsigned int lanes;
 108         int ret;
 109 
 110         mutex_lock(&pf->lock);
 111 
 112         rtnl_lock();
 113         ret = nfp_devlink_fill_eth_port_from_id(pf, port_index, &eth_port);
 114         rtnl_unlock();
 115         if (ret)
 116                 goto out;
 117 
 118         if (!eth_port.is_split) {
 119                 ret = -EINVAL;
 120                 goto out;
 121         }
 122 
 123         /* Special case the 100G CXP -> 2x40G unsplit */
 124         lanes = eth_port.port_lanes;
 125         if (eth_port.port_lanes == 8)
 126                 lanes = 10;
 127 
 128         ret = nfp_devlink_set_lanes(pf, eth_port.index, lanes);
 129 out:
 130         mutex_unlock(&pf->lock);
 131 
 132         return ret;
 133 }
 134 
 135 static int
 136 nfp_devlink_sb_pool_get(struct devlink *devlink, unsigned int sb_index,
 137                         u16 pool_index, struct devlink_sb_pool_info *pool_info)
 138 {
 139         struct nfp_pf *pf = devlink_priv(devlink);
 140 
 141         return nfp_shared_buf_pool_get(pf, sb_index, pool_index, pool_info);
 142 }
 143 
 144 static int
 145 nfp_devlink_sb_pool_set(struct devlink *devlink, unsigned int sb_index,
 146                         u16 pool_index,
 147                         u32 size, enum devlink_sb_threshold_type threshold_type,
 148                         struct netlink_ext_ack *extack)
 149 {
 150         struct nfp_pf *pf = devlink_priv(devlink);
 151 
 152         return nfp_shared_buf_pool_set(pf, sb_index, pool_index,
 153                                        size, threshold_type);
 154 }
 155 
 156 static int nfp_devlink_eswitch_mode_get(struct devlink *devlink, u16 *mode)
 157 {
 158         struct nfp_pf *pf = devlink_priv(devlink);
 159 
 160         return nfp_app_eswitch_mode_get(pf->app, mode);
 161 }
 162 
 163 static int nfp_devlink_eswitch_mode_set(struct devlink *devlink, u16 mode,
 164                                         struct netlink_ext_ack *extack)
 165 {
 166         struct nfp_pf *pf = devlink_priv(devlink);
 167         int ret;
 168 
 169         mutex_lock(&pf->lock);
 170         ret = nfp_app_eswitch_mode_set(pf->app, mode);
 171         mutex_unlock(&pf->lock);
 172 
 173         return ret;
 174 }
 175 
 176 static const struct nfp_devlink_versions_simple {
 177         const char *key;
 178         const char *hwinfo;
 179 } nfp_devlink_versions_hwinfo[] = {
 180         { DEVLINK_INFO_VERSION_GENERIC_BOARD_ID,        "assembly.partno", },
 181         { DEVLINK_INFO_VERSION_GENERIC_BOARD_REV,       "assembly.revision", },
 182         { DEVLINK_INFO_VERSION_GENERIC_BOARD_MANUFACTURE, "assembly.vendor", },
 183         { "board.model", /* code name */                "assembly.model", },
 184 };
 185 
 186 static int
 187 nfp_devlink_versions_get_hwinfo(struct nfp_pf *pf, struct devlink_info_req *req)
 188 {
 189         unsigned int i;
 190         int err;
 191 
 192         for (i = 0; i < ARRAY_SIZE(nfp_devlink_versions_hwinfo); i++) {
 193                 const struct nfp_devlink_versions_simple *info;
 194                 const char *val;
 195 
 196                 info = &nfp_devlink_versions_hwinfo[i];
 197 
 198                 val = nfp_hwinfo_lookup(pf->hwinfo, info->hwinfo);
 199                 if (!val)
 200                         continue;
 201 
 202                 err = devlink_info_version_fixed_put(req, info->key, val);
 203                 if (err)
 204                         return err;
 205         }
 206 
 207         return 0;
 208 }
 209 
 210 static const struct nfp_devlink_versions {
 211         enum nfp_nsp_versions id;
 212         const char *key;
 213 } nfp_devlink_versions_nsp[] = {
 214         { NFP_VERSIONS_BUNDLE,  "fw.bundle_id", },
 215         { NFP_VERSIONS_BSP,     DEVLINK_INFO_VERSION_GENERIC_FW_MGMT, },
 216         { NFP_VERSIONS_CPLD,    "fw.cpld", },
 217         { NFP_VERSIONS_APP,     DEVLINK_INFO_VERSION_GENERIC_FW_APP, },
 218         { NFP_VERSIONS_UNDI,    DEVLINK_INFO_VERSION_GENERIC_FW_UNDI, },
 219         { NFP_VERSIONS_NCSI,    DEVLINK_INFO_VERSION_GENERIC_FW_NCSI, },
 220         { NFP_VERSIONS_CFGR,    "chip.init", },
 221 };
 222 
 223 static int
 224 nfp_devlink_versions_get_nsp(struct devlink_info_req *req, bool flash,
 225                              const u8 *buf, unsigned int size)
 226 {
 227         unsigned int i;
 228         int err;
 229 
 230         for (i = 0; i < ARRAY_SIZE(nfp_devlink_versions_nsp); i++) {
 231                 const struct nfp_devlink_versions *info;
 232                 const char *version;
 233 
 234                 info = &nfp_devlink_versions_nsp[i];
 235 
 236                 version = nfp_nsp_versions_get(info->id, flash, buf, size);
 237                 if (IS_ERR(version)) {
 238                         if (PTR_ERR(version) == -ENOENT)
 239                                 continue;
 240                         else
 241                                 return PTR_ERR(version);
 242                 }
 243 
 244                 if (flash)
 245                         err = devlink_info_version_stored_put(req, info->key,
 246                                                               version);
 247                 else
 248                         err = devlink_info_version_running_put(req, info->key,
 249                                                                version);
 250                 if (err)
 251                         return err;
 252         }
 253 
 254         return 0;
 255 }
 256 
 257 static int
 258 nfp_devlink_info_get(struct devlink *devlink, struct devlink_info_req *req,
 259                      struct netlink_ext_ack *extack)
 260 {
 261         struct nfp_pf *pf = devlink_priv(devlink);
 262         const char *sn, *vendor, *part;
 263         struct nfp_nsp *nsp;
 264         char *buf = NULL;
 265         int err;
 266 
 267         err = devlink_info_driver_name_put(req, "nfp");
 268         if (err)
 269                 return err;
 270 
 271         vendor = nfp_hwinfo_lookup(pf->hwinfo, "assembly.vendor");
 272         part = nfp_hwinfo_lookup(pf->hwinfo, "assembly.partno");
 273         sn = nfp_hwinfo_lookup(pf->hwinfo, "assembly.serial");
 274         if (vendor && part && sn) {
 275                 char *buf;
 276 
 277                 buf = kmalloc(strlen(vendor) + strlen(part) + strlen(sn) + 1,
 278                               GFP_KERNEL);
 279                 if (!buf)
 280                         return -ENOMEM;
 281 
 282                 buf[0] = '\0';
 283                 strcat(buf, vendor);
 284                 strcat(buf, part);
 285                 strcat(buf, sn);
 286 
 287                 err = devlink_info_serial_number_put(req, buf);
 288                 kfree(buf);
 289                 if (err)
 290                         return err;
 291         }
 292 
 293         nsp = nfp_nsp_open(pf->cpp);
 294         if (IS_ERR(nsp)) {
 295                 NL_SET_ERR_MSG_MOD(extack, "can't access NSP");
 296                 return PTR_ERR(nsp);
 297         }
 298 
 299         if (nfp_nsp_has_versions(nsp)) {
 300                 buf = kzalloc(NFP_NSP_VERSION_BUFSZ, GFP_KERNEL);
 301                 if (!buf) {
 302                         err = -ENOMEM;
 303                         goto err_close_nsp;
 304                 }
 305 
 306                 err = nfp_nsp_versions(nsp, buf, NFP_NSP_VERSION_BUFSZ);
 307                 if (err)
 308                         goto err_free_buf;
 309 
 310                 err = nfp_devlink_versions_get_nsp(req, false,
 311                                                    buf, NFP_NSP_VERSION_BUFSZ);
 312                 if (err)
 313                         goto err_free_buf;
 314 
 315                 err = nfp_devlink_versions_get_nsp(req, true,
 316                                                    buf, NFP_NSP_VERSION_BUFSZ);
 317                 if (err)
 318                         goto err_free_buf;
 319 
 320                 kfree(buf);
 321         }
 322 
 323         nfp_nsp_close(nsp);
 324 
 325         return nfp_devlink_versions_get_hwinfo(pf, req);
 326 
 327 err_free_buf:
 328         kfree(buf);
 329 err_close_nsp:
 330         nfp_nsp_close(nsp);
 331         return err;
 332 }
 333 
 334 static int
 335 nfp_devlink_flash_update(struct devlink *devlink, const char *path,
 336                          const char *component, struct netlink_ext_ack *extack)
 337 {
 338         if (component)
 339                 return -EOPNOTSUPP;
 340         return nfp_flash_update_common(devlink_priv(devlink), path, extack);
 341 }
 342 
 343 const struct devlink_ops nfp_devlink_ops = {
 344         .port_split             = nfp_devlink_port_split,
 345         .port_unsplit           = nfp_devlink_port_unsplit,
 346         .sb_pool_get            = nfp_devlink_sb_pool_get,
 347         .sb_pool_set            = nfp_devlink_sb_pool_set,
 348         .eswitch_mode_get       = nfp_devlink_eswitch_mode_get,
 349         .eswitch_mode_set       = nfp_devlink_eswitch_mode_set,
 350         .info_get               = nfp_devlink_info_get,
 351         .flash_update           = nfp_devlink_flash_update,
 352 };
 353 
 354 int nfp_devlink_port_register(struct nfp_app *app, struct nfp_port *port)
 355 {
 356         struct nfp_eth_table_port eth_port;
 357         struct devlink *devlink;
 358         const u8 *serial;
 359         int serial_len;
 360         int ret;
 361 
 362         rtnl_lock();
 363         ret = nfp_devlink_fill_eth_port(port, &eth_port);
 364         rtnl_unlock();
 365         if (ret)
 366                 return ret;
 367 
 368         serial_len = nfp_cpp_serial(port->app->cpp, &serial);
 369         devlink_port_attrs_set(&port->dl_port, DEVLINK_PORT_FLAVOUR_PHYSICAL,
 370                                eth_port.label_port, eth_port.is_split,
 371                                eth_port.label_subport, serial, serial_len);
 372 
 373         devlink = priv_to_devlink(app->pf);
 374 
 375         return devlink_port_register(devlink, &port->dl_port, port->eth_id);
 376 }
 377 
 378 void nfp_devlink_port_unregister(struct nfp_port *port)
 379 {
 380         devlink_port_unregister(&port->dl_port);
 381 }
 382 
 383 void nfp_devlink_port_type_eth_set(struct nfp_port *port)
 384 {
 385         devlink_port_type_eth_set(&port->dl_port, port->netdev);
 386 }
 387 
 388 void nfp_devlink_port_type_clear(struct nfp_port *port)
 389 {
 390         devlink_port_type_clear(&port->dl_port);
 391 }
 392 
 393 struct devlink_port *nfp_devlink_get_devlink_port(struct net_device *netdev)
 394 {
 395         struct nfp_port *port;
 396 
 397         port = nfp_port_from_netdev(netdev);
 398         if (!port)
 399                 return NULL;
 400 
 401         return &port->dl_port;
 402 }

/* [<][>][^][v][top][bottom][index][help] */