linux/drivers/scsi/bfa/bfa_fcport.c
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
   3 * All rights reserved
   4 * www.brocade.com
   5 *
   6 * Linux driver for Brocade Fibre Channel Host Bus Adapter.
   7 *
   8 * This program is free software; you can redistribute it and/or modify it
   9 * under the terms of the GNU General Public License (GPL) Version 2 as
  10 * published by the Free Software Foundation
  11 *
  12 * This program is distributed in the hope that it will be useful, but
  13 * WITHOUT ANY WARRANTY; without even the implied warranty of
  14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  15 * General Public License for more details.
  16 */
  17
  18#include <bfa.h>
  19#include <bfa_svc.h>
  20#include <bfi/bfi_pport.h>
  21#include <cs/bfa_debug.h>
  22#include <aen/bfa_aen.h>
  23#include <cs/bfa_plog.h>
  24#include <aen/bfa_aen_port.h>
  25
  26BFA_TRC_FILE(HAL, PPORT);
  27BFA_MODULE(pport);
  28
  29#define bfa_pport_callback(__pport, __event) do {                       \
  30        if ((__pport)->bfa->fcs) {      \
  31                (__pport)->event_cbfn((__pport)->event_cbarg, (__event));      \
  32        } else {                                                        \
  33                (__pport)->hcb_event = (__event);      \
  34                bfa_cb_queue((__pport)->bfa, &(__pport)->hcb_qe,        \
  35                __bfa_cb_port_event, (__pport));      \
  36        }                                                               \
  37} while (0)
  38
  39/*
  40 * The port is considered disabled if corresponding physical port or IOC are
  41 * disabled explicitly
  42 */
  43#define BFA_PORT_IS_DISABLED(bfa) \
  44        ((bfa_pport_is_disabled(bfa) == BFA_TRUE) || \
  45        (bfa_ioc_is_disabled(&bfa->ioc) == BFA_TRUE))
  46
  47/*
  48 * forward declarations
  49 */
  50static bfa_boolean_t bfa_pport_send_enable(struct bfa_pport_s *port);
  51static bfa_boolean_t bfa_pport_send_disable(struct bfa_pport_s *port);
  52static void     bfa_pport_update_linkinfo(struct bfa_pport_s *pport);
  53static void     bfa_pport_reset_linkinfo(struct bfa_pport_s *pport);
  54static void     bfa_pport_set_wwns(struct bfa_pport_s *port);
  55static void     __bfa_cb_port_event(void *cbarg, bfa_boolean_t complete);
  56static void     __bfa_cb_port_stats(void *cbarg, bfa_boolean_t complete);
  57static void     __bfa_cb_port_stats_clr(void *cbarg, bfa_boolean_t complete);
  58static void     bfa_port_stats_timeout(void *cbarg);
  59static void     bfa_port_stats_clr_timeout(void *cbarg);
  60
  61/**
  62 *  bfa_pport_private
  63 */
  64
  65/**
  66 * BFA port state machine events
  67 */
  68enum bfa_pport_sm_event {
  69        BFA_PPORT_SM_START = 1, /*  start port state machine */
  70        BFA_PPORT_SM_STOP = 2,  /*  stop port state machine */
  71        BFA_PPORT_SM_ENABLE = 3,        /*  enable port */
  72        BFA_PPORT_SM_DISABLE = 4,       /*  disable port state machine */
  73        BFA_PPORT_SM_FWRSP = 5, /*  firmware enable/disable rsp */
  74        BFA_PPORT_SM_LINKUP = 6,        /*  firmware linkup event */
  75        BFA_PPORT_SM_LINKDOWN = 7,      /*  firmware linkup down */
  76        BFA_PPORT_SM_QRESUME = 8,       /*  CQ space available */
  77        BFA_PPORT_SM_HWFAIL = 9,        /*  IOC h/w failure */
  78};
  79
  80static void     bfa_pport_sm_uninit(struct bfa_pport_s *pport,
  81                                    enum bfa_pport_sm_event event);
  82static void     bfa_pport_sm_enabling_qwait(struct bfa_pport_s *pport,
  83                                            enum bfa_pport_sm_event event);
  84static void     bfa_pport_sm_enabling(struct bfa_pport_s *pport,
  85                                      enum bfa_pport_sm_event event);
  86static void     bfa_pport_sm_linkdown(struct bfa_pport_s *pport,
  87                                      enum bfa_pport_sm_event event);
  88static void     bfa_pport_sm_linkup(struct bfa_pport_s *pport,
  89                                    enum bfa_pport_sm_event event);
  90static void     bfa_pport_sm_disabling(struct bfa_pport_s *pport,
  91                                       enum bfa_pport_sm_event event);
  92static void     bfa_pport_sm_disabling_qwait(struct bfa_pport_s *pport,
  93                                             enum bfa_pport_sm_event event);
  94static void     bfa_pport_sm_disabled(struct bfa_pport_s *pport,
  95                                      enum bfa_pport_sm_event event);
  96static void     bfa_pport_sm_stopped(struct bfa_pport_s *pport,
  97                                     enum bfa_pport_sm_event event);
  98static void     bfa_pport_sm_iocdown(struct bfa_pport_s *pport,
  99                                     enum bfa_pport_sm_event event);
 100static void     bfa_pport_sm_iocfail(struct bfa_pport_s *pport,
 101                                     enum bfa_pport_sm_event event);
 102
 103static struct bfa_sm_table_s hal_pport_sm_table[] = {
 104        {BFA_SM(bfa_pport_sm_uninit), BFA_PPORT_ST_UNINIT},
 105        {BFA_SM(bfa_pport_sm_enabling_qwait), BFA_PPORT_ST_ENABLING_QWAIT},
 106        {BFA_SM(bfa_pport_sm_enabling), BFA_PPORT_ST_ENABLING},
 107        {BFA_SM(bfa_pport_sm_linkdown), BFA_PPORT_ST_LINKDOWN},
 108        {BFA_SM(bfa_pport_sm_linkup), BFA_PPORT_ST_LINKUP},
 109        {BFA_SM(bfa_pport_sm_disabling_qwait),
 110         BFA_PPORT_ST_DISABLING_QWAIT},
 111        {BFA_SM(bfa_pport_sm_disabling), BFA_PPORT_ST_DISABLING},
 112        {BFA_SM(bfa_pport_sm_disabled), BFA_PPORT_ST_DISABLED},
 113        {BFA_SM(bfa_pport_sm_stopped), BFA_PPORT_ST_STOPPED},
 114        {BFA_SM(bfa_pport_sm_iocdown), BFA_PPORT_ST_IOCDOWN},
 115        {BFA_SM(bfa_pport_sm_iocfail), BFA_PPORT_ST_IOCDOWN},
 116};
 117
 118static void
 119bfa_pport_aen_post(struct bfa_pport_s *pport, enum bfa_port_aen_event event)
 120{
 121        union bfa_aen_data_u aen_data;
 122        struct bfa_log_mod_s *logmod = pport->bfa->logm;
 123        wwn_t           pwwn = pport->pwwn;
 124        char            pwwn_ptr[BFA_STRING_32];
 125        struct bfa_ioc_attr_s ioc_attr;
 126
 127        wwn2str(pwwn_ptr, pwwn);
 128        switch (event) {
 129        case BFA_PORT_AEN_ONLINE:
 130                bfa_log(logmod, BFA_AEN_PORT_ONLINE, pwwn_ptr);
 131                break;
 132        case BFA_PORT_AEN_OFFLINE:
 133                bfa_log(logmod, BFA_AEN_PORT_OFFLINE, pwwn_ptr);
 134                break;
 135        case BFA_PORT_AEN_ENABLE:
 136                bfa_log(logmod, BFA_AEN_PORT_ENABLE, pwwn_ptr);
 137                break;
 138        case BFA_PORT_AEN_DISABLE:
 139                bfa_log(logmod, BFA_AEN_PORT_DISABLE, pwwn_ptr);
 140                break;
 141        case BFA_PORT_AEN_DISCONNECT:
 142                bfa_log(logmod, BFA_AEN_PORT_DISCONNECT, pwwn_ptr);
 143                break;
 144        case BFA_PORT_AEN_QOS_NEG:
 145                bfa_log(logmod, BFA_AEN_PORT_QOS_NEG, pwwn_ptr);
 146                break;
 147        default:
 148                break;
 149        }
 150
 151        bfa_ioc_get_attr(&pport->bfa->ioc, &ioc_attr);
 152        aen_data.port.ioc_type = ioc_attr.ioc_type;
 153        aen_data.port.pwwn = pwwn;
 154}
 155
 156static void
 157bfa_pport_sm_uninit(struct bfa_pport_s *pport, enum bfa_pport_sm_event event)
 158{
 159        bfa_trc(pport->bfa, event);
 160
 161        switch (event) {
 162        case BFA_PPORT_SM_START:
 163                /**
 164                 * Start event after IOC is configured and BFA is started.
 165                 */
 166                if (bfa_pport_send_enable(pport))
 167                        bfa_sm_set_state(pport, bfa_pport_sm_enabling);
 168                else
 169                        bfa_sm_set_state(pport, bfa_pport_sm_enabling_qwait);
 170                break;
 171
 172        case BFA_PPORT_SM_ENABLE:
 173                /**
 174                 * Port is persistently configured to be in enabled state. Do
 175                 * not change state. Port enabling is done when START event is
 176                 * received.
 177                 */
 178                break;
 179
 180        case BFA_PPORT_SM_DISABLE:
 181                /**
 182                 * If a port is persistently configured to be disabled, the
 183                 * first event will a port disable request.
 184                 */
 185                bfa_sm_set_state(pport, bfa_pport_sm_disabled);
 186                break;
 187
 188        case BFA_PPORT_SM_HWFAIL:
 189                bfa_sm_set_state(pport, bfa_pport_sm_iocdown);
 190                break;
 191
 192        default:
 193                bfa_sm_fault(pport->bfa, event);
 194        }
 195}
 196
 197static void
 198bfa_pport_sm_enabling_qwait(struct bfa_pport_s *pport,
 199                            enum bfa_pport_sm_event event)
 200{
 201        bfa_trc(pport->bfa, event);
 202
 203        switch (event) {
 204        case BFA_PPORT_SM_QRESUME:
 205                bfa_sm_set_state(pport, bfa_pport_sm_enabling);
 206                bfa_pport_send_enable(pport);
 207                break;
 208
 209        case BFA_PPORT_SM_STOP:
 210                bfa_reqq_wcancel(&pport->reqq_wait);
 211                bfa_sm_set_state(pport, bfa_pport_sm_stopped);
 212                break;
 213
 214        case BFA_PPORT_SM_ENABLE:
 215                /**
 216                 * Already enable is in progress.
 217                 */
 218                break;
 219
 220        case BFA_PPORT_SM_DISABLE:
 221                /**
 222                 * Just send disable request to firmware when room becomes
 223                 * available in request queue.
 224                 */
 225                bfa_sm_set_state(pport, bfa_pport_sm_disabled);
 226                bfa_reqq_wcancel(&pport->reqq_wait);
 227                bfa_plog_str(pport->bfa->plog, BFA_PL_MID_HAL,
 228                             BFA_PL_EID_PORT_DISABLE, 0, "Port Disable");
 229                bfa_pport_aen_post(pport, BFA_PORT_AEN_DISABLE);
 230                break;
 231
 232        case BFA_PPORT_SM_LINKUP:
 233        case BFA_PPORT_SM_LINKDOWN:
 234                /**
 235                 * Possible to get link events when doing back-to-back
 236                 * enable/disables.
 237                 */
 238                break;
 239
 240        case BFA_PPORT_SM_HWFAIL:
 241                bfa_reqq_wcancel(&pport->reqq_wait);
 242                bfa_sm_set_state(pport, bfa_pport_sm_iocdown);
 243                break;
 244
 245        default:
 246                bfa_sm_fault(pport->bfa, event);
 247        }
 248}
 249
 250static void
 251bfa_pport_sm_enabling(struct bfa_pport_s *pport, enum bfa_pport_sm_event event)
 252{
 253        bfa_trc(pport->bfa, event);
 254
 255        switch (event) {
 256        case BFA_PPORT_SM_FWRSP:
 257        case BFA_PPORT_SM_LINKDOWN:
 258                bfa_sm_set_state(pport, bfa_pport_sm_linkdown);
 259                break;
 260
 261        case BFA_PPORT_SM_LINKUP:
 262                bfa_pport_update_linkinfo(pport);
 263                bfa_sm_set_state(pport, bfa_pport_sm_linkup);
 264
 265                bfa_assert(pport->event_cbfn);
 266                bfa_pport_callback(pport, BFA_PPORT_LINKUP);
 267                break;
 268
 269        case BFA_PPORT_SM_ENABLE:
 270                /**
 271                 * Already being enabled.
 272                 */
 273                break;
 274
 275        case BFA_PPORT_SM_DISABLE:
 276                if (bfa_pport_send_disable(pport))
 277                        bfa_sm_set_state(pport, bfa_pport_sm_disabling);
 278                else
 279                        bfa_sm_set_state(pport, bfa_pport_sm_disabling_qwait);
 280
 281                bfa_plog_str(pport->bfa->plog, BFA_PL_MID_HAL,
 282                             BFA_PL_EID_PORT_DISABLE, 0, "Port Disable");
 283                bfa_pport_aen_post(pport, BFA_PORT_AEN_DISABLE);
 284                break;
 285
 286        case BFA_PPORT_SM_STOP:
 287                bfa_sm_set_state(pport, bfa_pport_sm_stopped);
 288                break;
 289
 290        case BFA_PPORT_SM_HWFAIL:
 291                bfa_sm_set_state(pport, bfa_pport_sm_iocdown);
 292                break;
 293
 294        default:
 295                bfa_sm_fault(pport->bfa, event);
 296        }
 297}
 298
 299static void
 300bfa_pport_sm_linkdown(struct bfa_pport_s *pport, enum bfa_pport_sm_event event)
 301{
 302        bfa_trc(pport->bfa, event);
 303
 304        switch (event) {
 305        case BFA_PPORT_SM_LINKUP:
 306                bfa_pport_update_linkinfo(pport);
 307                bfa_sm_set_state(pport, bfa_pport_sm_linkup);
 308                bfa_assert(pport->event_cbfn);
 309                bfa_plog_str(pport->bfa->plog, BFA_PL_MID_HAL,
 310                             BFA_PL_EID_PORT_ST_CHANGE, 0, "Port Linkup");
 311                bfa_pport_callback(pport, BFA_PPORT_LINKUP);
 312                bfa_pport_aen_post(pport, BFA_PORT_AEN_ONLINE);
 313                /**
 314                 * If QoS is enabled and it is not online,
 315                 * Send a separate event.
 316                 */
 317                if ((pport->cfg.qos_enabled)
 318                    && (bfa_os_ntohl(pport->qos_attr.state) != BFA_QOS_ONLINE))
 319                        bfa_pport_aen_post(pport, BFA_PORT_AEN_QOS_NEG);
 320
 321                break;
 322
 323        case BFA_PPORT_SM_LINKDOWN:
 324                /**
 325                 * Possible to get link down event.
 326                 */
 327                break;
 328
 329        case BFA_PPORT_SM_ENABLE:
 330                /**
 331                 * Already enabled.
 332                 */
 333                break;
 334
 335        case BFA_PPORT_SM_DISABLE:
 336                if (bfa_pport_send_disable(pport))
 337                        bfa_sm_set_state(pport, bfa_pport_sm_disabling);
 338                else
 339                        bfa_sm_set_state(pport, bfa_pport_sm_disabling_qwait);
 340
 341                bfa_plog_str(pport->bfa->plog, BFA_PL_MID_HAL,
 342                             BFA_PL_EID_PORT_DISABLE, 0, "Port Disable");
 343                bfa_pport_aen_post(pport, BFA_PORT_AEN_DISABLE);
 344                break;
 345
 346        case BFA_PPORT_SM_STOP:
 347                bfa_sm_set_state(pport, bfa_pport_sm_stopped);
 348                break;
 349
 350        case BFA_PPORT_SM_HWFAIL:
 351                bfa_sm_set_state(pport, bfa_pport_sm_iocdown);
 352                break;
 353
 354        default:
 355                bfa_sm_fault(pport->bfa, event);
 356        }
 357}
 358
 359static void
 360bfa_pport_sm_linkup(struct bfa_pport_s *pport, enum bfa_pport_sm_event event)
 361{
 362        bfa_trc(pport->bfa, event);
 363
 364        switch (event) {
 365        case BFA_PPORT_SM_ENABLE:
 366                /**
 367                 * Already enabled.
 368                 */
 369                break;
 370
 371        case BFA_PPORT_SM_DISABLE:
 372                if (bfa_pport_send_disable(pport))
 373                        bfa_sm_set_state(pport, bfa_pport_sm_disabling);
 374                else
 375                        bfa_sm_set_state(pport, bfa_pport_sm_disabling_qwait);
 376
 377                bfa_pport_reset_linkinfo(pport);
 378                bfa_pport_callback(pport, BFA_PPORT_LINKDOWN);
 379                bfa_plog_str(pport->bfa->plog, BFA_PL_MID_HAL,
 380                             BFA_PL_EID_PORT_DISABLE, 0, "Port Disable");
 381                bfa_pport_aen_post(pport, BFA_PORT_AEN_OFFLINE);
 382                bfa_pport_aen_post(pport, BFA_PORT_AEN_DISABLE);
 383                break;
 384
 385        case BFA_PPORT_SM_LINKDOWN:
 386                bfa_sm_set_state(pport, bfa_pport_sm_linkdown);
 387                bfa_pport_reset_linkinfo(pport);
 388                bfa_pport_callback(pport, BFA_PPORT_LINKDOWN);
 389                bfa_plog_str(pport->bfa->plog, BFA_PL_MID_HAL,
 390                             BFA_PL_EID_PORT_ST_CHANGE, 0, "Port Linkdown");
 391                if (BFA_PORT_IS_DISABLED(pport->bfa)) {
 392                        bfa_pport_aen_post(pport, BFA_PORT_AEN_OFFLINE);
 393                } else {
 394                        bfa_pport_aen_post(pport, BFA_PORT_AEN_DISCONNECT);
 395                }
 396                break;
 397
 398        case BFA_PPORT_SM_STOP:
 399                bfa_sm_set_state(pport, bfa_pport_sm_stopped);
 400                bfa_pport_reset_linkinfo(pport);
 401                if (BFA_PORT_IS_DISABLED(pport->bfa)) {
 402                        bfa_pport_aen_post(pport, BFA_PORT_AEN_OFFLINE);
 403                } else {
 404                        bfa_pport_aen_post(pport, BFA_PORT_AEN_DISCONNECT);
 405                }
 406                break;
 407
 408        case BFA_PPORT_SM_HWFAIL:
 409                bfa_sm_set_state(pport, bfa_pport_sm_iocdown);
 410                bfa_pport_reset_linkinfo(pport);
 411                bfa_pport_callback(pport, BFA_PPORT_LINKDOWN);
 412                if (BFA_PORT_IS_DISABLED(pport->bfa)) {
 413                        bfa_pport_aen_post(pport, BFA_PORT_AEN_OFFLINE);
 414                } else {
 415                        bfa_pport_aen_post(pport, BFA_PORT_AEN_DISCONNECT);
 416                }
 417                break;
 418
 419        default:
 420                bfa_sm_fault(pport->bfa, event);
 421        }
 422}
 423
 424static void
 425bfa_pport_sm_disabling_qwait(struct bfa_pport_s *pport,
 426                             enum bfa_pport_sm_event event)
 427{
 428        bfa_trc(pport->bfa, event);
 429
 430        switch (event) {
 431        case BFA_PPORT_SM_QRESUME:
 432                bfa_sm_set_state(pport, bfa_pport_sm_disabling);
 433                bfa_pport_send_disable(pport);
 434                break;
 435
 436        case BFA_PPORT_SM_STOP:
 437                bfa_sm_set_state(pport, bfa_pport_sm_stopped);
 438                bfa_reqq_wcancel(&pport->reqq_wait);
 439                break;
 440
 441        case BFA_PPORT_SM_DISABLE:
 442                /**
 443                 * Already being disabled.
 444                 */
 445                break;
 446
 447        case BFA_PPORT_SM_LINKUP:
 448        case BFA_PPORT_SM_LINKDOWN:
 449                /**
 450                 * Possible to get link events when doing back-to-back
 451                 * enable/disables.
 452                 */
 453                break;
 454
 455        case BFA_PPORT_SM_HWFAIL:
 456                bfa_sm_set_state(pport, bfa_pport_sm_iocfail);
 457                bfa_reqq_wcancel(&pport->reqq_wait);
 458                break;
 459
 460        default:
 461                bfa_sm_fault(pport->bfa, event);
 462        }
 463}
 464
 465static void
 466bfa_pport_sm_disabling(struct bfa_pport_s *pport, enum bfa_pport_sm_event event)
 467{
 468        bfa_trc(pport->bfa, event);
 469
 470        switch (event) {
 471        case BFA_PPORT_SM_FWRSP:
 472                bfa_sm_set_state(pport, bfa_pport_sm_disabled);
 473                break;
 474
 475        case BFA_PPORT_SM_DISABLE:
 476                /**
 477                 * Already being disabled.
 478                 */
 479                break;
 480
 481        case BFA_PPORT_SM_ENABLE:
 482                if (bfa_pport_send_enable(pport))
 483                        bfa_sm_set_state(pport, bfa_pport_sm_enabling);
 484                else
 485                        bfa_sm_set_state(pport, bfa_pport_sm_enabling_qwait);
 486
 487                bfa_plog_str(pport->bfa->plog, BFA_PL_MID_HAL,
 488                             BFA_PL_EID_PORT_ENABLE, 0, "Port Enable");
 489                bfa_pport_aen_post(pport, BFA_PORT_AEN_ENABLE);
 490                break;
 491
 492        case BFA_PPORT_SM_STOP:
 493                bfa_sm_set_state(pport, bfa_pport_sm_stopped);
 494                break;
 495
 496        case BFA_PPORT_SM_LINKUP:
 497        case BFA_PPORT_SM_LINKDOWN:
 498                /**
 499                 * Possible to get link events when doing back-to-back
 500                 * enable/disables.
 501                 */
 502                break;
 503
 504        case BFA_PPORT_SM_HWFAIL:
 505                bfa_sm_set_state(pport, bfa_pport_sm_iocfail);
 506                break;
 507
 508        default:
 509                bfa_sm_fault(pport->bfa, event);
 510        }
 511}
 512
 513static void
 514bfa_pport_sm_disabled(struct bfa_pport_s *pport, enum bfa_pport_sm_event event)
 515{
 516        bfa_trc(pport->bfa, event);
 517
 518        switch (event) {
 519        case BFA_PPORT_SM_START:
 520                /**
 521                 * Ignore start event for a port that is disabled.
 522                 */
 523                break;
 524
 525        case BFA_PPORT_SM_STOP:
 526                bfa_sm_set_state(pport, bfa_pport_sm_stopped);
 527                break;
 528
 529        case BFA_PPORT_SM_ENABLE:
 530                if (bfa_pport_send_enable(pport))
 531                        bfa_sm_set_state(pport, bfa_pport_sm_enabling);
 532                else
 533                        bfa_sm_set_state(pport, bfa_pport_sm_enabling_qwait);
 534
 535                bfa_plog_str(pport->bfa->plog, BFA_PL_MID_HAL,
 536                             BFA_PL_EID_PORT_ENABLE, 0, "Port Enable");
 537                bfa_pport_aen_post(pport, BFA_PORT_AEN_ENABLE);
 538                break;
 539
 540        case BFA_PPORT_SM_DISABLE:
 541                /**
 542                 * Already disabled.
 543                 */
 544                break;
 545
 546        case BFA_PPORT_SM_HWFAIL:
 547                bfa_sm_set_state(pport, bfa_pport_sm_iocfail);
 548                break;
 549
 550        default:
 551                bfa_sm_fault(pport->bfa, event);
 552        }
 553}
 554
 555static void
 556bfa_pport_sm_stopped(struct bfa_pport_s *pport, enum bfa_pport_sm_event event)
 557{
 558        bfa_trc(pport->bfa, event);
 559
 560        switch (event) {
 561        case BFA_PPORT_SM_START:
 562                if (bfa_pport_send_enable(pport))
 563                        bfa_sm_set_state(pport, bfa_pport_sm_enabling);
 564                else
 565                        bfa_sm_set_state(pport, bfa_pport_sm_enabling_qwait);
 566                break;
 567
 568        default:
 569                /**
 570                 * Ignore all other events.
 571                 */
 572                ;
 573        }
 574}
 575
 576/**
 577 * Port is enabled. IOC is down/failed.
 578 */
 579static void
 580bfa_pport_sm_iocdown(struct bfa_pport_s *pport, enum bfa_pport_sm_event event)
 581{
 582        bfa_trc(pport->bfa, event);
 583
 584        switch (event) {
 585        case BFA_PPORT_SM_START:
 586                if (bfa_pport_send_enable(pport))
 587                        bfa_sm_set_state(pport, bfa_pport_sm_enabling);
 588                else
 589                        bfa_sm_set_state(pport, bfa_pport_sm_enabling_qwait);
 590                break;
 591
 592        default:
 593                /**
 594                 * Ignore all events.
 595                 */
 596                ;
 597        }
 598}
 599
 600/**
 601 * Port is disabled. IOC is down/failed.
 602 */
 603static void
 604bfa_pport_sm_iocfail(struct bfa_pport_s *pport, enum bfa_pport_sm_event event)
 605{
 606        bfa_trc(pport->bfa, event);
 607
 608        switch (event) {
 609        case BFA_PPORT_SM_START:
 610                bfa_sm_set_state(pport, bfa_pport_sm_disabled);
 611                break;
 612
 613        case BFA_PPORT_SM_ENABLE:
 614                bfa_sm_set_state(pport, bfa_pport_sm_iocdown);
 615                break;
 616
 617        default:
 618                /**
 619                 * Ignore all events.
 620                 */
 621                ;
 622        }
 623}
 624
 625
 626
 627/**
 628 *  bfa_pport_private
 629 */
 630
 631static void
 632__bfa_cb_port_event(void *cbarg, bfa_boolean_t complete)
 633{
 634        struct bfa_pport_s *pport = cbarg;
 635
 636        if (complete)
 637                pport->event_cbfn(pport->event_cbarg, pport->hcb_event);
 638}
 639
 640#define PPORT_STATS_DMA_SZ (BFA_ROUNDUP(sizeof(union bfa_pport_stats_u), \
 641                                                        BFA_CACHELINE_SZ))
 642
 643static void
 644bfa_pport_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *ndm_len,
 645                  u32 *dm_len)
 646{
 647        *dm_len += PPORT_STATS_DMA_SZ;
 648}
 649
 650static void
 651bfa_pport_qresume(void *cbarg)
 652{
 653        struct bfa_pport_s *port = cbarg;
 654
 655        bfa_sm_send_event(port, BFA_PPORT_SM_QRESUME);
 656}
 657
 658static void
 659bfa_pport_mem_claim(struct bfa_pport_s *pport, struct bfa_meminfo_s *meminfo)
 660{
 661        u8        *dm_kva;
 662        u64        dm_pa;
 663
 664        dm_kva = bfa_meminfo_dma_virt(meminfo);
 665        dm_pa = bfa_meminfo_dma_phys(meminfo);
 666
 667        pport->stats_kva = dm_kva;
 668        pport->stats_pa = dm_pa;
 669        pport->stats = (union bfa_pport_stats_u *)dm_kva;
 670
 671        dm_kva += PPORT_STATS_DMA_SZ;
 672        dm_pa += PPORT_STATS_DMA_SZ;
 673
 674        bfa_meminfo_dma_virt(meminfo) = dm_kva;
 675        bfa_meminfo_dma_phys(meminfo) = dm_pa;
 676}
 677
 678/**
 679 * Memory initialization.
 680 */
 681static void
 682bfa_pport_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
 683                 struct bfa_meminfo_s *meminfo, struct bfa_pcidev_s *pcidev)
 684{
 685        struct bfa_pport_s *pport = BFA_PORT_MOD(bfa);
 686        struct bfa_pport_cfg_s *port_cfg = &pport->cfg;
 687
 688        bfa_os_memset(pport, 0, sizeof(struct bfa_pport_s));
 689        pport->bfa = bfa;
 690
 691        bfa_pport_mem_claim(pport, meminfo);
 692
 693        bfa_sm_set_state(pport, bfa_pport_sm_uninit);
 694
 695        /**
 696         * initialize and set default configuration
 697         */
 698        port_cfg->topology = BFA_PPORT_TOPOLOGY_P2P;
 699        port_cfg->speed = BFA_PPORT_SPEED_AUTO;
 700        port_cfg->trunked = BFA_FALSE;
 701        port_cfg->maxfrsize = 0;
 702
 703        port_cfg->trl_def_speed = BFA_PPORT_SPEED_1GBPS;
 704
 705        bfa_reqq_winit(&pport->reqq_wait, bfa_pport_qresume, pport);
 706}
 707
 708static void
 709bfa_pport_initdone(struct bfa_s *bfa)
 710{
 711        struct bfa_pport_s *pport = BFA_PORT_MOD(bfa);
 712
 713        /**
 714         * Initialize port attributes from IOC hardware data.
 715         */
 716        bfa_pport_set_wwns(pport);
 717        if (pport->cfg.maxfrsize == 0)
 718                pport->cfg.maxfrsize = bfa_ioc_maxfrsize(&bfa->ioc);
 719        pport->cfg.rx_bbcredit = bfa_ioc_rx_bbcredit(&bfa->ioc);
 720        pport->speed_sup = bfa_ioc_speed_sup(&bfa->ioc);
 721
 722        bfa_assert(pport->cfg.maxfrsize);
 723        bfa_assert(pport->cfg.rx_bbcredit);
 724        bfa_assert(pport->speed_sup);
 725}
 726
 727static void
 728bfa_pport_detach(struct bfa_s *bfa)
 729{
 730}
 731
 732/**
 733 * Called when IOC is ready.
 734 */
 735static void
 736bfa_pport_start(struct bfa_s *bfa)
 737{
 738        bfa_sm_send_event(BFA_PORT_MOD(bfa), BFA_PPORT_SM_START);
 739}
 740
 741/**
 742 * Called before IOC is stopped.
 743 */
 744static void
 745bfa_pport_stop(struct bfa_s *bfa)
 746{
 747        bfa_sm_send_event(BFA_PORT_MOD(bfa), BFA_PPORT_SM_STOP);
 748}
 749
 750/**
 751 * Called when IOC failure is detected.
 752 */
 753static void
 754bfa_pport_iocdisable(struct bfa_s *bfa)
 755{
 756        bfa_sm_send_event(BFA_PORT_MOD(bfa), BFA_PPORT_SM_HWFAIL);
 757}
 758
 759static void
 760bfa_pport_update_linkinfo(struct bfa_pport_s *pport)
 761{
 762        struct bfi_pport_event_s *pevent = pport->event_arg.i2hmsg.event;
 763
 764        pport->speed = pevent->link_state.speed;
 765        pport->topology = pevent->link_state.topology;
 766
 767        if (pport->topology == BFA_PPORT_TOPOLOGY_LOOP)
 768                pport->myalpa = pevent->link_state.tl.loop_info.myalpa;
 769
 770        /*
 771         * QoS Details
 772         */
 773        bfa_os_assign(pport->qos_attr, pevent->link_state.qos_attr);
 774        bfa_os_assign(pport->qos_vc_attr, pevent->link_state.qos_vc_attr);
 775
 776        bfa_trc(pport->bfa, pport->speed);
 777        bfa_trc(pport->bfa, pport->topology);
 778}
 779
 780static void
 781bfa_pport_reset_linkinfo(struct bfa_pport_s *pport)
 782{
 783        pport->speed = BFA_PPORT_SPEED_UNKNOWN;
 784        pport->topology = BFA_PPORT_TOPOLOGY_NONE;
 785}
 786
 787/**
 788 * Send port enable message to firmware.
 789 */
 790static          bfa_boolean_t
 791bfa_pport_send_enable(struct bfa_pport_s *port)
 792{
 793        struct bfi_pport_enable_req_s *m;
 794
 795        /**
 796         * Increment message tag before queue check, so that responses to old
 797         * requests are discarded.
 798         */
 799        port->msgtag++;
 800
 801        /**
 802         * check for room in queue to send request now
 803         */
 804        m = bfa_reqq_next(port->bfa, BFA_REQQ_PORT);
 805        if (!m) {
 806                bfa_reqq_wait(port->bfa, BFA_REQQ_PORT, &port->reqq_wait);
 807                return BFA_FALSE;
 808        }
 809
 810        bfi_h2i_set(m->mh, BFI_MC_FC_PORT, BFI_PPORT_H2I_ENABLE_REQ,
 811                    bfa_lpuid(port->bfa));
 812        m->nwwn = port->nwwn;
 813        m->pwwn = port->pwwn;
 814        m->port_cfg = port->cfg;
 815        m->msgtag = port->msgtag;
 816        m->port_cfg.maxfrsize = bfa_os_htons(port->cfg.maxfrsize);
 817        bfa_dma_be_addr_set(m->stats_dma_addr, port->stats_pa);
 818        bfa_trc(port->bfa, m->stats_dma_addr.a32.addr_lo);
 819        bfa_trc(port->bfa, m->stats_dma_addr.a32.addr_hi);
 820
 821        /**
 822         * queue I/O message to firmware
 823         */
 824        bfa_reqq_produce(port->bfa, BFA_REQQ_PORT);
 825        return BFA_TRUE;
 826}
 827
 828/**
 829 * Send port disable message to firmware.
 830 */
 831static          bfa_boolean_t
 832bfa_pport_send_disable(struct bfa_pport_s *port)
 833{
 834        bfi_pport_disable_req_t *m;
 835
 836        /**
 837         * Increment message tag before queue check, so that responses to old
 838         * requests are discarded.
 839         */
 840        port->msgtag++;
 841
 842        /**
 843         * check for room in queue to send request now
 844         */
 845        m = bfa_reqq_next(port->bfa, BFA_REQQ_PORT);
 846        if (!m) {
 847                bfa_reqq_wait(port->bfa, BFA_REQQ_PORT, &port->reqq_wait);
 848                return BFA_FALSE;
 849        }
 850
 851        bfi_h2i_set(m->mh, BFI_MC_FC_PORT, BFI_PPORT_H2I_DISABLE_REQ,
 852                    bfa_lpuid(port->bfa));
 853        m->msgtag = port->msgtag;
 854
 855        /**
 856         * queue I/O message to firmware
 857         */
 858        bfa_reqq_produce(port->bfa, BFA_REQQ_PORT);
 859
 860        return BFA_TRUE;
 861}
 862
 863static void
 864bfa_pport_set_wwns(struct bfa_pport_s *port)
 865{
 866        port->pwwn = bfa_ioc_get_pwwn(&port->bfa->ioc);
 867        port->nwwn = bfa_ioc_get_nwwn(&port->bfa->ioc);
 868
 869        bfa_trc(port->bfa, port->pwwn);
 870        bfa_trc(port->bfa, port->nwwn);
 871}
 872
 873static void
 874bfa_port_send_txcredit(void *port_cbarg)
 875{
 876
 877        struct bfa_pport_s *port = port_cbarg;
 878        struct bfi_pport_set_svc_params_req_s *m;
 879
 880        /**
 881         * check for room in queue to send request now
 882         */
 883        m = bfa_reqq_next(port->bfa, BFA_REQQ_PORT);
 884        if (!m) {
 885                bfa_trc(port->bfa, port->cfg.tx_bbcredit);
 886                return;
 887        }
 888
 889        bfi_h2i_set(m->mh, BFI_MC_FC_PORT, BFI_PPORT_H2I_SET_SVC_PARAMS_REQ,
 890                    bfa_lpuid(port->bfa));
 891        m->tx_bbcredit = bfa_os_htons((u16) port->cfg.tx_bbcredit);
 892
 893        /**
 894         * queue I/O message to firmware
 895         */
 896        bfa_reqq_produce(port->bfa, BFA_REQQ_PORT);
 897}
 898
 899
 900
 901/**
 902 *  bfa_pport_public
 903 */
 904
 905/**
 906 * Firmware message handler.
 907 */
 908void
 909bfa_pport_isr(struct bfa_s *bfa, struct bfi_msg_s *msg)
 910{
 911        struct bfa_pport_s *pport = BFA_PORT_MOD(bfa);
 912        union bfi_pport_i2h_msg_u i2hmsg;
 913
 914        i2hmsg.msg = msg;
 915        pport->event_arg.i2hmsg = i2hmsg;
 916
 917        switch (msg->mhdr.msg_id) {
 918        case BFI_PPORT_I2H_ENABLE_RSP:
 919                if (pport->msgtag == i2hmsg.enable_rsp->msgtag)
 920                        bfa_sm_send_event(pport, BFA_PPORT_SM_FWRSP);
 921                break;
 922
 923        case BFI_PPORT_I2H_DISABLE_RSP:
 924                if (pport->msgtag == i2hmsg.enable_rsp->msgtag)
 925                        bfa_sm_send_event(pport, BFA_PPORT_SM_FWRSP);
 926                break;
 927
 928        case BFI_PPORT_I2H_EVENT:
 929                switch (i2hmsg.event->link_state.linkstate) {
 930                case BFA_PPORT_LINKUP:
 931                        bfa_sm_send_event(pport, BFA_PPORT_SM_LINKUP);
 932                        break;
 933                case BFA_PPORT_LINKDOWN:
 934                        bfa_sm_send_event(pport, BFA_PPORT_SM_LINKDOWN);
 935                        break;
 936                case BFA_PPORT_TRUNK_LINKDOWN:
 937                        /** todo: event notification */
 938                        break;
 939                }
 940                break;
 941
 942        case BFI_PPORT_I2H_GET_STATS_RSP:
 943        case BFI_PPORT_I2H_GET_QOS_STATS_RSP:
 944                /*
 945                 * check for timer pop before processing the rsp
 946                 */
 947                if (pport->stats_busy == BFA_FALSE
 948                    || pport->stats_status == BFA_STATUS_ETIMER)
 949                        break;
 950
 951                bfa_timer_stop(&pport->timer);
 952                pport->stats_status = i2hmsg.getstats_rsp->status;
 953                bfa_cb_queue(pport->bfa, &pport->hcb_qe, __bfa_cb_port_stats,
 954                             pport);
 955                break;
 956        case BFI_PPORT_I2H_CLEAR_STATS_RSP:
 957        case BFI_PPORT_I2H_CLEAR_QOS_STATS_RSP:
 958                /*
 959                 * check for timer pop before processing the rsp
 960                 */
 961                if (pport->stats_busy == BFA_FALSE
 962                    || pport->stats_status == BFA_STATUS_ETIMER)
 963                        break;
 964
 965                bfa_timer_stop(&pport->timer);
 966                pport->stats_status = BFA_STATUS_OK;
 967                bfa_cb_queue(pport->bfa, &pport->hcb_qe,
 968                             __bfa_cb_port_stats_clr, pport);
 969                break;
 970
 971        default:
 972                bfa_assert(0);
 973        }
 974}
 975
 976
 977
 978/**
 979 *  bfa_pport_api
 980 */
 981
 982/**
 983 * Registered callback for port events.
 984 */
 985void
 986bfa_pport_event_register(struct bfa_s *bfa,
 987                         void (*cbfn) (void *cbarg, bfa_pport_event_t event),
 988                         void *cbarg)
 989{
 990        struct bfa_pport_s *pport = BFA_PORT_MOD(bfa);
 991
 992        pport->event_cbfn = cbfn;
 993        pport->event_cbarg = cbarg;
 994}
 995
 996bfa_status_t
 997bfa_pport_enable(struct bfa_s *bfa)
 998{
 999        struct bfa_pport_s *pport = BFA_PORT_MOD(bfa);
1000
1001        if (pport->diag_busy)
1002                return (BFA_STATUS_DIAG_BUSY);
1003        else if (bfa_sm_cmp_state
1004                 (BFA_PORT_MOD(bfa), bfa_pport_sm_disabling_qwait))
1005                return (BFA_STATUS_DEVBUSY);
1006
1007        bfa_sm_send_event(BFA_PORT_MOD(bfa), BFA_PPORT_SM_ENABLE);
1008        return BFA_STATUS_OK;
1009}
1010
1011bfa_status_t
1012bfa_pport_disable(struct bfa_s *bfa)
1013{
1014        bfa_sm_send_event(BFA_PORT_MOD(bfa), BFA_PPORT_SM_DISABLE);
1015        return BFA_STATUS_OK;
1016}
1017
1018/**
1019 * Configure port speed.
1020 */
1021bfa_status_t
1022bfa_pport_cfg_speed(struct bfa_s *bfa, enum bfa_pport_speed speed)
1023{
1024        struct bfa_pport_s *pport = BFA_PORT_MOD(bfa);
1025
1026        bfa_trc(bfa, speed);
1027
1028        if ((speed != BFA_PPORT_SPEED_AUTO) && (speed > pport->speed_sup)) {
1029                bfa_trc(bfa, pport->speed_sup);
1030                return BFA_STATUS_UNSUPP_SPEED;
1031        }
1032
1033        pport->cfg.speed = speed;
1034
1035        return (BFA_STATUS_OK);
1036}
1037
1038/**
1039 * Get current speed.
1040 */
1041enum bfa_pport_speed
1042bfa_pport_get_speed(struct bfa_s *bfa)
1043{
1044        struct bfa_pport_s *port = BFA_PORT_MOD(bfa);
1045
1046        return port->speed;
1047}
1048
1049/**
1050 * Configure port topology.
1051 */
1052bfa_status_t
1053bfa_pport_cfg_topology(struct bfa_s *bfa, enum bfa_pport_topology topology)
1054{
1055        struct bfa_pport_s *pport = BFA_PORT_MOD(bfa);
1056
1057        bfa_trc(bfa, topology);
1058        bfa_trc(bfa, pport->cfg.topology);
1059
1060        switch (topology) {
1061        case BFA_PPORT_TOPOLOGY_P2P:
1062        case BFA_PPORT_TOPOLOGY_LOOP:
1063        case BFA_PPORT_TOPOLOGY_AUTO:
1064                break;
1065
1066        default:
1067                return BFA_STATUS_EINVAL;
1068        }
1069
1070        pport->cfg.topology = topology;
1071        return (BFA_STATUS_OK);
1072}
1073
1074/**
1075 * Get current topology.
1076 */
1077enum bfa_pport_topology
1078bfa_pport_get_topology(struct bfa_s *bfa)
1079{
1080        struct bfa_pport_s *port = BFA_PORT_MOD(bfa);
1081
1082        return port->topology;
1083}
1084
1085bfa_status_t
1086bfa_pport_cfg_hardalpa(struct bfa_s *bfa, u8 alpa)
1087{
1088        struct bfa_pport_s *pport = BFA_PORT_MOD(bfa);
1089
1090        bfa_trc(bfa, alpa);
1091        bfa_trc(bfa, pport->cfg.cfg_hardalpa);
1092        bfa_trc(bfa, pport->cfg.hardalpa);
1093
1094        pport->cfg.cfg_hardalpa = BFA_TRUE;
1095        pport->cfg.hardalpa = alpa;
1096
1097        return (BFA_STATUS_OK);
1098}
1099
1100bfa_status_t
1101bfa_pport_clr_hardalpa(struct bfa_s *bfa)
1102{
1103        struct bfa_pport_s *pport = BFA_PORT_MOD(bfa);
1104
1105        bfa_trc(bfa, pport->cfg.cfg_hardalpa);
1106        bfa_trc(bfa, pport->cfg.hardalpa);
1107
1108        pport->cfg.cfg_hardalpa = BFA_FALSE;
1109        return (BFA_STATUS_OK);
1110}
1111
1112bfa_boolean_t
1113bfa_pport_get_hardalpa(struct bfa_s *bfa, u8 *alpa)
1114{
1115        struct bfa_pport_s *port = BFA_PORT_MOD(bfa);
1116
1117        *alpa = port->cfg.hardalpa;
1118        return port->cfg.cfg_hardalpa;
1119}
1120
1121u8
1122bfa_pport_get_myalpa(struct bfa_s *bfa)
1123{
1124        struct bfa_pport_s *port = BFA_PORT_MOD(bfa);
1125
1126        return port->myalpa;
1127}
1128
1129bfa_status_t
1130bfa_pport_cfg_maxfrsize(struct bfa_s *bfa, u16 maxfrsize)
1131{
1132        struct bfa_pport_s *pport = BFA_PORT_MOD(bfa);
1133
1134        bfa_trc(bfa, maxfrsize);
1135        bfa_trc(bfa, pport->cfg.maxfrsize);
1136
1137        /*
1138         * with in range
1139         */
1140        if ((maxfrsize > FC_MAX_PDUSZ) || (maxfrsize < FC_MIN_PDUSZ))
1141                return (BFA_STATUS_INVLD_DFSZ);
1142
1143        /*
1144         * power of 2, if not the max frame size of 2112
1145         */
1146        if ((maxfrsize != FC_MAX_PDUSZ) && (maxfrsize & (maxfrsize - 1)))
1147                return (BFA_STATUS_INVLD_DFSZ);
1148
1149        pport->cfg.maxfrsize = maxfrsize;
1150        return (BFA_STATUS_OK);
1151}
1152
1153u16
1154bfa_pport_get_maxfrsize(struct bfa_s *bfa)
1155{
1156        struct bfa_pport_s *port = BFA_PORT_MOD(bfa);
1157
1158        return port->cfg.maxfrsize;
1159}
1160
1161u32
1162bfa_pport_mypid(struct bfa_s *bfa)
1163{
1164        struct bfa_pport_s *port = BFA_PORT_MOD(bfa);
1165
1166        return port->mypid;
1167}
1168
1169u8
1170bfa_pport_get_rx_bbcredit(struct bfa_s *bfa)
1171{
1172        struct bfa_pport_s *port = BFA_PORT_MOD(bfa);
1173
1174        return port->cfg.rx_bbcredit;
1175}
1176
1177void
1178bfa_pport_set_tx_bbcredit(struct bfa_s *bfa, u16 tx_bbcredit)
1179{
1180        struct bfa_pport_s *port = BFA_PORT_MOD(bfa);
1181
1182        port->cfg.tx_bbcredit = (u8) tx_bbcredit;
1183        bfa_port_send_txcredit(port);
1184}
1185
1186/**
1187 * Get port attributes.
1188 */
1189
1190wwn_t
1191bfa_pport_get_wwn(struct bfa_s *bfa, bfa_boolean_t node)
1192{
1193        struct bfa_pport_s *pport = BFA_PORT_MOD(bfa);
1194        if (node)
1195                return pport->nwwn;
1196        else
1197                return pport->pwwn;
1198}
1199
1200void
1201bfa_pport_get_attr(struct bfa_s *bfa, struct bfa_pport_attr_s *attr)
1202{
1203        struct bfa_pport_s *pport = BFA_PORT_MOD(bfa);
1204
1205        bfa_os_memset(attr, 0, sizeof(struct bfa_pport_attr_s));
1206
1207        attr->nwwn = pport->nwwn;
1208        attr->pwwn = pport->pwwn;
1209
1210        bfa_os_memcpy(&attr->pport_cfg, &pport->cfg,
1211                      sizeof(struct bfa_pport_cfg_s));
1212        /*
1213         * speed attributes
1214         */
1215        attr->pport_cfg.speed = pport->cfg.speed;
1216        attr->speed_supported = pport->speed_sup;
1217        attr->speed = pport->speed;
1218        attr->cos_supported = FC_CLASS_3;
1219
1220        /*
1221         * topology attributes
1222         */
1223        attr->pport_cfg.topology = pport->cfg.topology;
1224        attr->topology = pport->topology;
1225
1226        /*
1227         * beacon attributes
1228         */
1229        attr->beacon = pport->beacon;
1230        attr->link_e2e_beacon = pport->link_e2e_beacon;
1231        attr->plog_enabled = bfa_plog_get_setting(pport->bfa->plog);
1232
1233        attr->pport_cfg.path_tov = bfa_fcpim_path_tov_get(bfa);
1234        attr->pport_cfg.q_depth = bfa_fcpim_qdepth_get(bfa);
1235        attr->port_state = bfa_sm_to_state(hal_pport_sm_table, pport->sm);
1236        if (bfa_ioc_is_disabled(&pport->bfa->ioc))
1237                attr->port_state = BFA_PPORT_ST_IOCDIS;
1238        else if (bfa_ioc_fw_mismatch(&pport->bfa->ioc))
1239                attr->port_state = BFA_PPORT_ST_FWMISMATCH;
1240}
1241
1242static void
1243bfa_port_stats_query(void *cbarg)
1244{
1245        struct bfa_pport_s *port = (struct bfa_pport_s *)cbarg;
1246        bfi_pport_get_stats_req_t *msg;
1247
1248        msg = bfa_reqq_next(port->bfa, BFA_REQQ_PORT);
1249
1250        if (!msg) {
1251                port->stats_qfull = BFA_TRUE;
1252                bfa_reqq_winit(&port->stats_reqq_wait, bfa_port_stats_query,
1253                               port);
1254                bfa_reqq_wait(port->bfa, BFA_REQQ_PORT, &port->stats_reqq_wait);
1255                return;
1256        }
1257        port->stats_qfull = BFA_FALSE;
1258
1259        bfa_os_memset(msg, 0, sizeof(bfi_pport_get_stats_req_t));
1260        bfi_h2i_set(msg->mh, BFI_MC_FC_PORT, BFI_PPORT_H2I_GET_STATS_REQ,
1261                    bfa_lpuid(port->bfa));
1262        bfa_reqq_produce(port->bfa, BFA_REQQ_PORT);
1263
1264        return;
1265}
1266
1267static void
1268bfa_port_stats_clear(void *cbarg)
1269{
1270        struct bfa_pport_s *port = (struct bfa_pport_s *)cbarg;
1271        bfi_pport_clear_stats_req_t *msg;
1272
1273        msg = bfa_reqq_next(port->bfa, BFA_REQQ_PORT);
1274
1275        if (!msg) {
1276                port->stats_qfull = BFA_TRUE;
1277                bfa_reqq_winit(&port->stats_reqq_wait, bfa_port_stats_clear,
1278                               port);
1279                bfa_reqq_wait(port->bfa, BFA_REQQ_PORT, &port->stats_reqq_wait);
1280                return;
1281        }
1282        port->stats_qfull = BFA_FALSE;
1283
1284        bfa_os_memset(msg, 0, sizeof(bfi_pport_clear_stats_req_t));
1285        bfi_h2i_set(msg->mh, BFI_MC_FC_PORT, BFI_PPORT_H2I_CLEAR_STATS_REQ,
1286                    bfa_lpuid(port->bfa));
1287        bfa_reqq_produce(port->bfa, BFA_REQQ_PORT);
1288        return;
1289}
1290
1291static void
1292bfa_port_qos_stats_clear(void *cbarg)
1293{
1294        struct bfa_pport_s *port = (struct bfa_pport_s *)cbarg;
1295        bfi_pport_clear_qos_stats_req_t *msg;
1296
1297        msg = bfa_reqq_next(port->bfa, BFA_REQQ_PORT);
1298
1299        if (!msg) {
1300                port->stats_qfull = BFA_TRUE;
1301                bfa_reqq_winit(&port->stats_reqq_wait, bfa_port_qos_stats_clear,
1302                               port);
1303                bfa_reqq_wait(port->bfa, BFA_REQQ_PORT, &port->stats_reqq_wait);
1304                return;
1305        }
1306        port->stats_qfull = BFA_FALSE;
1307
1308        bfa_os_memset(msg, 0, sizeof(bfi_pport_clear_qos_stats_req_t));
1309        bfi_h2i_set(msg->mh, BFI_MC_FC_PORT, BFI_PPORT_H2I_CLEAR_QOS_STATS_REQ,
1310                    bfa_lpuid(port->bfa));
1311        bfa_reqq_produce(port->bfa, BFA_REQQ_PORT);
1312        return;
1313}
1314
1315static void
1316bfa_pport_stats_swap(union bfa_pport_stats_u *d, union bfa_pport_stats_u *s)
1317{
1318        u32       *dip = (u32 *) d;
1319        u32       *sip = (u32 *) s;
1320        int             i;
1321
1322        /*
1323         * Do 64 bit fields swap first
1324         */
1325        for (i = 0;
1326             i <
1327             ((sizeof(union bfa_pport_stats_u) -
1328               sizeof(struct bfa_qos_stats_s)) / sizeof(u32)); i = i + 2) {
1329#ifdef __BIGENDIAN
1330                dip[i] = bfa_os_ntohl(sip[i]);
1331                dip[i + 1] = bfa_os_ntohl(sip[i + 1]);
1332#else
1333                dip[i] = bfa_os_ntohl(sip[i + 1]);
1334                dip[i + 1] = bfa_os_ntohl(sip[i]);
1335#endif
1336        }
1337
1338        /*
1339         * Now swap the 32 bit fields
1340         */
1341        for (; i < (sizeof(union bfa_pport_stats_u) / sizeof(u32)); ++i)
1342                dip[i] = bfa_os_ntohl(sip[i]);
1343}
1344
1345static void
1346__bfa_cb_port_stats_clr(void *cbarg, bfa_boolean_t complete)
1347{
1348        struct bfa_pport_s *port = cbarg;
1349
1350        if (complete) {
1351                port->stats_cbfn(port->stats_cbarg, port->stats_status);
1352        } else {
1353                port->stats_busy = BFA_FALSE;
1354                port->stats_status = BFA_STATUS_OK;
1355        }
1356}
1357
1358static void
1359bfa_port_stats_clr_timeout(void *cbarg)
1360{
1361        struct bfa_pport_s *port = (struct bfa_pport_s *)cbarg;
1362
1363        bfa_trc(port->bfa, port->stats_qfull);
1364
1365        if (port->stats_qfull) {
1366                bfa_reqq_wcancel(&port->stats_reqq_wait);
1367                port->stats_qfull = BFA_FALSE;
1368        }
1369
1370        port->stats_status = BFA_STATUS_ETIMER;
1371        bfa_cb_queue(port->bfa, &port->hcb_qe, __bfa_cb_port_stats_clr, port);
1372}
1373
1374static void
1375__bfa_cb_port_stats(void *cbarg, bfa_boolean_t complete)
1376{
1377        struct bfa_pport_s *port = cbarg;
1378
1379        if (complete) {
1380                if (port->stats_status == BFA_STATUS_OK)
1381                        bfa_pport_stats_swap(port->stats_ret, port->stats);
1382                port->stats_cbfn(port->stats_cbarg, port->stats_status);
1383        } else {
1384                port->stats_busy = BFA_FALSE;
1385                port->stats_status = BFA_STATUS_OK;
1386        }
1387}
1388
1389static void
1390bfa_port_stats_timeout(void *cbarg)
1391{
1392        struct bfa_pport_s *port = (struct bfa_pport_s *)cbarg;
1393
1394        bfa_trc(port->bfa, port->stats_qfull);
1395
1396        if (port->stats_qfull) {
1397                bfa_reqq_wcancel(&port->stats_reqq_wait);
1398                port->stats_qfull = BFA_FALSE;
1399        }
1400
1401        port->stats_status = BFA_STATUS_ETIMER;
1402        bfa_cb_queue(port->bfa, &port->hcb_qe, __bfa_cb_port_stats, port);
1403}
1404
1405#define BFA_PORT_STATS_TOV      1000
1406
1407/**
1408 * Fetch port attributes.
1409 */
1410bfa_status_t
1411bfa_pport_get_stats(struct bfa_s *bfa, union bfa_pport_stats_u *stats,
1412                    bfa_cb_pport_t cbfn, void *cbarg)
1413{
1414        struct bfa_pport_s *port = BFA_PORT_MOD(bfa);
1415
1416        if (port->stats_busy) {
1417                bfa_trc(bfa, port->stats_busy);
1418                return (BFA_STATUS_DEVBUSY);
1419        }
1420
1421        port->stats_busy = BFA_TRUE;
1422        port->stats_ret = stats;
1423        port->stats_cbfn = cbfn;
1424        port->stats_cbarg = cbarg;
1425
1426        bfa_port_stats_query(port);
1427
1428        bfa_timer_start(bfa, &port->timer, bfa_port_stats_timeout, port,
1429                        BFA_PORT_STATS_TOV);
1430        return (BFA_STATUS_OK);
1431}
1432
1433bfa_status_t
1434bfa_pport_clear_stats(struct bfa_s *bfa, bfa_cb_pport_t cbfn, void *cbarg)
1435{
1436        struct bfa_pport_s *port = BFA_PORT_MOD(bfa);
1437
1438        if (port->stats_busy) {
1439                bfa_trc(bfa, port->stats_busy);
1440                return (BFA_STATUS_DEVBUSY);
1441        }
1442
1443        port->stats_busy = BFA_TRUE;
1444        port->stats_cbfn = cbfn;
1445        port->stats_cbarg = cbarg;
1446
1447        bfa_port_stats_clear(port);
1448
1449        bfa_timer_start(bfa, &port->timer, bfa_port_stats_clr_timeout, port,
1450                        BFA_PORT_STATS_TOV);
1451        return (BFA_STATUS_OK);
1452}
1453
1454bfa_status_t
1455bfa_pport_trunk_enable(struct bfa_s *bfa, u8 bitmap)
1456{
1457        struct bfa_pport_s *pport = BFA_PORT_MOD(bfa);
1458
1459        bfa_trc(bfa, bitmap);
1460        bfa_trc(bfa, pport->cfg.trunked);
1461        bfa_trc(bfa, pport->cfg.trunk_ports);
1462
1463        if (!bitmap || (bitmap & (bitmap - 1)))
1464                return BFA_STATUS_EINVAL;
1465
1466        pport->cfg.trunked = BFA_TRUE;
1467        pport->cfg.trunk_ports = bitmap;
1468
1469        return BFA_STATUS_OK;
1470}
1471
1472void
1473bfa_pport_qos_get_attr(struct bfa_s *bfa, struct bfa_qos_attr_s *qos_attr)
1474{
1475        struct bfa_pport_s *pport = BFA_PORT_MOD(bfa);
1476
1477        qos_attr->state = bfa_os_ntohl(pport->qos_attr.state);
1478        qos_attr->total_bb_cr = bfa_os_ntohl(pport->qos_attr.total_bb_cr);
1479}
1480
1481void
1482bfa_pport_qos_get_vc_attr(struct bfa_s *bfa,
1483                          struct bfa_qos_vc_attr_s *qos_vc_attr)
1484{
1485        struct bfa_pport_s *pport = BFA_PORT_MOD(bfa);
1486        struct bfa_qos_vc_attr_s *bfa_vc_attr = &pport->qos_vc_attr;
1487        u32        i = 0;
1488
1489        qos_vc_attr->total_vc_count = bfa_os_ntohs(bfa_vc_attr->total_vc_count);
1490        qos_vc_attr->shared_credit = bfa_os_ntohs(bfa_vc_attr->shared_credit);
1491        qos_vc_attr->elp_opmode_flags =
1492                bfa_os_ntohl(bfa_vc_attr->elp_opmode_flags);
1493
1494        /*
1495         * Individual VC info
1496         */
1497        while (i < qos_vc_attr->total_vc_count) {
1498                qos_vc_attr->vc_info[i].vc_credit =
1499                        bfa_vc_attr->vc_info[i].vc_credit;
1500                qos_vc_attr->vc_info[i].borrow_credit =
1501                        bfa_vc_attr->vc_info[i].borrow_credit;
1502                qos_vc_attr->vc_info[i].priority =
1503                        bfa_vc_attr->vc_info[i].priority;
1504                ++i;
1505        }
1506}
1507
1508/**
1509 * Fetch QoS Stats.
1510 */
1511bfa_status_t
1512bfa_pport_get_qos_stats(struct bfa_s *bfa, union bfa_pport_stats_u *stats,
1513                        bfa_cb_pport_t cbfn, void *cbarg)
1514{
1515        /*
1516         * QoS stats is embedded in port stats
1517         */
1518        return (bfa_pport_get_stats(bfa, stats, cbfn, cbarg));
1519}
1520
1521bfa_status_t
1522bfa_pport_clear_qos_stats(struct bfa_s *bfa, bfa_cb_pport_t cbfn, void *cbarg)
1523{
1524        struct bfa_pport_s *port = BFA_PORT_MOD(bfa);
1525
1526        if (port->stats_busy) {
1527                bfa_trc(bfa, port->stats_busy);
1528                return (BFA_STATUS_DEVBUSY);
1529        }
1530
1531        port->stats_busy = BFA_TRUE;
1532        port->stats_cbfn = cbfn;
1533        port->stats_cbarg = cbarg;
1534
1535        bfa_port_qos_stats_clear(port);
1536
1537        bfa_timer_start(bfa, &port->timer, bfa_port_stats_clr_timeout, port,
1538                        BFA_PORT_STATS_TOV);
1539        return (BFA_STATUS_OK);
1540}
1541
1542/**
1543 * Fetch port attributes.
1544 */
1545bfa_status_t
1546bfa_pport_trunk_disable(struct bfa_s *bfa)
1547{
1548        return (BFA_STATUS_OK);
1549}
1550
1551bfa_boolean_t
1552bfa_pport_trunk_query(struct bfa_s *bfa, u32 *bitmap)
1553{
1554        struct bfa_pport_s *port = BFA_PORT_MOD(bfa);
1555
1556        *bitmap = port->cfg.trunk_ports;
1557        return port->cfg.trunked;
1558}
1559
1560bfa_boolean_t
1561bfa_pport_is_disabled(struct bfa_s *bfa)
1562{
1563        struct bfa_pport_s *port = BFA_PORT_MOD(bfa);
1564
1565        return (bfa_sm_to_state(hal_pport_sm_table, port->sm) ==
1566                BFA_PPORT_ST_DISABLED);
1567
1568}
1569
1570bfa_boolean_t
1571bfa_pport_is_ratelim(struct bfa_s *bfa)
1572{
1573        struct bfa_pport_s *pport = BFA_PORT_MOD(bfa);
1574
1575return (pport->cfg.ratelimit ? BFA_TRUE : BFA_FALSE);
1576
1577}
1578
1579void
1580bfa_pport_cfg_qos(struct bfa_s *bfa, bfa_boolean_t on_off)
1581{
1582        struct bfa_pport_s *pport = BFA_PORT_MOD(bfa);
1583
1584        bfa_trc(bfa, on_off);
1585        bfa_trc(bfa, pport->cfg.qos_enabled);
1586
1587        pport->cfg.qos_enabled = on_off;
1588}
1589
1590void
1591bfa_pport_cfg_ratelim(struct bfa_s *bfa, bfa_boolean_t on_off)
1592{
1593        struct bfa_pport_s *pport = BFA_PORT_MOD(bfa);
1594
1595        bfa_trc(bfa, on_off);
1596        bfa_trc(bfa, pport->cfg.ratelimit);
1597
1598        pport->cfg.ratelimit = on_off;
1599        if (pport->cfg.trl_def_speed == BFA_PPORT_SPEED_UNKNOWN)
1600                pport->cfg.trl_def_speed = BFA_PPORT_SPEED_1GBPS;
1601}
1602
1603/**
1604 * Configure default minimum ratelim speed
1605 */
1606bfa_status_t
1607bfa_pport_cfg_ratelim_speed(struct bfa_s *bfa, enum bfa_pport_speed speed)
1608{
1609        struct bfa_pport_s *pport = BFA_PORT_MOD(bfa);
1610
1611        bfa_trc(bfa, speed);
1612
1613        /*
1614         * Auto and speeds greater than the supported speed, are invalid
1615         */
1616        if ((speed == BFA_PPORT_SPEED_AUTO) || (speed > pport->speed_sup)) {
1617                bfa_trc(bfa, pport->speed_sup);
1618                return BFA_STATUS_UNSUPP_SPEED;
1619        }
1620
1621        pport->cfg.trl_def_speed = speed;
1622
1623        return (BFA_STATUS_OK);
1624}
1625
1626/**
1627 * Get default minimum ratelim speed
1628 */
1629enum bfa_pport_speed
1630bfa_pport_get_ratelim_speed(struct bfa_s *bfa)
1631{
1632        struct bfa_pport_s *pport = BFA_PORT_MOD(bfa);
1633
1634        bfa_trc(bfa, pport->cfg.trl_def_speed);
1635        return (pport->cfg.trl_def_speed);
1636
1637}
1638
1639void
1640bfa_pport_busy(struct bfa_s *bfa, bfa_boolean_t status)
1641{
1642        struct bfa_pport_s *pport = BFA_PORT_MOD(bfa);
1643
1644        bfa_trc(bfa, status);
1645        bfa_trc(bfa, pport->diag_busy);
1646
1647        pport->diag_busy = status;
1648}
1649
1650void
1651bfa_pport_beacon(struct bfa_s *bfa, bfa_boolean_t beacon,
1652                 bfa_boolean_t link_e2e_beacon)
1653{
1654        struct bfa_pport_s *pport = BFA_PORT_MOD(bfa);
1655
1656        bfa_trc(bfa, beacon);
1657        bfa_trc(bfa, link_e2e_beacon);
1658        bfa_trc(bfa, pport->beacon);
1659        bfa_trc(bfa, pport->link_e2e_beacon);
1660
1661        pport->beacon = beacon;
1662        pport->link_e2e_beacon = link_e2e_beacon;
1663}
1664
1665bfa_boolean_t
1666bfa_pport_is_linkup(struct bfa_s *bfa)
1667{
1668        return bfa_sm_cmp_state(BFA_PORT_MOD(bfa), bfa_pport_sm_linkup);
1669}
1670
1671
1672