linux/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp_eth.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2015-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 */
  33
  34/* Authors: David Brunecz <david.brunecz@netronome.com>
  35 *          Jakub Kicinski <jakub.kicinski@netronome.com>
  36 *          Jason Mcmullan <jason.mcmullan@netronome.com>
  37 */
  38
  39#include <linux/bitfield.h>
  40#include <linux/ethtool.h>
  41#include <linux/if_ether.h>
  42#include <linux/kernel.h>
  43#include <linux/module.h>
  44
  45#include "nfp.h"
  46#include "nfp_nsp.h"
  47#include "nfp6000/nfp6000.h"
  48
  49#define NSP_ETH_NBI_PORT_COUNT          24
  50#define NSP_ETH_MAX_COUNT               (2 * NSP_ETH_NBI_PORT_COUNT)
  51#define NSP_ETH_TABLE_SIZE              (NSP_ETH_MAX_COUNT *            \
  52                                         sizeof(union eth_table_entry))
  53
  54#define NSP_ETH_PORT_LANES              GENMASK_ULL(3, 0)
  55#define NSP_ETH_PORT_INDEX              GENMASK_ULL(15, 8)
  56#define NSP_ETH_PORT_LABEL              GENMASK_ULL(53, 48)
  57#define NSP_ETH_PORT_PHYLABEL           GENMASK_ULL(59, 54)
  58
  59#define NSP_ETH_PORT_LANES_MASK         cpu_to_le64(NSP_ETH_PORT_LANES)
  60
  61#define NSP_ETH_STATE_CONFIGURED        BIT_ULL(0)
  62#define NSP_ETH_STATE_ENABLED           BIT_ULL(1)
  63#define NSP_ETH_STATE_TX_ENABLED        BIT_ULL(2)
  64#define NSP_ETH_STATE_RX_ENABLED        BIT_ULL(3)
  65#define NSP_ETH_STATE_RATE              GENMASK_ULL(11, 8)
  66#define NSP_ETH_STATE_INTERFACE         GENMASK_ULL(19, 12)
  67#define NSP_ETH_STATE_MEDIA             GENMASK_ULL(21, 20)
  68#define NSP_ETH_STATE_OVRD_CHNG         BIT_ULL(22)
  69#define NSP_ETH_STATE_ANEG              GENMASK_ULL(25, 23)
  70
  71#define NSP_ETH_CTRL_CONFIGURED         BIT_ULL(0)
  72#define NSP_ETH_CTRL_ENABLED            BIT_ULL(1)
  73#define NSP_ETH_CTRL_TX_ENABLED         BIT_ULL(2)
  74#define NSP_ETH_CTRL_RX_ENABLED         BIT_ULL(3)
  75#define NSP_ETH_CTRL_SET_RATE           BIT_ULL(4)
  76#define NSP_ETH_CTRL_SET_LANES          BIT_ULL(5)
  77#define NSP_ETH_CTRL_SET_ANEG           BIT_ULL(6)
  78
  79enum nfp_eth_raw {
  80        NSP_ETH_RAW_PORT = 0,
  81        NSP_ETH_RAW_STATE,
  82        NSP_ETH_RAW_MAC,
  83        NSP_ETH_RAW_CONTROL,
  84
  85        NSP_ETH_NUM_RAW
  86};
  87
  88enum nfp_eth_rate {
  89        RATE_INVALID = 0,
  90        RATE_10M,
  91        RATE_100M,
  92        RATE_1G,
  93        RATE_10G,
  94        RATE_25G,
  95};
  96
  97union eth_table_entry {
  98        struct {
  99                __le64 port;
 100                __le64 state;
 101                u8 mac_addr[6];
 102                u8 resv[2];
 103                __le64 control;
 104        };
 105        __le64 raw[NSP_ETH_NUM_RAW];
 106};
 107
 108static const struct {
 109        enum nfp_eth_rate rate;
 110        unsigned int speed;
 111} nsp_eth_rate_tbl[] = {
 112        { RATE_INVALID, 0, },
 113        { RATE_10M,     SPEED_10, },
 114        { RATE_100M,    SPEED_100, },
 115        { RATE_1G,      SPEED_1000, },
 116        { RATE_10G,     SPEED_10000, },
 117        { RATE_25G,     SPEED_25000, },
 118};
 119
 120static unsigned int nfp_eth_rate2speed(enum nfp_eth_rate rate)
 121{
 122        int i;
 123
 124        for (i = 0; i < ARRAY_SIZE(nsp_eth_rate_tbl); i++)
 125                if (nsp_eth_rate_tbl[i].rate == rate)
 126                        return nsp_eth_rate_tbl[i].speed;
 127
 128        return 0;
 129}
 130
 131static unsigned int nfp_eth_speed2rate(unsigned int speed)
 132{
 133        int i;
 134
 135        for (i = 0; i < ARRAY_SIZE(nsp_eth_rate_tbl); i++)
 136                if (nsp_eth_rate_tbl[i].speed == speed)
 137                        return nsp_eth_rate_tbl[i].rate;
 138
 139        return RATE_INVALID;
 140}
 141
 142static void nfp_eth_copy_mac_reverse(u8 *dst, const u8 *src)
 143{
 144        int i;
 145
 146        for (i = 0; i < ETH_ALEN; i++)
 147                dst[ETH_ALEN - i - 1] = src[i];
 148}
 149
 150static void
 151nfp_eth_port_translate(struct nfp_nsp *nsp, const union eth_table_entry *src,
 152                       unsigned int index, struct nfp_eth_table_port *dst)
 153{
 154        unsigned int rate;
 155        u64 port, state;
 156
 157        port = le64_to_cpu(src->port);
 158        state = le64_to_cpu(src->state);
 159
 160        dst->eth_index = FIELD_GET(NSP_ETH_PORT_INDEX, port);
 161        dst->index = index;
 162        dst->nbi = index / NSP_ETH_NBI_PORT_COUNT;
 163        dst->base = index % NSP_ETH_NBI_PORT_COUNT;
 164        dst->lanes = FIELD_GET(NSP_ETH_PORT_LANES, port);
 165
 166        dst->enabled = FIELD_GET(NSP_ETH_STATE_ENABLED, state);
 167        dst->tx_enabled = FIELD_GET(NSP_ETH_STATE_TX_ENABLED, state);
 168        dst->rx_enabled = FIELD_GET(NSP_ETH_STATE_RX_ENABLED, state);
 169
 170        rate = nfp_eth_rate2speed(FIELD_GET(NSP_ETH_STATE_RATE, state));
 171        dst->speed = dst->lanes * rate;
 172
 173        dst->interface = FIELD_GET(NSP_ETH_STATE_INTERFACE, state);
 174        dst->media = FIELD_GET(NSP_ETH_STATE_MEDIA, state);
 175
 176        nfp_eth_copy_mac_reverse(dst->mac_addr, src->mac_addr);
 177
 178        dst->label_port = FIELD_GET(NSP_ETH_PORT_PHYLABEL, port);
 179        dst->label_subport = FIELD_GET(NSP_ETH_PORT_LABEL, port);
 180
 181        if (nfp_nsp_get_abi_ver_minor(nsp) < 17)
 182                return;
 183
 184        dst->override_changed = FIELD_GET(NSP_ETH_STATE_OVRD_CHNG, state);
 185        dst->aneg = FIELD_GET(NSP_ETH_STATE_ANEG, state);
 186}
 187
 188static void
 189nfp_eth_mark_split_ports(struct nfp_cpp *cpp, struct nfp_eth_table *table)
 190{
 191        unsigned int i, j;
 192
 193        for (i = 0; i < table->count; i++)
 194                for (j = 0; j < table->count; j++) {
 195                        if (i == j)
 196                                continue;
 197                        if (table->ports[i].label_port !=
 198                            table->ports[j].label_port)
 199                                continue;
 200                        if (table->ports[i].label_subport ==
 201                            table->ports[j].label_subport)
 202                                nfp_warn(cpp,
 203                                         "Port %d subport %d is a duplicate\n",
 204                                         table->ports[i].label_port,
 205                                         table->ports[i].label_subport);
 206
 207                        table->ports[i].is_split = true;
 208                        break;
 209                }
 210}
 211
 212static void
 213nfp_eth_calc_port_type(struct nfp_cpp *cpp, struct nfp_eth_table_port *entry)
 214{
 215        if (entry->interface == NFP_INTERFACE_NONE) {
 216                entry->port_type = PORT_NONE;
 217                return;
 218        }
 219
 220        if (entry->media == NFP_MEDIA_FIBRE)
 221                entry->port_type = PORT_FIBRE;
 222        else
 223                entry->port_type = PORT_DA;
 224}
 225
 226/**
 227 * nfp_eth_read_ports() - retrieve port information
 228 * @cpp:        NFP CPP handle
 229 *
 230 * Read the port information from the device.  Returned structure should
 231 * be freed with kfree() once no longer needed.
 232 *
 233 * Return: populated ETH table or NULL on error.
 234 */
 235struct nfp_eth_table *nfp_eth_read_ports(struct nfp_cpp *cpp)
 236{
 237        struct nfp_eth_table *ret;
 238        struct nfp_nsp *nsp;
 239
 240        nsp = nfp_nsp_open(cpp);
 241        if (IS_ERR(nsp))
 242                return NULL;
 243
 244        ret = __nfp_eth_read_ports(cpp, nsp);
 245        nfp_nsp_close(nsp);
 246
 247        return ret;
 248}
 249
 250struct nfp_eth_table *
 251__nfp_eth_read_ports(struct nfp_cpp *cpp, struct nfp_nsp *nsp)
 252{
 253        union eth_table_entry *entries;
 254        struct nfp_eth_table *table;
 255        int i, j, ret, cnt = 0;
 256
 257        entries = kzalloc(NSP_ETH_TABLE_SIZE, GFP_KERNEL);
 258        if (!entries)
 259                return NULL;
 260
 261        ret = nfp_nsp_read_eth_table(nsp, entries, NSP_ETH_TABLE_SIZE);
 262        if (ret < 0) {
 263                nfp_err(cpp, "reading port table failed %d\n", ret);
 264                goto err;
 265        }
 266
 267        for (i = 0; i < NSP_ETH_MAX_COUNT; i++)
 268                if (entries[i].port & NSP_ETH_PORT_LANES_MASK)
 269                        cnt++;
 270
 271        /* Some versions of flash will give us 0 instead of port count.
 272         * For those that give a port count, verify it against the value
 273         * calculated above.
 274         */
 275        if (ret && ret != cnt) {
 276                nfp_err(cpp, "table entry count reported (%d) does not match entries present (%d)\n",
 277                        ret, cnt);
 278                goto err;
 279        }
 280
 281        table = kzalloc(sizeof(*table) +
 282                        sizeof(struct nfp_eth_table_port) * cnt, GFP_KERNEL);
 283        if (!table)
 284                goto err;
 285
 286        table->count = cnt;
 287        for (i = 0, j = 0; i < NSP_ETH_MAX_COUNT; i++)
 288                if (entries[i].port & NSP_ETH_PORT_LANES_MASK)
 289                        nfp_eth_port_translate(nsp, &entries[i], i,
 290                                               &table->ports[j++]);
 291
 292        nfp_eth_mark_split_ports(cpp, table);
 293        for (i = 0; i < table->count; i++)
 294                nfp_eth_calc_port_type(cpp, &table->ports[i]);
 295
 296        kfree(entries);
 297
 298        return table;
 299
 300err:
 301        kfree(entries);
 302        return NULL;
 303}
 304
 305struct nfp_nsp *nfp_eth_config_start(struct nfp_cpp *cpp, unsigned int idx)
 306{
 307        union eth_table_entry *entries;
 308        struct nfp_nsp *nsp;
 309        int ret;
 310
 311        entries = kzalloc(NSP_ETH_TABLE_SIZE, GFP_KERNEL);
 312        if (!entries)
 313                return ERR_PTR(-ENOMEM);
 314
 315        nsp = nfp_nsp_open(cpp);
 316        if (IS_ERR(nsp)) {
 317                kfree(entries);
 318                return nsp;
 319        }
 320
 321        ret = nfp_nsp_read_eth_table(nsp, entries, NSP_ETH_TABLE_SIZE);
 322        if (ret < 0) {
 323                nfp_err(cpp, "reading port table failed %d\n", ret);
 324                goto err;
 325        }
 326
 327        if (!(entries[idx].port & NSP_ETH_PORT_LANES_MASK)) {
 328                nfp_warn(cpp, "trying to set port state on disabled port %d\n",
 329                         idx);
 330                goto err;
 331        }
 332
 333        nfp_nsp_config_set_state(nsp, entries, idx);
 334        return nsp;
 335
 336err:
 337        nfp_nsp_close(nsp);
 338        kfree(entries);
 339        return ERR_PTR(-EIO);
 340}
 341
 342void nfp_eth_config_cleanup_end(struct nfp_nsp *nsp)
 343{
 344        union eth_table_entry *entries = nfp_nsp_config_entries(nsp);
 345
 346        nfp_nsp_config_set_modified(nsp, false);
 347        nfp_nsp_config_clear_state(nsp);
 348        nfp_nsp_close(nsp);
 349        kfree(entries);
 350}
 351
 352/**
 353 * nfp_eth_config_commit_end() - perform recorded configuration changes
 354 * @nsp:        NFP NSP handle returned from nfp_eth_config_start()
 355 *
 356 * Perform the configuration which was requested with __nfp_eth_set_*()
 357 * helpers and recorded in @nsp state.  If device was already configured
 358 * as requested or no __nfp_eth_set_*() operations were made no NSP command
 359 * will be performed.
 360 *
 361 * Return:
 362 * 0 - configuration successful;
 363 * 1 - no changes were needed;
 364 * -ERRNO - configuration failed.
 365 */
 366int nfp_eth_config_commit_end(struct nfp_nsp *nsp)
 367{
 368        union eth_table_entry *entries = nfp_nsp_config_entries(nsp);
 369        int ret = 1;
 370
 371        if (nfp_nsp_config_modified(nsp)) {
 372                ret = nfp_nsp_write_eth_table(nsp, entries, NSP_ETH_TABLE_SIZE);
 373                ret = ret < 0 ? ret : 0;
 374        }
 375
 376        nfp_eth_config_cleanup_end(nsp);
 377
 378        return ret;
 379}
 380
 381/**
 382 * nfp_eth_set_mod_enable() - set PHY module enable control bit
 383 * @cpp:        NFP CPP handle
 384 * @idx:        NFP chip-wide port index
 385 * @enable:     Desired state
 386 *
 387 * Enable or disable PHY module (this usually means setting the TX lanes
 388 * disable bits).
 389 *
 390 * Return: 0 or -ERRNO.
 391 */
 392int nfp_eth_set_mod_enable(struct nfp_cpp *cpp, unsigned int idx, bool enable)
 393{
 394        union eth_table_entry *entries;
 395        struct nfp_nsp *nsp;
 396        u64 reg;
 397
 398        nsp = nfp_eth_config_start(cpp, idx);
 399        if (IS_ERR(nsp))
 400                return PTR_ERR(nsp);
 401
 402        entries = nfp_nsp_config_entries(nsp);
 403
 404        /* Check if we are already in requested state */
 405        reg = le64_to_cpu(entries[idx].state);
 406        if (enable != FIELD_GET(NSP_ETH_CTRL_ENABLED, reg)) {
 407                reg = le64_to_cpu(entries[idx].control);
 408                reg &= ~NSP_ETH_CTRL_ENABLED;
 409                reg |= FIELD_PREP(NSP_ETH_CTRL_ENABLED, enable);
 410                entries[idx].control = cpu_to_le64(reg);
 411
 412                nfp_nsp_config_set_modified(nsp, true);
 413        }
 414
 415        return nfp_eth_config_commit_end(nsp);
 416}
 417
 418/**
 419 * nfp_eth_set_configured() - set PHY module configured control bit
 420 * @cpp:        NFP CPP handle
 421 * @idx:        NFP chip-wide port index
 422 * @configed:   Desired state
 423 *
 424 * Set the ifup/ifdown state on the PHY.
 425 *
 426 * Return: 0 or -ERRNO.
 427 */
 428int nfp_eth_set_configured(struct nfp_cpp *cpp, unsigned int idx, bool configed)
 429{
 430        union eth_table_entry *entries;
 431        struct nfp_nsp *nsp;
 432        u64 reg;
 433
 434        nsp = nfp_eth_config_start(cpp, idx);
 435        if (IS_ERR(nsp))
 436                return PTR_ERR(nsp);
 437
 438        entries = nfp_nsp_config_entries(nsp);
 439
 440        /* Check if we are already in requested state */
 441        reg = le64_to_cpu(entries[idx].state);
 442        if (configed != FIELD_GET(NSP_ETH_STATE_CONFIGURED, reg)) {
 443                reg = le64_to_cpu(entries[idx].control);
 444                reg &= ~NSP_ETH_CTRL_CONFIGURED;
 445                reg |= FIELD_PREP(NSP_ETH_CTRL_CONFIGURED, configed);
 446                entries[idx].control = cpu_to_le64(reg);
 447
 448                nfp_nsp_config_set_modified(nsp, true);
 449        }
 450
 451        return nfp_eth_config_commit_end(nsp);
 452}
 453
 454/* Force inline, FIELD_* macroes require masks to be compilation-time known */
 455static __always_inline int
 456nfp_eth_set_bit_config(struct nfp_nsp *nsp, unsigned int raw_idx,
 457                       const u64 mask, unsigned int val, const u64 ctrl_bit)
 458{
 459        union eth_table_entry *entries = nfp_nsp_config_entries(nsp);
 460        unsigned int idx = nfp_nsp_config_idx(nsp);
 461        u64 reg;
 462
 463        /* Note: set features were added in ABI 0.14 but the error
 464         *       codes were initially not populated correctly.
 465         */
 466        if (nfp_nsp_get_abi_ver_minor(nsp) < 17) {
 467                nfp_err(nfp_nsp_cpp(nsp),
 468                        "set operations not supported, please update flash\n");
 469                return -EOPNOTSUPP;
 470        }
 471
 472        /* Check if we are already in requested state */
 473        reg = le64_to_cpu(entries[idx].raw[raw_idx]);
 474        if (val == FIELD_GET(mask, reg))
 475                return 0;
 476
 477        reg &= ~mask;
 478        reg |= FIELD_PREP(mask, val);
 479        entries[idx].raw[raw_idx] = cpu_to_le64(reg);
 480
 481        entries[idx].control |= cpu_to_le64(ctrl_bit);
 482
 483        nfp_nsp_config_set_modified(nsp, true);
 484
 485        return 0;
 486}
 487
 488/**
 489 * __nfp_eth_set_aneg() - set PHY autonegotiation control bit
 490 * @nsp:        NFP NSP handle returned from nfp_eth_config_start()
 491 * @mode:       Desired autonegotiation mode
 492 *
 493 * Allow/disallow PHY module to advertise/perform autonegotiation.
 494 * Will write to hwinfo overrides in the flash (persistent config).
 495 *
 496 * Return: 0 or -ERRNO.
 497 */
 498int __nfp_eth_set_aneg(struct nfp_nsp *nsp, enum nfp_eth_aneg mode)
 499{
 500        return nfp_eth_set_bit_config(nsp, NSP_ETH_RAW_STATE,
 501                                      NSP_ETH_STATE_ANEG, mode,
 502                                      NSP_ETH_CTRL_SET_ANEG);
 503}
 504
 505/**
 506 * __nfp_eth_set_speed() - set interface speed/rate
 507 * @nsp:        NFP NSP handle returned from nfp_eth_config_start()
 508 * @speed:      Desired speed (per lane)
 509 *
 510 * Set lane speed.  Provided @speed value should be subport speed divided
 511 * by number of lanes this subport is spanning (i.e. 10000 for 40G, 25000 for
 512 * 50G, etc.)
 513 * Will write to hwinfo overrides in the flash (persistent config).
 514 *
 515 * Return: 0 or -ERRNO.
 516 */
 517int __nfp_eth_set_speed(struct nfp_nsp *nsp, unsigned int speed)
 518{
 519        enum nfp_eth_rate rate;
 520
 521        rate = nfp_eth_speed2rate(speed);
 522        if (rate == RATE_INVALID) {
 523                nfp_warn(nfp_nsp_cpp(nsp),
 524                         "could not find matching lane rate for speed %u\n",
 525                         speed);
 526                return -EINVAL;
 527        }
 528
 529        return nfp_eth_set_bit_config(nsp, NSP_ETH_RAW_STATE,
 530                                      NSP_ETH_STATE_RATE, rate,
 531                                      NSP_ETH_CTRL_SET_RATE);
 532}
 533
 534/**
 535 * __nfp_eth_set_split() - set interface lane split
 536 * @nsp:        NFP NSP handle returned from nfp_eth_config_start()
 537 * @lanes:      Desired lanes per port
 538 *
 539 * Set number of lanes in the port.
 540 * Will write to hwinfo overrides in the flash (persistent config).
 541 *
 542 * Return: 0 or -ERRNO.
 543 */
 544int __nfp_eth_set_split(struct nfp_nsp *nsp, unsigned int lanes)
 545{
 546        return nfp_eth_set_bit_config(nsp, NSP_ETH_RAW_PORT, NSP_ETH_PORT_LANES,
 547                                      lanes, NSP_ETH_CTRL_SET_LANES);
 548}
 549