linux/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_utils_fw.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/* Atlantic Network Driver
   3 * Copyright (C) 2020 Marvell International Ltd.
   4 */
   5
   6#include <linux/iopoll.h>
   7
   8#include "aq_hw.h"
   9#include "aq_hw_utils.h"
  10#include "aq_nic.h"
  11#include "hw_atl/hw_atl_llh.h"
  12#include "hw_atl2_utils.h"
  13#include "hw_atl2_llh.h"
  14#include "hw_atl2_internal.h"
  15
  16#define AQ_A2_FW_READ_TRY_MAX 1000
  17
  18#define hw_atl2_shared_buffer_write(HW, ITEM, VARIABLE) \
  19{\
  20        BUILD_BUG_ON_MSG((offsetof(struct fw_interface_in, ITEM) % \
  21                         sizeof(u32)) != 0,\
  22                         "Unaligned write " # ITEM);\
  23        BUILD_BUG_ON_MSG((sizeof(VARIABLE) %  sizeof(u32)) != 0,\
  24                         "Unaligned write length " # ITEM);\
  25        hw_atl2_mif_shared_buf_write(HW,\
  26                (offsetof(struct fw_interface_in, ITEM) / sizeof(u32)),\
  27                (u32 *)&(VARIABLE), sizeof(VARIABLE) / sizeof(u32));\
  28}
  29
  30#define hw_atl2_shared_buffer_get(HW, ITEM, VARIABLE) \
  31{\
  32        BUILD_BUG_ON_MSG((offsetof(struct fw_interface_in, ITEM) % \
  33                         sizeof(u32)) != 0,\
  34                         "Unaligned get " # ITEM);\
  35        BUILD_BUG_ON_MSG((sizeof(VARIABLE) %  sizeof(u32)) != 0,\
  36                         "Unaligned get length " # ITEM);\
  37        hw_atl2_mif_shared_buf_get(HW, \
  38                (offsetof(struct fw_interface_in, ITEM) / sizeof(u32)),\
  39                (u32 *)&(VARIABLE), \
  40                sizeof(VARIABLE) / sizeof(u32));\
  41}
  42
  43/* This should never be used on non atomic fields,
  44 * treat any > u32 read as non atomic.
  45 */
  46#define hw_atl2_shared_buffer_read(HW, ITEM, VARIABLE) \
  47{\
  48        BUILD_BUG_ON_MSG((offsetof(struct fw_interface_out, ITEM) % \
  49                         sizeof(u32)) != 0,\
  50                         "Unaligned read " # ITEM);\
  51        BUILD_BUG_ON_MSG((sizeof(VARIABLE) %  sizeof(u32)) != 0,\
  52                         "Unaligned read length " # ITEM);\
  53        BUILD_BUG_ON_MSG(sizeof(VARIABLE) > sizeof(u32),\
  54                         "Non atomic read " # ITEM);\
  55        hw_atl2_mif_shared_buf_read(HW, \
  56                (offsetof(struct fw_interface_out, ITEM) / sizeof(u32)),\
  57                (u32 *)&(VARIABLE), sizeof(VARIABLE) / sizeof(u32));\
  58}
  59
  60#define hw_atl2_shared_buffer_read_safe(HW, ITEM, DATA) \
  61({\
  62        BUILD_BUG_ON_MSG((offsetof(struct fw_interface_out, ITEM) % \
  63                         sizeof(u32)) != 0,\
  64                         "Unaligned read_safe " # ITEM);\
  65        BUILD_BUG_ON_MSG((sizeof(((struct fw_interface_out *)0)->ITEM) % \
  66                         sizeof(u32)) != 0,\
  67                         "Unaligned read_safe length " # ITEM);\
  68        hw_atl2_shared_buffer_read_block((HW), \
  69                (offsetof(struct fw_interface_out, ITEM) / sizeof(u32)),\
  70                sizeof(((struct fw_interface_out *)0)->ITEM) / sizeof(u32),\
  71                (DATA));\
  72})
  73
  74static int hw_atl2_shared_buffer_read_block(struct aq_hw_s *self,
  75                                            u32 offset, u32 dwords, void *data)
  76{
  77        struct transaction_counter_s tid1, tid2;
  78        int cnt = 0;
  79
  80        do {
  81                do {
  82                        hw_atl2_shared_buffer_read(self, transaction_id, tid1);
  83                        cnt++;
  84                        if (cnt > AQ_A2_FW_READ_TRY_MAX)
  85                                return -ETIME;
  86                        if (tid1.transaction_cnt_a != tid1.transaction_cnt_b)
  87                                udelay(1);
  88                } while (tid1.transaction_cnt_a != tid1.transaction_cnt_b);
  89
  90                hw_atl2_mif_shared_buf_read(self, offset, (u32 *)data, dwords);
  91
  92                hw_atl2_shared_buffer_read(self, transaction_id, tid2);
  93
  94                cnt++;
  95                if (cnt > AQ_A2_FW_READ_TRY_MAX)
  96                        return -ETIME;
  97        } while (tid2.transaction_cnt_a != tid2.transaction_cnt_b ||
  98                 tid1.transaction_cnt_a != tid2.transaction_cnt_a);
  99
 100        return 0;
 101}
 102
 103static inline int hw_atl2_shared_buffer_finish_ack(struct aq_hw_s *self)
 104{
 105        u32 val;
 106        int err;
 107
 108        hw_atl2_mif_host_finished_write_set(self, 1U);
 109        err = readx_poll_timeout_atomic(hw_atl2_mif_mcp_finished_read_get,
 110                                        self, val, val == 0U,
 111                                        100, 100000U);
 112        WARN(err, "hw_atl2_shared_buffer_finish_ack");
 113
 114        return err;
 115}
 116
 117static int aq_a2_fw_init(struct aq_hw_s *self)
 118{
 119        struct link_control_s link_control;
 120        u32 mtu;
 121        u32 val;
 122        int err;
 123
 124        hw_atl2_shared_buffer_get(self, link_control, link_control);
 125        link_control.mode = AQ_HOST_MODE_ACTIVE;
 126        hw_atl2_shared_buffer_write(self, link_control, link_control);
 127
 128        hw_atl2_shared_buffer_get(self, mtu, mtu);
 129        mtu = HW_ATL2_MTU_JUMBO;
 130        hw_atl2_shared_buffer_write(self, mtu, mtu);
 131
 132        hw_atl2_mif_host_finished_write_set(self, 1U);
 133        err = readx_poll_timeout_atomic(hw_atl2_mif_mcp_finished_read_get,
 134                                        self, val, val == 0U,
 135                                        100, 5000000U);
 136        WARN(err, "hw_atl2_shared_buffer_finish_ack");
 137
 138        return err;
 139}
 140
 141static int aq_a2_fw_deinit(struct aq_hw_s *self)
 142{
 143        struct link_control_s link_control;
 144
 145        hw_atl2_shared_buffer_get(self, link_control, link_control);
 146        link_control.mode = AQ_HOST_MODE_SHUTDOWN;
 147        hw_atl2_shared_buffer_write(self, link_control, link_control);
 148
 149        return hw_atl2_shared_buffer_finish_ack(self);
 150}
 151
 152static void a2_link_speed_mask2fw(u32 speed,
 153                                  struct link_options_s *link_options)
 154{
 155        link_options->rate_10G = !!(speed & AQ_NIC_RATE_10G);
 156        link_options->rate_5G = !!(speed & AQ_NIC_RATE_5G);
 157        link_options->rate_N5G = !!(speed & AQ_NIC_RATE_5GSR);
 158        link_options->rate_2P5G = !!(speed & AQ_NIC_RATE_2G5);
 159        link_options->rate_N2P5G = link_options->rate_2P5G;
 160        link_options->rate_1G = !!(speed & AQ_NIC_RATE_1G);
 161        link_options->rate_100M = !!(speed & AQ_NIC_RATE_100M);
 162        link_options->rate_10M = !!(speed & AQ_NIC_RATE_10M);
 163
 164        link_options->rate_1G_hd = !!(speed & AQ_NIC_RATE_1G_HALF);
 165        link_options->rate_100M_hd = !!(speed & AQ_NIC_RATE_100M_HALF);
 166        link_options->rate_10M_hd = !!(speed & AQ_NIC_RATE_10M_HALF);
 167}
 168
 169static u32 a2_fw_dev_to_eee_mask(struct device_link_caps_s *device_link_caps)
 170{
 171        u32 rate = 0;
 172
 173        if (device_link_caps->eee_10G)
 174                rate |= AQ_NIC_RATE_EEE_10G;
 175        if (device_link_caps->eee_5G)
 176                rate |= AQ_NIC_RATE_EEE_5G;
 177        if (device_link_caps->eee_2P5G)
 178                rate |= AQ_NIC_RATE_EEE_2G5;
 179        if (device_link_caps->eee_1G)
 180                rate |= AQ_NIC_RATE_EEE_1G;
 181        if (device_link_caps->eee_100M)
 182                rate |= AQ_NIC_RATE_EEE_100M;
 183
 184        return rate;
 185}
 186
 187static u32 a2_fw_lkp_to_mask(struct lkp_link_caps_s *lkp_link_caps)
 188{
 189        u32 rate = 0;
 190
 191        if (lkp_link_caps->rate_10G)
 192                rate |= AQ_NIC_RATE_10G;
 193        if (lkp_link_caps->rate_5G)
 194                rate |= AQ_NIC_RATE_5G;
 195        if (lkp_link_caps->rate_N5G)
 196                rate |= AQ_NIC_RATE_5GSR;
 197        if (lkp_link_caps->rate_2P5G)
 198                rate |= AQ_NIC_RATE_2G5;
 199        if (lkp_link_caps->rate_1G)
 200                rate |= AQ_NIC_RATE_1G;
 201        if (lkp_link_caps->rate_1G_hd)
 202                rate |= AQ_NIC_RATE_1G_HALF;
 203        if (lkp_link_caps->rate_100M)
 204                rate |= AQ_NIC_RATE_100M;
 205        if (lkp_link_caps->rate_100M_hd)
 206                rate |= AQ_NIC_RATE_100M_HALF;
 207        if (lkp_link_caps->rate_10M)
 208                rate |= AQ_NIC_RATE_10M;
 209        if (lkp_link_caps->rate_10M_hd)
 210                rate |= AQ_NIC_RATE_10M_HALF;
 211
 212        if (lkp_link_caps->eee_10G)
 213                rate |= AQ_NIC_RATE_EEE_10G;
 214        if (lkp_link_caps->eee_5G)
 215                rate |= AQ_NIC_RATE_EEE_5G;
 216        if (lkp_link_caps->eee_2P5G)
 217                rate |= AQ_NIC_RATE_EEE_2G5;
 218        if (lkp_link_caps->eee_1G)
 219                rate |= AQ_NIC_RATE_EEE_1G;
 220        if (lkp_link_caps->eee_100M)
 221                rate |= AQ_NIC_RATE_EEE_100M;
 222
 223        return rate;
 224}
 225
 226static int aq_a2_fw_set_link_speed(struct aq_hw_s *self, u32 speed)
 227{
 228        struct link_options_s link_options;
 229
 230        hw_atl2_shared_buffer_get(self, link_options, link_options);
 231        link_options.link_up = 1U;
 232        a2_link_speed_mask2fw(speed, &link_options);
 233        hw_atl2_shared_buffer_write(self, link_options, link_options);
 234
 235        return hw_atl2_shared_buffer_finish_ack(self);
 236}
 237
 238static void aq_a2_fw_set_mpi_flow_control(struct aq_hw_s *self,
 239                                          struct link_options_s *link_options)
 240{
 241        u32 flow_control = self->aq_nic_cfg->fc.req;
 242
 243        link_options->pause_rx = !!(flow_control & AQ_NIC_FC_RX);
 244        link_options->pause_tx = !!(flow_control & AQ_NIC_FC_TX);
 245}
 246
 247static void aq_a2_fw_upd_eee_rate_bits(struct aq_hw_s *self,
 248                                       struct link_options_s *link_options,
 249                                       u32 eee_speeds)
 250{
 251        link_options->eee_10G =  !!(eee_speeds & AQ_NIC_RATE_EEE_10G);
 252        link_options->eee_5G = !!(eee_speeds & AQ_NIC_RATE_EEE_5G);
 253        link_options->eee_2P5G = !!(eee_speeds & AQ_NIC_RATE_EEE_2G5);
 254        link_options->eee_1G = !!(eee_speeds & AQ_NIC_RATE_EEE_1G);
 255        link_options->eee_100M = !!(eee_speeds & AQ_NIC_RATE_EEE_100M);
 256}
 257
 258static int aq_a2_fw_set_state(struct aq_hw_s *self,
 259                              enum hal_atl_utils_fw_state_e state)
 260{
 261        struct link_options_s link_options;
 262
 263        hw_atl2_shared_buffer_get(self, link_options, link_options);
 264
 265        switch (state) {
 266        case MPI_INIT:
 267                link_options.link_up = 1U;
 268                aq_a2_fw_upd_eee_rate_bits(self, &link_options,
 269                                           self->aq_nic_cfg->eee_speeds);
 270                aq_a2_fw_set_mpi_flow_control(self, &link_options);
 271                break;
 272        case MPI_DEINIT:
 273                link_options.link_up = 0U;
 274                break;
 275        case MPI_RESET:
 276        case MPI_POWER:
 277                /* No actions */
 278                break;
 279        }
 280
 281        hw_atl2_shared_buffer_write(self, link_options, link_options);
 282
 283        return hw_atl2_shared_buffer_finish_ack(self);
 284}
 285
 286static int aq_a2_fw_update_link_status(struct aq_hw_s *self)
 287{
 288        struct lkp_link_caps_s lkp_link_caps;
 289        struct link_status_s link_status;
 290
 291        hw_atl2_shared_buffer_read(self, link_status, link_status);
 292
 293        switch (link_status.link_rate) {
 294        case AQ_A2_FW_LINK_RATE_10G:
 295                self->aq_link_status.mbps = 10000;
 296                break;
 297        case AQ_A2_FW_LINK_RATE_5G:
 298                self->aq_link_status.mbps = 5000;
 299                break;
 300        case AQ_A2_FW_LINK_RATE_2G5:
 301                self->aq_link_status.mbps = 2500;
 302                break;
 303        case AQ_A2_FW_LINK_RATE_1G:
 304                self->aq_link_status.mbps = 1000;
 305                break;
 306        case AQ_A2_FW_LINK_RATE_100M:
 307                self->aq_link_status.mbps = 100;
 308                break;
 309        case AQ_A2_FW_LINK_RATE_10M:
 310                self->aq_link_status.mbps = 10;
 311                break;
 312        default:
 313                self->aq_link_status.mbps = 0;
 314        }
 315        self->aq_link_status.full_duplex = link_status.duplex;
 316
 317        hw_atl2_shared_buffer_read(self, lkp_link_caps, lkp_link_caps);
 318
 319        self->aq_link_status.lp_link_speed_msk =
 320                                 a2_fw_lkp_to_mask(&lkp_link_caps);
 321        self->aq_link_status.lp_flow_control =
 322                                ((lkp_link_caps.pause_rx) ? AQ_NIC_FC_RX : 0) |
 323                                ((lkp_link_caps.pause_tx) ? AQ_NIC_FC_TX : 0);
 324
 325        return 0;
 326}
 327
 328static int aq_a2_fw_get_mac_permanent(struct aq_hw_s *self, u8 *mac)
 329{
 330        struct mac_address_aligned_s mac_address;
 331
 332        hw_atl2_shared_buffer_get(self, mac_address, mac_address);
 333        ether_addr_copy(mac, (u8 *)mac_address.aligned.mac_address);
 334
 335        return 0;
 336}
 337
 338static int aq_a2_fw_update_stats(struct aq_hw_s *self)
 339{
 340        struct hw_atl2_priv *priv = (struct hw_atl2_priv *)self->priv;
 341        struct statistics_s stats;
 342
 343        hw_atl2_shared_buffer_read_safe(self, stats, &stats);
 344
 345#define AQ_SDELTA(_N_, _F_) (self->curr_stats._N_ += \
 346                        stats.msm._F_ - priv->last_stats.msm._F_)
 347
 348        if (self->aq_link_status.mbps) {
 349                AQ_SDELTA(uprc, rx_unicast_frames);
 350                AQ_SDELTA(mprc, rx_multicast_frames);
 351                AQ_SDELTA(bprc, rx_broadcast_frames);
 352                AQ_SDELTA(erpr, rx_error_frames);
 353
 354                AQ_SDELTA(uptc, tx_unicast_frames);
 355                AQ_SDELTA(mptc, tx_multicast_frames);
 356                AQ_SDELTA(bptc, tx_broadcast_frames);
 357                AQ_SDELTA(erpt, tx_errors);
 358
 359                AQ_SDELTA(ubrc, rx_unicast_octets);
 360                AQ_SDELTA(ubtc, tx_unicast_octets);
 361                AQ_SDELTA(mbrc, rx_multicast_octets);
 362                AQ_SDELTA(mbtc, tx_multicast_octets);
 363                AQ_SDELTA(bbrc, rx_broadcast_octets);
 364                AQ_SDELTA(bbtc, tx_broadcast_octets);
 365        }
 366#undef AQ_SDELTA
 367        self->curr_stats.dma_pkt_rc =
 368                hw_atl_stats_rx_dma_good_pkt_counter_get(self);
 369        self->curr_stats.dma_pkt_tc =
 370                hw_atl_stats_tx_dma_good_pkt_counter_get(self);
 371        self->curr_stats.dma_oct_rc =
 372                hw_atl_stats_rx_dma_good_octet_counter_get(self);
 373        self->curr_stats.dma_oct_tc =
 374                hw_atl_stats_tx_dma_good_octet_counter_get(self);
 375        self->curr_stats.dpc = hw_atl_rpb_rx_dma_drop_pkt_cnt_get(self);
 376
 377        memcpy(&priv->last_stats, &stats, sizeof(stats));
 378
 379        return 0;
 380}
 381
 382static int aq_a2_fw_get_phy_temp(struct aq_hw_s *self, int *temp)
 383{
 384        struct phy_health_monitor_s phy_health_monitor;
 385
 386        hw_atl2_shared_buffer_read_safe(self, phy_health_monitor,
 387                                        &phy_health_monitor);
 388
 389        *temp = (int8_t)phy_health_monitor.phy_temperature * 1000;
 390        return 0;
 391}
 392
 393static int aq_a2_fw_get_mac_temp(struct aq_hw_s *self, int *temp)
 394{
 395        /* There's only one temperature sensor on A2, use it for
 396         * both MAC and PHY.
 397         */
 398        return aq_a2_fw_get_phy_temp(self, temp);
 399}
 400
 401static int aq_a2_fw_set_eee_rate(struct aq_hw_s *self, u32 speed)
 402{
 403        struct link_options_s link_options;
 404
 405        hw_atl2_shared_buffer_get(self, link_options, link_options);
 406
 407        aq_a2_fw_upd_eee_rate_bits(self, &link_options, speed);
 408
 409        hw_atl2_shared_buffer_write(self, link_options, link_options);
 410
 411        return hw_atl2_shared_buffer_finish_ack(self);
 412}
 413
 414static int aq_a2_fw_get_eee_rate(struct aq_hw_s *self, u32 *rate,
 415                                 u32 *supported_rates)
 416{
 417        struct device_link_caps_s device_link_caps;
 418        struct lkp_link_caps_s lkp_link_caps;
 419
 420        hw_atl2_shared_buffer_read(self, device_link_caps, device_link_caps);
 421        hw_atl2_shared_buffer_read(self, lkp_link_caps, lkp_link_caps);
 422
 423        *supported_rates = a2_fw_dev_to_eee_mask(&device_link_caps);
 424        *rate = a2_fw_lkp_to_mask(&lkp_link_caps);
 425
 426        return 0;
 427}
 428
 429static int aq_a2_fw_renegotiate(struct aq_hw_s *self)
 430{
 431        struct link_options_s link_options;
 432        int err;
 433
 434        hw_atl2_shared_buffer_get(self, link_options, link_options);
 435        link_options.link_renegotiate = 1U;
 436        hw_atl2_shared_buffer_write(self, link_options, link_options);
 437
 438        err = hw_atl2_shared_buffer_finish_ack(self);
 439
 440        /* We should put renegotiate status back to zero
 441         * after command completes
 442         */
 443        link_options.link_renegotiate = 0U;
 444        hw_atl2_shared_buffer_write(self, link_options, link_options);
 445
 446        return err;
 447}
 448
 449static int aq_a2_fw_set_flow_control(struct aq_hw_s *self)
 450{
 451        struct link_options_s link_options;
 452
 453        hw_atl2_shared_buffer_get(self, link_options, link_options);
 454
 455        aq_a2_fw_set_mpi_flow_control(self, &link_options);
 456
 457        hw_atl2_shared_buffer_write(self, link_options, link_options);
 458
 459        return hw_atl2_shared_buffer_finish_ack(self);
 460}
 461
 462static u32 aq_a2_fw_get_flow_control(struct aq_hw_s *self, u32 *fcmode)
 463{
 464        struct link_status_s link_status;
 465
 466        hw_atl2_shared_buffer_read(self, link_status, link_status);
 467
 468        *fcmode = ((link_status.pause_rx) ? AQ_NIC_FC_RX : 0) |
 469                  ((link_status.pause_tx) ? AQ_NIC_FC_TX : 0);
 470        return 0;
 471}
 472
 473static int aq_a2_fw_set_phyloopback(struct aq_hw_s *self, u32 mode, bool enable)
 474{
 475        struct link_options_s link_options;
 476
 477        hw_atl2_shared_buffer_get(self, link_options, link_options);
 478
 479        switch (mode) {
 480        case AQ_HW_LOOPBACK_PHYINT_SYS:
 481                link_options.internal_loopback = enable;
 482                break;
 483        case AQ_HW_LOOPBACK_PHYEXT_SYS:
 484                link_options.external_loopback = enable;
 485                break;
 486        default:
 487                return -EINVAL;
 488        }
 489
 490        hw_atl2_shared_buffer_write(self, link_options, link_options);
 491
 492        return hw_atl2_shared_buffer_finish_ack(self);
 493}
 494
 495u32 hw_atl2_utils_get_fw_version(struct aq_hw_s *self)
 496{
 497        struct version_s version;
 498
 499        hw_atl2_shared_buffer_read_safe(self, version, &version);
 500
 501        /* A2 FW version is stored in reverse order */
 502        return version.mac.major << 24 |
 503               version.mac.minor << 16 |
 504               version.mac.build;
 505}
 506
 507int hw_atl2_utils_get_action_resolve_table_caps(struct aq_hw_s *self,
 508                                                u8 *base_index, u8 *count)
 509{
 510        struct filter_caps_s filter_caps;
 511        int err;
 512
 513        err = hw_atl2_shared_buffer_read_safe(self, filter_caps, &filter_caps);
 514        if (err)
 515                return err;
 516
 517        *base_index = filter_caps.rslv_tbl_base_index;
 518        *count = filter_caps.rslv_tbl_count;
 519        return 0;
 520}
 521
 522static int aq_a2_fw_set_downshift(struct aq_hw_s *self, u32 counter)
 523{
 524        struct link_options_s link_options;
 525
 526        hw_atl2_shared_buffer_get(self, link_options, link_options);
 527        link_options.downshift = !!counter;
 528        link_options.downshift_retry = counter;
 529        hw_atl2_shared_buffer_write(self, link_options, link_options);
 530
 531        return hw_atl2_shared_buffer_finish_ack(self);
 532}
 533
 534const struct aq_fw_ops aq_a2_fw_ops = {
 535        .init               = aq_a2_fw_init,
 536        .deinit             = aq_a2_fw_deinit,
 537        .reset              = NULL,
 538        .renegotiate        = aq_a2_fw_renegotiate,
 539        .get_mac_permanent  = aq_a2_fw_get_mac_permanent,
 540        .set_link_speed     = aq_a2_fw_set_link_speed,
 541        .set_state          = aq_a2_fw_set_state,
 542        .update_link_status = aq_a2_fw_update_link_status,
 543        .update_stats       = aq_a2_fw_update_stats,
 544        .get_mac_temp       = aq_a2_fw_get_mac_temp,
 545        .get_phy_temp       = aq_a2_fw_get_phy_temp,
 546        .set_eee_rate       = aq_a2_fw_set_eee_rate,
 547        .get_eee_rate       = aq_a2_fw_get_eee_rate,
 548        .set_flow_control   = aq_a2_fw_set_flow_control,
 549        .get_flow_control   = aq_a2_fw_get_flow_control,
 550        .set_phyloopback    = aq_a2_fw_set_phyloopback,
 551        .set_downshift      = aq_a2_fw_set_downshift,
 552};
 553