linux/drivers/scsi/bfa/bfa_ioc.c
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2005-2010 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 "bfad_drv.h"
  19#include "bfad_im.h"
  20#include "bfa_ioc.h"
  21#include "bfi_reg.h"
  22#include "bfa_defs.h"
  23#include "bfa_defs_svc.h"
  24
  25BFA_TRC_FILE(CNA, IOC);
  26
  27/*
  28 * IOC local definitions
  29 */
  30#define BFA_IOC_TOV             3000    /* msecs */
  31#define BFA_IOC_HWSEM_TOV       500     /* msecs */
  32#define BFA_IOC_HB_TOV          500     /* msecs */
  33#define BFA_IOC_TOV_RECOVER      BFA_IOC_HB_TOV
  34#define BFA_IOC_POLL_TOV        BFA_TIMER_FREQ
  35
  36#define bfa_ioc_timer_start(__ioc)                                      \
  37        bfa_timer_begin((__ioc)->timer_mod, &(__ioc)->ioc_timer,        \
  38                        bfa_ioc_timeout, (__ioc), BFA_IOC_TOV)
  39#define bfa_ioc_timer_stop(__ioc)   bfa_timer_stop(&(__ioc)->ioc_timer)
  40
  41#define bfa_hb_timer_start(__ioc)                                       \
  42        bfa_timer_begin((__ioc)->timer_mod, &(__ioc)->hb_timer,         \
  43                        bfa_ioc_hb_check, (__ioc), BFA_IOC_HB_TOV)
  44#define bfa_hb_timer_stop(__ioc)        bfa_timer_stop(&(__ioc)->hb_timer)
  45
  46#define BFA_DBG_FWTRC_OFF(_fn)  (BFI_IOC_TRC_OFF + BFA_DBG_FWTRC_LEN * (_fn))
  47
  48/*
  49 * Asic specific macros : see bfa_hw_cb.c and bfa_hw_ct.c for details.
  50 */
  51
  52#define bfa_ioc_firmware_lock(__ioc)                    \
  53                        ((__ioc)->ioc_hwif->ioc_firmware_lock(__ioc))
  54#define bfa_ioc_firmware_unlock(__ioc)                  \
  55                        ((__ioc)->ioc_hwif->ioc_firmware_unlock(__ioc))
  56#define bfa_ioc_reg_init(__ioc) ((__ioc)->ioc_hwif->ioc_reg_init(__ioc))
  57#define bfa_ioc_map_port(__ioc) ((__ioc)->ioc_hwif->ioc_map_port(__ioc))
  58#define bfa_ioc_notify_fail(__ioc)              \
  59                        ((__ioc)->ioc_hwif->ioc_notify_fail(__ioc))
  60#define bfa_ioc_sync_start(__ioc)               \
  61                        ((__ioc)->ioc_hwif->ioc_sync_start(__ioc))
  62#define bfa_ioc_sync_join(__ioc)                \
  63                        ((__ioc)->ioc_hwif->ioc_sync_join(__ioc))
  64#define bfa_ioc_sync_leave(__ioc)               \
  65                        ((__ioc)->ioc_hwif->ioc_sync_leave(__ioc))
  66#define bfa_ioc_sync_ack(__ioc)                 \
  67                        ((__ioc)->ioc_hwif->ioc_sync_ack(__ioc))
  68#define bfa_ioc_sync_complete(__ioc)            \
  69                        ((__ioc)->ioc_hwif->ioc_sync_complete(__ioc))
  70
  71#define bfa_ioc_mbox_cmd_pending(__ioc)         \
  72                        (!list_empty(&((__ioc)->mbox_mod.cmd_q)) || \
  73                        readl((__ioc)->ioc_regs.hfn_mbox_cmd))
  74
  75bfa_boolean_t bfa_auto_recover = BFA_TRUE;
  76
  77/*
  78 * forward declarations
  79 */
  80static void bfa_ioc_hw_sem_get(struct bfa_ioc_s *ioc);
  81static void bfa_ioc_hwinit(struct bfa_ioc_s *ioc, bfa_boolean_t force);
  82static void bfa_ioc_timeout(void *ioc);
  83static void bfa_ioc_poll_fwinit(struct bfa_ioc_s *ioc);
  84static void bfa_ioc_send_enable(struct bfa_ioc_s *ioc);
  85static void bfa_ioc_send_disable(struct bfa_ioc_s *ioc);
  86static void bfa_ioc_send_getattr(struct bfa_ioc_s *ioc);
  87static void bfa_ioc_hb_monitor(struct bfa_ioc_s *ioc);
  88static void bfa_ioc_mbox_poll(struct bfa_ioc_s *ioc);
  89static void bfa_ioc_mbox_flush(struct bfa_ioc_s *ioc);
  90static void bfa_ioc_recover(struct bfa_ioc_s *ioc);
  91static void bfa_ioc_event_notify(struct bfa_ioc_s *ioc ,
  92                                enum bfa_ioc_event_e event);
  93static void bfa_ioc_disable_comp(struct bfa_ioc_s *ioc);
  94static void bfa_ioc_lpu_stop(struct bfa_ioc_s *ioc);
  95static void bfa_ioc_fail_notify(struct bfa_ioc_s *ioc);
  96static void bfa_ioc_pf_fwmismatch(struct bfa_ioc_s *ioc);
  97
  98/*
  99 * IOC state machine definitions/declarations
 100 */
 101enum ioc_event {
 102        IOC_E_RESET             = 1,    /*  IOC reset request           */
 103        IOC_E_ENABLE            = 2,    /*  IOC enable request          */
 104        IOC_E_DISABLE           = 3,    /*  IOC disable request */
 105        IOC_E_DETACH            = 4,    /*  driver detach cleanup       */
 106        IOC_E_ENABLED           = 5,    /*  f/w enabled         */
 107        IOC_E_FWRSP_GETATTR     = 6,    /*  IOC get attribute response  */
 108        IOC_E_DISABLED          = 7,    /*  f/w disabled                */
 109        IOC_E_PFFAILED          = 8,    /*  failure notice by iocpf sm  */
 110        IOC_E_HBFAIL            = 9,    /*  heartbeat failure           */
 111        IOC_E_HWERROR           = 10,   /*  hardware error interrupt    */
 112        IOC_E_TIMEOUT           = 11,   /*  timeout                     */
 113        IOC_E_HWFAILED          = 12,   /*  PCI mapping failure notice  */
 114};
 115
 116bfa_fsm_state_decl(bfa_ioc, uninit, struct bfa_ioc_s, enum ioc_event);
 117bfa_fsm_state_decl(bfa_ioc, reset, struct bfa_ioc_s, enum ioc_event);
 118bfa_fsm_state_decl(bfa_ioc, enabling, struct bfa_ioc_s, enum ioc_event);
 119bfa_fsm_state_decl(bfa_ioc, getattr, struct bfa_ioc_s, enum ioc_event);
 120bfa_fsm_state_decl(bfa_ioc, op, struct bfa_ioc_s, enum ioc_event);
 121bfa_fsm_state_decl(bfa_ioc, fail_retry, struct bfa_ioc_s, enum ioc_event);
 122bfa_fsm_state_decl(bfa_ioc, fail, struct bfa_ioc_s, enum ioc_event);
 123bfa_fsm_state_decl(bfa_ioc, disabling, struct bfa_ioc_s, enum ioc_event);
 124bfa_fsm_state_decl(bfa_ioc, disabled, struct bfa_ioc_s, enum ioc_event);
 125bfa_fsm_state_decl(bfa_ioc, hwfail, struct bfa_ioc_s, enum ioc_event);
 126
 127static struct bfa_sm_table_s ioc_sm_table[] = {
 128        {BFA_SM(bfa_ioc_sm_uninit), BFA_IOC_UNINIT},
 129        {BFA_SM(bfa_ioc_sm_reset), BFA_IOC_RESET},
 130        {BFA_SM(bfa_ioc_sm_enabling), BFA_IOC_ENABLING},
 131        {BFA_SM(bfa_ioc_sm_getattr), BFA_IOC_GETATTR},
 132        {BFA_SM(bfa_ioc_sm_op), BFA_IOC_OPERATIONAL},
 133        {BFA_SM(bfa_ioc_sm_fail_retry), BFA_IOC_INITFAIL},
 134        {BFA_SM(bfa_ioc_sm_fail), BFA_IOC_FAIL},
 135        {BFA_SM(bfa_ioc_sm_disabling), BFA_IOC_DISABLING},
 136        {BFA_SM(bfa_ioc_sm_disabled), BFA_IOC_DISABLED},
 137        {BFA_SM(bfa_ioc_sm_hwfail), BFA_IOC_HWFAIL},
 138};
 139
 140/*
 141 * IOCPF state machine definitions/declarations
 142 */
 143
 144#define bfa_iocpf_timer_start(__ioc)                                    \
 145        bfa_timer_begin((__ioc)->timer_mod, &(__ioc)->ioc_timer,        \
 146                        bfa_iocpf_timeout, (__ioc), BFA_IOC_TOV)
 147#define bfa_iocpf_timer_stop(__ioc)     bfa_timer_stop(&(__ioc)->ioc_timer)
 148
 149#define bfa_iocpf_poll_timer_start(__ioc)                               \
 150        bfa_timer_begin((__ioc)->timer_mod, &(__ioc)->ioc_timer,        \
 151                        bfa_iocpf_poll_timeout, (__ioc), BFA_IOC_POLL_TOV)
 152
 153#define bfa_sem_timer_start(__ioc)                                      \
 154        bfa_timer_begin((__ioc)->timer_mod, &(__ioc)->sem_timer,        \
 155                        bfa_iocpf_sem_timeout, (__ioc), BFA_IOC_HWSEM_TOV)
 156#define bfa_sem_timer_stop(__ioc)       bfa_timer_stop(&(__ioc)->sem_timer)
 157
 158/*
 159 * Forward declareations for iocpf state machine
 160 */
 161static void bfa_iocpf_timeout(void *ioc_arg);
 162static void bfa_iocpf_sem_timeout(void *ioc_arg);
 163static void bfa_iocpf_poll_timeout(void *ioc_arg);
 164
 165/*
 166 * IOCPF state machine events
 167 */
 168enum iocpf_event {
 169        IOCPF_E_ENABLE          = 1,    /*  IOCPF enable request        */
 170        IOCPF_E_DISABLE         = 2,    /*  IOCPF disable request       */
 171        IOCPF_E_STOP            = 3,    /*  stop on driver detach       */
 172        IOCPF_E_FWREADY         = 4,    /*  f/w initialization done     */
 173        IOCPF_E_FWRSP_ENABLE    = 5,    /*  enable f/w response */
 174        IOCPF_E_FWRSP_DISABLE   = 6,    /*  disable f/w response        */
 175        IOCPF_E_FAIL            = 7,    /*  failure notice by ioc sm    */
 176        IOCPF_E_INITFAIL        = 8,    /*  init fail notice by ioc sm  */
 177        IOCPF_E_GETATTRFAIL     = 9,    /*  init fail notice by ioc sm  */
 178        IOCPF_E_SEMLOCKED       = 10,   /*  h/w semaphore is locked     */
 179        IOCPF_E_TIMEOUT         = 11,   /*  f/w response timeout        */
 180        IOCPF_E_SEM_ERROR       = 12,   /*  h/w sem mapping error       */
 181};
 182
 183/*
 184 * IOCPF states
 185 */
 186enum bfa_iocpf_state {
 187        BFA_IOCPF_RESET         = 1,    /*  IOC is in reset state */
 188        BFA_IOCPF_SEMWAIT       = 2,    /*  Waiting for IOC h/w semaphore */
 189        BFA_IOCPF_HWINIT        = 3,    /*  IOC h/w is being initialized */
 190        BFA_IOCPF_READY         = 4,    /*  IOCPF is initialized */
 191        BFA_IOCPF_INITFAIL      = 5,    /*  IOCPF failed */
 192        BFA_IOCPF_FAIL          = 6,    /*  IOCPF failed */
 193        BFA_IOCPF_DISABLING     = 7,    /*  IOCPF is being disabled */
 194        BFA_IOCPF_DISABLED      = 8,    /*  IOCPF is disabled */
 195        BFA_IOCPF_FWMISMATCH    = 9,    /*  IOC f/w different from drivers */
 196};
 197
 198bfa_fsm_state_decl(bfa_iocpf, reset, struct bfa_iocpf_s, enum iocpf_event);
 199bfa_fsm_state_decl(bfa_iocpf, fwcheck, struct bfa_iocpf_s, enum iocpf_event);
 200bfa_fsm_state_decl(bfa_iocpf, mismatch, struct bfa_iocpf_s, enum iocpf_event);
 201bfa_fsm_state_decl(bfa_iocpf, semwait, struct bfa_iocpf_s, enum iocpf_event);
 202bfa_fsm_state_decl(bfa_iocpf, hwinit, struct bfa_iocpf_s, enum iocpf_event);
 203bfa_fsm_state_decl(bfa_iocpf, enabling, struct bfa_iocpf_s, enum iocpf_event);
 204bfa_fsm_state_decl(bfa_iocpf, ready, struct bfa_iocpf_s, enum iocpf_event);
 205bfa_fsm_state_decl(bfa_iocpf, initfail_sync, struct bfa_iocpf_s,
 206                                                enum iocpf_event);
 207bfa_fsm_state_decl(bfa_iocpf, initfail, struct bfa_iocpf_s, enum iocpf_event);
 208bfa_fsm_state_decl(bfa_iocpf, fail_sync, struct bfa_iocpf_s, enum iocpf_event);
 209bfa_fsm_state_decl(bfa_iocpf, fail, struct bfa_iocpf_s, enum iocpf_event);
 210bfa_fsm_state_decl(bfa_iocpf, disabling, struct bfa_iocpf_s, enum iocpf_event);
 211bfa_fsm_state_decl(bfa_iocpf, disabling_sync, struct bfa_iocpf_s,
 212                                                enum iocpf_event);
 213bfa_fsm_state_decl(bfa_iocpf, disabled, struct bfa_iocpf_s, enum iocpf_event);
 214
 215static struct bfa_sm_table_s iocpf_sm_table[] = {
 216        {BFA_SM(bfa_iocpf_sm_reset), BFA_IOCPF_RESET},
 217        {BFA_SM(bfa_iocpf_sm_fwcheck), BFA_IOCPF_FWMISMATCH},
 218        {BFA_SM(bfa_iocpf_sm_mismatch), BFA_IOCPF_FWMISMATCH},
 219        {BFA_SM(bfa_iocpf_sm_semwait), BFA_IOCPF_SEMWAIT},
 220        {BFA_SM(bfa_iocpf_sm_hwinit), BFA_IOCPF_HWINIT},
 221        {BFA_SM(bfa_iocpf_sm_enabling), BFA_IOCPF_HWINIT},
 222        {BFA_SM(bfa_iocpf_sm_ready), BFA_IOCPF_READY},
 223        {BFA_SM(bfa_iocpf_sm_initfail_sync), BFA_IOCPF_INITFAIL},
 224        {BFA_SM(bfa_iocpf_sm_initfail), BFA_IOCPF_INITFAIL},
 225        {BFA_SM(bfa_iocpf_sm_fail_sync), BFA_IOCPF_FAIL},
 226        {BFA_SM(bfa_iocpf_sm_fail), BFA_IOCPF_FAIL},
 227        {BFA_SM(bfa_iocpf_sm_disabling), BFA_IOCPF_DISABLING},
 228        {BFA_SM(bfa_iocpf_sm_disabling_sync), BFA_IOCPF_DISABLING},
 229        {BFA_SM(bfa_iocpf_sm_disabled), BFA_IOCPF_DISABLED},
 230};
 231
 232/*
 233 * IOC State Machine
 234 */
 235
 236/*
 237 * Beginning state. IOC uninit state.
 238 */
 239
 240static void
 241bfa_ioc_sm_uninit_entry(struct bfa_ioc_s *ioc)
 242{
 243}
 244
 245/*
 246 * IOC is in uninit state.
 247 */
 248static void
 249bfa_ioc_sm_uninit(struct bfa_ioc_s *ioc, enum ioc_event event)
 250{
 251        bfa_trc(ioc, event);
 252
 253        switch (event) {
 254        case IOC_E_RESET:
 255                bfa_fsm_set_state(ioc, bfa_ioc_sm_reset);
 256                break;
 257
 258        default:
 259                bfa_sm_fault(ioc, event);
 260        }
 261}
 262/*
 263 * Reset entry actions -- initialize state machine
 264 */
 265static void
 266bfa_ioc_sm_reset_entry(struct bfa_ioc_s *ioc)
 267{
 268        bfa_fsm_set_state(&ioc->iocpf, bfa_iocpf_sm_reset);
 269}
 270
 271/*
 272 * IOC is in reset state.
 273 */
 274static void
 275bfa_ioc_sm_reset(struct bfa_ioc_s *ioc, enum ioc_event event)
 276{
 277        bfa_trc(ioc, event);
 278
 279        switch (event) {
 280        case IOC_E_ENABLE:
 281                bfa_fsm_set_state(ioc, bfa_ioc_sm_enabling);
 282                break;
 283
 284        case IOC_E_DISABLE:
 285                bfa_ioc_disable_comp(ioc);
 286                break;
 287
 288        case IOC_E_DETACH:
 289                bfa_fsm_set_state(ioc, bfa_ioc_sm_uninit);
 290                break;
 291
 292        default:
 293                bfa_sm_fault(ioc, event);
 294        }
 295}
 296
 297
 298static void
 299bfa_ioc_sm_enabling_entry(struct bfa_ioc_s *ioc)
 300{
 301        bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_ENABLE);
 302}
 303
 304/*
 305 * Host IOC function is being enabled, awaiting response from firmware.
 306 * Semaphore is acquired.
 307 */
 308static void
 309bfa_ioc_sm_enabling(struct bfa_ioc_s *ioc, enum ioc_event event)
 310{
 311        bfa_trc(ioc, event);
 312
 313        switch (event) {
 314        case IOC_E_ENABLED:
 315                bfa_fsm_set_state(ioc, bfa_ioc_sm_getattr);
 316                break;
 317
 318        case IOC_E_PFFAILED:
 319                /* !!! fall through !!! */
 320        case IOC_E_HWERROR:
 321                ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
 322                bfa_fsm_set_state(ioc, bfa_ioc_sm_fail);
 323                if (event != IOC_E_PFFAILED)
 324                        bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_INITFAIL);
 325                break;
 326
 327        case IOC_E_HWFAILED:
 328                ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
 329                bfa_fsm_set_state(ioc, bfa_ioc_sm_hwfail);
 330                break;
 331
 332        case IOC_E_DISABLE:
 333                bfa_fsm_set_state(ioc, bfa_ioc_sm_disabling);
 334                break;
 335
 336        case IOC_E_DETACH:
 337                bfa_fsm_set_state(ioc, bfa_ioc_sm_uninit);
 338                bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_STOP);
 339                break;
 340
 341        case IOC_E_ENABLE:
 342                break;
 343
 344        default:
 345                bfa_sm_fault(ioc, event);
 346        }
 347}
 348
 349
 350static void
 351bfa_ioc_sm_getattr_entry(struct bfa_ioc_s *ioc)
 352{
 353        bfa_ioc_timer_start(ioc);
 354        bfa_ioc_send_getattr(ioc);
 355}
 356
 357/*
 358 * IOC configuration in progress. Timer is active.
 359 */
 360static void
 361bfa_ioc_sm_getattr(struct bfa_ioc_s *ioc, enum ioc_event event)
 362{
 363        bfa_trc(ioc, event);
 364
 365        switch (event) {
 366        case IOC_E_FWRSP_GETATTR:
 367                bfa_ioc_timer_stop(ioc);
 368                bfa_fsm_set_state(ioc, bfa_ioc_sm_op);
 369                break;
 370
 371        case IOC_E_PFFAILED:
 372        case IOC_E_HWERROR:
 373                bfa_ioc_timer_stop(ioc);
 374                /* !!! fall through !!! */
 375        case IOC_E_TIMEOUT:
 376                ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
 377                bfa_fsm_set_state(ioc, bfa_ioc_sm_fail);
 378                if (event != IOC_E_PFFAILED)
 379                        bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_GETATTRFAIL);
 380                break;
 381
 382        case IOC_E_DISABLE:
 383                bfa_ioc_timer_stop(ioc);
 384                bfa_fsm_set_state(ioc, bfa_ioc_sm_disabling);
 385                break;
 386
 387        case IOC_E_ENABLE:
 388                break;
 389
 390        default:
 391                bfa_sm_fault(ioc, event);
 392        }
 393}
 394
 395static void
 396bfa_ioc_sm_op_entry(struct bfa_ioc_s *ioc)
 397{
 398        struct bfad_s *bfad = (struct bfad_s *)ioc->bfa->bfad;
 399
 400        ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_OK);
 401        bfa_ioc_event_notify(ioc, BFA_IOC_E_ENABLED);
 402        bfa_ioc_hb_monitor(ioc);
 403        BFA_LOG(KERN_INFO, bfad, bfa_log_level, "IOC enabled\n");
 404        bfa_ioc_aen_post(ioc, BFA_IOC_AEN_ENABLE);
 405}
 406
 407static void
 408bfa_ioc_sm_op(struct bfa_ioc_s *ioc, enum ioc_event event)
 409{
 410        bfa_trc(ioc, event);
 411
 412        switch (event) {
 413        case IOC_E_ENABLE:
 414                break;
 415
 416        case IOC_E_DISABLE:
 417                bfa_hb_timer_stop(ioc);
 418                bfa_fsm_set_state(ioc, bfa_ioc_sm_disabling);
 419                break;
 420
 421        case IOC_E_PFFAILED:
 422        case IOC_E_HWERROR:
 423                bfa_hb_timer_stop(ioc);
 424                /* !!! fall through !!! */
 425        case IOC_E_HBFAIL:
 426                if (ioc->iocpf.auto_recover)
 427                        bfa_fsm_set_state(ioc, bfa_ioc_sm_fail_retry);
 428                else
 429                        bfa_fsm_set_state(ioc, bfa_ioc_sm_fail);
 430
 431                bfa_ioc_fail_notify(ioc);
 432
 433                if (event != IOC_E_PFFAILED)
 434                        bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_FAIL);
 435                break;
 436
 437        default:
 438                bfa_sm_fault(ioc, event);
 439        }
 440}
 441
 442
 443static void
 444bfa_ioc_sm_disabling_entry(struct bfa_ioc_s *ioc)
 445{
 446        struct bfad_s *bfad = (struct bfad_s *)ioc->bfa->bfad;
 447        bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_DISABLE);
 448        BFA_LOG(KERN_INFO, bfad, bfa_log_level, "IOC disabled\n");
 449        bfa_ioc_aen_post(ioc, BFA_IOC_AEN_DISABLE);
 450}
 451
 452/*
 453 * IOC is being disabled
 454 */
 455static void
 456bfa_ioc_sm_disabling(struct bfa_ioc_s *ioc, enum ioc_event event)
 457{
 458        bfa_trc(ioc, event);
 459
 460        switch (event) {
 461        case IOC_E_DISABLED:
 462                bfa_fsm_set_state(ioc, bfa_ioc_sm_disabled);
 463                break;
 464
 465        case IOC_E_HWERROR:
 466                /*
 467                 * No state change.  Will move to disabled state
 468                 * after iocpf sm completes failure processing and
 469                 * moves to disabled state.
 470                 */
 471                bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_FAIL);
 472                break;
 473
 474        case IOC_E_HWFAILED:
 475                bfa_fsm_set_state(ioc, bfa_ioc_sm_hwfail);
 476                bfa_ioc_disable_comp(ioc);
 477                break;
 478
 479        default:
 480                bfa_sm_fault(ioc, event);
 481        }
 482}
 483
 484/*
 485 * IOC disable completion entry.
 486 */
 487static void
 488bfa_ioc_sm_disabled_entry(struct bfa_ioc_s *ioc)
 489{
 490        bfa_ioc_disable_comp(ioc);
 491}
 492
 493static void
 494bfa_ioc_sm_disabled(struct bfa_ioc_s *ioc, enum ioc_event event)
 495{
 496        bfa_trc(ioc, event);
 497
 498        switch (event) {
 499        case IOC_E_ENABLE:
 500                bfa_fsm_set_state(ioc, bfa_ioc_sm_enabling);
 501                break;
 502
 503        case IOC_E_DISABLE:
 504                ioc->cbfn->disable_cbfn(ioc->bfa);
 505                break;
 506
 507        case IOC_E_DETACH:
 508                bfa_fsm_set_state(ioc, bfa_ioc_sm_uninit);
 509                bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_STOP);
 510                break;
 511
 512        default:
 513                bfa_sm_fault(ioc, event);
 514        }
 515}
 516
 517
 518static void
 519bfa_ioc_sm_fail_retry_entry(struct bfa_ioc_s *ioc)
 520{
 521        bfa_trc(ioc, 0);
 522}
 523
 524/*
 525 * Hardware initialization retry.
 526 */
 527static void
 528bfa_ioc_sm_fail_retry(struct bfa_ioc_s *ioc, enum ioc_event event)
 529{
 530        bfa_trc(ioc, event);
 531
 532        switch (event) {
 533        case IOC_E_ENABLED:
 534                bfa_fsm_set_state(ioc, bfa_ioc_sm_getattr);
 535                break;
 536
 537        case IOC_E_PFFAILED:
 538        case IOC_E_HWERROR:
 539                /*
 540                 * Initialization retry failed.
 541                 */
 542                ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
 543                bfa_fsm_set_state(ioc, bfa_ioc_sm_fail);
 544                if (event != IOC_E_PFFAILED)
 545                        bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_INITFAIL);
 546                break;
 547
 548        case IOC_E_HWFAILED:
 549                ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
 550                bfa_fsm_set_state(ioc, bfa_ioc_sm_hwfail);
 551                break;
 552
 553        case IOC_E_ENABLE:
 554                break;
 555
 556        case IOC_E_DISABLE:
 557                bfa_fsm_set_state(ioc, bfa_ioc_sm_disabling);
 558                break;
 559
 560        case IOC_E_DETACH:
 561                bfa_fsm_set_state(ioc, bfa_ioc_sm_uninit);
 562                bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_STOP);
 563                break;
 564
 565        default:
 566                bfa_sm_fault(ioc, event);
 567        }
 568}
 569
 570
 571static void
 572bfa_ioc_sm_fail_entry(struct bfa_ioc_s *ioc)
 573{
 574        bfa_trc(ioc, 0);
 575}
 576
 577/*
 578 * IOC failure.
 579 */
 580static void
 581bfa_ioc_sm_fail(struct bfa_ioc_s *ioc, enum ioc_event event)
 582{
 583        bfa_trc(ioc, event);
 584
 585        switch (event) {
 586
 587        case IOC_E_ENABLE:
 588                ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
 589                break;
 590
 591        case IOC_E_DISABLE:
 592                bfa_fsm_set_state(ioc, bfa_ioc_sm_disabling);
 593                break;
 594
 595        case IOC_E_DETACH:
 596                bfa_fsm_set_state(ioc, bfa_ioc_sm_uninit);
 597                bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_STOP);
 598                break;
 599
 600        case IOC_E_HWERROR:
 601        case IOC_E_HWFAILED:
 602                /*
 603                 * HB failure / HW error notification, ignore.
 604                 */
 605                break;
 606        default:
 607                bfa_sm_fault(ioc, event);
 608        }
 609}
 610
 611static void
 612bfa_ioc_sm_hwfail_entry(struct bfa_ioc_s *ioc)
 613{
 614        bfa_trc(ioc, 0);
 615}
 616
 617static void
 618bfa_ioc_sm_hwfail(struct bfa_ioc_s *ioc, enum ioc_event event)
 619{
 620        bfa_trc(ioc, event);
 621
 622        switch (event) {
 623        case IOC_E_ENABLE:
 624                ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
 625                break;
 626
 627        case IOC_E_DISABLE:
 628                ioc->cbfn->disable_cbfn(ioc->bfa);
 629                break;
 630
 631        case IOC_E_DETACH:
 632                bfa_fsm_set_state(ioc, bfa_ioc_sm_uninit);
 633                break;
 634
 635        case IOC_E_HWERROR:
 636                /* Ignore - already in hwfail state */
 637                break;
 638
 639        default:
 640                bfa_sm_fault(ioc, event);
 641        }
 642}
 643
 644/*
 645 * IOCPF State Machine
 646 */
 647
 648/*
 649 * Reset entry actions -- initialize state machine
 650 */
 651static void
 652bfa_iocpf_sm_reset_entry(struct bfa_iocpf_s *iocpf)
 653{
 654        iocpf->fw_mismatch_notified = BFA_FALSE;
 655        iocpf->auto_recover = bfa_auto_recover;
 656}
 657
 658/*
 659 * Beginning state. IOC is in reset state.
 660 */
 661static void
 662bfa_iocpf_sm_reset(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
 663{
 664        struct bfa_ioc_s *ioc = iocpf->ioc;
 665
 666        bfa_trc(ioc, event);
 667
 668        switch (event) {
 669        case IOCPF_E_ENABLE:
 670                bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fwcheck);
 671                break;
 672
 673        case IOCPF_E_STOP:
 674                break;
 675
 676        default:
 677                bfa_sm_fault(ioc, event);
 678        }
 679}
 680
 681/*
 682 * Semaphore should be acquired for version check.
 683 */
 684static void
 685bfa_iocpf_sm_fwcheck_entry(struct bfa_iocpf_s *iocpf)
 686{
 687        struct bfi_ioc_image_hdr_s      fwhdr;
 688        u32     r32, fwstate, pgnum, pgoff, loff = 0;
 689        int     i;
 690
 691        /*
 692         * Spin on init semaphore to serialize.
 693         */
 694        r32 = readl(iocpf->ioc->ioc_regs.ioc_init_sem_reg);
 695        while (r32 & 0x1) {
 696                udelay(20);
 697                r32 = readl(iocpf->ioc->ioc_regs.ioc_init_sem_reg);
 698        }
 699
 700        /* h/w sem init */
 701        fwstate = readl(iocpf->ioc->ioc_regs.ioc_fwstate);
 702        if (fwstate == BFI_IOC_UNINIT) {
 703                writel(1, iocpf->ioc->ioc_regs.ioc_init_sem_reg);
 704                goto sem_get;
 705        }
 706
 707        bfa_ioc_fwver_get(iocpf->ioc, &fwhdr);
 708
 709        if (swab32(fwhdr.exec) == BFI_FWBOOT_TYPE_NORMAL) {
 710                writel(1, iocpf->ioc->ioc_regs.ioc_init_sem_reg);
 711                goto sem_get;
 712        }
 713
 714        /*
 715         * Clear fwver hdr
 716         */
 717        pgnum = PSS_SMEM_PGNUM(iocpf->ioc->ioc_regs.smem_pg0, loff);
 718        pgoff = PSS_SMEM_PGOFF(loff);
 719        writel(pgnum, iocpf->ioc->ioc_regs.host_page_num_fn);
 720
 721        for (i = 0; i < sizeof(struct bfi_ioc_image_hdr_s) / sizeof(u32); i++) {
 722                bfa_mem_write(iocpf->ioc->ioc_regs.smem_page_start, loff, 0);
 723                loff += sizeof(u32);
 724        }
 725
 726        bfa_trc(iocpf->ioc, fwstate);
 727        bfa_trc(iocpf->ioc, swab32(fwhdr.exec));
 728        writel(BFI_IOC_UNINIT, iocpf->ioc->ioc_regs.ioc_fwstate);
 729        writel(BFI_IOC_UNINIT, iocpf->ioc->ioc_regs.alt_ioc_fwstate);
 730
 731        /*
 732         * Unlock the hw semaphore. Should be here only once per boot.
 733         */
 734        bfa_ioc_ownership_reset(iocpf->ioc);
 735
 736        /*
 737         * unlock init semaphore.
 738         */
 739        writel(1, iocpf->ioc->ioc_regs.ioc_init_sem_reg);
 740
 741sem_get:
 742        bfa_ioc_hw_sem_get(iocpf->ioc);
 743}
 744
 745/*
 746 * Awaiting h/w semaphore to continue with version check.
 747 */
 748static void
 749bfa_iocpf_sm_fwcheck(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
 750{
 751        struct bfa_ioc_s *ioc = iocpf->ioc;
 752
 753        bfa_trc(ioc, event);
 754
 755        switch (event) {
 756        case IOCPF_E_SEMLOCKED:
 757                if (bfa_ioc_firmware_lock(ioc)) {
 758                        if (bfa_ioc_sync_start(ioc)) {
 759                                bfa_ioc_sync_join(ioc);
 760                                bfa_fsm_set_state(iocpf, bfa_iocpf_sm_hwinit);
 761                        } else {
 762                                bfa_ioc_firmware_unlock(ioc);
 763                                writel(1, ioc->ioc_regs.ioc_sem_reg);
 764                                bfa_sem_timer_start(ioc);
 765                        }
 766                } else {
 767                        writel(1, ioc->ioc_regs.ioc_sem_reg);
 768                        bfa_fsm_set_state(iocpf, bfa_iocpf_sm_mismatch);
 769                }
 770                break;
 771
 772        case IOCPF_E_SEM_ERROR:
 773                bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail);
 774                bfa_fsm_send_event(ioc, IOC_E_HWFAILED);
 775                break;
 776
 777        case IOCPF_E_DISABLE:
 778                bfa_sem_timer_stop(ioc);
 779                bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset);
 780                bfa_fsm_send_event(ioc, IOC_E_DISABLED);
 781                break;
 782
 783        case IOCPF_E_STOP:
 784                bfa_sem_timer_stop(ioc);
 785                bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset);
 786                break;
 787
 788        default:
 789                bfa_sm_fault(ioc, event);
 790        }
 791}
 792
 793/*
 794 * Notify enable completion callback.
 795 */
 796static void
 797bfa_iocpf_sm_mismatch_entry(struct bfa_iocpf_s *iocpf)
 798{
 799        /*
 800         * Call only the first time sm enters fwmismatch state.
 801         */
 802        if (iocpf->fw_mismatch_notified == BFA_FALSE)
 803                bfa_ioc_pf_fwmismatch(iocpf->ioc);
 804
 805        iocpf->fw_mismatch_notified = BFA_TRUE;
 806        bfa_iocpf_timer_start(iocpf->ioc);
 807}
 808
 809/*
 810 * Awaiting firmware version match.
 811 */
 812static void
 813bfa_iocpf_sm_mismatch(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
 814{
 815        struct bfa_ioc_s *ioc = iocpf->ioc;
 816
 817        bfa_trc(ioc, event);
 818
 819        switch (event) {
 820        case IOCPF_E_TIMEOUT:
 821                bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fwcheck);
 822                break;
 823
 824        case IOCPF_E_DISABLE:
 825                bfa_iocpf_timer_stop(ioc);
 826                bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset);
 827                bfa_fsm_send_event(ioc, IOC_E_DISABLED);
 828                break;
 829
 830        case IOCPF_E_STOP:
 831                bfa_iocpf_timer_stop(ioc);
 832                bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset);
 833                break;
 834
 835        default:
 836                bfa_sm_fault(ioc, event);
 837        }
 838}
 839
 840/*
 841 * Request for semaphore.
 842 */
 843static void
 844bfa_iocpf_sm_semwait_entry(struct bfa_iocpf_s *iocpf)
 845{
 846        bfa_ioc_hw_sem_get(iocpf->ioc);
 847}
 848
 849/*
 850 * Awaiting semaphore for h/w initialzation.
 851 */
 852static void
 853bfa_iocpf_sm_semwait(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
 854{
 855        struct bfa_ioc_s *ioc = iocpf->ioc;
 856
 857        bfa_trc(ioc, event);
 858
 859        switch (event) {
 860        case IOCPF_E_SEMLOCKED:
 861                if (bfa_ioc_sync_complete(ioc)) {
 862                        bfa_ioc_sync_join(ioc);
 863                        bfa_fsm_set_state(iocpf, bfa_iocpf_sm_hwinit);
 864                } else {
 865                        writel(1, ioc->ioc_regs.ioc_sem_reg);
 866                        bfa_sem_timer_start(ioc);
 867                }
 868                break;
 869
 870        case IOCPF_E_SEM_ERROR:
 871                bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail);
 872                bfa_fsm_send_event(ioc, IOC_E_HWFAILED);
 873                break;
 874
 875        case IOCPF_E_DISABLE:
 876                bfa_sem_timer_stop(ioc);
 877                bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling_sync);
 878                break;
 879
 880        default:
 881                bfa_sm_fault(ioc, event);
 882        }
 883}
 884
 885static void
 886bfa_iocpf_sm_hwinit_entry(struct bfa_iocpf_s *iocpf)
 887{
 888        iocpf->poll_time = 0;
 889        bfa_ioc_hwinit(iocpf->ioc, BFA_FALSE);
 890}
 891
 892/*
 893 * Hardware is being initialized. Interrupts are enabled.
 894 * Holding hardware semaphore lock.
 895 */
 896static void
 897bfa_iocpf_sm_hwinit(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
 898{
 899        struct bfa_ioc_s *ioc = iocpf->ioc;
 900
 901        bfa_trc(ioc, event);
 902
 903        switch (event) {
 904        case IOCPF_E_FWREADY:
 905                bfa_fsm_set_state(iocpf, bfa_iocpf_sm_enabling);
 906                break;
 907
 908        case IOCPF_E_TIMEOUT:
 909                writel(1, ioc->ioc_regs.ioc_sem_reg);
 910                bfa_fsm_send_event(ioc, IOC_E_PFFAILED);
 911                bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail_sync);
 912                break;
 913
 914        case IOCPF_E_DISABLE:
 915                bfa_iocpf_timer_stop(ioc);
 916                bfa_ioc_sync_leave(ioc);
 917                writel(1, ioc->ioc_regs.ioc_sem_reg);
 918                bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabled);
 919                break;
 920
 921        default:
 922                bfa_sm_fault(ioc, event);
 923        }
 924}
 925
 926static void
 927bfa_iocpf_sm_enabling_entry(struct bfa_iocpf_s *iocpf)
 928{
 929        bfa_iocpf_timer_start(iocpf->ioc);
 930        /*
 931         * Enable Interrupts before sending fw IOC ENABLE cmd.
 932         */
 933        iocpf->ioc->cbfn->reset_cbfn(iocpf->ioc->bfa);
 934        bfa_ioc_send_enable(iocpf->ioc);
 935}
 936
 937/*
 938 * Host IOC function is being enabled, awaiting response from firmware.
 939 * Semaphore is acquired.
 940 */
 941static void
 942bfa_iocpf_sm_enabling(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
 943{
 944        struct bfa_ioc_s *ioc = iocpf->ioc;
 945
 946        bfa_trc(ioc, event);
 947
 948        switch (event) {
 949        case IOCPF_E_FWRSP_ENABLE:
 950                bfa_iocpf_timer_stop(ioc);
 951                writel(1, ioc->ioc_regs.ioc_sem_reg);
 952                bfa_fsm_set_state(iocpf, bfa_iocpf_sm_ready);
 953                break;
 954
 955        case IOCPF_E_INITFAIL:
 956                bfa_iocpf_timer_stop(ioc);
 957                /*
 958                 * !!! fall through !!!
 959                 */
 960
 961        case IOCPF_E_TIMEOUT:
 962                writel(1, ioc->ioc_regs.ioc_sem_reg);
 963                if (event == IOCPF_E_TIMEOUT)
 964                        bfa_fsm_send_event(ioc, IOC_E_PFFAILED);
 965                bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail_sync);
 966                break;
 967
 968        case IOCPF_E_DISABLE:
 969                bfa_iocpf_timer_stop(ioc);
 970                writel(1, ioc->ioc_regs.ioc_sem_reg);
 971                bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling);
 972                break;
 973
 974        default:
 975                bfa_sm_fault(ioc, event);
 976        }
 977}
 978
 979static void
 980bfa_iocpf_sm_ready_entry(struct bfa_iocpf_s *iocpf)
 981{
 982        bfa_fsm_send_event(iocpf->ioc, IOC_E_ENABLED);
 983}
 984
 985static void
 986bfa_iocpf_sm_ready(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
 987{
 988        struct bfa_ioc_s *ioc = iocpf->ioc;
 989
 990        bfa_trc(ioc, event);
 991
 992        switch (event) {
 993        case IOCPF_E_DISABLE:
 994                bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling);
 995                break;
 996
 997        case IOCPF_E_GETATTRFAIL:
 998                bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail_sync);
 999                break;
1000
1001        case IOCPF_E_FAIL:
1002                bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail_sync);
1003                break;
1004
1005        default:
1006                bfa_sm_fault(ioc, event);
1007        }
1008}
1009
1010static void
1011bfa_iocpf_sm_disabling_entry(struct bfa_iocpf_s *iocpf)
1012{
1013        bfa_iocpf_timer_start(iocpf->ioc);
1014        bfa_ioc_send_disable(iocpf->ioc);
1015}
1016
1017/*
1018 * IOC is being disabled
1019 */
1020static void
1021bfa_iocpf_sm_disabling(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
1022{
1023        struct bfa_ioc_s *ioc = iocpf->ioc;
1024
1025        bfa_trc(ioc, event);
1026
1027        switch (event) {
1028        case IOCPF_E_FWRSP_DISABLE:
1029                bfa_iocpf_timer_stop(ioc);
1030                bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling_sync);
1031                break;
1032
1033        case IOCPF_E_FAIL:
1034                bfa_iocpf_timer_stop(ioc);
1035                /*
1036                 * !!! fall through !!!
1037                 */
1038
1039        case IOCPF_E_TIMEOUT:
1040                writel(BFI_IOC_FAIL, ioc->ioc_regs.ioc_fwstate);
1041                bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling_sync);
1042                break;
1043
1044        case IOCPF_E_FWRSP_ENABLE:
1045                break;
1046
1047        default:
1048                bfa_sm_fault(ioc, event);
1049        }
1050}
1051
1052static void
1053bfa_iocpf_sm_disabling_sync_entry(struct bfa_iocpf_s *iocpf)
1054{
1055        bfa_ioc_hw_sem_get(iocpf->ioc);
1056}
1057
1058/*
1059 * IOC hb ack request is being removed.
1060 */
1061static void
1062bfa_iocpf_sm_disabling_sync(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
1063{
1064        struct bfa_ioc_s *ioc = iocpf->ioc;
1065
1066        bfa_trc(ioc, event);
1067
1068        switch (event) {
1069        case IOCPF_E_SEMLOCKED:
1070                bfa_ioc_sync_leave(ioc);
1071                writel(1, ioc->ioc_regs.ioc_sem_reg);
1072                bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabled);
1073                break;
1074
1075        case IOCPF_E_SEM_ERROR:
1076                bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail);
1077                bfa_fsm_send_event(ioc, IOC_E_HWFAILED);
1078                break;
1079
1080        case IOCPF_E_FAIL:
1081                break;
1082
1083        default:
1084                bfa_sm_fault(ioc, event);
1085        }
1086}
1087
1088/*
1089 * IOC disable completion entry.
1090 */
1091static void
1092bfa_iocpf_sm_disabled_entry(struct bfa_iocpf_s *iocpf)
1093{
1094        bfa_ioc_mbox_flush(iocpf->ioc);
1095        bfa_fsm_send_event(iocpf->ioc, IOC_E_DISABLED);
1096}
1097
1098static void
1099bfa_iocpf_sm_disabled(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
1100{
1101        struct bfa_ioc_s *ioc = iocpf->ioc;
1102
1103        bfa_trc(ioc, event);
1104
1105        switch (event) {
1106        case IOCPF_E_ENABLE:
1107                bfa_fsm_set_state(iocpf, bfa_iocpf_sm_semwait);
1108                break;
1109
1110        case IOCPF_E_STOP:
1111                bfa_ioc_firmware_unlock(ioc);
1112                bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset);
1113                break;
1114
1115        default:
1116                bfa_sm_fault(ioc, event);
1117        }
1118}
1119
1120static void
1121bfa_iocpf_sm_initfail_sync_entry(struct bfa_iocpf_s *iocpf)
1122{
1123        bfa_ioc_debug_save_ftrc(iocpf->ioc);
1124        bfa_ioc_hw_sem_get(iocpf->ioc);
1125}
1126
1127/*
1128 * Hardware initialization failed.
1129 */
1130static void
1131bfa_iocpf_sm_initfail_sync(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
1132{
1133        struct bfa_ioc_s *ioc = iocpf->ioc;
1134
1135        bfa_trc(ioc, event);
1136
1137        switch (event) {
1138        case IOCPF_E_SEMLOCKED:
1139                bfa_ioc_notify_fail(ioc);
1140                bfa_ioc_sync_leave(ioc);
1141                writel(BFI_IOC_FAIL, ioc->ioc_regs.ioc_fwstate);
1142                writel(1, ioc->ioc_regs.ioc_sem_reg);
1143                bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail);
1144                break;
1145
1146        case IOCPF_E_SEM_ERROR:
1147                bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail);
1148                bfa_fsm_send_event(ioc, IOC_E_HWFAILED);
1149                break;
1150
1151        case IOCPF_E_DISABLE:
1152                bfa_sem_timer_stop(ioc);
1153                bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling_sync);
1154                break;
1155
1156        case IOCPF_E_STOP:
1157                bfa_sem_timer_stop(ioc);
1158                bfa_ioc_firmware_unlock(ioc);
1159                bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset);
1160                break;
1161
1162        case IOCPF_E_FAIL:
1163                break;
1164
1165        default:
1166                bfa_sm_fault(ioc, event);
1167        }
1168}
1169
1170static void
1171bfa_iocpf_sm_initfail_entry(struct bfa_iocpf_s *iocpf)
1172{
1173        bfa_trc(iocpf->ioc, 0);
1174}
1175
1176/*
1177 * Hardware initialization failed.
1178 */
1179static void
1180bfa_iocpf_sm_initfail(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
1181{
1182        struct bfa_ioc_s *ioc = iocpf->ioc;
1183
1184        bfa_trc(ioc, event);
1185
1186        switch (event) {
1187        case IOCPF_E_DISABLE:
1188                bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabled);
1189                break;
1190
1191        case IOCPF_E_STOP:
1192                bfa_ioc_firmware_unlock(ioc);
1193                bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset);
1194                break;
1195
1196        default:
1197                bfa_sm_fault(ioc, event);
1198        }
1199}
1200
1201static void
1202bfa_iocpf_sm_fail_sync_entry(struct bfa_iocpf_s *iocpf)
1203{
1204        /*
1205         * Mark IOC as failed in hardware and stop firmware.
1206         */
1207        bfa_ioc_lpu_stop(iocpf->ioc);
1208
1209        /*
1210         * Flush any queued up mailbox requests.
1211         */
1212        bfa_ioc_mbox_flush(iocpf->ioc);
1213
1214        bfa_ioc_hw_sem_get(iocpf->ioc);
1215}
1216
1217static void
1218bfa_iocpf_sm_fail_sync(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
1219{
1220        struct bfa_ioc_s *ioc = iocpf->ioc;
1221
1222        bfa_trc(ioc, event);
1223
1224        switch (event) {
1225        case IOCPF_E_SEMLOCKED:
1226                bfa_ioc_sync_ack(ioc);
1227                bfa_ioc_notify_fail(ioc);
1228                if (!iocpf->auto_recover) {
1229                        bfa_ioc_sync_leave(ioc);
1230                        writel(BFI_IOC_FAIL, ioc->ioc_regs.ioc_fwstate);
1231                        writel(1, ioc->ioc_regs.ioc_sem_reg);
1232                        bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail);
1233                } else {
1234                        if (bfa_ioc_sync_complete(ioc))
1235                                bfa_fsm_set_state(iocpf, bfa_iocpf_sm_hwinit);
1236                        else {
1237                                writel(1, ioc->ioc_regs.ioc_sem_reg);
1238                                bfa_fsm_set_state(iocpf, bfa_iocpf_sm_semwait);
1239                        }
1240                }
1241                break;
1242
1243        case IOCPF_E_SEM_ERROR:
1244                bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail);
1245                bfa_fsm_send_event(ioc, IOC_E_HWFAILED);
1246                break;
1247
1248        case IOCPF_E_DISABLE:
1249                bfa_sem_timer_stop(ioc);
1250                bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling_sync);
1251                break;
1252
1253        case IOCPF_E_FAIL:
1254                break;
1255
1256        default:
1257                bfa_sm_fault(ioc, event);
1258        }
1259}
1260
1261static void
1262bfa_iocpf_sm_fail_entry(struct bfa_iocpf_s *iocpf)
1263{
1264        bfa_trc(iocpf->ioc, 0);
1265}
1266
1267/*
1268 * IOC is in failed state.
1269 */
1270static void
1271bfa_iocpf_sm_fail(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
1272{
1273        struct bfa_ioc_s *ioc = iocpf->ioc;
1274
1275        bfa_trc(ioc, event);
1276
1277        switch (event) {
1278        case IOCPF_E_DISABLE:
1279                bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabled);
1280                break;
1281
1282        default:
1283                bfa_sm_fault(ioc, event);
1284        }
1285}
1286
1287/*
1288 *  BFA IOC private functions
1289 */
1290
1291/*
1292 * Notify common modules registered for notification.
1293 */
1294static void
1295bfa_ioc_event_notify(struct bfa_ioc_s *ioc, enum bfa_ioc_event_e event)
1296{
1297        struct bfa_ioc_notify_s *notify;
1298        struct list_head        *qe;
1299
1300        list_for_each(qe, &ioc->notify_q) {
1301                notify = (struct bfa_ioc_notify_s *)qe;
1302                notify->cbfn(notify->cbarg, event);
1303        }
1304}
1305
1306static void
1307bfa_ioc_disable_comp(struct bfa_ioc_s *ioc)
1308{
1309        ioc->cbfn->disable_cbfn(ioc->bfa);
1310        bfa_ioc_event_notify(ioc, BFA_IOC_E_DISABLED);
1311}
1312
1313bfa_boolean_t
1314bfa_ioc_sem_get(void __iomem *sem_reg)
1315{
1316        u32 r32;
1317        int cnt = 0;
1318#define BFA_SEM_SPINCNT 3000
1319
1320        r32 = readl(sem_reg);
1321
1322        while ((r32 & 1) && (cnt < BFA_SEM_SPINCNT)) {
1323                cnt++;
1324                udelay(2);
1325                r32 = readl(sem_reg);
1326        }
1327
1328        if (!(r32 & 1))
1329                return BFA_TRUE;
1330
1331        return BFA_FALSE;
1332}
1333
1334static void
1335bfa_ioc_hw_sem_get(struct bfa_ioc_s *ioc)
1336{
1337        u32     r32;
1338
1339        /*
1340         * First read to the semaphore register will return 0, subsequent reads
1341         * will return 1. Semaphore is released by writing 1 to the register
1342         */
1343        r32 = readl(ioc->ioc_regs.ioc_sem_reg);
1344        if (r32 == ~0) {
1345                WARN_ON(r32 == ~0);
1346                bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_SEM_ERROR);
1347                return;
1348        }
1349        if (!(r32 & 1)) {
1350                bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_SEMLOCKED);
1351                return;
1352        }
1353
1354        bfa_sem_timer_start(ioc);
1355}
1356
1357/*
1358 * Initialize LPU local memory (aka secondary memory / SRAM)
1359 */
1360static void
1361bfa_ioc_lmem_init(struct bfa_ioc_s *ioc)
1362{
1363        u32     pss_ctl;
1364        int             i;
1365#define PSS_LMEM_INIT_TIME  10000
1366
1367        pss_ctl = readl(ioc->ioc_regs.pss_ctl_reg);
1368        pss_ctl &= ~__PSS_LMEM_RESET;
1369        pss_ctl |= __PSS_LMEM_INIT_EN;
1370
1371        /*
1372         * i2c workaround 12.5khz clock
1373         */
1374        pss_ctl |= __PSS_I2C_CLK_DIV(3UL);
1375        writel(pss_ctl, ioc->ioc_regs.pss_ctl_reg);
1376
1377        /*
1378         * wait for memory initialization to be complete
1379         */
1380        i = 0;
1381        do {
1382                pss_ctl = readl(ioc->ioc_regs.pss_ctl_reg);
1383                i++;
1384        } while (!(pss_ctl & __PSS_LMEM_INIT_DONE) && (i < PSS_LMEM_INIT_TIME));
1385
1386        /*
1387         * If memory initialization is not successful, IOC timeout will catch
1388         * such failures.
1389         */
1390        WARN_ON(!(pss_ctl & __PSS_LMEM_INIT_DONE));
1391        bfa_trc(ioc, pss_ctl);
1392
1393        pss_ctl &= ~(__PSS_LMEM_INIT_DONE | __PSS_LMEM_INIT_EN);
1394        writel(pss_ctl, ioc->ioc_regs.pss_ctl_reg);
1395}
1396
1397static void
1398bfa_ioc_lpu_start(struct bfa_ioc_s *ioc)
1399{
1400        u32     pss_ctl;
1401
1402        /*
1403         * Take processor out of reset.
1404         */
1405        pss_ctl = readl(ioc->ioc_regs.pss_ctl_reg);
1406        pss_ctl &= ~__PSS_LPU0_RESET;
1407
1408        writel(pss_ctl, ioc->ioc_regs.pss_ctl_reg);
1409}
1410
1411static void
1412bfa_ioc_lpu_stop(struct bfa_ioc_s *ioc)
1413{
1414        u32     pss_ctl;
1415
1416        /*
1417         * Put processors in reset.
1418         */
1419        pss_ctl = readl(ioc->ioc_regs.pss_ctl_reg);
1420        pss_ctl |= (__PSS_LPU0_RESET | __PSS_LPU1_RESET);
1421
1422        writel(pss_ctl, ioc->ioc_regs.pss_ctl_reg);
1423}
1424
1425/*
1426 * Get driver and firmware versions.
1427 */
1428void
1429bfa_ioc_fwver_get(struct bfa_ioc_s *ioc, struct bfi_ioc_image_hdr_s *fwhdr)
1430{
1431        u32     pgnum, pgoff;
1432        u32     loff = 0;
1433        int             i;
1434        u32     *fwsig = (u32 *) fwhdr;
1435
1436        pgnum = PSS_SMEM_PGNUM(ioc->ioc_regs.smem_pg0, loff);
1437        pgoff = PSS_SMEM_PGOFF(loff);
1438        writel(pgnum, ioc->ioc_regs.host_page_num_fn);
1439
1440        for (i = 0; i < (sizeof(struct bfi_ioc_image_hdr_s) / sizeof(u32));
1441             i++) {
1442                fwsig[i] =
1443                        bfa_mem_read(ioc->ioc_regs.smem_page_start, loff);
1444                loff += sizeof(u32);
1445        }
1446}
1447
1448/*
1449 * Returns TRUE if same.
1450 */
1451bfa_boolean_t
1452bfa_ioc_fwver_cmp(struct bfa_ioc_s *ioc, struct bfi_ioc_image_hdr_s *fwhdr)
1453{
1454        struct bfi_ioc_image_hdr_s *drv_fwhdr;
1455        int i;
1456
1457        drv_fwhdr = (struct bfi_ioc_image_hdr_s *)
1458                bfa_cb_image_get_chunk(bfa_ioc_asic_gen(ioc), 0);
1459
1460        for (i = 0; i < BFI_IOC_MD5SUM_SZ; i++) {
1461                if (fwhdr->md5sum[i] != cpu_to_le32(drv_fwhdr->md5sum[i])) {
1462                        bfa_trc(ioc, i);
1463                        bfa_trc(ioc, fwhdr->md5sum[i]);
1464                        bfa_trc(ioc, drv_fwhdr->md5sum[i]);
1465                        return BFA_FALSE;
1466                }
1467        }
1468
1469        bfa_trc(ioc, fwhdr->md5sum[0]);
1470        return BFA_TRUE;
1471}
1472
1473/*
1474 * Return true if current running version is valid. Firmware signature and
1475 * execution context (driver/bios) must match.
1476 */
1477static bfa_boolean_t
1478bfa_ioc_fwver_valid(struct bfa_ioc_s *ioc, u32 boot_env)
1479{
1480        struct bfi_ioc_image_hdr_s fwhdr, *drv_fwhdr;
1481
1482        bfa_ioc_fwver_get(ioc, &fwhdr);
1483        drv_fwhdr = (struct bfi_ioc_image_hdr_s *)
1484                bfa_cb_image_get_chunk(bfa_ioc_asic_gen(ioc), 0);
1485
1486        if (fwhdr.signature != cpu_to_le32(drv_fwhdr->signature)) {
1487                bfa_trc(ioc, fwhdr.signature);
1488                bfa_trc(ioc, drv_fwhdr->signature);
1489                return BFA_FALSE;
1490        }
1491
1492        if (swab32(fwhdr.bootenv) != boot_env) {
1493                bfa_trc(ioc, fwhdr.bootenv);
1494                bfa_trc(ioc, boot_env);
1495                return BFA_FALSE;
1496        }
1497
1498        return bfa_ioc_fwver_cmp(ioc, &fwhdr);
1499}
1500
1501/*
1502 * Conditionally flush any pending message from firmware at start.
1503 */
1504static void
1505bfa_ioc_msgflush(struct bfa_ioc_s *ioc)
1506{
1507        u32     r32;
1508
1509        r32 = readl(ioc->ioc_regs.lpu_mbox_cmd);
1510        if (r32)
1511                writel(1, ioc->ioc_regs.lpu_mbox_cmd);
1512}
1513
1514static void
1515bfa_ioc_hwinit(struct bfa_ioc_s *ioc, bfa_boolean_t force)
1516{
1517        enum bfi_ioc_state ioc_fwstate;
1518        bfa_boolean_t fwvalid;
1519        u32 boot_type;
1520        u32 boot_env;
1521
1522        ioc_fwstate = readl(ioc->ioc_regs.ioc_fwstate);
1523
1524        if (force)
1525                ioc_fwstate = BFI_IOC_UNINIT;
1526
1527        bfa_trc(ioc, ioc_fwstate);
1528
1529        boot_type = BFI_FWBOOT_TYPE_NORMAL;
1530        boot_env = BFI_FWBOOT_ENV_OS;
1531
1532        /*
1533         * check if firmware is valid
1534         */
1535        fwvalid = (ioc_fwstate == BFI_IOC_UNINIT) ?
1536                BFA_FALSE : bfa_ioc_fwver_valid(ioc, boot_env);
1537
1538        if (!fwvalid) {
1539                bfa_ioc_boot(ioc, boot_type, boot_env);
1540                bfa_ioc_poll_fwinit(ioc);
1541                return;
1542        }
1543
1544        /*
1545         * If hardware initialization is in progress (initialized by other IOC),
1546         * just wait for an initialization completion interrupt.
1547         */
1548        if (ioc_fwstate == BFI_IOC_INITING) {
1549                bfa_ioc_poll_fwinit(ioc);
1550                return;
1551        }
1552
1553        /*
1554         * If IOC function is disabled and firmware version is same,
1555         * just re-enable IOC.
1556         *
1557         * If option rom, IOC must not be in operational state. With
1558         * convergence, IOC will be in operational state when 2nd driver
1559         * is loaded.
1560         */
1561        if (ioc_fwstate == BFI_IOC_DISABLED || ioc_fwstate == BFI_IOC_OP) {
1562
1563                /*
1564                 * When using MSI-X any pending firmware ready event should
1565                 * be flushed. Otherwise MSI-X interrupts are not delivered.
1566                 */
1567                bfa_ioc_msgflush(ioc);
1568                bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_FWREADY);
1569                return;
1570        }
1571
1572        /*
1573         * Initialize the h/w for any other states.
1574         */
1575        bfa_ioc_boot(ioc, boot_type, boot_env);
1576        bfa_ioc_poll_fwinit(ioc);
1577}
1578
1579static void
1580bfa_ioc_timeout(void *ioc_arg)
1581{
1582        struct bfa_ioc_s  *ioc = (struct bfa_ioc_s *) ioc_arg;
1583
1584        bfa_trc(ioc, 0);
1585        bfa_fsm_send_event(ioc, IOC_E_TIMEOUT);
1586}
1587
1588void
1589bfa_ioc_mbox_send(struct bfa_ioc_s *ioc, void *ioc_msg, int len)
1590{
1591        u32 *msgp = (u32 *) ioc_msg;
1592        u32 i;
1593
1594        bfa_trc(ioc, msgp[0]);
1595        bfa_trc(ioc, len);
1596
1597        WARN_ON(len > BFI_IOC_MSGLEN_MAX);
1598
1599        /*
1600         * first write msg to mailbox registers
1601         */
1602        for (i = 0; i < len / sizeof(u32); i++)
1603                writel(cpu_to_le32(msgp[i]),
1604                        ioc->ioc_regs.hfn_mbox + i * sizeof(u32));
1605
1606        for (; i < BFI_IOC_MSGLEN_MAX / sizeof(u32); i++)
1607                writel(0, ioc->ioc_regs.hfn_mbox + i * sizeof(u32));
1608
1609        /*
1610         * write 1 to mailbox CMD to trigger LPU event
1611         */
1612        writel(1, ioc->ioc_regs.hfn_mbox_cmd);
1613        (void) readl(ioc->ioc_regs.hfn_mbox_cmd);
1614}
1615
1616static void
1617bfa_ioc_send_enable(struct bfa_ioc_s *ioc)
1618{
1619        struct bfi_ioc_ctrl_req_s enable_req;
1620        struct timeval tv;
1621
1622        bfi_h2i_set(enable_req.mh, BFI_MC_IOC, BFI_IOC_H2I_ENABLE_REQ,
1623                    bfa_ioc_portid(ioc));
1624        enable_req.clscode = cpu_to_be16(ioc->clscode);
1625        do_gettimeofday(&tv);
1626        enable_req.tv_sec = be32_to_cpu(tv.tv_sec);
1627        bfa_ioc_mbox_send(ioc, &enable_req, sizeof(struct bfi_ioc_ctrl_req_s));
1628}
1629
1630static void
1631bfa_ioc_send_disable(struct bfa_ioc_s *ioc)
1632{
1633        struct bfi_ioc_ctrl_req_s disable_req;
1634
1635        bfi_h2i_set(disable_req.mh, BFI_MC_IOC, BFI_IOC_H2I_DISABLE_REQ,
1636                    bfa_ioc_portid(ioc));
1637        bfa_ioc_mbox_send(ioc, &disable_req, sizeof(struct bfi_ioc_ctrl_req_s));
1638}
1639
1640static void
1641bfa_ioc_send_getattr(struct bfa_ioc_s *ioc)
1642{
1643        struct bfi_ioc_getattr_req_s    attr_req;
1644
1645        bfi_h2i_set(attr_req.mh, BFI_MC_IOC, BFI_IOC_H2I_GETATTR_REQ,
1646                    bfa_ioc_portid(ioc));
1647        bfa_dma_be_addr_set(attr_req.attr_addr, ioc->attr_dma.pa);
1648        bfa_ioc_mbox_send(ioc, &attr_req, sizeof(attr_req));
1649}
1650
1651static void
1652bfa_ioc_hb_check(void *cbarg)
1653{
1654        struct bfa_ioc_s  *ioc = cbarg;
1655        u32     hb_count;
1656
1657        hb_count = readl(ioc->ioc_regs.heartbeat);
1658        if (ioc->hb_count == hb_count) {
1659                bfa_ioc_recover(ioc);
1660                return;
1661        } else {
1662                ioc->hb_count = hb_count;
1663        }
1664
1665        bfa_ioc_mbox_poll(ioc);
1666        bfa_hb_timer_start(ioc);
1667}
1668
1669static void
1670bfa_ioc_hb_monitor(struct bfa_ioc_s *ioc)
1671{
1672        ioc->hb_count = readl(ioc->ioc_regs.heartbeat);
1673        bfa_hb_timer_start(ioc);
1674}
1675
1676/*
1677 *      Initiate a full firmware download.
1678 */
1679static void
1680bfa_ioc_download_fw(struct bfa_ioc_s *ioc, u32 boot_type,
1681                    u32 boot_env)
1682{
1683        u32 *fwimg;
1684        u32 pgnum, pgoff;
1685        u32 loff = 0;
1686        u32 chunkno = 0;
1687        u32 i;
1688        u32 asicmode;
1689
1690        bfa_trc(ioc, bfa_cb_image_get_size(bfa_ioc_asic_gen(ioc)));
1691        fwimg = bfa_cb_image_get_chunk(bfa_ioc_asic_gen(ioc), chunkno);
1692
1693        pgnum = PSS_SMEM_PGNUM(ioc->ioc_regs.smem_pg0, loff);
1694        pgoff = PSS_SMEM_PGOFF(loff);
1695
1696        writel(pgnum, ioc->ioc_regs.host_page_num_fn);
1697
1698        for (i = 0; i < bfa_cb_image_get_size(bfa_ioc_asic_gen(ioc)); i++) {
1699
1700                if (BFA_IOC_FLASH_CHUNK_NO(i) != chunkno) {
1701                        chunkno = BFA_IOC_FLASH_CHUNK_NO(i);
1702                        fwimg = bfa_cb_image_get_chunk(bfa_ioc_asic_gen(ioc),
1703                                        BFA_IOC_FLASH_CHUNK_ADDR(chunkno));
1704                }
1705
1706                /*
1707                 * write smem
1708                 */
1709                bfa_mem_write(ioc->ioc_regs.smem_page_start, loff,
1710                        cpu_to_le32(fwimg[BFA_IOC_FLASH_OFFSET_IN_CHUNK(i)]));
1711
1712                loff += sizeof(u32);
1713
1714                /*
1715                 * handle page offset wrap around
1716                 */
1717                loff = PSS_SMEM_PGOFF(loff);
1718                if (loff == 0) {
1719                        pgnum++;
1720                        writel(pgnum, ioc->ioc_regs.host_page_num_fn);
1721                }
1722        }
1723
1724        writel(PSS_SMEM_PGNUM(ioc->ioc_regs.smem_pg0, 0),
1725                        ioc->ioc_regs.host_page_num_fn);
1726
1727        /*
1728         * Set boot type and device mode at the end.
1729         */
1730        asicmode = BFI_FWBOOT_DEVMODE(ioc->asic_gen, ioc->asic_mode,
1731                                ioc->port0_mode, ioc->port1_mode);
1732        bfa_mem_write(ioc->ioc_regs.smem_page_start, BFI_FWBOOT_DEVMODE_OFF,
1733                        swab32(asicmode));
1734        bfa_mem_write(ioc->ioc_regs.smem_page_start, BFI_FWBOOT_TYPE_OFF,
1735                        swab32(boot_type));
1736        bfa_mem_write(ioc->ioc_regs.smem_page_start, BFI_FWBOOT_ENV_OFF,
1737                        swab32(boot_env));
1738}
1739
1740
1741/*
1742 * Update BFA configuration from firmware configuration.
1743 */
1744static void
1745bfa_ioc_getattr_reply(struct bfa_ioc_s *ioc)
1746{
1747        struct bfi_ioc_attr_s   *attr = ioc->attr;
1748
1749        attr->adapter_prop  = be32_to_cpu(attr->adapter_prop);
1750        attr->card_type     = be32_to_cpu(attr->card_type);
1751        attr->maxfrsize     = be16_to_cpu(attr->maxfrsize);
1752        ioc->fcmode     = (attr->port_mode == BFI_PORT_MODE_FC);
1753        attr->mfg_year  = be16_to_cpu(attr->mfg_year);
1754
1755        bfa_fsm_send_event(ioc, IOC_E_FWRSP_GETATTR);
1756}
1757
1758/*
1759 * Attach time initialization of mbox logic.
1760 */
1761static void
1762bfa_ioc_mbox_attach(struct bfa_ioc_s *ioc)
1763{
1764        struct bfa_ioc_mbox_mod_s       *mod = &ioc->mbox_mod;
1765        int     mc;
1766
1767        INIT_LIST_HEAD(&mod->cmd_q);
1768        for (mc = 0; mc < BFI_MC_MAX; mc++) {
1769                mod->mbhdlr[mc].cbfn = NULL;
1770                mod->mbhdlr[mc].cbarg = ioc->bfa;
1771        }
1772}
1773
1774/*
1775 * Mbox poll timer -- restarts any pending mailbox requests.
1776 */
1777static void
1778bfa_ioc_mbox_poll(struct bfa_ioc_s *ioc)
1779{
1780        struct bfa_ioc_mbox_mod_s       *mod = &ioc->mbox_mod;
1781        struct bfa_mbox_cmd_s           *cmd;
1782        u32                     stat;
1783
1784        /*
1785         * If no command pending, do nothing
1786         */
1787        if (list_empty(&mod->cmd_q))
1788                return;
1789
1790        /*
1791         * If previous command is not yet fetched by firmware, do nothing
1792         */
1793        stat = readl(ioc->ioc_regs.hfn_mbox_cmd);
1794        if (stat)
1795                return;
1796
1797        /*
1798         * Enqueue command to firmware.
1799         */
1800        bfa_q_deq(&mod->cmd_q, &cmd);
1801        bfa_ioc_mbox_send(ioc, cmd->msg, sizeof(cmd->msg));
1802}
1803
1804/*
1805 * Cleanup any pending requests.
1806 */
1807static void
1808bfa_ioc_mbox_flush(struct bfa_ioc_s *ioc)
1809{
1810        struct bfa_ioc_mbox_mod_s       *mod = &ioc->mbox_mod;
1811        struct bfa_mbox_cmd_s           *cmd;
1812
1813        while (!list_empty(&mod->cmd_q))
1814                bfa_q_deq(&mod->cmd_q, &cmd);
1815}
1816
1817/*
1818 * Read data from SMEM to host through PCI memmap
1819 *
1820 * @param[in]   ioc     memory for IOC
1821 * @param[in]   tbuf    app memory to store data from smem
1822 * @param[in]   soff    smem offset
1823 * @param[in]   sz      size of smem in bytes
1824 */
1825static bfa_status_t
1826bfa_ioc_smem_read(struct bfa_ioc_s *ioc, void *tbuf, u32 soff, u32 sz)
1827{
1828        u32 pgnum, loff;
1829        __be32 r32;
1830        int i, len;
1831        u32 *buf = tbuf;
1832
1833        pgnum = PSS_SMEM_PGNUM(ioc->ioc_regs.smem_pg0, soff);
1834        loff = PSS_SMEM_PGOFF(soff);
1835        bfa_trc(ioc, pgnum);
1836        bfa_trc(ioc, loff);
1837        bfa_trc(ioc, sz);
1838
1839        /*
1840         *  Hold semaphore to serialize pll init and fwtrc.
1841         */
1842        if (BFA_FALSE == bfa_ioc_sem_get(ioc->ioc_regs.ioc_init_sem_reg)) {
1843                bfa_trc(ioc, 0);
1844                return BFA_STATUS_FAILED;
1845        }
1846
1847        writel(pgnum, ioc->ioc_regs.host_page_num_fn);
1848
1849        len = sz/sizeof(u32);
1850        bfa_trc(ioc, len);
1851        for (i = 0; i < len; i++) {
1852                r32 = bfa_mem_read(ioc->ioc_regs.smem_page_start, loff);
1853                buf[i] = be32_to_cpu(r32);
1854                loff += sizeof(u32);
1855
1856                /*
1857                 * handle page offset wrap around
1858                 */
1859                loff = PSS_SMEM_PGOFF(loff);
1860                if (loff == 0) {
1861                        pgnum++;
1862                        writel(pgnum, ioc->ioc_regs.host_page_num_fn);
1863                }
1864        }
1865        writel(PSS_SMEM_PGNUM(ioc->ioc_regs.smem_pg0, 0),
1866                        ioc->ioc_regs.host_page_num_fn);
1867        /*
1868         *  release semaphore.
1869         */
1870        readl(ioc->ioc_regs.ioc_init_sem_reg);
1871        writel(1, ioc->ioc_regs.ioc_init_sem_reg);
1872
1873        bfa_trc(ioc, pgnum);
1874        return BFA_STATUS_OK;
1875}
1876
1877/*
1878 * Clear SMEM data from host through PCI memmap
1879 *
1880 * @param[in]   ioc     memory for IOC
1881 * @param[in]   soff    smem offset
1882 * @param[in]   sz      size of smem in bytes
1883 */
1884static bfa_status_t
1885bfa_ioc_smem_clr(struct bfa_ioc_s *ioc, u32 soff, u32 sz)
1886{
1887        int i, len;
1888        u32 pgnum, loff;
1889
1890        pgnum = PSS_SMEM_PGNUM(ioc->ioc_regs.smem_pg0, soff);
1891        loff = PSS_SMEM_PGOFF(soff);
1892        bfa_trc(ioc, pgnum);
1893        bfa_trc(ioc, loff);
1894        bfa_trc(ioc, sz);
1895
1896        /*
1897         *  Hold semaphore to serialize pll init and fwtrc.
1898         */
1899        if (BFA_FALSE == bfa_ioc_sem_get(ioc->ioc_regs.ioc_init_sem_reg)) {
1900                bfa_trc(ioc, 0);
1901                return BFA_STATUS_FAILED;
1902        }
1903
1904        writel(pgnum, ioc->ioc_regs.host_page_num_fn);
1905
1906        len = sz/sizeof(u32); /* len in words */
1907        bfa_trc(ioc, len);
1908        for (i = 0; i < len; i++) {
1909                bfa_mem_write(ioc->ioc_regs.smem_page_start, loff, 0);
1910                loff += sizeof(u32);
1911
1912                /*
1913                 * handle page offset wrap around
1914                 */
1915                loff = PSS_SMEM_PGOFF(loff);
1916                if (loff == 0) {
1917                        pgnum++;
1918                        writel(pgnum, ioc->ioc_regs.host_page_num_fn);
1919                }
1920        }
1921        writel(PSS_SMEM_PGNUM(ioc->ioc_regs.smem_pg0, 0),
1922                        ioc->ioc_regs.host_page_num_fn);
1923
1924        /*
1925         *  release semaphore.
1926         */
1927        readl(ioc->ioc_regs.ioc_init_sem_reg);
1928        writel(1, ioc->ioc_regs.ioc_init_sem_reg);
1929        bfa_trc(ioc, pgnum);
1930        return BFA_STATUS_OK;
1931}
1932
1933static void
1934bfa_ioc_fail_notify(struct bfa_ioc_s *ioc)
1935{
1936        struct bfad_s *bfad = (struct bfad_s *)ioc->bfa->bfad;
1937
1938        /*
1939         * Notify driver and common modules registered for notification.
1940         */
1941        ioc->cbfn->hbfail_cbfn(ioc->bfa);
1942        bfa_ioc_event_notify(ioc, BFA_IOC_E_FAILED);
1943
1944        bfa_ioc_debug_save_ftrc(ioc);
1945
1946        BFA_LOG(KERN_CRIT, bfad, bfa_log_level,
1947                "Heart Beat of IOC has failed\n");
1948        bfa_ioc_aen_post(ioc, BFA_IOC_AEN_HBFAIL);
1949
1950}
1951
1952static void
1953bfa_ioc_pf_fwmismatch(struct bfa_ioc_s *ioc)
1954{
1955        struct bfad_s *bfad = (struct bfad_s *)ioc->bfa->bfad;
1956        /*
1957         * Provide enable completion callback.
1958         */
1959        ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
1960        BFA_LOG(KERN_WARNING, bfad, bfa_log_level,
1961                "Running firmware version is incompatible "
1962                "with the driver version\n");
1963        bfa_ioc_aen_post(ioc, BFA_IOC_AEN_FWMISMATCH);
1964}
1965
1966bfa_status_t
1967bfa_ioc_pll_init(struct bfa_ioc_s *ioc)
1968{
1969
1970        /*
1971         *  Hold semaphore so that nobody can access the chip during init.
1972         */
1973        bfa_ioc_sem_get(ioc->ioc_regs.ioc_init_sem_reg);
1974
1975        bfa_ioc_pll_init_asic(ioc);
1976
1977        ioc->pllinit = BFA_TRUE;
1978
1979        /*
1980         * Initialize LMEM
1981         */
1982        bfa_ioc_lmem_init(ioc);
1983
1984        /*
1985         *  release semaphore.
1986         */
1987        readl(ioc->ioc_regs.ioc_init_sem_reg);
1988        writel(1, ioc->ioc_regs.ioc_init_sem_reg);
1989
1990        return BFA_STATUS_OK;
1991}
1992
1993/*
1994 * Interface used by diag module to do firmware boot with memory test
1995 * as the entry vector.
1996 */
1997void
1998bfa_ioc_boot(struct bfa_ioc_s *ioc, u32 boot_type, u32 boot_env)
1999{
2000        bfa_ioc_stats(ioc, ioc_boots);
2001
2002        if (bfa_ioc_pll_init(ioc) != BFA_STATUS_OK)
2003                return;
2004
2005        /*
2006         * Initialize IOC state of all functions on a chip reset.
2007         */
2008        if (boot_type == BFI_FWBOOT_TYPE_MEMTEST) {
2009                writel(BFI_IOC_MEMTEST, ioc->ioc_regs.ioc_fwstate);
2010                writel(BFI_IOC_MEMTEST, ioc->ioc_regs.alt_ioc_fwstate);
2011        } else {
2012                writel(BFI_IOC_INITING, ioc->ioc_regs.ioc_fwstate);
2013                writel(BFI_IOC_INITING, ioc->ioc_regs.alt_ioc_fwstate);
2014        }
2015
2016        bfa_ioc_msgflush(ioc);
2017        bfa_ioc_download_fw(ioc, boot_type, boot_env);
2018        bfa_ioc_lpu_start(ioc);
2019}
2020
2021/*
2022 * Enable/disable IOC failure auto recovery.
2023 */
2024void
2025bfa_ioc_auto_recover(bfa_boolean_t auto_recover)
2026{
2027        bfa_auto_recover = auto_recover;
2028}
2029
2030
2031
2032bfa_boolean_t
2033bfa_ioc_is_operational(struct bfa_ioc_s *ioc)
2034{
2035        return bfa_fsm_cmp_state(ioc, bfa_ioc_sm_op);
2036}
2037
2038bfa_boolean_t
2039bfa_ioc_is_initialized(struct bfa_ioc_s *ioc)
2040{
2041        u32 r32 = readl(ioc->ioc_regs.ioc_fwstate);
2042
2043        return ((r32 != BFI_IOC_UNINIT) &&
2044                (r32 != BFI_IOC_INITING) &&
2045                (r32 != BFI_IOC_MEMTEST));
2046}
2047
2048bfa_boolean_t
2049bfa_ioc_msgget(struct bfa_ioc_s *ioc, void *mbmsg)
2050{
2051        __be32  *msgp = mbmsg;
2052        u32     r32;
2053        int             i;
2054
2055        r32 = readl(ioc->ioc_regs.lpu_mbox_cmd);
2056        if ((r32 & 1) == 0)
2057                return BFA_FALSE;
2058
2059        /*
2060         * read the MBOX msg
2061         */
2062        for (i = 0; i < (sizeof(union bfi_ioc_i2h_msg_u) / sizeof(u32));
2063             i++) {
2064                r32 = readl(ioc->ioc_regs.lpu_mbox +
2065                                   i * sizeof(u32));
2066                msgp[i] = cpu_to_be32(r32);
2067        }
2068
2069        /*
2070         * turn off mailbox interrupt by clearing mailbox status
2071         */
2072        writel(1, ioc->ioc_regs.lpu_mbox_cmd);
2073        readl(ioc->ioc_regs.lpu_mbox_cmd);
2074
2075        return BFA_TRUE;
2076}
2077
2078void
2079bfa_ioc_isr(struct bfa_ioc_s *ioc, struct bfi_mbmsg_s *m)
2080{
2081        union bfi_ioc_i2h_msg_u *msg;
2082        struct bfa_iocpf_s *iocpf = &ioc->iocpf;
2083
2084        msg = (union bfi_ioc_i2h_msg_u *) m;
2085
2086        bfa_ioc_stats(ioc, ioc_isrs);
2087
2088        switch (msg->mh.msg_id) {
2089        case BFI_IOC_I2H_HBEAT:
2090                break;
2091
2092        case BFI_IOC_I2H_ENABLE_REPLY:
2093                ioc->port_mode = ioc->port_mode_cfg =
2094                                (enum bfa_mode_s)msg->fw_event.port_mode;
2095                ioc->ad_cap_bm = msg->fw_event.cap_bm;
2096                bfa_fsm_send_event(iocpf, IOCPF_E_FWRSP_ENABLE);
2097                break;
2098
2099        case BFI_IOC_I2H_DISABLE_REPLY:
2100                bfa_fsm_send_event(iocpf, IOCPF_E_FWRSP_DISABLE);
2101                break;
2102
2103        case BFI_IOC_I2H_GETATTR_REPLY:
2104                bfa_ioc_getattr_reply(ioc);
2105                break;
2106
2107        default:
2108                bfa_trc(ioc, msg->mh.msg_id);
2109                WARN_ON(1);
2110        }
2111}
2112
2113/*
2114 * IOC attach time initialization and setup.
2115 *
2116 * @param[in]   ioc     memory for IOC
2117 * @param[in]   bfa     driver instance structure
2118 */
2119void
2120bfa_ioc_attach(struct bfa_ioc_s *ioc, void *bfa, struct bfa_ioc_cbfn_s *cbfn,
2121               struct bfa_timer_mod_s *timer_mod)
2122{
2123        ioc->bfa        = bfa;
2124        ioc->cbfn       = cbfn;
2125        ioc->timer_mod  = timer_mod;
2126        ioc->fcmode     = BFA_FALSE;
2127        ioc->pllinit    = BFA_FALSE;
2128        ioc->dbg_fwsave_once = BFA_TRUE;
2129        ioc->iocpf.ioc  = ioc;
2130
2131        bfa_ioc_mbox_attach(ioc);
2132        INIT_LIST_HEAD(&ioc->notify_q);
2133
2134        bfa_fsm_set_state(ioc, bfa_ioc_sm_uninit);
2135        bfa_fsm_send_event(ioc, IOC_E_RESET);
2136}
2137
2138/*
2139 * Driver detach time IOC cleanup.
2140 */
2141void
2142bfa_ioc_detach(struct bfa_ioc_s *ioc)
2143{
2144        bfa_fsm_send_event(ioc, IOC_E_DETACH);
2145        INIT_LIST_HEAD(&ioc->notify_q);
2146}
2147
2148/*
2149 * Setup IOC PCI properties.
2150 *
2151 * @param[in]   pcidev  PCI device information for this IOC
2152 */
2153void
2154bfa_ioc_pci_init(struct bfa_ioc_s *ioc, struct bfa_pcidev_s *pcidev,
2155                enum bfi_pcifn_class clscode)
2156{
2157        ioc->clscode    = clscode;
2158        ioc->pcidev     = *pcidev;
2159
2160        /*
2161         * Initialize IOC and device personality
2162         */
2163        ioc->port0_mode = ioc->port1_mode = BFI_PORT_MODE_FC;
2164        ioc->asic_mode  = BFI_ASIC_MODE_FC;
2165
2166        switch (pcidev->device_id) {
2167        case BFA_PCI_DEVICE_ID_FC_8G1P:
2168        case BFA_PCI_DEVICE_ID_FC_8G2P:
2169                ioc->asic_gen = BFI_ASIC_GEN_CB;
2170                ioc->fcmode = BFA_TRUE;
2171                ioc->port_mode = ioc->port_mode_cfg = BFA_MODE_HBA;
2172                ioc->ad_cap_bm = BFA_CM_HBA;
2173                break;
2174
2175        case BFA_PCI_DEVICE_ID_CT:
2176                ioc->asic_gen = BFI_ASIC_GEN_CT;
2177                ioc->port0_mode = ioc->port1_mode = BFI_PORT_MODE_ETH;
2178                ioc->asic_mode  = BFI_ASIC_MODE_ETH;
2179                ioc->port_mode = ioc->port_mode_cfg = BFA_MODE_CNA;
2180                ioc->ad_cap_bm = BFA_CM_CNA;
2181                break;
2182
2183        case BFA_PCI_DEVICE_ID_CT_FC:
2184                ioc->asic_gen = BFI_ASIC_GEN_CT;
2185                ioc->fcmode = BFA_TRUE;
2186                ioc->port_mode = ioc->port_mode_cfg = BFA_MODE_HBA;
2187                ioc->ad_cap_bm = BFA_CM_HBA;
2188                break;
2189
2190        case BFA_PCI_DEVICE_ID_CT2:
2191                ioc->asic_gen = BFI_ASIC_GEN_CT2;
2192                if (clscode == BFI_PCIFN_CLASS_FC &&
2193                    pcidev->ssid == BFA_PCI_CT2_SSID_FC) {
2194                        ioc->asic_mode  = BFI_ASIC_MODE_FC16;
2195                        ioc->fcmode = BFA_TRUE;
2196                        ioc->port_mode = ioc->port_mode_cfg = BFA_MODE_HBA;
2197                        ioc->ad_cap_bm = BFA_CM_HBA;
2198                } else {
2199                        ioc->port0_mode = ioc->port1_mode = BFI_PORT_MODE_ETH;
2200                        ioc->asic_mode  = BFI_ASIC_MODE_ETH;
2201                        if (pcidev->ssid == BFA_PCI_CT2_SSID_FCoE) {
2202                                ioc->port_mode =
2203                                ioc->port_mode_cfg = BFA_MODE_CNA;
2204                                ioc->ad_cap_bm = BFA_CM_CNA;
2205                        } else {
2206                                ioc->port_mode =
2207                                ioc->port_mode_cfg = BFA_MODE_NIC;
2208                                ioc->ad_cap_bm = BFA_CM_NIC;
2209                        }
2210                }
2211                break;
2212
2213        default:
2214                WARN_ON(1);
2215        }
2216
2217        /*
2218         * Set asic specific interfaces. See bfa_ioc_cb.c and bfa_ioc_ct.c
2219         */
2220        if (ioc->asic_gen == BFI_ASIC_GEN_CB)
2221                bfa_ioc_set_cb_hwif(ioc);
2222        else if (ioc->asic_gen == BFI_ASIC_GEN_CT)
2223                bfa_ioc_set_ct_hwif(ioc);
2224        else {
2225                WARN_ON(ioc->asic_gen != BFI_ASIC_GEN_CT2);
2226                bfa_ioc_set_ct2_hwif(ioc);
2227                bfa_ioc_ct2_poweron(ioc);
2228        }
2229
2230        bfa_ioc_map_port(ioc);
2231        bfa_ioc_reg_init(ioc);
2232}
2233
2234/*
2235 * Initialize IOC dma memory
2236 *
2237 * @param[in]   dm_kva  kernel virtual address of IOC dma memory
2238 * @param[in]   dm_pa   physical address of IOC dma memory
2239 */
2240void
2241bfa_ioc_mem_claim(struct bfa_ioc_s *ioc,  u8 *dm_kva, u64 dm_pa)
2242{
2243        /*
2244         * dma memory for firmware attribute
2245         */
2246        ioc->attr_dma.kva = dm_kva;
2247        ioc->attr_dma.pa = dm_pa;
2248        ioc->attr = (struct bfi_ioc_attr_s *) dm_kva;
2249}
2250
2251void
2252bfa_ioc_enable(struct bfa_ioc_s *ioc)
2253{
2254        bfa_ioc_stats(ioc, ioc_enables);
2255        ioc->dbg_fwsave_once = BFA_TRUE;
2256
2257        bfa_fsm_send_event(ioc, IOC_E_ENABLE);
2258}
2259
2260void
2261bfa_ioc_disable(struct bfa_ioc_s *ioc)
2262{
2263        bfa_ioc_stats(ioc, ioc_disables);
2264        bfa_fsm_send_event(ioc, IOC_E_DISABLE);
2265}
2266
2267void
2268bfa_ioc_suspend(struct bfa_ioc_s *ioc)
2269{
2270        ioc->dbg_fwsave_once = BFA_TRUE;
2271        bfa_fsm_send_event(ioc, IOC_E_HWERROR);
2272}
2273
2274/*
2275 * Initialize memory for saving firmware trace. Driver must initialize
2276 * trace memory before call bfa_ioc_enable().
2277 */
2278void
2279bfa_ioc_debug_memclaim(struct bfa_ioc_s *ioc, void *dbg_fwsave)
2280{
2281        ioc->dbg_fwsave     = dbg_fwsave;
2282        ioc->dbg_fwsave_len = BFA_DBG_FWTRC_LEN;
2283}
2284
2285/*
2286 * Register mailbox message handler functions
2287 *
2288 * @param[in]   ioc             IOC instance
2289 * @param[in]   mcfuncs         message class handler functions
2290 */
2291void
2292bfa_ioc_mbox_register(struct bfa_ioc_s *ioc, bfa_ioc_mbox_mcfunc_t *mcfuncs)
2293{
2294        struct bfa_ioc_mbox_mod_s       *mod = &ioc->mbox_mod;
2295        int                             mc;
2296
2297        for (mc = 0; mc < BFI_MC_MAX; mc++)
2298                mod->mbhdlr[mc].cbfn = mcfuncs[mc];
2299}
2300
2301/*
2302 * Register mailbox message handler function, to be called by common modules
2303 */
2304void
2305bfa_ioc_mbox_regisr(struct bfa_ioc_s *ioc, enum bfi_mclass mc,
2306                    bfa_ioc_mbox_mcfunc_t cbfn, void *cbarg)
2307{
2308        struct bfa_ioc_mbox_mod_s       *mod = &ioc->mbox_mod;
2309
2310        mod->mbhdlr[mc].cbfn    = cbfn;
2311        mod->mbhdlr[mc].cbarg   = cbarg;
2312}
2313
2314/*
2315 * Queue a mailbox command request to firmware. Waits if mailbox is busy.
2316 * Responsibility of caller to serialize
2317 *
2318 * @param[in]   ioc     IOC instance
2319 * @param[i]    cmd     Mailbox command
2320 */
2321void
2322bfa_ioc_mbox_queue(struct bfa_ioc_s *ioc, struct bfa_mbox_cmd_s *cmd)
2323{
2324        struct bfa_ioc_mbox_mod_s       *mod = &ioc->mbox_mod;
2325        u32                     stat;
2326
2327        /*
2328         * If a previous command is pending, queue new command
2329         */
2330        if (!list_empty(&mod->cmd_q)) {
2331                list_add_tail(&cmd->qe, &mod->cmd_q);
2332                return;
2333        }
2334
2335        /*
2336         * If mailbox is busy, queue command for poll timer
2337         */
2338        stat = readl(ioc->ioc_regs.hfn_mbox_cmd);
2339        if (stat) {
2340                list_add_tail(&cmd->qe, &mod->cmd_q);
2341                return;
2342        }
2343
2344        /*
2345         * mailbox is free -- queue command to firmware
2346         */
2347        bfa_ioc_mbox_send(ioc, cmd->msg, sizeof(cmd->msg));
2348}
2349
2350/*
2351 * Handle mailbox interrupts
2352 */
2353void
2354bfa_ioc_mbox_isr(struct bfa_ioc_s *ioc)
2355{
2356        struct bfa_ioc_mbox_mod_s       *mod = &ioc->mbox_mod;
2357        struct bfi_mbmsg_s              m;
2358        int                             mc;
2359
2360        if (bfa_ioc_msgget(ioc, &m)) {
2361                /*
2362                 * Treat IOC message class as special.
2363                 */
2364                mc = m.mh.msg_class;
2365                if (mc == BFI_MC_IOC) {
2366                        bfa_ioc_isr(ioc, &m);
2367                        return;
2368                }
2369
2370                if ((mc >= BFI_MC_MAX) || (mod->mbhdlr[mc].cbfn == NULL))
2371                        return;
2372
2373                mod->mbhdlr[mc].cbfn(mod->mbhdlr[mc].cbarg, &m);
2374        }
2375
2376        bfa_ioc_lpu_read_stat(ioc);
2377
2378        /*
2379         * Try to send pending mailbox commands
2380         */
2381        bfa_ioc_mbox_poll(ioc);
2382}
2383
2384void
2385bfa_ioc_error_isr(struct bfa_ioc_s *ioc)
2386{
2387        bfa_ioc_stats(ioc, ioc_hbfails);
2388        ioc->stats.hb_count = ioc->hb_count;
2389        bfa_fsm_send_event(ioc, IOC_E_HWERROR);
2390}
2391
2392/*
2393 * return true if IOC is disabled
2394 */
2395bfa_boolean_t
2396bfa_ioc_is_disabled(struct bfa_ioc_s *ioc)
2397{
2398        return bfa_fsm_cmp_state(ioc, bfa_ioc_sm_disabling) ||
2399                bfa_fsm_cmp_state(ioc, bfa_ioc_sm_disabled);
2400}
2401
2402/*
2403 * return true if IOC firmware is different.
2404 */
2405bfa_boolean_t
2406bfa_ioc_fw_mismatch(struct bfa_ioc_s *ioc)
2407{
2408        return bfa_fsm_cmp_state(ioc, bfa_ioc_sm_reset) ||
2409                bfa_fsm_cmp_state(&ioc->iocpf, bfa_iocpf_sm_fwcheck) ||
2410                bfa_fsm_cmp_state(&ioc->iocpf, bfa_iocpf_sm_mismatch);
2411}
2412
2413#define bfa_ioc_state_disabled(__sm)            \
2414        (((__sm) == BFI_IOC_UNINIT) ||          \
2415         ((__sm) == BFI_IOC_INITING) ||         \
2416         ((__sm) == BFI_IOC_HWINIT) ||          \
2417         ((__sm) == BFI_IOC_DISABLED) ||        \
2418         ((__sm) == BFI_IOC_FAIL) ||            \
2419         ((__sm) == BFI_IOC_CFG_DISABLED))
2420
2421/*
2422 * Check if adapter is disabled -- both IOCs should be in a disabled
2423 * state.
2424 */
2425bfa_boolean_t
2426bfa_ioc_adapter_is_disabled(struct bfa_ioc_s *ioc)
2427{
2428        u32     ioc_state;
2429
2430        if (!bfa_fsm_cmp_state(ioc, bfa_ioc_sm_disabled))
2431                return BFA_FALSE;
2432
2433        ioc_state = readl(ioc->ioc_regs.ioc_fwstate);
2434        if (!bfa_ioc_state_disabled(ioc_state))
2435                return BFA_FALSE;
2436
2437        if (ioc->pcidev.device_id != BFA_PCI_DEVICE_ID_FC_8G1P) {
2438                ioc_state = readl(ioc->ioc_regs.alt_ioc_fwstate);
2439                if (!bfa_ioc_state_disabled(ioc_state))
2440                        return BFA_FALSE;
2441        }
2442
2443        return BFA_TRUE;
2444}
2445
2446/*
2447 * Reset IOC fwstate registers.
2448 */
2449void
2450bfa_ioc_reset_fwstate(struct bfa_ioc_s *ioc)
2451{
2452        writel(BFI_IOC_UNINIT, ioc->ioc_regs.ioc_fwstate);
2453        writel(BFI_IOC_UNINIT, ioc->ioc_regs.alt_ioc_fwstate);
2454}
2455
2456#define BFA_MFG_NAME "Brocade"
2457void
2458bfa_ioc_get_adapter_attr(struct bfa_ioc_s *ioc,
2459                         struct bfa_adapter_attr_s *ad_attr)
2460{
2461        struct bfi_ioc_attr_s   *ioc_attr;
2462
2463        ioc_attr = ioc->attr;
2464
2465        bfa_ioc_get_adapter_serial_num(ioc, ad_attr->serial_num);
2466        bfa_ioc_get_adapter_fw_ver(ioc, ad_attr->fw_ver);
2467        bfa_ioc_get_adapter_optrom_ver(ioc, ad_attr->optrom_ver);
2468        bfa_ioc_get_adapter_manufacturer(ioc, ad_attr->manufacturer);
2469        memcpy(&ad_attr->vpd, &ioc_attr->vpd,
2470                      sizeof(struct bfa_mfg_vpd_s));
2471
2472        ad_attr->nports = bfa_ioc_get_nports(ioc);
2473        ad_attr->max_speed = bfa_ioc_speed_sup(ioc);
2474
2475        bfa_ioc_get_adapter_model(ioc, ad_attr->model);
2476        /* For now, model descr uses same model string */
2477        bfa_ioc_get_adapter_model(ioc, ad_attr->model_descr);
2478
2479        ad_attr->card_type = ioc_attr->card_type;
2480        ad_attr->is_mezz = bfa_mfg_is_mezz(ioc_attr->card_type);
2481
2482        if (BFI_ADAPTER_IS_SPECIAL(ioc_attr->adapter_prop))
2483                ad_attr->prototype = 1;
2484        else
2485                ad_attr->prototype = 0;
2486
2487        ad_attr->pwwn = ioc->attr->pwwn;
2488        ad_attr->mac  = bfa_ioc_get_mac(ioc);
2489
2490        ad_attr->pcie_gen = ioc_attr->pcie_gen;
2491        ad_attr->pcie_lanes = ioc_attr->pcie_lanes;
2492        ad_attr->pcie_lanes_orig = ioc_attr->pcie_lanes_orig;
2493        ad_attr->asic_rev = ioc_attr->asic_rev;
2494
2495        bfa_ioc_get_pci_chip_rev(ioc, ad_attr->hw_ver);
2496
2497        ad_attr->cna_capable = bfa_ioc_is_cna(ioc);
2498        ad_attr->trunk_capable = (ad_attr->nports > 1) &&
2499                                  !bfa_ioc_is_cna(ioc) && !ad_attr->is_mezz;
2500        ad_attr->mfg_day = ioc_attr->mfg_day;
2501        ad_attr->mfg_month = ioc_attr->mfg_month;
2502        ad_attr->mfg_year = ioc_attr->mfg_year;
2503}
2504
2505enum bfa_ioc_type_e
2506bfa_ioc_get_type(struct bfa_ioc_s *ioc)
2507{
2508        if (ioc->clscode == BFI_PCIFN_CLASS_ETH)
2509                return BFA_IOC_TYPE_LL;
2510
2511        WARN_ON(ioc->clscode != BFI_PCIFN_CLASS_FC);
2512
2513        return (ioc->attr->port_mode == BFI_PORT_MODE_FC)
2514                ? BFA_IOC_TYPE_FC : BFA_IOC_TYPE_FCoE;
2515}
2516
2517void
2518bfa_ioc_get_adapter_serial_num(struct bfa_ioc_s *ioc, char *serial_num)
2519{
2520        memset((void *)serial_num, 0, BFA_ADAPTER_SERIAL_NUM_LEN);
2521        memcpy((void *)serial_num,
2522                        (void *)ioc->attr->brcd_serialnum,
2523                        BFA_ADAPTER_SERIAL_NUM_LEN);
2524}
2525
2526void
2527bfa_ioc_get_adapter_fw_ver(struct bfa_ioc_s *ioc, char *fw_ver)
2528{
2529        memset((void *)fw_ver, 0, BFA_VERSION_LEN);
2530        memcpy(fw_ver, ioc->attr->fw_version, BFA_VERSION_LEN);
2531}
2532
2533void
2534bfa_ioc_get_pci_chip_rev(struct bfa_ioc_s *ioc, char *chip_rev)
2535{
2536        WARN_ON(!chip_rev);
2537
2538        memset((void *)chip_rev, 0, BFA_IOC_CHIP_REV_LEN);
2539
2540        chip_rev[0] = 'R';
2541        chip_rev[1] = 'e';
2542        chip_rev[2] = 'v';
2543        chip_rev[3] = '-';
2544        chip_rev[4] = ioc->attr->asic_rev;
2545        chip_rev[5] = '\0';
2546}
2547
2548void
2549bfa_ioc_get_adapter_optrom_ver(struct bfa_ioc_s *ioc, char *optrom_ver)
2550{
2551        memset((void *)optrom_ver, 0, BFA_VERSION_LEN);
2552        memcpy(optrom_ver, ioc->attr->optrom_version,
2553                      BFA_VERSION_LEN);
2554}
2555
2556void
2557bfa_ioc_get_adapter_manufacturer(struct bfa_ioc_s *ioc, char *manufacturer)
2558{
2559        memset((void *)manufacturer, 0, BFA_ADAPTER_MFG_NAME_LEN);
2560        memcpy(manufacturer, BFA_MFG_NAME, BFA_ADAPTER_MFG_NAME_LEN);
2561}
2562
2563void
2564bfa_ioc_get_adapter_model(struct bfa_ioc_s *ioc, char *model)
2565{
2566        struct bfi_ioc_attr_s   *ioc_attr;
2567
2568        WARN_ON(!model);
2569        memset((void *)model, 0, BFA_ADAPTER_MODEL_NAME_LEN);
2570
2571        ioc_attr = ioc->attr;
2572
2573        snprintf(model, BFA_ADAPTER_MODEL_NAME_LEN, "%s-%u",
2574                        BFA_MFG_NAME, ioc_attr->card_type);
2575}
2576
2577enum bfa_ioc_state
2578bfa_ioc_get_state(struct bfa_ioc_s *ioc)
2579{
2580        enum bfa_iocpf_state iocpf_st;
2581        enum bfa_ioc_state ioc_st = bfa_sm_to_state(ioc_sm_table, ioc->fsm);
2582
2583        if (ioc_st == BFA_IOC_ENABLING ||
2584                ioc_st == BFA_IOC_FAIL || ioc_st == BFA_IOC_INITFAIL) {
2585
2586                iocpf_st = bfa_sm_to_state(iocpf_sm_table, ioc->iocpf.fsm);
2587
2588                switch (iocpf_st) {
2589                case BFA_IOCPF_SEMWAIT:
2590                        ioc_st = BFA_IOC_SEMWAIT;
2591                        break;
2592
2593                case BFA_IOCPF_HWINIT:
2594                        ioc_st = BFA_IOC_HWINIT;
2595                        break;
2596
2597                case BFA_IOCPF_FWMISMATCH:
2598                        ioc_st = BFA_IOC_FWMISMATCH;
2599                        break;
2600
2601                case BFA_IOCPF_FAIL:
2602                        ioc_st = BFA_IOC_FAIL;
2603                        break;
2604
2605                case BFA_IOCPF_INITFAIL:
2606                        ioc_st = BFA_IOC_INITFAIL;
2607                        break;
2608
2609                default:
2610                        break;
2611                }
2612        }
2613
2614        return ioc_st;
2615}
2616
2617void
2618bfa_ioc_get_attr(struct bfa_ioc_s *ioc, struct bfa_ioc_attr_s *ioc_attr)
2619{
2620        memset((void *)ioc_attr, 0, sizeof(struct bfa_ioc_attr_s));
2621
2622        ioc_attr->state = bfa_ioc_get_state(ioc);
2623        ioc_attr->port_id = ioc->port_id;
2624        ioc_attr->port_mode = ioc->port_mode;
2625        ioc_attr->port_mode_cfg = ioc->port_mode_cfg;
2626        ioc_attr->cap_bm = ioc->ad_cap_bm;
2627
2628        ioc_attr->ioc_type = bfa_ioc_get_type(ioc);
2629
2630        bfa_ioc_get_adapter_attr(ioc, &ioc_attr->adapter_attr);
2631
2632        ioc_attr->pci_attr.device_id = ioc->pcidev.device_id;
2633        ioc_attr->pci_attr.pcifn = ioc->pcidev.pci_func;
2634        bfa_ioc_get_pci_chip_rev(ioc, ioc_attr->pci_attr.chip_rev);
2635}
2636
2637mac_t
2638bfa_ioc_get_mac(struct bfa_ioc_s *ioc)
2639{
2640        /*
2641         * Check the IOC type and return the appropriate MAC
2642         */
2643        if (bfa_ioc_get_type(ioc) == BFA_IOC_TYPE_FCoE)
2644                return ioc->attr->fcoe_mac;
2645        else
2646                return ioc->attr->mac;
2647}
2648
2649mac_t
2650bfa_ioc_get_mfg_mac(struct bfa_ioc_s *ioc)
2651{
2652        mac_t   m;
2653
2654        m = ioc->attr->mfg_mac;
2655        if (bfa_mfg_is_old_wwn_mac_model(ioc->attr->card_type))
2656                m.mac[MAC_ADDRLEN - 1] += bfa_ioc_pcifn(ioc);
2657        else
2658                bfa_mfg_increment_wwn_mac(&(m.mac[MAC_ADDRLEN-3]),
2659                        bfa_ioc_pcifn(ioc));
2660
2661        return m;
2662}
2663
2664/*
2665 * Send AEN notification
2666 */
2667void
2668bfa_ioc_aen_post(struct bfa_ioc_s *ioc, enum bfa_ioc_aen_event event)
2669{
2670        struct bfad_s *bfad = (struct bfad_s *)ioc->bfa->bfad;
2671        struct bfa_aen_entry_s  *aen_entry;
2672        enum bfa_ioc_type_e ioc_type;
2673
2674        bfad_get_aen_entry(bfad, aen_entry);
2675        if (!aen_entry)
2676                return;
2677
2678        ioc_type = bfa_ioc_get_type(ioc);
2679        switch (ioc_type) {
2680        case BFA_IOC_TYPE_FC:
2681                aen_entry->aen_data.ioc.pwwn = ioc->attr->pwwn;
2682                break;
2683        case BFA_IOC_TYPE_FCoE:
2684                aen_entry->aen_data.ioc.pwwn = ioc->attr->pwwn;
2685                aen_entry->aen_data.ioc.mac = bfa_ioc_get_mac(ioc);
2686                break;
2687        case BFA_IOC_TYPE_LL:
2688                aen_entry->aen_data.ioc.mac = bfa_ioc_get_mac(ioc);
2689                break;
2690        default:
2691                WARN_ON(ioc_type != BFA_IOC_TYPE_FC);
2692                break;
2693        }
2694
2695        /* Send the AEN notification */
2696        aen_entry->aen_data.ioc.ioc_type = ioc_type;
2697        bfad_im_post_vendor_event(aen_entry, bfad, ++ioc->ioc_aen_seq,
2698                                  BFA_AEN_CAT_IOC, event);
2699}
2700
2701/*
2702 * Retrieve saved firmware trace from a prior IOC failure.
2703 */
2704bfa_status_t
2705bfa_ioc_debug_fwsave(struct bfa_ioc_s *ioc, void *trcdata, int *trclen)
2706{
2707        int     tlen;
2708
2709        if (ioc->dbg_fwsave_len == 0)
2710                return BFA_STATUS_ENOFSAVE;
2711
2712        tlen = *trclen;
2713        if (tlen > ioc->dbg_fwsave_len)
2714                tlen = ioc->dbg_fwsave_len;
2715
2716        memcpy(trcdata, ioc->dbg_fwsave, tlen);
2717        *trclen = tlen;
2718        return BFA_STATUS_OK;
2719}
2720
2721
2722/*
2723 * Retrieve saved firmware trace from a prior IOC failure.
2724 */
2725bfa_status_t
2726bfa_ioc_debug_fwtrc(struct bfa_ioc_s *ioc, void *trcdata, int *trclen)
2727{
2728        u32 loff = BFA_DBG_FWTRC_OFF(bfa_ioc_portid(ioc));
2729        int tlen;
2730        bfa_status_t status;
2731
2732        bfa_trc(ioc, *trclen);
2733
2734        tlen = *trclen;
2735        if (tlen > BFA_DBG_FWTRC_LEN)
2736                tlen = BFA_DBG_FWTRC_LEN;
2737
2738        status = bfa_ioc_smem_read(ioc, trcdata, loff, tlen);
2739        *trclen = tlen;
2740        return status;
2741}
2742
2743static void
2744bfa_ioc_send_fwsync(struct bfa_ioc_s *ioc)
2745{
2746        struct bfa_mbox_cmd_s cmd;
2747        struct bfi_ioc_ctrl_req_s *req = (struct bfi_ioc_ctrl_req_s *) cmd.msg;
2748
2749        bfi_h2i_set(req->mh, BFI_MC_IOC, BFI_IOC_H2I_DBG_SYNC,
2750                    bfa_ioc_portid(ioc));
2751        req->clscode = cpu_to_be16(ioc->clscode);
2752        bfa_ioc_mbox_queue(ioc, &cmd);
2753}
2754
2755static void
2756bfa_ioc_fwsync(struct bfa_ioc_s *ioc)
2757{
2758        u32 fwsync_iter = 1000;
2759
2760        bfa_ioc_send_fwsync(ioc);
2761
2762        /*
2763         * After sending a fw sync mbox command wait for it to
2764         * take effect.  We will not wait for a response because
2765         *    1. fw_sync mbox cmd doesn't have a response.
2766         *    2. Even if we implement that,  interrupts might not
2767         *       be enabled when we call this function.
2768         * So, just keep checking if any mbox cmd is pending, and
2769         * after waiting for a reasonable amount of time, go ahead.
2770         * It is possible that fw has crashed and the mbox command
2771         * is never acknowledged.
2772         */
2773        while (bfa_ioc_mbox_cmd_pending(ioc) && fwsync_iter > 0)
2774                fwsync_iter--;
2775}
2776
2777/*
2778 * Dump firmware smem
2779 */
2780bfa_status_t
2781bfa_ioc_debug_fwcore(struct bfa_ioc_s *ioc, void *buf,
2782                                u32 *offset, int *buflen)
2783{
2784        u32 loff;
2785        int dlen;
2786        bfa_status_t status;
2787        u32 smem_len = BFA_IOC_FW_SMEM_SIZE(ioc);
2788
2789        if (*offset >= smem_len) {
2790                *offset = *buflen = 0;
2791                return BFA_STATUS_EINVAL;
2792        }
2793
2794        loff = *offset;
2795        dlen = *buflen;
2796
2797        /*
2798         * First smem read, sync smem before proceeding
2799         * No need to sync before reading every chunk.
2800         */
2801        if (loff == 0)
2802                bfa_ioc_fwsync(ioc);
2803
2804        if ((loff + dlen) >= smem_len)
2805                dlen = smem_len - loff;
2806
2807        status = bfa_ioc_smem_read(ioc, buf, loff, dlen);
2808
2809        if (status != BFA_STATUS_OK) {
2810                *offset = *buflen = 0;
2811                return status;
2812        }
2813
2814        *offset += dlen;
2815
2816        if (*offset >= smem_len)
2817                *offset = 0;
2818
2819        *buflen = dlen;
2820
2821        return status;
2822}
2823
2824/*
2825 * Firmware statistics
2826 */
2827bfa_status_t
2828bfa_ioc_fw_stats_get(struct bfa_ioc_s *ioc, void *stats)
2829{
2830        u32 loff = BFI_IOC_FWSTATS_OFF + \
2831                BFI_IOC_FWSTATS_SZ * (bfa_ioc_portid(ioc));
2832        int tlen;
2833        bfa_status_t status;
2834
2835        if (ioc->stats_busy) {
2836                bfa_trc(ioc, ioc->stats_busy);
2837                return BFA_STATUS_DEVBUSY;
2838        }
2839        ioc->stats_busy = BFA_TRUE;
2840
2841        tlen = sizeof(struct bfa_fw_stats_s);
2842        status = bfa_ioc_smem_read(ioc, stats, loff, tlen);
2843
2844        ioc->stats_busy = BFA_FALSE;
2845        return status;
2846}
2847
2848bfa_status_t
2849bfa_ioc_fw_stats_clear(struct bfa_ioc_s *ioc)
2850{
2851        u32 loff = BFI_IOC_FWSTATS_OFF + \
2852                BFI_IOC_FWSTATS_SZ * (bfa_ioc_portid(ioc));
2853        int tlen;
2854        bfa_status_t status;
2855
2856        if (ioc->stats_busy) {
2857                bfa_trc(ioc, ioc->stats_busy);
2858                return BFA_STATUS_DEVBUSY;
2859        }
2860        ioc->stats_busy = BFA_TRUE;
2861
2862        tlen = sizeof(struct bfa_fw_stats_s);
2863        status = bfa_ioc_smem_clr(ioc, loff, tlen);
2864
2865        ioc->stats_busy = BFA_FALSE;
2866        return status;
2867}
2868
2869/*
2870 * Save firmware trace if configured.
2871 */
2872void
2873bfa_ioc_debug_save_ftrc(struct bfa_ioc_s *ioc)
2874{
2875        int             tlen;
2876
2877        if (ioc->dbg_fwsave_once) {
2878                ioc->dbg_fwsave_once = BFA_FALSE;
2879                if (ioc->dbg_fwsave_len) {
2880                        tlen = ioc->dbg_fwsave_len;
2881                        bfa_ioc_debug_fwtrc(ioc, ioc->dbg_fwsave, &tlen);
2882                }
2883        }
2884}
2885
2886/*
2887 * Firmware failure detected. Start recovery actions.
2888 */
2889static void
2890bfa_ioc_recover(struct bfa_ioc_s *ioc)
2891{
2892        bfa_ioc_stats(ioc, ioc_hbfails);
2893        ioc->stats.hb_count = ioc->hb_count;
2894        bfa_fsm_send_event(ioc, IOC_E_HBFAIL);
2895}
2896
2897/*
2898 *  BFA IOC PF private functions
2899 */
2900static void
2901bfa_iocpf_timeout(void *ioc_arg)
2902{
2903        struct bfa_ioc_s  *ioc = (struct bfa_ioc_s *) ioc_arg;
2904
2905        bfa_trc(ioc, 0);
2906        bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_TIMEOUT);
2907}
2908
2909static void
2910bfa_iocpf_sem_timeout(void *ioc_arg)
2911{
2912        struct bfa_ioc_s  *ioc = (struct bfa_ioc_s *) ioc_arg;
2913
2914        bfa_ioc_hw_sem_get(ioc);
2915}
2916
2917static void
2918bfa_ioc_poll_fwinit(struct bfa_ioc_s *ioc)
2919{
2920        u32 fwstate = readl(ioc->ioc_regs.ioc_fwstate);
2921
2922        bfa_trc(ioc, fwstate);
2923
2924        if (fwstate == BFI_IOC_DISABLED) {
2925                bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_FWREADY);
2926                return;
2927        }
2928
2929        if (ioc->iocpf.poll_time >= (3 * BFA_IOC_TOV))
2930                bfa_iocpf_timeout(ioc);
2931        else {
2932                ioc->iocpf.poll_time += BFA_IOC_POLL_TOV;
2933                bfa_iocpf_poll_timer_start(ioc);
2934        }
2935}
2936
2937static void
2938bfa_iocpf_poll_timeout(void *ioc_arg)
2939{
2940        struct bfa_ioc_s *ioc = (struct bfa_ioc_s *) ioc_arg;
2941
2942        bfa_ioc_poll_fwinit(ioc);
2943}
2944
2945/*
2946 *  bfa timer function
2947 */
2948void
2949bfa_timer_beat(struct bfa_timer_mod_s *mod)
2950{
2951        struct list_head *qh = &mod->timer_q;
2952        struct list_head *qe, *qe_next;
2953        struct bfa_timer_s *elem;
2954        struct list_head timedout_q;
2955
2956        INIT_LIST_HEAD(&timedout_q);
2957
2958        qe = bfa_q_next(qh);
2959
2960        while (qe != qh) {
2961                qe_next = bfa_q_next(qe);
2962
2963                elem = (struct bfa_timer_s *) qe;
2964                if (elem->timeout <= BFA_TIMER_FREQ) {
2965                        elem->timeout = 0;
2966                        list_del(&elem->qe);
2967                        list_add_tail(&elem->qe, &timedout_q);
2968                } else {
2969                        elem->timeout -= BFA_TIMER_FREQ;
2970                }
2971
2972                qe = qe_next;   /* go to next elem */
2973        }
2974
2975        /*
2976         * Pop all the timeout entries
2977         */
2978        while (!list_empty(&timedout_q)) {
2979                bfa_q_deq(&timedout_q, &elem);
2980                elem->timercb(elem->arg);
2981        }
2982}
2983
2984/*
2985 * Should be called with lock protection
2986 */
2987void
2988bfa_timer_begin(struct bfa_timer_mod_s *mod, struct bfa_timer_s *timer,
2989                    void (*timercb) (void *), void *arg, unsigned int timeout)
2990{
2991
2992        WARN_ON(timercb == NULL);
2993        WARN_ON(bfa_q_is_on_q(&mod->timer_q, timer));
2994
2995        timer->timeout = timeout;
2996        timer->timercb = timercb;
2997        timer->arg = arg;
2998
2999        list_add_tail(&timer->qe, &mod->timer_q);
3000}
3001
3002/*
3003 * Should be called with lock protection
3004 */
3005void
3006bfa_timer_stop(struct bfa_timer_s *timer)
3007{
3008        WARN_ON(list_empty(&timer->qe));
3009
3010        list_del(&timer->qe);
3011}
3012
3013/*
3014 *      ASIC block related
3015 */
3016static void
3017bfa_ablk_config_swap(struct bfa_ablk_cfg_s *cfg)
3018{
3019        struct bfa_ablk_cfg_inst_s *cfg_inst;
3020        int i, j;
3021        u16     be16;
3022
3023        for (i = 0; i < BFA_ABLK_MAX; i++) {
3024                cfg_inst = &cfg->inst[i];
3025                for (j = 0; j < BFA_ABLK_MAX_PFS; j++) {
3026                        be16 = cfg_inst->pf_cfg[j].pers;
3027                        cfg_inst->pf_cfg[j].pers = be16_to_cpu(be16);
3028                        be16 = cfg_inst->pf_cfg[j].num_qpairs;
3029                        cfg_inst->pf_cfg[j].num_qpairs = be16_to_cpu(be16);
3030                        be16 = cfg_inst->pf_cfg[j].num_vectors;
3031                        cfg_inst->pf_cfg[j].num_vectors = be16_to_cpu(be16);
3032                        be16 = cfg_inst->pf_cfg[j].bw_min;
3033                        cfg_inst->pf_cfg[j].bw_min = be16_to_cpu(be16);
3034                        be16 = cfg_inst->pf_cfg[j].bw_max;
3035                        cfg_inst->pf_cfg[j].bw_max = be16_to_cpu(be16);
3036                }
3037        }
3038}
3039
3040static void
3041bfa_ablk_isr(void *cbarg, struct bfi_mbmsg_s *msg)
3042{
3043        struct bfa_ablk_s *ablk = (struct bfa_ablk_s *)cbarg;
3044        struct bfi_ablk_i2h_rsp_s *rsp = (struct bfi_ablk_i2h_rsp_s *)msg;
3045        bfa_ablk_cbfn_t cbfn;
3046
3047        WARN_ON(msg->mh.msg_class != BFI_MC_ABLK);
3048        bfa_trc(ablk->ioc, msg->mh.msg_id);
3049
3050        switch (msg->mh.msg_id) {
3051        case BFI_ABLK_I2H_QUERY:
3052                if (rsp->status == BFA_STATUS_OK) {
3053                        memcpy(ablk->cfg, ablk->dma_addr.kva,
3054                                sizeof(struct bfa_ablk_cfg_s));
3055                        bfa_ablk_config_swap(ablk->cfg);
3056                        ablk->cfg = NULL;
3057                }
3058                break;
3059
3060        case BFI_ABLK_I2H_ADPT_CONFIG:
3061        case BFI_ABLK_I2H_PORT_CONFIG:
3062                /* update config port mode */
3063                ablk->ioc->port_mode_cfg = rsp->port_mode;
3064
3065        case BFI_ABLK_I2H_PF_DELETE:
3066        case BFI_ABLK_I2H_PF_UPDATE:
3067        case BFI_ABLK_I2H_OPTROM_ENABLE:
3068        case BFI_ABLK_I2H_OPTROM_DISABLE:
3069                /* No-op */
3070                break;
3071
3072        case BFI_ABLK_I2H_PF_CREATE:
3073                *(ablk->pcifn) = rsp->pcifn;
3074                ablk->pcifn = NULL;
3075                break;
3076
3077        default:
3078                WARN_ON(1);
3079        }
3080
3081        ablk->busy = BFA_FALSE;
3082        if (ablk->cbfn) {
3083                cbfn = ablk->cbfn;
3084                ablk->cbfn = NULL;
3085                cbfn(ablk->cbarg, rsp->status);
3086        }
3087}
3088
3089static void
3090bfa_ablk_notify(void *cbarg, enum bfa_ioc_event_e event)
3091{
3092        struct bfa_ablk_s *ablk = (struct bfa_ablk_s *)cbarg;
3093
3094        bfa_trc(ablk->ioc, event);
3095
3096        switch (event) {
3097        case BFA_IOC_E_ENABLED:
3098                WARN_ON(ablk->busy != BFA_FALSE);
3099                break;
3100
3101        case BFA_IOC_E_DISABLED:
3102        case BFA_IOC_E_FAILED:
3103                /* Fail any pending requests */
3104                ablk->pcifn = NULL;
3105                if (ablk->busy) {
3106                        if (ablk->cbfn)
3107                                ablk->cbfn(ablk->cbarg, BFA_STATUS_FAILED);
3108                        ablk->cbfn = NULL;
3109                        ablk->busy = BFA_FALSE;
3110                }
3111                break;
3112
3113        default:
3114                WARN_ON(1);
3115                break;
3116        }
3117}
3118
3119u32
3120bfa_ablk_meminfo(void)
3121{
3122        return BFA_ROUNDUP(sizeof(struct bfa_ablk_cfg_s), BFA_DMA_ALIGN_SZ);
3123}
3124
3125void
3126bfa_ablk_memclaim(struct bfa_ablk_s *ablk, u8 *dma_kva, u64 dma_pa)
3127{
3128        ablk->dma_addr.kva = dma_kva;
3129        ablk->dma_addr.pa  = dma_pa;
3130}
3131
3132void
3133bfa_ablk_attach(struct bfa_ablk_s *ablk, struct bfa_ioc_s *ioc)
3134{
3135        ablk->ioc = ioc;
3136
3137        bfa_ioc_mbox_regisr(ablk->ioc, BFI_MC_ABLK, bfa_ablk_isr, ablk);
3138        bfa_q_qe_init(&ablk->ioc_notify);
3139        bfa_ioc_notify_init(&ablk->ioc_notify, bfa_ablk_notify, ablk);
3140        list_add_tail(&ablk->ioc_notify.qe, &ablk->ioc->notify_q);
3141}
3142
3143bfa_status_t
3144bfa_ablk_query(struct bfa_ablk_s *ablk, struct bfa_ablk_cfg_s *ablk_cfg,
3145                bfa_ablk_cbfn_t cbfn, void *cbarg)
3146{
3147        struct bfi_ablk_h2i_query_s *m;
3148
3149        WARN_ON(!ablk_cfg);
3150
3151        if (!bfa_ioc_is_operational(ablk->ioc)) {
3152                bfa_trc(ablk->ioc, BFA_STATUS_IOC_FAILURE);
3153                return BFA_STATUS_IOC_FAILURE;
3154        }
3155
3156        if (ablk->busy) {
3157                bfa_trc(ablk->ioc, BFA_STATUS_DEVBUSY);
3158                return  BFA_STATUS_DEVBUSY;
3159        }
3160
3161        ablk->cfg = ablk_cfg;
3162        ablk->cbfn  = cbfn;
3163        ablk->cbarg = cbarg;
3164        ablk->busy  = BFA_TRUE;
3165
3166        m = (struct bfi_ablk_h2i_query_s *)ablk->mb.msg;
3167        bfi_h2i_set(m->mh, BFI_MC_ABLK, BFI_ABLK_H2I_QUERY,
3168                    bfa_ioc_portid(ablk->ioc));
3169        bfa_dma_be_addr_set(m->addr, ablk->dma_addr.pa);
3170        bfa_ioc_mbox_queue(ablk->ioc, &ablk->mb);
3171
3172        return BFA_STATUS_OK;
3173}
3174
3175bfa_status_t
3176bfa_ablk_pf_create(struct bfa_ablk_s *ablk, u16 *pcifn,
3177                u8 port, enum bfi_pcifn_class personality,
3178                u16 bw_min, u16 bw_max,
3179                bfa_ablk_cbfn_t cbfn, void *cbarg)
3180{
3181        struct bfi_ablk_h2i_pf_req_s *m;
3182
3183        if (!bfa_ioc_is_operational(ablk->ioc)) {
3184                bfa_trc(ablk->ioc, BFA_STATUS_IOC_FAILURE);
3185                return BFA_STATUS_IOC_FAILURE;
3186        }
3187
3188        if (ablk->busy) {
3189                bfa_trc(ablk->ioc, BFA_STATUS_DEVBUSY);
3190                return  BFA_STATUS_DEVBUSY;
3191        }
3192
3193        ablk->pcifn = pcifn;
3194        ablk->cbfn = cbfn;
3195        ablk->cbarg = cbarg;
3196        ablk->busy  = BFA_TRUE;
3197
3198        m = (struct bfi_ablk_h2i_pf_req_s *)ablk->mb.msg;
3199        bfi_h2i_set(m->mh, BFI_MC_ABLK, BFI_ABLK_H2I_PF_CREATE,
3200                    bfa_ioc_portid(ablk->ioc));
3201        m->pers = cpu_to_be16((u16)personality);
3202        m->bw_min = cpu_to_be16(bw_min);
3203        m->bw_max = cpu_to_be16(bw_max);
3204        m->port = port;
3205        bfa_ioc_mbox_queue(ablk->ioc, &ablk->mb);
3206
3207        return BFA_STATUS_OK;
3208}
3209
3210bfa_status_t
3211bfa_ablk_pf_delete(struct bfa_ablk_s *ablk, int pcifn,
3212                bfa_ablk_cbfn_t cbfn, void *cbarg)
3213{
3214        struct bfi_ablk_h2i_pf_req_s *m;
3215
3216        if (!bfa_ioc_is_operational(ablk->ioc)) {
3217                bfa_trc(ablk->ioc, BFA_STATUS_IOC_FAILURE);
3218                return BFA_STATUS_IOC_FAILURE;
3219        }
3220
3221        if (ablk->busy) {
3222                bfa_trc(ablk->ioc, BFA_STATUS_DEVBUSY);
3223                return  BFA_STATUS_DEVBUSY;
3224        }
3225
3226        ablk->cbfn  = cbfn;
3227        ablk->cbarg = cbarg;
3228        ablk->busy  = BFA_TRUE;
3229
3230        m = (struct bfi_ablk_h2i_pf_req_s *)ablk->mb.msg;
3231        bfi_h2i_set(m->mh, BFI_MC_ABLK, BFI_ABLK_H2I_PF_DELETE,
3232                    bfa_ioc_portid(ablk->ioc));
3233        m->pcifn = (u8)pcifn;
3234        bfa_ioc_mbox_queue(ablk->ioc, &ablk->mb);
3235
3236        return BFA_STATUS_OK;
3237}
3238
3239bfa_status_t
3240bfa_ablk_adapter_config(struct bfa_ablk_s *ablk, enum bfa_mode_s mode,
3241                int max_pf, int max_vf, bfa_ablk_cbfn_t cbfn, void *cbarg)
3242{
3243        struct bfi_ablk_h2i_cfg_req_s *m;
3244
3245        if (!bfa_ioc_is_operational(ablk->ioc)) {
3246                bfa_trc(ablk->ioc, BFA_STATUS_IOC_FAILURE);
3247                return BFA_STATUS_IOC_FAILURE;
3248        }
3249
3250        if (ablk->busy) {
3251                bfa_trc(ablk->ioc, BFA_STATUS_DEVBUSY);
3252                return  BFA_STATUS_DEVBUSY;
3253        }
3254
3255        ablk->cbfn  = cbfn;
3256        ablk->cbarg = cbarg;
3257        ablk->busy  = BFA_TRUE;
3258
3259        m = (struct bfi_ablk_h2i_cfg_req_s *)ablk->mb.msg;
3260        bfi_h2i_set(m->mh, BFI_MC_ABLK, BFI_ABLK_H2I_ADPT_CONFIG,
3261                    bfa_ioc_portid(ablk->ioc));
3262        m->mode = (u8)mode;
3263        m->max_pf = (u8)max_pf;
3264        m->max_vf = (u8)max_vf;
3265        bfa_ioc_mbox_queue(ablk->ioc, &ablk->mb);
3266
3267        return BFA_STATUS_OK;
3268}
3269
3270bfa_status_t
3271bfa_ablk_port_config(struct bfa_ablk_s *ablk, int port, enum bfa_mode_s mode,
3272                int max_pf, int max_vf, bfa_ablk_cbfn_t cbfn, void *cbarg)
3273{
3274        struct bfi_ablk_h2i_cfg_req_s *m;
3275
3276        if (!bfa_ioc_is_operational(ablk->ioc)) {
3277                bfa_trc(ablk->ioc, BFA_STATUS_IOC_FAILURE);
3278                return BFA_STATUS_IOC_FAILURE;
3279        }
3280
3281        if (ablk->busy) {
3282                bfa_trc(ablk->ioc, BFA_STATUS_DEVBUSY);
3283                return  BFA_STATUS_DEVBUSY;
3284        }
3285
3286        ablk->cbfn  = cbfn;
3287        ablk->cbarg = cbarg;
3288        ablk->busy  = BFA_TRUE;
3289
3290        m = (struct bfi_ablk_h2i_cfg_req_s *)ablk->mb.msg;
3291        bfi_h2i_set(m->mh, BFI_MC_ABLK, BFI_ABLK_H2I_PORT_CONFIG,
3292                bfa_ioc_portid(ablk->ioc));
3293        m->port = (u8)port;
3294        m->mode = (u8)mode;
3295        m->max_pf = (u8)max_pf;
3296        m->max_vf = (u8)max_vf;
3297        bfa_ioc_mbox_queue(ablk->ioc, &ablk->mb);
3298
3299        return BFA_STATUS_OK;
3300}
3301
3302bfa_status_t
3303bfa_ablk_pf_update(struct bfa_ablk_s *ablk, int pcifn, u16 bw_min,
3304                   u16 bw_max, bfa_ablk_cbfn_t cbfn, void *cbarg)
3305{
3306        struct bfi_ablk_h2i_pf_req_s *m;
3307
3308        if (!bfa_ioc_is_operational(ablk->ioc)) {
3309                bfa_trc(ablk->ioc, BFA_STATUS_IOC_FAILURE);
3310                return BFA_STATUS_IOC_FAILURE;
3311        }
3312
3313        if (ablk->busy) {
3314                bfa_trc(ablk->ioc, BFA_STATUS_DEVBUSY);
3315                return  BFA_STATUS_DEVBUSY;
3316        }
3317
3318        ablk->cbfn  = cbfn;
3319        ablk->cbarg = cbarg;
3320        ablk->busy  = BFA_TRUE;
3321
3322        m = (struct bfi_ablk_h2i_pf_req_s *)ablk->mb.msg;
3323        bfi_h2i_set(m->mh, BFI_MC_ABLK, BFI_ABLK_H2I_PF_UPDATE,
3324                bfa_ioc_portid(ablk->ioc));
3325        m->pcifn = (u8)pcifn;
3326        m->bw_min = cpu_to_be16(bw_min);
3327        m->bw_max = cpu_to_be16(bw_max);
3328        bfa_ioc_mbox_queue(ablk->ioc, &ablk->mb);
3329
3330        return BFA_STATUS_OK;
3331}
3332
3333bfa_status_t
3334bfa_ablk_optrom_en(struct bfa_ablk_s *ablk, bfa_ablk_cbfn_t cbfn, void *cbarg)
3335{
3336        struct bfi_ablk_h2i_optrom_s *m;
3337
3338        if (!bfa_ioc_is_operational(ablk->ioc)) {
3339                bfa_trc(ablk->ioc, BFA_STATUS_IOC_FAILURE);
3340                return BFA_STATUS_IOC_FAILURE;
3341        }
3342
3343        if (ablk->busy) {
3344                bfa_trc(ablk->ioc, BFA_STATUS_DEVBUSY);
3345                return  BFA_STATUS_DEVBUSY;
3346        }
3347
3348        ablk->cbfn  = cbfn;
3349        ablk->cbarg = cbarg;
3350        ablk->busy  = BFA_TRUE;
3351
3352        m = (struct bfi_ablk_h2i_optrom_s *)ablk->mb.msg;
3353        bfi_h2i_set(m->mh, BFI_MC_ABLK, BFI_ABLK_H2I_OPTROM_ENABLE,
3354                bfa_ioc_portid(ablk->ioc));
3355        bfa_ioc_mbox_queue(ablk->ioc, &ablk->mb);
3356
3357        return BFA_STATUS_OK;
3358}
3359
3360bfa_status_t
3361bfa_ablk_optrom_dis(struct bfa_ablk_s *ablk, bfa_ablk_cbfn_t cbfn, void *cbarg)
3362{
3363        struct bfi_ablk_h2i_optrom_s *m;
3364
3365        if (!bfa_ioc_is_operational(ablk->ioc)) {
3366                bfa_trc(ablk->ioc, BFA_STATUS_IOC_FAILURE);
3367                return BFA_STATUS_IOC_FAILURE;
3368        }
3369
3370        if (ablk->busy) {
3371                bfa_trc(ablk->ioc, BFA_STATUS_DEVBUSY);
3372                return  BFA_STATUS_DEVBUSY;
3373        }
3374
3375        ablk->cbfn  = cbfn;
3376        ablk->cbarg = cbarg;
3377        ablk->busy  = BFA_TRUE;
3378
3379        m = (struct bfi_ablk_h2i_optrom_s *)ablk->mb.msg;
3380        bfi_h2i_set(m->mh, BFI_MC_ABLK, BFI_ABLK_H2I_OPTROM_DISABLE,
3381                bfa_ioc_portid(ablk->ioc));
3382        bfa_ioc_mbox_queue(ablk->ioc, &ablk->mb);
3383
3384        return BFA_STATUS_OK;
3385}
3386
3387/*
3388 *      SFP module specific
3389 */
3390
3391/* forward declarations */
3392static void bfa_sfp_getdata_send(struct bfa_sfp_s *sfp);
3393static void bfa_sfp_media_get(struct bfa_sfp_s *sfp);
3394static bfa_status_t bfa_sfp_speed_valid(struct bfa_sfp_s *sfp,
3395                                enum bfa_port_speed portspeed);
3396
3397static void
3398bfa_cb_sfp_show(struct bfa_sfp_s *sfp)
3399{
3400        bfa_trc(sfp, sfp->lock);
3401        if (sfp->cbfn)
3402                sfp->cbfn(sfp->cbarg, sfp->status);
3403        sfp->lock = 0;
3404        sfp->cbfn = NULL;
3405}
3406
3407static void
3408bfa_cb_sfp_state_query(struct bfa_sfp_s *sfp)
3409{
3410        bfa_trc(sfp, sfp->portspeed);
3411        if (sfp->media) {
3412                bfa_sfp_media_get(sfp);
3413                if (sfp->state_query_cbfn)
3414                        sfp->state_query_cbfn(sfp->state_query_cbarg,
3415                                        sfp->status);
3416                        sfp->media = NULL;
3417                }
3418
3419                if (sfp->portspeed) {
3420                        sfp->status = bfa_sfp_speed_valid(sfp, sfp->portspeed);
3421                        if (sfp->state_query_cbfn)
3422                                sfp->state_query_cbfn(sfp->state_query_cbarg,
3423                                                sfp->status);
3424                                sfp->portspeed = BFA_PORT_SPEED_UNKNOWN;
3425                }
3426
3427                sfp->state_query_lock = 0;
3428                sfp->state_query_cbfn = NULL;
3429}
3430
3431/*
3432 *      IOC event handler.
3433 */
3434static void
3435bfa_sfp_notify(void *sfp_arg, enum bfa_ioc_event_e event)
3436{
3437        struct bfa_sfp_s *sfp = sfp_arg;
3438
3439        bfa_trc(sfp, event);
3440        bfa_trc(sfp, sfp->lock);
3441        bfa_trc(sfp, sfp->state_query_lock);
3442
3443        switch (event) {
3444        case BFA_IOC_E_DISABLED:
3445        case BFA_IOC_E_FAILED:
3446                if (sfp->lock) {
3447                        sfp->status = BFA_STATUS_IOC_FAILURE;
3448                        bfa_cb_sfp_show(sfp);
3449                }
3450
3451                if (sfp->state_query_lock) {
3452                        sfp->status = BFA_STATUS_IOC_FAILURE;
3453                        bfa_cb_sfp_state_query(sfp);
3454                }
3455                break;
3456
3457        default:
3458                break;
3459        }
3460}
3461
3462/*
3463 * SFP's State Change Notification post to AEN
3464 */
3465static void
3466bfa_sfp_scn_aen_post(struct bfa_sfp_s *sfp, struct bfi_sfp_scn_s *rsp)
3467{
3468        struct bfad_s *bfad = (struct bfad_s *)sfp->ioc->bfa->bfad;
3469        struct bfa_aen_entry_s  *aen_entry;
3470        enum bfa_port_aen_event aen_evt = 0;
3471
3472        bfa_trc(sfp, (((u64)rsp->pomlvl) << 16) | (((u64)rsp->sfpid) << 8) |
3473                      ((u64)rsp->event));
3474
3475        bfad_get_aen_entry(bfad, aen_entry);
3476        if (!aen_entry)
3477                return;
3478
3479        aen_entry->aen_data.port.ioc_type = bfa_ioc_get_type(sfp->ioc);
3480        aen_entry->aen_data.port.pwwn = sfp->ioc->attr->pwwn;
3481        aen_entry->aen_data.port.mac = bfa_ioc_get_mac(sfp->ioc);
3482
3483        switch (rsp->event) {
3484        case BFA_SFP_SCN_INSERTED:
3485                aen_evt = BFA_PORT_AEN_SFP_INSERT;
3486                break;
3487        case BFA_SFP_SCN_REMOVED:
3488                aen_evt = BFA_PORT_AEN_SFP_REMOVE;
3489                break;
3490        case BFA_SFP_SCN_FAILED:
3491                aen_evt = BFA_PORT_AEN_SFP_ACCESS_ERROR;
3492                break;
3493        case BFA_SFP_SCN_UNSUPPORT:
3494                aen_evt = BFA_PORT_AEN_SFP_UNSUPPORT;
3495                break;
3496        case BFA_SFP_SCN_POM:
3497                aen_evt = BFA_PORT_AEN_SFP_POM;
3498                aen_entry->aen_data.port.level = rsp->pomlvl;
3499                break;
3500        default:
3501                bfa_trc(sfp, rsp->event);
3502                WARN_ON(1);
3503        }
3504
3505        /* Send the AEN notification */
3506        bfad_im_post_vendor_event(aen_entry, bfad, ++sfp->ioc->ioc_aen_seq,
3507                                  BFA_AEN_CAT_PORT, aen_evt);
3508}
3509
3510/*
3511 *      SFP get data send
3512 */
3513static void
3514bfa_sfp_getdata_send(struct bfa_sfp_s *sfp)
3515{
3516        struct bfi_sfp_req_s *req = (struct bfi_sfp_req_s *)sfp->mbcmd.msg;
3517
3518        bfa_trc(sfp, req->memtype);
3519
3520        /* build host command */
3521        bfi_h2i_set(req->mh, BFI_MC_SFP, BFI_SFP_H2I_SHOW,
3522                        bfa_ioc_portid(sfp->ioc));
3523
3524        /* send mbox cmd */
3525        bfa_ioc_mbox_queue(sfp->ioc, &sfp->mbcmd);
3526}
3527
3528/*
3529 *      SFP is valid, read sfp data
3530 */
3531static void
3532bfa_sfp_getdata(struct bfa_sfp_s *sfp, enum bfi_sfp_mem_e memtype)
3533{
3534        struct bfi_sfp_req_s *req = (struct bfi_sfp_req_s *)sfp->mbcmd.msg;
3535
3536        WARN_ON(sfp->lock != 0);
3537        bfa_trc(sfp, sfp->state);
3538
3539        sfp->lock = 1;
3540        sfp->memtype = memtype;
3541        req->memtype = memtype;
3542
3543        /* Setup SG list */
3544        bfa_alen_set(&req->alen, sizeof(struct sfp_mem_s), sfp->dbuf_pa);
3545
3546        bfa_sfp_getdata_send(sfp);
3547}
3548
3549/*
3550 *      SFP scn handler
3551 */
3552static void
3553bfa_sfp_scn(struct bfa_sfp_s *sfp, struct bfi_mbmsg_s *msg)
3554{
3555        struct bfi_sfp_scn_s *rsp = (struct bfi_sfp_scn_s *) msg;
3556
3557        switch (rsp->event) {
3558        case BFA_SFP_SCN_INSERTED:
3559                sfp->state = BFA_SFP_STATE_INSERTED;
3560                sfp->data_valid = 0;
3561                bfa_sfp_scn_aen_post(sfp, rsp);
3562                break;
3563        case BFA_SFP_SCN_REMOVED:
3564                sfp->state = BFA_SFP_STATE_REMOVED;
3565                sfp->data_valid = 0;
3566                bfa_sfp_scn_aen_post(sfp, rsp);
3567                 break;
3568        case BFA_SFP_SCN_FAILED:
3569                sfp->state = BFA_SFP_STATE_FAILED;
3570                sfp->data_valid = 0;
3571                bfa_sfp_scn_aen_post(sfp, rsp);
3572                break;
3573        case BFA_SFP_SCN_UNSUPPORT:
3574                sfp->state = BFA_SFP_STATE_UNSUPPORT;
3575                bfa_sfp_scn_aen_post(sfp, rsp);
3576                if (!sfp->lock)
3577                        bfa_sfp_getdata(sfp, BFI_SFP_MEM_ALL);
3578                break;
3579        case BFA_SFP_SCN_POM:
3580                bfa_sfp_scn_aen_post(sfp, rsp);
3581                break;
3582        case BFA_SFP_SCN_VALID:
3583                sfp->state = BFA_SFP_STATE_VALID;
3584                if (!sfp->lock)
3585                        bfa_sfp_getdata(sfp, BFI_SFP_MEM_ALL);
3586                break;
3587        default:
3588                bfa_trc(sfp, rsp->event);
3589                WARN_ON(1);
3590        }
3591}
3592
3593/*
3594 * SFP show complete
3595 */
3596static void
3597bfa_sfp_show_comp(struct bfa_sfp_s *sfp, struct bfi_mbmsg_s *msg)
3598{
3599        struct bfi_sfp_rsp_s *rsp = (struct bfi_sfp_rsp_s *) msg;
3600
3601        if (!sfp->lock) {
3602                /*
3603                 * receiving response after ioc failure
3604                 */
3605                bfa_trc(sfp, sfp->lock);
3606                return;
3607        }
3608
3609        bfa_trc(sfp, rsp->status);
3610        if (rsp->status == BFA_STATUS_OK) {
3611                sfp->data_valid = 1;
3612                if (sfp->state == BFA_SFP_STATE_VALID)
3613                        sfp->status = BFA_STATUS_OK;
3614                else if (sfp->state == BFA_SFP_STATE_UNSUPPORT)
3615                        sfp->status = BFA_STATUS_SFP_UNSUPP;
3616                else
3617                        bfa_trc(sfp, sfp->state);
3618        } else {
3619                sfp->data_valid = 0;
3620                sfp->status = rsp->status;
3621                /* sfpshow shouldn't change sfp state */
3622        }
3623
3624        bfa_trc(sfp, sfp->memtype);
3625        if (sfp->memtype == BFI_SFP_MEM_DIAGEXT) {
3626                bfa_trc(sfp, sfp->data_valid);
3627                if (sfp->data_valid) {
3628                        u32     size = sizeof(struct sfp_mem_s);
3629                        u8 *des = (u8 *) &(sfp->sfpmem->srlid_base);
3630                        memcpy(des, sfp->dbuf_kva, size);
3631                }
3632                /*
3633                 * Queue completion callback.
3634                 */
3635                bfa_cb_sfp_show(sfp);
3636        } else
3637                sfp->lock = 0;
3638
3639        bfa_trc(sfp, sfp->state_query_lock);
3640        if (sfp->state_query_lock) {
3641                sfp->state = rsp->state;
3642                /* Complete callback */
3643                bfa_cb_sfp_state_query(sfp);
3644        }
3645}
3646
3647/*
3648 *      SFP query fw sfp state
3649 */
3650static void
3651bfa_sfp_state_query(struct bfa_sfp_s *sfp)
3652{
3653        struct bfi_sfp_req_s *req = (struct bfi_sfp_req_s *)sfp->mbcmd.msg;
3654
3655        /* Should not be doing query if not in _INIT state */
3656        WARN_ON(sfp->state != BFA_SFP_STATE_INIT);
3657        WARN_ON(sfp->state_query_lock != 0);
3658        bfa_trc(sfp, sfp->state);
3659
3660        sfp->state_query_lock = 1;
3661        req->memtype = 0;
3662
3663        if (!sfp->lock)
3664                bfa_sfp_getdata(sfp, BFI_SFP_MEM_ALL);
3665}
3666
3667static void
3668bfa_sfp_media_get(struct bfa_sfp_s *sfp)
3669{
3670        enum bfa_defs_sfp_media_e *media = sfp->media;
3671
3672        *media = BFA_SFP_MEDIA_UNKNOWN;
3673
3674        if (sfp->state == BFA_SFP_STATE_UNSUPPORT)
3675                *media = BFA_SFP_MEDIA_UNSUPPORT;
3676        else if (sfp->state == BFA_SFP_STATE_VALID) {
3677                union sfp_xcvr_e10g_code_u e10g;
3678                struct sfp_mem_s *sfpmem = (struct sfp_mem_s *)sfp->dbuf_kva;
3679                u16 xmtr_tech = (sfpmem->srlid_base.xcvr[4] & 0x3) << 7 |
3680                                (sfpmem->srlid_base.xcvr[5] >> 1);
3681
3682                e10g.b = sfpmem->srlid_base.xcvr[0];
3683                bfa_trc(sfp, e10g.b);
3684                bfa_trc(sfp, xmtr_tech);
3685                /* check fc transmitter tech */
3686                if ((xmtr_tech & SFP_XMTR_TECH_CU) ||
3687                    (xmtr_tech & SFP_XMTR_TECH_CP) ||
3688                    (xmtr_tech & SFP_XMTR_TECH_CA))
3689                        *media = BFA_SFP_MEDIA_CU;
3690                else if ((xmtr_tech & SFP_XMTR_TECH_EL_INTRA) ||
3691                         (xmtr_tech & SFP_XMTR_TECH_EL_INTER))
3692                        *media = BFA_SFP_MEDIA_EL;
3693                else if ((xmtr_tech & SFP_XMTR_TECH_LL) ||
3694                         (xmtr_tech & SFP_XMTR_TECH_LC))
3695                        *media = BFA_SFP_MEDIA_LW;
3696                else if ((xmtr_tech & SFP_XMTR_TECH_SL) ||
3697                         (xmtr_tech & SFP_XMTR_TECH_SN) ||
3698                         (xmtr_tech & SFP_XMTR_TECH_SA))
3699                        *media = BFA_SFP_MEDIA_SW;
3700                /* Check 10G Ethernet Compilance code */
3701                else if (e10g.r.e10g_sr)
3702                        *media = BFA_SFP_MEDIA_SW;
3703                else if (e10g.r.e10g_lrm && e10g.r.e10g_lr)
3704                        *media = BFA_SFP_MEDIA_LW;
3705                else if (e10g.r.e10g_unall)
3706                        *media = BFA_SFP_MEDIA_UNKNOWN;
3707                else
3708                        bfa_trc(sfp, 0);
3709        } else
3710                bfa_trc(sfp, sfp->state);
3711}
3712
3713static bfa_status_t
3714bfa_sfp_speed_valid(struct bfa_sfp_s *sfp, enum bfa_port_speed portspeed)
3715{
3716        struct sfp_mem_s *sfpmem = (struct sfp_mem_s *)sfp->dbuf_kva;
3717        struct sfp_xcvr_s *xcvr = (struct sfp_xcvr_s *) sfpmem->srlid_base.xcvr;
3718        union sfp_xcvr_fc3_code_u fc3 = xcvr->fc3;
3719        union sfp_xcvr_e10g_code_u e10g = xcvr->e10g;
3720
3721        if (portspeed == BFA_PORT_SPEED_10GBPS) {
3722                if (e10g.r.e10g_sr || e10g.r.e10g_lr)
3723                        return BFA_STATUS_OK;
3724                else {
3725                        bfa_trc(sfp, e10g.b);
3726                        return BFA_STATUS_UNSUPP_SPEED;
3727                }
3728        }
3729        if (((portspeed & BFA_PORT_SPEED_16GBPS) && fc3.r.mb1600) ||
3730            ((portspeed & BFA_PORT_SPEED_8GBPS) && fc3.r.mb800) ||
3731            ((portspeed & BFA_PORT_SPEED_4GBPS) && fc3.r.mb400) ||
3732            ((portspeed & BFA_PORT_SPEED_2GBPS) && fc3.r.mb200) ||
3733            ((portspeed & BFA_PORT_SPEED_1GBPS) && fc3.r.mb100))
3734                return BFA_STATUS_OK;
3735        else {
3736                bfa_trc(sfp, portspeed);
3737                bfa_trc(sfp, fc3.b);
3738                bfa_trc(sfp, e10g.b);
3739                return BFA_STATUS_UNSUPP_SPEED;
3740        }
3741}
3742
3743/*
3744 *      SFP hmbox handler
3745 */
3746void
3747bfa_sfp_intr(void *sfparg, struct bfi_mbmsg_s *msg)
3748{
3749        struct bfa_sfp_s *sfp = sfparg;
3750
3751        switch (msg->mh.msg_id) {
3752        case BFI_SFP_I2H_SHOW:
3753                bfa_sfp_show_comp(sfp, msg);
3754                break;
3755
3756        case BFI_SFP_I2H_SCN:
3757                bfa_sfp_scn(sfp, msg);
3758                break;
3759
3760        default:
3761                bfa_trc(sfp, msg->mh.msg_id);
3762                WARN_ON(1);
3763        }
3764}
3765
3766/*
3767 *      Return DMA memory needed by sfp module.
3768 */
3769u32
3770bfa_sfp_meminfo(void)
3771{
3772        return BFA_ROUNDUP(sizeof(struct sfp_mem_s), BFA_DMA_ALIGN_SZ);
3773}
3774
3775/*
3776 *      Attach virtual and physical memory for SFP.
3777 */
3778void
3779bfa_sfp_attach(struct bfa_sfp_s *sfp, struct bfa_ioc_s *ioc, void *dev,
3780                struct bfa_trc_mod_s *trcmod)
3781{
3782        sfp->dev = dev;
3783        sfp->ioc = ioc;
3784        sfp->trcmod = trcmod;
3785
3786        sfp->cbfn = NULL;
3787        sfp->cbarg = NULL;
3788        sfp->sfpmem = NULL;
3789        sfp->lock = 0;
3790        sfp->data_valid = 0;
3791        sfp->state = BFA_SFP_STATE_INIT;
3792        sfp->state_query_lock = 0;
3793        sfp->state_query_cbfn = NULL;
3794        sfp->state_query_cbarg = NULL;
3795        sfp->media = NULL;
3796        sfp->portspeed = BFA_PORT_SPEED_UNKNOWN;
3797        sfp->is_elb = BFA_FALSE;
3798
3799        bfa_ioc_mbox_regisr(sfp->ioc, BFI_MC_SFP, bfa_sfp_intr, sfp);
3800        bfa_q_qe_init(&sfp->ioc_notify);
3801        bfa_ioc_notify_init(&sfp->ioc_notify, bfa_sfp_notify, sfp);
3802        list_add_tail(&sfp->ioc_notify.qe, &sfp->ioc->notify_q);
3803}
3804
3805/*
3806 *      Claim Memory for SFP
3807 */
3808void
3809bfa_sfp_memclaim(struct bfa_sfp_s *sfp, u8 *dm_kva, u64 dm_pa)
3810{
3811        sfp->dbuf_kva   = dm_kva;
3812        sfp->dbuf_pa    = dm_pa;
3813        memset(sfp->dbuf_kva, 0, sizeof(struct sfp_mem_s));
3814
3815        dm_kva += BFA_ROUNDUP(sizeof(struct sfp_mem_s), BFA_DMA_ALIGN_SZ);
3816        dm_pa += BFA_ROUNDUP(sizeof(struct sfp_mem_s), BFA_DMA_ALIGN_SZ);
3817}
3818
3819/*
3820 * Show SFP eeprom content
3821 *
3822 * @param[in] sfp   - bfa sfp module
3823 *
3824 * @param[out] sfpmem - sfp eeprom data
3825 *
3826 */
3827bfa_status_t
3828bfa_sfp_show(struct bfa_sfp_s *sfp, struct sfp_mem_s *sfpmem,
3829                bfa_cb_sfp_t cbfn, void *cbarg)
3830{
3831
3832        if (!bfa_ioc_is_operational(sfp->ioc)) {
3833                bfa_trc(sfp, 0);
3834                return BFA_STATUS_IOC_NON_OP;
3835        }
3836
3837        if (sfp->lock) {
3838                bfa_trc(sfp, 0);
3839                return BFA_STATUS_DEVBUSY;
3840        }
3841
3842        sfp->cbfn = cbfn;
3843        sfp->cbarg = cbarg;
3844        sfp->sfpmem = sfpmem;
3845
3846        bfa_sfp_getdata(sfp, BFI_SFP_MEM_DIAGEXT);
3847        return BFA_STATUS_OK;
3848}
3849
3850/*
3851 * Return SFP Media type
3852 *
3853 * @param[in] sfp   - bfa sfp module
3854 *
3855 * @param[out] media - port speed from user
3856 *
3857 */
3858bfa_status_t
3859bfa_sfp_media(struct bfa_sfp_s *sfp, enum bfa_defs_sfp_media_e *media,
3860                bfa_cb_sfp_t cbfn, void *cbarg)
3861{
3862        if (!bfa_ioc_is_operational(sfp->ioc)) {
3863                bfa_trc(sfp, 0);
3864                return BFA_STATUS_IOC_NON_OP;
3865        }
3866
3867        sfp->media = media;
3868        if (sfp->state == BFA_SFP_STATE_INIT) {
3869                if (sfp->state_query_lock) {
3870                        bfa_trc(sfp, 0);
3871                        return BFA_STATUS_DEVBUSY;
3872                } else {
3873                        sfp->state_query_cbfn = cbfn;
3874                        sfp->state_query_cbarg = cbarg;
3875                        bfa_sfp_state_query(sfp);
3876                        return BFA_STATUS_SFP_NOT_READY;
3877                }
3878        }
3879
3880        bfa_sfp_media_get(sfp);
3881        return BFA_STATUS_OK;
3882}
3883
3884/*
3885 * Check if user set port speed is allowed by the SFP
3886 *
3887 * @param[in] sfp   - bfa sfp module
3888 * @param[in] portspeed - port speed from user
3889 *
3890 */
3891bfa_status_t
3892bfa_sfp_speed(struct bfa_sfp_s *sfp, enum bfa_port_speed portspeed,
3893                bfa_cb_sfp_t cbfn, void *cbarg)
3894{
3895        WARN_ON(portspeed == BFA_PORT_SPEED_UNKNOWN);
3896
3897        if (!bfa_ioc_is_operational(sfp->ioc))
3898                return BFA_STATUS_IOC_NON_OP;
3899
3900        /* For Mezz card, all speed is allowed */
3901        if (bfa_mfg_is_mezz(sfp->ioc->attr->card_type))
3902                return BFA_STATUS_OK;
3903
3904        /* Check SFP state */
3905        sfp->portspeed = portspeed;
3906        if (sfp->state == BFA_SFP_STATE_INIT) {
3907                if (sfp->state_query_lock) {
3908                        bfa_trc(sfp, 0);
3909                        return BFA_STATUS_DEVBUSY;
3910                } else {
3911                        sfp->state_query_cbfn = cbfn;
3912                        sfp->state_query_cbarg = cbarg;
3913                        bfa_sfp_state_query(sfp);
3914                        return BFA_STATUS_SFP_NOT_READY;
3915                }
3916        }
3917
3918        if (sfp->state == BFA_SFP_STATE_REMOVED ||
3919            sfp->state == BFA_SFP_STATE_FAILED) {
3920                bfa_trc(sfp, sfp->state);
3921                return BFA_STATUS_NO_SFP_DEV;
3922        }
3923
3924        if (sfp->state == BFA_SFP_STATE_INSERTED) {
3925                bfa_trc(sfp, sfp->state);
3926                return BFA_STATUS_DEVBUSY;  /* sfp is reading data */
3927        }
3928
3929        /* For eloopback, all speed is allowed */
3930        if (sfp->is_elb)
3931                return BFA_STATUS_OK;
3932
3933        return bfa_sfp_speed_valid(sfp, portspeed);
3934}
3935
3936/*
3937 *      Flash module specific
3938 */
3939
3940/*
3941 * FLASH DMA buffer should be big enough to hold both MFG block and
3942 * asic block(64k) at the same time and also should be 2k aligned to
3943 * avoid write segement to cross sector boundary.
3944 */
3945#define BFA_FLASH_SEG_SZ        2048
3946#define BFA_FLASH_DMA_BUF_SZ    \
3947        BFA_ROUNDUP(0x010000 + sizeof(struct bfa_mfg_block_s), BFA_FLASH_SEG_SZ)
3948
3949static void
3950bfa_flash_aen_audit_post(struct bfa_ioc_s *ioc, enum bfa_audit_aen_event event,
3951                        int inst, int type)
3952{
3953        struct bfad_s *bfad = (struct bfad_s *)ioc->bfa->bfad;
3954        struct bfa_aen_entry_s  *aen_entry;
3955
3956        bfad_get_aen_entry(bfad, aen_entry);
3957        if (!aen_entry)
3958                return;
3959
3960        aen_entry->aen_data.audit.pwwn = ioc->attr->pwwn;
3961        aen_entry->aen_data.audit.partition_inst = inst;
3962        aen_entry->aen_data.audit.partition_type = type;
3963
3964        /* Send the AEN notification */
3965        bfad_im_post_vendor_event(aen_entry, bfad, ++ioc->ioc_aen_seq,
3966                                  BFA_AEN_CAT_AUDIT, event);
3967}
3968
3969static void
3970bfa_flash_cb(struct bfa_flash_s *flash)
3971{
3972        flash->op_busy = 0;
3973        if (flash->cbfn)
3974                flash->cbfn(flash->cbarg, flash->status);
3975}
3976
3977static void
3978bfa_flash_notify(void *cbarg, enum bfa_ioc_event_e event)
3979{
3980        struct bfa_flash_s      *flash = cbarg;
3981
3982        bfa_trc(flash, event);
3983        switch (event) {
3984        case BFA_IOC_E_DISABLED:
3985        case BFA_IOC_E_FAILED:
3986                if (flash->op_busy) {
3987                        flash->status = BFA_STATUS_IOC_FAILURE;
3988                        flash->cbfn(flash->cbarg, flash->status);
3989                        flash->op_busy = 0;
3990                }
3991                break;
3992
3993        default:
3994                break;
3995        }
3996}
3997
3998/*
3999 * Send flash attribute query request.
4000 *
4001 * @param[in] cbarg - callback argument
4002 */
4003static void
4004bfa_flash_query_send(void *cbarg)
4005{
4006        struct bfa_flash_s *flash = cbarg;
4007        struct bfi_flash_query_req_s *msg =
4008                        (struct bfi_flash_query_req_s *) flash->mb.msg;
4009
4010        bfi_h2i_set(msg->mh, BFI_MC_FLASH, BFI_FLASH_H2I_QUERY_REQ,
4011                bfa_ioc_portid(flash->ioc));
4012        bfa_alen_set(&msg->alen, sizeof(struct bfa_flash_attr_s),
4013                flash->dbuf_pa);
4014        bfa_ioc_mbox_queue(flash->ioc, &flash->mb);
4015}
4016
4017/*
4018 * Send flash write request.
4019 *
4020 * @param[in] cbarg - callback argument
4021 */
4022static void
4023bfa_flash_write_send(struct bfa_flash_s *flash)
4024{
4025        struct bfi_flash_write_req_s *msg =
4026                        (struct bfi_flash_write_req_s *) flash->mb.msg;
4027        u32     len;
4028
4029        msg->type = be32_to_cpu(flash->type);
4030        msg->instance = flash->instance;
4031        msg->offset = be32_to_cpu(flash->addr_off + flash->offset);
4032        len = (flash->residue < BFA_FLASH_DMA_BUF_SZ) ?
4033                flash->residue : BFA_FLASH_DMA_BUF_SZ;
4034        msg->length = be32_to_cpu(len);
4035
4036        /* indicate if it's the last msg of the whole write operation */
4037        msg->last = (len == flash->residue) ? 1 : 0;
4038
4039        bfi_h2i_set(msg->mh, BFI_MC_FLASH, BFI_FLASH_H2I_WRITE_REQ,
4040                        bfa_ioc_portid(flash->ioc));
4041        bfa_alen_set(&msg->alen, len, flash->dbuf_pa);
4042        memcpy(flash->dbuf_kva, flash->ubuf + flash->offset, len);
4043        bfa_ioc_mbox_queue(flash->ioc, &flash->mb);
4044
4045        flash->residue -= len;
4046        flash->offset += len;
4047}
4048
4049/*
4050 * Send flash read request.
4051 *
4052 * @param[in] cbarg - callback argument
4053 */
4054static void
4055bfa_flash_read_send(void *cbarg)
4056{
4057        struct bfa_flash_s *flash = cbarg;
4058        struct bfi_flash_read_req_s *msg =
4059                        (struct bfi_flash_read_req_s *) flash->mb.msg;
4060        u32     len;
4061
4062        msg->type = be32_to_cpu(flash->type);
4063        msg->instance = flash->instance;
4064        msg->offset = be32_to_cpu(flash->addr_off + flash->offset);
4065        len = (flash->residue < BFA_FLASH_DMA_BUF_SZ) ?
4066                        flash->residue : BFA_FLASH_DMA_BUF_SZ;
4067        msg->length = be32_to_cpu(len);
4068        bfi_h2i_set(msg->mh, BFI_MC_FLASH, BFI_FLASH_H2I_READ_REQ,
4069                bfa_ioc_portid(flash->ioc));
4070        bfa_alen_set(&msg->alen, len, flash->dbuf_pa);
4071        bfa_ioc_mbox_queue(flash->ioc, &flash->mb);
4072}
4073
4074/*
4075 * Send flash erase request.
4076 *
4077 * @param[in] cbarg - callback argument
4078 */
4079static void
4080bfa_flash_erase_send(void *cbarg)
4081{
4082        struct bfa_flash_s *flash = cbarg;
4083        struct bfi_flash_erase_req_s *msg =
4084                        (struct bfi_flash_erase_req_s *) flash->mb.msg;
4085
4086        msg->type = be32_to_cpu(flash->type);
4087        msg->instance = flash->instance;
4088        bfi_h2i_set(msg->mh, BFI_MC_FLASH, BFI_FLASH_H2I_ERASE_REQ,
4089                        bfa_ioc_portid(flash->ioc));
4090        bfa_ioc_mbox_queue(flash->ioc, &flash->mb);
4091}
4092
4093/*
4094 * Process flash response messages upon receiving interrupts.
4095 *
4096 * @param[in] flasharg - flash structure
4097 * @param[in] msg - message structure
4098 */
4099static void
4100bfa_flash_intr(void *flasharg, struct bfi_mbmsg_s *msg)
4101{
4102        struct bfa_flash_s *flash = flasharg;
4103        u32     status;
4104
4105        union {
4106                struct bfi_flash_query_rsp_s *query;
4107                struct bfi_flash_erase_rsp_s *erase;
4108                struct bfi_flash_write_rsp_s *write;
4109                struct bfi_flash_read_rsp_s *read;
4110                struct bfi_flash_event_s *event;
4111                struct bfi_mbmsg_s   *msg;
4112        } m;
4113
4114        m.msg = msg;
4115        bfa_trc(flash, msg->mh.msg_id);
4116
4117        if (!flash->op_busy && msg->mh.msg_id != BFI_FLASH_I2H_EVENT) {
4118                /* receiving response after ioc failure */
4119                bfa_trc(flash, 0x9999);
4120                return;
4121        }
4122
4123        switch (msg->mh.msg_id) {
4124        case BFI_FLASH_I2H_QUERY_RSP:
4125                status = be32_to_cpu(m.query->status);
4126                bfa_trc(flash, status);
4127                if (status == BFA_STATUS_OK) {
4128                        u32     i;
4129                        struct bfa_flash_attr_s *attr, *f;
4130
4131                        attr = (struct bfa_flash_attr_s *) flash->ubuf;
4132                        f = (struct bfa_flash_attr_s *) flash->dbuf_kva;
4133                        attr->status = be32_to_cpu(f->status);
4134                        attr->npart = be32_to_cpu(f->npart);
4135                        bfa_trc(flash, attr->status);
4136                        bfa_trc(flash, attr->npart);
4137                        for (i = 0; i < attr->npart; i++) {
4138                                attr->part[i].part_type =
4139                                        be32_to_cpu(f->part[i].part_type);
4140                                attr->part[i].part_instance =
4141                                        be32_to_cpu(f->part[i].part_instance);
4142                                attr->part[i].part_off =
4143                                        be32_to_cpu(f->part[i].part_off);
4144                                attr->part[i].part_size =
4145                                        be32_to_cpu(f->part[i].part_size);
4146                                attr->part[i].part_len =
4147                                        be32_to_cpu(f->part[i].part_len);
4148                                attr->part[i].part_status =
4149                                        be32_to_cpu(f->part[i].part_status);
4150                        }
4151                }
4152                flash->status = status;
4153                bfa_flash_cb(flash);
4154                break;
4155        case BFI_FLASH_I2H_ERASE_RSP:
4156                status = be32_to_cpu(m.erase->status);
4157                bfa_trc(flash, status);
4158                flash->status = status;
4159                bfa_flash_cb(flash);
4160                break;
4161        case BFI_FLASH_I2H_WRITE_RSP:
4162                status = be32_to_cpu(m.write->status);
4163                bfa_trc(flash, status);
4164                if (status != BFA_STATUS_OK || flash->residue == 0) {
4165                        flash->status = status;
4166                        bfa_flash_cb(flash);
4167                } else {
4168                        bfa_trc(flash, flash->offset);
4169                        bfa_flash_write_send(flash);
4170                }
4171                break;
4172        case BFI_FLASH_I2H_READ_RSP:
4173                status = be32_to_cpu(m.read->status);
4174                bfa_trc(flash, status);
4175                if (status != BFA_STATUS_OK) {
4176                        flash->status = status;
4177                        bfa_flash_cb(flash);
4178                } else {
4179                        u32 len = be32_to_cpu(m.read->length);
4180                        bfa_trc(flash, flash->offset);
4181                        bfa_trc(flash, len);
4182                        memcpy(flash->ubuf + flash->offset,
4183                                flash->dbuf_kva, len);
4184                        flash->residue -= len;
4185                        flash->offset += len;
4186                        if (flash->residue == 0) {
4187                                flash->status = status;
4188                                bfa_flash_cb(flash);
4189                        } else
4190                                bfa_flash_read_send(flash);
4191                }
4192                break;
4193        case BFI_FLASH_I2H_BOOT_VER_RSP:
4194                break;
4195        case BFI_FLASH_I2H_EVENT:
4196                status = be32_to_cpu(m.event->status);
4197                bfa_trc(flash, status);
4198                if (status == BFA_STATUS_BAD_FWCFG)
4199                        bfa_ioc_aen_post(flash->ioc, BFA_IOC_AEN_FWCFG_ERROR);
4200                else if (status == BFA_STATUS_INVALID_VENDOR) {
4201                        u32 param;
4202                        param = be32_to_cpu(m.event->param);
4203                        bfa_trc(flash, param);
4204                        bfa_ioc_aen_post(flash->ioc,
4205                                BFA_IOC_AEN_INVALID_VENDOR);
4206                }
4207                break;
4208
4209        default:
4210                WARN_ON(1);
4211        }
4212}
4213
4214/*
4215 * Flash memory info API.
4216 *
4217 * @param[in] mincfg - minimal cfg variable
4218 */
4219u32
4220bfa_flash_meminfo(bfa_boolean_t mincfg)
4221{
4222        /* min driver doesn't need flash */
4223        if (mincfg)
4224                return 0;
4225        return BFA_ROUNDUP(BFA_FLASH_DMA_BUF_SZ, BFA_DMA_ALIGN_SZ);
4226}
4227
4228/*
4229 * Flash attach API.
4230 *
4231 * @param[in] flash - flash structure
4232 * @param[in] ioc  - ioc structure
4233 * @param[in] dev  - device structure
4234 * @param[in] trcmod - trace module
4235 * @param[in] logmod - log module
4236 */
4237void
4238bfa_flash_attach(struct bfa_flash_s *flash, struct bfa_ioc_s *ioc, void *dev,
4239                struct bfa_trc_mod_s *trcmod, bfa_boolean_t mincfg)
4240{
4241        flash->ioc = ioc;
4242        flash->trcmod = trcmod;
4243        flash->cbfn = NULL;
4244        flash->cbarg = NULL;
4245        flash->op_busy = 0;
4246
4247        bfa_ioc_mbox_regisr(flash->ioc, BFI_MC_FLASH, bfa_flash_intr, flash);
4248        bfa_q_qe_init(&flash->ioc_notify);
4249        bfa_ioc_notify_init(&flash->ioc_notify, bfa_flash_notify, flash);
4250        list_add_tail(&flash->ioc_notify.qe, &flash->ioc->notify_q);
4251
4252        /* min driver doesn't need flash */
4253        if (mincfg) {
4254                flash->dbuf_kva = NULL;
4255                flash->dbuf_pa = 0;
4256        }
4257}
4258
4259/*
4260 * Claim memory for flash
4261 *
4262 * @param[in] flash - flash structure
4263 * @param[in] dm_kva - pointer to virtual memory address
4264 * @param[in] dm_pa - physical memory address
4265 * @param[in] mincfg - minimal cfg variable
4266 */
4267void
4268bfa_flash_memclaim(struct bfa_flash_s *flash, u8 *dm_kva, u64 dm_pa,
4269                bfa_boolean_t mincfg)
4270{
4271        if (mincfg)
4272                return;
4273
4274        flash->dbuf_kva = dm_kva;
4275        flash->dbuf_pa = dm_pa;
4276        memset(flash->dbuf_kva, 0, BFA_FLASH_DMA_BUF_SZ);
4277        dm_kva += BFA_ROUNDUP(BFA_FLASH_DMA_BUF_SZ, BFA_DMA_ALIGN_SZ);
4278        dm_pa += BFA_ROUNDUP(BFA_FLASH_DMA_BUF_SZ, BFA_DMA_ALIGN_SZ);
4279}
4280
4281/*
4282 * Get flash attribute.
4283 *
4284 * @param[in] flash - flash structure
4285 * @param[in] attr - flash attribute structure
4286 * @param[in] cbfn - callback function
4287 * @param[in] cbarg - callback argument
4288 *
4289 * Return status.
4290 */
4291bfa_status_t
4292bfa_flash_get_attr(struct bfa_flash_s *flash, struct bfa_flash_attr_s *attr,
4293                bfa_cb_flash_t cbfn, void *cbarg)
4294{
4295        bfa_trc(flash, BFI_FLASH_H2I_QUERY_REQ);
4296
4297        if (!bfa_ioc_is_operational(flash->ioc))
4298                return BFA_STATUS_IOC_NON_OP;
4299
4300        if (flash->op_busy) {
4301                bfa_trc(flash, flash->op_busy);
4302                return BFA_STATUS_DEVBUSY;
4303        }
4304
4305        flash->op_busy = 1;
4306        flash->cbfn = cbfn;
4307        flash->cbarg = cbarg;
4308        flash->ubuf = (u8 *) attr;
4309        bfa_flash_query_send(flash);
4310
4311        return BFA_STATUS_OK;
4312}
4313
4314/*
4315 * Erase flash partition.
4316 *
4317 * @param[in] flash - flash structure
4318 * @param[in] type - flash partition type
4319 * @param[in] instance - flash partition instance
4320 * @param[in] cbfn - callback function
4321 * @param[in] cbarg - callback argument
4322 *
4323 * Return status.
4324 */
4325bfa_status_t
4326bfa_flash_erase_part(struct bfa_flash_s *flash, enum bfa_flash_part_type type,
4327                u8 instance, bfa_cb_flash_t cbfn, void *cbarg)
4328{
4329        bfa_trc(flash, BFI_FLASH_H2I_ERASE_REQ);
4330        bfa_trc(flash, type);
4331        bfa_trc(flash, instance);
4332
4333        if (!bfa_ioc_is_operational(flash->ioc))
4334                return BFA_STATUS_IOC_NON_OP;
4335
4336        if (flash->op_busy) {
4337                bfa_trc(flash, flash->op_busy);
4338                return BFA_STATUS_DEVBUSY;
4339        }
4340
4341        flash->op_busy = 1;
4342        flash->cbfn = cbfn;
4343        flash->cbarg = cbarg;
4344        flash->type = type;
4345        flash->instance = instance;
4346
4347        bfa_flash_erase_send(flash);
4348        bfa_flash_aen_audit_post(flash->ioc, BFA_AUDIT_AEN_FLASH_ERASE,
4349                                instance, type);
4350        return BFA_STATUS_OK;
4351}
4352
4353/*
4354 * Update flash partition.
4355 *
4356 * @param[in] flash - flash structure
4357 * @param[in] type - flash partition type
4358 * @param[in] instance - flash partition instance
4359 * @param[in] buf - update data buffer
4360 * @param[in] len - data buffer length
4361 * @param[in] offset - offset relative to the partition starting address
4362 * @param[in] cbfn - callback function
4363 * @param[in] cbarg - callback argument
4364 *
4365 * Return status.
4366 */
4367bfa_status_t
4368bfa_flash_update_part(struct bfa_flash_s *flash, enum bfa_flash_part_type type,
4369                u8 instance, void *buf, u32 len, u32 offset,
4370                bfa_cb_flash_t cbfn, void *cbarg)
4371{
4372        bfa_trc(flash, BFI_FLASH_H2I_WRITE_REQ);
4373        bfa_trc(flash, type);
4374        bfa_trc(flash, instance);
4375        bfa_trc(flash, len);
4376        bfa_trc(flash, offset);
4377
4378        if (!bfa_ioc_is_operational(flash->ioc))
4379                return BFA_STATUS_IOC_NON_OP;
4380
4381        /*
4382         * 'len' must be in word (4-byte) boundary
4383         * 'offset' must be in sector (16kb) boundary
4384         */
4385        if (!len || (len & 0x03) || (offset & 0x00003FFF))
4386                return BFA_STATUS_FLASH_BAD_LEN;
4387
4388        if (type == BFA_FLASH_PART_MFG)
4389                return BFA_STATUS_EINVAL;
4390
4391        if (flash->op_busy) {
4392                bfa_trc(flash, flash->op_busy);
4393                return BFA_STATUS_DEVBUSY;
4394        }
4395
4396        flash->op_busy = 1;
4397        flash->cbfn = cbfn;
4398        flash->cbarg = cbarg;
4399        flash->type = type;
4400        flash->instance = instance;
4401        flash->residue = len;
4402        flash->offset = 0;
4403        flash->addr_off = offset;
4404        flash->ubuf = buf;
4405
4406        bfa_flash_write_send(flash);
4407        return BFA_STATUS_OK;
4408}
4409
4410/*
4411 * Read flash partition.
4412 *
4413 * @param[in] flash - flash structure
4414 * @param[in] type - flash partition type
4415 * @param[in] instance - flash partition instance
4416 * @param[in] buf - read data buffer
4417 * @param[in] len - data buffer length
4418 * @param[in] offset - offset relative to the partition starting address
4419 * @param[in] cbfn - callback function
4420 * @param[in] cbarg - callback argument
4421 *
4422 * Return status.
4423 */
4424bfa_status_t
4425bfa_flash_read_part(struct bfa_flash_s *flash, enum bfa_flash_part_type type,
4426                u8 instance, void *buf, u32 len, u32 offset,
4427                bfa_cb_flash_t cbfn, void *cbarg)
4428{
4429        bfa_trc(flash, BFI_FLASH_H2I_READ_REQ);
4430        bfa_trc(flash, type);
4431        bfa_trc(flash, instance);
4432        bfa_trc(flash, len);
4433        bfa_trc(flash, offset);
4434
4435        if (!bfa_ioc_is_operational(flash->ioc))
4436                return BFA_STATUS_IOC_NON_OP;
4437
4438        /*
4439         * 'len' must be in word (4-byte) boundary
4440         * 'offset' must be in sector (16kb) boundary
4441         */
4442        if (!len || (len & 0x03) || (offset & 0x00003FFF))
4443                return BFA_STATUS_FLASH_BAD_LEN;
4444
4445        if (flash->op_busy) {
4446                bfa_trc(flash, flash->op_busy);
4447                return BFA_STATUS_DEVBUSY;
4448        }
4449
4450        flash->op_busy = 1;
4451        flash->cbfn = cbfn;
4452        flash->cbarg = cbarg;
4453        flash->type = type;
4454        flash->instance = instance;
4455        flash->residue = len;
4456        flash->offset = 0;
4457        flash->addr_off = offset;
4458        flash->ubuf = buf;
4459        bfa_flash_read_send(flash);
4460
4461        return BFA_STATUS_OK;
4462}
4463
4464/*
4465 *      DIAG module specific
4466 */
4467
4468#define BFA_DIAG_MEMTEST_TOV    50000   /* memtest timeout in msec */
4469#define CT2_BFA_DIAG_MEMTEST_TOV        (9*30*1000)  /* 4.5 min */
4470
4471/* IOC event handler */
4472static void
4473bfa_diag_notify(void *diag_arg, enum bfa_ioc_event_e event)
4474{
4475        struct bfa_diag_s *diag = diag_arg;
4476
4477        bfa_trc(diag, event);
4478        bfa_trc(diag, diag->block);
4479        bfa_trc(diag, diag->fwping.lock);
4480        bfa_trc(diag, diag->tsensor.lock);
4481
4482        switch (event) {
4483        case BFA_IOC_E_DISABLED:
4484        case BFA_IOC_E_FAILED:
4485                if (diag->fwping.lock) {
4486                        diag->fwping.status = BFA_STATUS_IOC_FAILURE;
4487                        diag->fwping.cbfn(diag->fwping.cbarg,
4488                                        diag->fwping.status);
4489                        diag->fwping.lock = 0;
4490                }
4491
4492                if (diag->tsensor.lock) {
4493                        diag->tsensor.status = BFA_STATUS_IOC_FAILURE;
4494                        diag->tsensor.cbfn(diag->tsensor.cbarg,
4495                                           diag->tsensor.status);
4496                        diag->tsensor.lock = 0;
4497                }
4498
4499                if (diag->block) {
4500                        if (diag->timer_active) {
4501                                bfa_timer_stop(&diag->timer);
4502                                diag->timer_active = 0;
4503                        }
4504
4505                        diag->status = BFA_STATUS_IOC_FAILURE;
4506                        diag->cbfn(diag->cbarg, diag->status);
4507                        diag->block = 0;
4508                }
4509                break;
4510
4511        default:
4512                break;
4513        }
4514}
4515
4516static void
4517bfa_diag_memtest_done(void *cbarg)
4518{
4519        struct bfa_diag_s *diag = cbarg;
4520        struct bfa_ioc_s  *ioc = diag->ioc;
4521        struct bfa_diag_memtest_result *res = diag->result;
4522        u32     loff = BFI_BOOT_MEMTEST_RES_ADDR;
4523        u32     pgnum, pgoff, i;
4524
4525        pgnum = PSS_SMEM_PGNUM(ioc->ioc_regs.smem_pg0, loff);
4526        pgoff = PSS_SMEM_PGOFF(loff);
4527
4528        writel(pgnum, ioc->ioc_regs.host_page_num_fn);
4529
4530        for (i = 0; i < (sizeof(struct bfa_diag_memtest_result) /
4531                         sizeof(u32)); i++) {
4532                /* read test result from smem */
4533                *((u32 *) res + i) =
4534                        bfa_mem_read(ioc->ioc_regs.smem_page_start, loff);
4535                loff += sizeof(u32);
4536        }
4537
4538        /* Reset IOC fwstates to BFI_IOC_UNINIT */
4539        bfa_ioc_reset_fwstate(ioc);
4540
4541        res->status = swab32(res->status);
4542        bfa_trc(diag, res->status);
4543
4544        if (res->status == BFI_BOOT_MEMTEST_RES_SIG)
4545                diag->status = BFA_STATUS_OK;
4546        else {
4547                diag->status = BFA_STATUS_MEMTEST_FAILED;
4548                res->addr = swab32(res->addr);
4549                res->exp = swab32(res->exp);
4550                res->act = swab32(res->act);
4551                res->err_status = swab32(res->err_status);
4552                res->err_status1 = swab32(res->err_status1);
4553                res->err_addr = swab32(res->err_addr);
4554                bfa_trc(diag, res->addr);
4555                bfa_trc(diag, res->exp);
4556                bfa_trc(diag, res->act);
4557                bfa_trc(diag, res->err_status);
4558                bfa_trc(diag, res->err_status1);
4559                bfa_trc(diag, res->err_addr);
4560        }
4561        diag->timer_active = 0;
4562        diag->cbfn(diag->cbarg, diag->status);
4563        diag->block = 0;
4564}
4565
4566/*
4567 * Firmware ping
4568 */
4569
4570/*
4571 * Perform DMA test directly
4572 */
4573static void
4574diag_fwping_send(struct bfa_diag_s *diag)
4575{
4576        struct bfi_diag_fwping_req_s *fwping_req;
4577        u32     i;
4578
4579        bfa_trc(diag, diag->fwping.dbuf_pa);
4580
4581        /* fill DMA area with pattern */
4582        for (i = 0; i < (BFI_DIAG_DMA_BUF_SZ >> 2); i++)
4583                *((u32 *)diag->fwping.dbuf_kva + i) = diag->fwping.data;
4584
4585        /* Fill mbox msg */
4586        fwping_req = (struct bfi_diag_fwping_req_s *)diag->fwping.mbcmd.msg;
4587
4588        /* Setup SG list */
4589        bfa_alen_set(&fwping_req->alen, BFI_DIAG_DMA_BUF_SZ,
4590                        diag->fwping.dbuf_pa);
4591        /* Set up dma count */
4592        fwping_req->count = cpu_to_be32(diag->fwping.count);
4593        /* Set up data pattern */
4594        fwping_req->data = diag->fwping.data;
4595
4596        /* build host command */
4597        bfi_h2i_set(fwping_req->mh, BFI_MC_DIAG, BFI_DIAG_H2I_FWPING,
4598                bfa_ioc_portid(diag->ioc));
4599
4600        /* send mbox cmd */
4601        bfa_ioc_mbox_queue(diag->ioc, &diag->fwping.mbcmd);
4602}
4603
4604static void
4605diag_fwping_comp(struct bfa_diag_s *diag,
4606                 struct bfi_diag_fwping_rsp_s *diag_rsp)
4607{
4608        u32     rsp_data = diag_rsp->data;
4609        u8      rsp_dma_status = diag_rsp->dma_status;
4610
4611        bfa_trc(diag, rsp_data);
4612        bfa_trc(diag, rsp_dma_status);
4613
4614        if (rsp_dma_status == BFA_STATUS_OK) {
4615                u32     i, pat;
4616                pat = (diag->fwping.count & 0x1) ? ~(diag->fwping.data) :
4617                        diag->fwping.data;
4618                /* Check mbox data */
4619                if (diag->fwping.data != rsp_data) {
4620                        bfa_trc(diag, rsp_data);
4621                        diag->fwping.result->dmastatus =
4622                                        BFA_STATUS_DATACORRUPTED;
4623                        diag->fwping.status = BFA_STATUS_DATACORRUPTED;
4624                        diag->fwping.cbfn(diag->fwping.cbarg,
4625                                        diag->fwping.status);
4626                        diag->fwping.lock = 0;
4627                        return;
4628                }
4629                /* Check dma pattern */
4630                for (i = 0; i < (BFI_DIAG_DMA_BUF_SZ >> 2); i++) {
4631                        if (*((u32 *)diag->fwping.dbuf_kva + i) != pat) {
4632                                bfa_trc(diag, i);
4633                                bfa_trc(diag, pat);
4634                                bfa_trc(diag,
4635                                        *((u32 *)diag->fwping.dbuf_kva + i));
4636                                diag->fwping.result->dmastatus =
4637                                                BFA_STATUS_DATACORRUPTED;
4638                                diag->fwping.status = BFA_STATUS_DATACORRUPTED;
4639                                diag->fwping.cbfn(diag->fwping.cbarg,
4640                                                diag->fwping.status);
4641                                diag->fwping.lock = 0;
4642                                return;
4643                        }
4644                }
4645                diag->fwping.result->dmastatus = BFA_STATUS_OK;
4646                diag->fwping.status = BFA_STATUS_OK;
4647                diag->fwping.cbfn(diag->fwping.cbarg, diag->fwping.status);
4648                diag->fwping.lock = 0;
4649        } else {
4650                diag->fwping.status = BFA_STATUS_HDMA_FAILED;
4651                diag->fwping.cbfn(diag->fwping.cbarg, diag->fwping.status);
4652                diag->fwping.lock = 0;
4653        }
4654}
4655
4656/*
4657 * Temperature Sensor
4658 */
4659
4660static void
4661diag_tempsensor_send(struct bfa_diag_s *diag)
4662{
4663        struct bfi_diag_ts_req_s *msg;
4664
4665        msg = (struct bfi_diag_ts_req_s *)diag->tsensor.mbcmd.msg;
4666        bfa_trc(diag, msg->temp);
4667        /* build host command */
4668        bfi_h2i_set(msg->mh, BFI_MC_DIAG, BFI_DIAG_H2I_TEMPSENSOR,
4669                bfa_ioc_portid(diag->ioc));
4670        /* send mbox cmd */
4671        bfa_ioc_mbox_queue(diag->ioc, &diag->tsensor.mbcmd);
4672}
4673
4674static void
4675diag_tempsensor_comp(struct bfa_diag_s *diag, bfi_diag_ts_rsp_t *rsp)
4676{
4677        if (!diag->tsensor.lock) {
4678                /* receiving response after ioc failure */
4679                bfa_trc(diag, diag->tsensor.lock);
4680                return;
4681        }
4682
4683        /*
4684         * ASIC junction tempsensor is a reg read operation
4685         * it will always return OK
4686         */
4687        diag->tsensor.temp->temp = be16_to_cpu(rsp->temp);
4688        diag->tsensor.temp->ts_junc = rsp->ts_junc;
4689        diag->tsensor.temp->ts_brd = rsp->ts_brd;
4690
4691        if (rsp->ts_brd) {
4692                /* tsensor.temp->status is brd_temp status */
4693                diag->tsensor.temp->status = rsp->status;
4694                if (rsp->status == BFA_STATUS_OK) {
4695                        diag->tsensor.temp->brd_temp =
4696                                be16_to_cpu(rsp->brd_temp);
4697                } else
4698                        diag->tsensor.temp->brd_temp = 0;
4699        }
4700
4701        bfa_trc(diag, rsp->status);
4702        bfa_trc(diag, rsp->ts_junc);
4703        bfa_trc(diag, rsp->temp);
4704        bfa_trc(diag, rsp->ts_brd);
4705        bfa_trc(diag, rsp->brd_temp);
4706
4707        /* tsensor status is always good bcos we always have junction temp */
4708        diag->tsensor.status = BFA_STATUS_OK;
4709        diag->tsensor.cbfn(diag->tsensor.cbarg, diag->tsensor.status);
4710        diag->tsensor.lock = 0;
4711}
4712
4713/*
4714 *      LED Test command
4715 */
4716static void
4717diag_ledtest_send(struct bfa_diag_s *diag, struct bfa_diag_ledtest_s *ledtest)
4718{
4719        struct bfi_diag_ledtest_req_s  *msg;
4720
4721        msg = (struct bfi_diag_ledtest_req_s *)diag->ledtest.mbcmd.msg;
4722        /* build host command */
4723        bfi_h2i_set(msg->mh, BFI_MC_DIAG, BFI_DIAG_H2I_LEDTEST,
4724                        bfa_ioc_portid(diag->ioc));
4725
4726        /*
4727         * convert the freq from N blinks per 10 sec to
4728         * crossbow ontime value. We do it here because division is need
4729         */
4730        if (ledtest->freq)
4731                ledtest->freq = 500 / ledtest->freq;
4732
4733        if (ledtest->freq == 0)
4734                ledtest->freq = 1;
4735
4736        bfa_trc(diag, ledtest->freq);
4737        /* mcpy(&ledtest_req->req, ledtest, sizeof(bfa_diag_ledtest_t)); */
4738        msg->cmd = (u8) ledtest->cmd;
4739        msg->color = (u8) ledtest->color;
4740        msg->portid = bfa_ioc_portid(diag->ioc);
4741        msg->led = ledtest->led;
4742        msg->freq = cpu_to_be16(ledtest->freq);
4743
4744        /* send mbox cmd */
4745        bfa_ioc_mbox_queue(diag->ioc, &diag->ledtest.mbcmd);
4746}
4747
4748static void
4749diag_ledtest_comp(struct bfa_diag_s *diag, struct bfi_diag_ledtest_rsp_s *msg)
4750{
4751        bfa_trc(diag, diag->ledtest.lock);
4752        diag->ledtest.lock = BFA_FALSE;
4753        /* no bfa_cb_queue is needed because driver is not waiting */
4754}
4755
4756/*
4757 * Port beaconing
4758 */
4759static void
4760diag_portbeacon_send(struct bfa_diag_s *diag, bfa_boolean_t beacon, u32 sec)
4761{
4762        struct bfi_diag_portbeacon_req_s *msg;
4763
4764        msg = (struct bfi_diag_portbeacon_req_s *)diag->beacon.mbcmd.msg;
4765        /* build host command */
4766        bfi_h2i_set(msg->mh, BFI_MC_DIAG, BFI_DIAG_H2I_PORTBEACON,
4767                bfa_ioc_portid(diag->ioc));
4768        msg->beacon = beacon;
4769        msg->period = cpu_to_be32(sec);
4770        /* send mbox cmd */
4771        bfa_ioc_mbox_queue(diag->ioc, &diag->beacon.mbcmd);
4772}
4773
4774static void
4775diag_portbeacon_comp(struct bfa_diag_s *diag)
4776{
4777        bfa_trc(diag, diag->beacon.state);
4778        diag->beacon.state = BFA_FALSE;
4779        if (diag->cbfn_beacon)
4780                diag->cbfn_beacon(diag->dev, BFA_FALSE, diag->beacon.link_e2e);
4781}
4782
4783/*
4784 *      Diag hmbox handler
4785 */
4786void
4787bfa_diag_intr(void *diagarg, struct bfi_mbmsg_s *msg)
4788{
4789        struct bfa_diag_s *diag = diagarg;
4790
4791        switch (msg->mh.msg_id) {
4792        case BFI_DIAG_I2H_PORTBEACON:
4793                diag_portbeacon_comp(diag);
4794                break;
4795        case BFI_DIAG_I2H_FWPING:
4796                diag_fwping_comp(diag, (struct bfi_diag_fwping_rsp_s *) msg);
4797                break;
4798        case BFI_DIAG_I2H_TEMPSENSOR:
4799                diag_tempsensor_comp(diag, (bfi_diag_ts_rsp_t *) msg);
4800                break;
4801        case BFI_DIAG_I2H_LEDTEST:
4802                diag_ledtest_comp(diag, (struct bfi_diag_ledtest_rsp_s *) msg);
4803                break;
4804        default:
4805                bfa_trc(diag, msg->mh.msg_id);
4806                WARN_ON(1);
4807        }
4808}
4809
4810/*
4811 * Gen RAM Test
4812 *
4813 *   @param[in] *diag           - diag data struct
4814 *   @param[in] *memtest        - mem test params input from upper layer,
4815 *   @param[in] pattern         - mem test pattern
4816 *   @param[in] *result         - mem test result
4817 *   @param[in] cbfn            - mem test callback functioin
4818 *   @param[in] cbarg           - callback functioin arg
4819 *
4820 *   @param[out]
4821 */
4822bfa_status_t
4823bfa_diag_memtest(struct bfa_diag_s *diag, struct bfa_diag_memtest_s *memtest,
4824                u32 pattern, struct bfa_diag_memtest_result *result,
4825                bfa_cb_diag_t cbfn, void *cbarg)
4826{
4827        u32     memtest_tov;
4828
4829        bfa_trc(diag, pattern);
4830
4831        if (!bfa_ioc_adapter_is_disabled(diag->ioc))
4832                return BFA_STATUS_ADAPTER_ENABLED;
4833
4834        /* check to see if there is another destructive diag cmd running */
4835        if (diag->block) {
4836                bfa_trc(diag, diag->block);
4837                return BFA_STATUS_DEVBUSY;
4838        } else
4839                diag->block = 1;
4840
4841        diag->result = result;
4842        diag->cbfn = cbfn;
4843        diag->cbarg = cbarg;
4844
4845        /* download memtest code and take LPU0 out of reset */
4846        bfa_ioc_boot(diag->ioc, BFI_FWBOOT_TYPE_MEMTEST, BFI_FWBOOT_ENV_OS);
4847
4848        memtest_tov = (bfa_ioc_asic_gen(diag->ioc) == BFI_ASIC_GEN_CT2) ?
4849                       CT2_BFA_DIAG_MEMTEST_TOV : BFA_DIAG_MEMTEST_TOV;
4850        bfa_timer_begin(diag->ioc->timer_mod, &diag->timer,
4851                        bfa_diag_memtest_done, diag, memtest_tov);
4852        diag->timer_active = 1;
4853        return BFA_STATUS_OK;
4854}
4855
4856/*
4857 * DIAG firmware ping command
4858 *
4859 *   @param[in] *diag           - diag data struct
4860 *   @param[in] cnt             - dma loop count for testing PCIE
4861 *   @param[in] data            - data pattern to pass in fw
4862 *   @param[in] *result         - pt to bfa_diag_fwping_result_t data struct
4863 *   @param[in] cbfn            - callback function
4864 *   @param[in] *cbarg          - callback functioin arg
4865 *
4866 *   @param[out]
4867 */
4868bfa_status_t
4869bfa_diag_fwping(struct bfa_diag_s *diag, u32 cnt, u32 data,
4870                struct bfa_diag_results_fwping *result, bfa_cb_diag_t cbfn,
4871                void *cbarg)
4872{
4873        bfa_trc(diag, cnt);
4874        bfa_trc(diag, data);
4875
4876        if (!bfa_ioc_is_operational(diag->ioc))
4877                return BFA_STATUS_IOC_NON_OP;
4878
4879        if (bfa_asic_id_ct2(bfa_ioc_devid((diag->ioc))) &&
4880            ((diag->ioc)->clscode == BFI_PCIFN_CLASS_ETH))
4881                return BFA_STATUS_CMD_NOTSUPP;
4882
4883        /* check to see if there is another destructive diag cmd running */
4884        if (diag->block || diag->fwping.lock) {
4885                bfa_trc(diag, diag->block);
4886                bfa_trc(diag, diag->fwping.lock);
4887                return BFA_STATUS_DEVBUSY;
4888        }
4889
4890        /* Initialization */
4891        diag->fwping.lock = 1;
4892        diag->fwping.cbfn = cbfn;
4893        diag->fwping.cbarg = cbarg;
4894        diag->fwping.result = result;
4895        diag->fwping.data = data;
4896        diag->fwping.count = cnt;
4897
4898        /* Init test results */
4899        diag->fwping.result->data = 0;
4900        diag->fwping.result->status = BFA_STATUS_OK;
4901
4902        /* kick off the first ping */
4903        diag_fwping_send(diag);
4904        return BFA_STATUS_OK;
4905}
4906
4907/*
4908 * Read Temperature Sensor
4909 *
4910 *   @param[in] *diag           - diag data struct
4911 *   @param[in] *result         - pt to bfa_diag_temp_t data struct
4912 *   @param[in] cbfn            - callback function
4913 *   @param[in] *cbarg          - callback functioin arg
4914 *
4915 *   @param[out]
4916 */
4917bfa_status_t
4918bfa_diag_tsensor_query(struct bfa_diag_s *diag,
4919                struct bfa_diag_results_tempsensor_s *result,
4920                bfa_cb_diag_t cbfn, void *cbarg)
4921{
4922        /* check to see if there is a destructive diag cmd running */
4923        if (diag->block || diag->tsensor.lock) {
4924                bfa_trc(diag, diag->block);
4925                bfa_trc(diag, diag->tsensor.lock);
4926                return BFA_STATUS_DEVBUSY;
4927        }
4928
4929        if (!bfa_ioc_is_operational(diag->ioc))
4930                return BFA_STATUS_IOC_NON_OP;
4931
4932        /* Init diag mod params */
4933        diag->tsensor.lock = 1;
4934        diag->tsensor.temp = result;
4935        diag->tsensor.cbfn = cbfn;
4936        diag->tsensor.cbarg = cbarg;
4937        diag->tsensor.status = BFA_STATUS_OK;
4938
4939        /* Send msg to fw */
4940        diag_tempsensor_send(diag);
4941
4942        return BFA_STATUS_OK;
4943}
4944
4945/*
4946 * LED Test command
4947 *
4948 *   @param[in] *diag           - diag data struct
4949 *   @param[in] *ledtest        - pt to ledtest data structure
4950 *
4951 *   @param[out]
4952 */
4953bfa_status_t
4954bfa_diag_ledtest(struct bfa_diag_s *diag, struct bfa_diag_ledtest_s *ledtest)
4955{
4956        bfa_trc(diag, ledtest->cmd);
4957
4958        if (!bfa_ioc_is_operational(diag->ioc))
4959                return BFA_STATUS_IOC_NON_OP;
4960
4961        if (diag->beacon.state)
4962                return BFA_STATUS_BEACON_ON;
4963
4964        if (diag->ledtest.lock)
4965                return BFA_STATUS_LEDTEST_OP;
4966
4967        /* Send msg to fw */
4968        diag->ledtest.lock = BFA_TRUE;
4969        diag_ledtest_send(diag, ledtest);
4970
4971        return BFA_STATUS_OK;
4972}
4973
4974/*
4975 * Port beaconing command
4976 *
4977 *   @param[in] *diag           - diag data struct
4978 *   @param[in] beacon          - port beaconing 1:ON   0:OFF
4979 *   @param[in] link_e2e_beacon - link beaconing 1:ON   0:OFF
4980 *   @param[in] sec             - beaconing duration in seconds
4981 *
4982 *   @param[out]
4983 */
4984bfa_status_t
4985bfa_diag_beacon_port(struct bfa_diag_s *diag, bfa_boolean_t beacon,
4986                bfa_boolean_t link_e2e_beacon, uint32_t sec)
4987{
4988        bfa_trc(diag, beacon);
4989        bfa_trc(diag, link_e2e_beacon);
4990        bfa_trc(diag, sec);
4991
4992        if (!bfa_ioc_is_operational(diag->ioc))
4993                return BFA_STATUS_IOC_NON_OP;
4994
4995        if (diag->ledtest.lock)
4996                return BFA_STATUS_LEDTEST_OP;
4997
4998        if (diag->beacon.state && beacon)       /* beacon alread on */
4999                return BFA_STATUS_BEACON_ON;
5000
5001        diag->beacon.state      = beacon;
5002        diag->beacon.link_e2e   = link_e2e_beacon;
5003        if (diag->cbfn_beacon)
5004                diag->cbfn_beacon(diag->dev, beacon, link_e2e_beacon);
5005
5006        /* Send msg to fw */
5007        diag_portbeacon_send(diag, beacon, sec);
5008
5009        return BFA_STATUS_OK;
5010}
5011
5012/*
5013 * Return DMA memory needed by diag module.
5014 */
5015u32
5016bfa_diag_meminfo(void)
5017{
5018        return BFA_ROUNDUP(BFI_DIAG_DMA_BUF_SZ, BFA_DMA_ALIGN_SZ);
5019}
5020
5021/*
5022 *      Attach virtual and physical memory for Diag.
5023 */
5024void
5025bfa_diag_attach(struct bfa_diag_s *diag, struct bfa_ioc_s *ioc, void *dev,
5026        bfa_cb_diag_beacon_t cbfn_beacon, struct bfa_trc_mod_s *trcmod)
5027{
5028        diag->dev = dev;
5029        diag->ioc = ioc;
5030        diag->trcmod = trcmod;
5031
5032        diag->block = 0;
5033        diag->cbfn = NULL;
5034        diag->cbarg = NULL;
5035        diag->result = NULL;
5036        diag->cbfn_beacon = cbfn_beacon;
5037
5038        bfa_ioc_mbox_regisr(diag->ioc, BFI_MC_DIAG, bfa_diag_intr, diag);
5039        bfa_q_qe_init(&diag->ioc_notify);
5040        bfa_ioc_notify_init(&diag->ioc_notify, bfa_diag_notify, diag);
5041        list_add_tail(&diag->ioc_notify.qe, &diag->ioc->notify_q);
5042}
5043
5044void
5045bfa_diag_memclaim(struct bfa_diag_s *diag, u8 *dm_kva, u64 dm_pa)
5046{
5047        diag->fwping.dbuf_kva = dm_kva;
5048        diag->fwping.dbuf_pa = dm_pa;
5049        memset(diag->fwping.dbuf_kva, 0, BFI_DIAG_DMA_BUF_SZ);
5050}
5051
5052/*
5053 *      PHY module specific
5054 */
5055#define BFA_PHY_DMA_BUF_SZ      0x02000         /* 8k dma buffer */
5056#define BFA_PHY_LOCK_STATUS     0x018878        /* phy semaphore status reg */
5057
5058static void
5059bfa_phy_ntoh32(u32 *obuf, u32 *ibuf, int sz)
5060{
5061        int i, m = sz >> 2;
5062
5063        for (i = 0; i < m; i++)
5064                obuf[i] = be32_to_cpu(ibuf[i]);
5065}
5066
5067static bfa_boolean_t
5068bfa_phy_present(struct bfa_phy_s *phy)
5069{
5070        return (phy->ioc->attr->card_type == BFA_MFG_TYPE_LIGHTNING);
5071}
5072
5073static void
5074bfa_phy_notify(void *cbarg, enum bfa_ioc_event_e event)
5075{
5076        struct bfa_phy_s *phy = cbarg;
5077
5078        bfa_trc(phy, event);
5079
5080        switch (event) {
5081        case BFA_IOC_E_DISABLED:
5082        case BFA_IOC_E_FAILED:
5083                if (phy->op_busy) {
5084                        phy->status = BFA_STATUS_IOC_FAILURE;
5085                        phy->cbfn(phy->cbarg, phy->status);
5086                        phy->op_busy = 0;
5087                }
5088                break;
5089
5090        default:
5091                break;
5092        }
5093}
5094
5095/*
5096 * Send phy attribute query request.
5097 *
5098 * @param[in] cbarg - callback argument
5099 */
5100static void
5101bfa_phy_query_send(void *cbarg)
5102{
5103        struct bfa_phy_s *phy = cbarg;
5104        struct bfi_phy_query_req_s *msg =
5105                        (struct bfi_phy_query_req_s *) phy->mb.msg;
5106
5107        msg->instance = phy->instance;
5108        bfi_h2i_set(msg->mh, BFI_MC_PHY, BFI_PHY_H2I_QUERY_REQ,
5109                bfa_ioc_portid(phy->ioc));
5110        bfa_alen_set(&msg->alen, sizeof(struct bfa_phy_attr_s), phy->dbuf_pa);
5111        bfa_ioc_mbox_queue(phy->ioc, &phy->mb);
5112}
5113
5114/*
5115 * Send phy write request.
5116 *
5117 * @param[in] cbarg - callback argument
5118 */
5119static void
5120bfa_phy_write_send(void *cbarg)
5121{
5122        struct bfa_phy_s *phy = cbarg;
5123        struct bfi_phy_write_req_s *msg =
5124                        (struct bfi_phy_write_req_s *) phy->mb.msg;
5125        u32     len;
5126        u16     *buf, *dbuf;
5127        int     i, sz;
5128
5129        msg->instance = phy->instance;
5130        msg->offset = cpu_to_be32(phy->addr_off + phy->offset);
5131        len = (phy->residue < BFA_PHY_DMA_BUF_SZ) ?
5132                        phy->residue : BFA_PHY_DMA_BUF_SZ;
5133        msg->length = cpu_to_be32(len);
5134
5135        /* indicate if it's the last msg of the whole write operation */
5136        msg->last = (len == phy->residue) ? 1 : 0;
5137
5138        bfi_h2i_set(msg->mh, BFI_MC_PHY, BFI_PHY_H2I_WRITE_REQ,
5139                bfa_ioc_portid(phy->ioc));
5140        bfa_alen_set(&msg->alen, len, phy->dbuf_pa);
5141
5142        buf = (u16 *) (phy->ubuf + phy->offset);
5143        dbuf = (u16 *)phy->dbuf_kva;
5144        sz = len >> 1;
5145        for (i = 0; i < sz; i++)
5146                buf[i] = cpu_to_be16(dbuf[i]);
5147
5148        bfa_ioc_mbox_queue(phy->ioc, &phy->mb);
5149
5150        phy->residue -= len;
5151        phy->offset += len;
5152}
5153
5154/*
5155 * Send phy read request.
5156 *
5157 * @param[in] cbarg - callback argument
5158 */
5159static void
5160bfa_phy_read_send(void *cbarg)
5161{
5162        struct bfa_phy_s *phy = cbarg;
5163        struct bfi_phy_read_req_s *msg =
5164                        (struct bfi_phy_read_req_s *) phy->mb.msg;
5165        u32     len;
5166
5167        msg->instance = phy->instance;
5168        msg->offset = cpu_to_be32(phy->addr_off + phy->offset);
5169        len = (phy->residue < BFA_PHY_DMA_BUF_SZ) ?
5170                        phy->residue : BFA_PHY_DMA_BUF_SZ;
5171        msg->length = cpu_to_be32(len);
5172        bfi_h2i_set(msg->mh, BFI_MC_PHY, BFI_PHY_H2I_READ_REQ,
5173                bfa_ioc_portid(phy->ioc));
5174        bfa_alen_set(&msg->alen, len, phy->dbuf_pa);
5175        bfa_ioc_mbox_queue(phy->ioc, &phy->mb);
5176}
5177
5178/*
5179 * Send phy stats request.
5180 *
5181 * @param[in] cbarg - callback argument
5182 */
5183static void
5184bfa_phy_stats_send(void *cbarg)
5185{
5186        struct bfa_phy_s *phy = cbarg;
5187        struct bfi_phy_stats_req_s *msg =
5188                        (struct bfi_phy_stats_req_s *) phy->mb.msg;
5189
5190        msg->instance = phy->instance;
5191        bfi_h2i_set(msg->mh, BFI_MC_PHY, BFI_PHY_H2I_STATS_REQ,
5192                bfa_ioc_portid(phy->ioc));
5193        bfa_alen_set(&msg->alen, sizeof(struct bfa_phy_stats_s), phy->dbuf_pa);
5194        bfa_ioc_mbox_queue(phy->ioc, &phy->mb);
5195}
5196
5197/*
5198 * Flash memory info API.
5199 *
5200 * @param[in] mincfg - minimal cfg variable
5201 */
5202u32
5203bfa_phy_meminfo(bfa_boolean_t mincfg)
5204{
5205        /* min driver doesn't need phy */
5206        if (mincfg)
5207                return 0;
5208
5209        return BFA_ROUNDUP(BFA_PHY_DMA_BUF_SZ, BFA_DMA_ALIGN_SZ);
5210}
5211
5212/*
5213 * Flash attach API.
5214 *
5215 * @param[in] phy - phy structure
5216 * @param[in] ioc  - ioc structure
5217 * @param[in] dev  - device structure
5218 * @param[in] trcmod - trace module
5219 * @param[in] logmod - log module
5220 */
5221void
5222bfa_phy_attach(struct bfa_phy_s *phy, struct bfa_ioc_s *ioc, void *dev,
5223                struct bfa_trc_mod_s *trcmod, bfa_boolean_t mincfg)
5224{
5225        phy->ioc = ioc;
5226        phy->trcmod = trcmod;
5227        phy->cbfn = NULL;
5228        phy->cbarg = NULL;
5229        phy->op_busy = 0;
5230
5231        bfa_ioc_mbox_regisr(phy->ioc, BFI_MC_PHY, bfa_phy_intr, phy);
5232        bfa_q_qe_init(&phy->ioc_notify);
5233        bfa_ioc_notify_init(&phy->ioc_notify, bfa_phy_notify, phy);
5234        list_add_tail(&phy->ioc_notify.qe, &phy->ioc->notify_q);
5235
5236        /* min driver doesn't need phy */
5237        if (mincfg) {
5238                phy->dbuf_kva = NULL;
5239                phy->dbuf_pa = 0;
5240        }
5241}
5242
5243/*
5244 * Claim memory for phy
5245 *
5246 * @param[in] phy - phy structure
5247 * @param[in] dm_kva - pointer to virtual memory address
5248 * @param[in] dm_pa - physical memory address
5249 * @param[in] mincfg - minimal cfg variable
5250 */
5251void
5252bfa_phy_memclaim(struct bfa_phy_s *phy, u8 *dm_kva, u64 dm_pa,
5253                bfa_boolean_t mincfg)
5254{
5255        if (mincfg)
5256                return;
5257
5258        phy->dbuf_kva = dm_kva;
5259        phy->dbuf_pa = dm_pa;
5260        memset(phy->dbuf_kva, 0, BFA_PHY_DMA_BUF_SZ);
5261        dm_kva += BFA_ROUNDUP(BFA_PHY_DMA_BUF_SZ, BFA_DMA_ALIGN_SZ);
5262        dm_pa += BFA_ROUNDUP(BFA_PHY_DMA_BUF_SZ, BFA_DMA_ALIGN_SZ);
5263}
5264
5265bfa_boolean_t
5266bfa_phy_busy(struct bfa_ioc_s *ioc)
5267{
5268        void __iomem    *rb;
5269
5270        rb = bfa_ioc_bar0(ioc);
5271        return readl(rb + BFA_PHY_LOCK_STATUS);
5272}
5273
5274/*
5275 * Get phy attribute.
5276 *
5277 * @param[in] phy - phy structure
5278 * @param[in] attr - phy attribute structure
5279 * @param[in] cbfn - callback function
5280 * @param[in] cbarg - callback argument
5281 *
5282 * Return status.
5283 */
5284bfa_status_t
5285bfa_phy_get_attr(struct bfa_phy_s *phy, u8 instance,
5286                struct bfa_phy_attr_s *attr, bfa_cb_phy_t cbfn, void *cbarg)
5287{
5288        bfa_trc(phy, BFI_PHY_H2I_QUERY_REQ);
5289        bfa_trc(phy, instance);
5290
5291        if (!bfa_phy_present(phy))
5292                return BFA_STATUS_PHY_NOT_PRESENT;
5293
5294        if (!bfa_ioc_is_operational(phy->ioc))
5295                return BFA_STATUS_IOC_NON_OP;
5296
5297        if (phy->op_busy || bfa_phy_busy(phy->ioc)) {
5298                bfa_trc(phy, phy->op_busy);
5299                return BFA_STATUS_DEVBUSY;
5300        }
5301
5302        phy->op_busy = 1;
5303        phy->cbfn = cbfn;
5304        phy->cbarg = cbarg;
5305        phy->instance = instance;
5306        phy->ubuf = (uint8_t *) attr;
5307        bfa_phy_query_send(phy);
5308
5309        return BFA_STATUS_OK;
5310}
5311
5312/*
5313 * Get phy stats.
5314 *
5315 * @param[in] phy - phy structure
5316 * @param[in] instance - phy image instance
5317 * @param[in] stats - pointer to phy stats
5318 * @param[in] cbfn - callback function
5319 * @param[in] cbarg - callback argument
5320 *
5321 * Return status.
5322 */
5323bfa_status_t
5324bfa_phy_get_stats(struct bfa_phy_s *phy, u8 instance,
5325                struct bfa_phy_stats_s *stats,
5326                bfa_cb_phy_t cbfn, void *cbarg)
5327{
5328        bfa_trc(phy, BFI_PHY_H2I_STATS_REQ);
5329        bfa_trc(phy, instance);
5330
5331        if (!bfa_phy_present(phy))
5332                return BFA_STATUS_PHY_NOT_PRESENT;
5333
5334        if (!bfa_ioc_is_operational(phy->ioc))
5335                return BFA_STATUS_IOC_NON_OP;
5336
5337        if (phy->op_busy || bfa_phy_busy(phy->ioc)) {
5338                bfa_trc(phy, phy->op_busy);
5339                return BFA_STATUS_DEVBUSY;
5340        }
5341
5342        phy->op_busy = 1;
5343        phy->cbfn = cbfn;
5344        phy->cbarg = cbarg;
5345        phy->instance = instance;
5346        phy->ubuf = (u8 *) stats;
5347        bfa_phy_stats_send(phy);
5348
5349        return BFA_STATUS_OK;
5350}
5351
5352/*
5353 * Update phy image.
5354 *
5355 * @param[in] phy - phy structure
5356 * @param[in] instance - phy image instance
5357 * @param[in] buf - update data buffer
5358 * @param[in] len - data buffer length
5359 * @param[in] offset - offset relative to starting address
5360 * @param[in] cbfn - callback function
5361 * @param[in] cbarg - callback argument
5362 *
5363 * Return status.
5364 */
5365bfa_status_t
5366bfa_phy_update(struct bfa_phy_s *phy, u8 instance,
5367                void *buf, u32 len, u32 offset,
5368                bfa_cb_phy_t cbfn, void *cbarg)
5369{
5370        bfa_trc(phy, BFI_PHY_H2I_WRITE_REQ);
5371        bfa_trc(phy, instance);
5372        bfa_trc(phy, len);
5373        bfa_trc(phy, offset);
5374
5375        if (!bfa_phy_present(phy))
5376                return BFA_STATUS_PHY_NOT_PRESENT;
5377
5378        if (!bfa_ioc_is_operational(phy->ioc))
5379                return BFA_STATUS_IOC_NON_OP;
5380
5381        /* 'len' must be in word (4-byte) boundary */
5382        if (!len || (len & 0x03))
5383                return BFA_STATUS_FAILED;
5384
5385        if (phy->op_busy || bfa_phy_busy(phy->ioc)) {
5386                bfa_trc(phy, phy->op_busy);
5387                return BFA_STATUS_DEVBUSY;
5388        }
5389
5390        phy->op_busy = 1;
5391        phy->cbfn = cbfn;
5392        phy->cbarg = cbarg;
5393        phy->instance = instance;
5394        phy->residue = len;
5395        phy->offset = 0;
5396        phy->addr_off = offset;
5397        phy->ubuf = buf;
5398
5399        bfa_phy_write_send(phy);
5400        return BFA_STATUS_OK;
5401}
5402
5403/*
5404 * Read phy image.
5405 *
5406 * @param[in] phy - phy structure
5407 * @param[in] instance - phy image instance
5408 * @param[in] buf - read data buffer
5409 * @param[in] len - data buffer length
5410 * @param[in] offset - offset relative to starting address
5411 * @param[in] cbfn - callback function
5412 * @param[in] cbarg - callback argument
5413 *
5414 * Return status.
5415 */
5416bfa_status_t
5417bfa_phy_read(struct bfa_phy_s *phy, u8 instance,
5418                void *buf, u32 len, u32 offset,
5419                bfa_cb_phy_t cbfn, void *cbarg)
5420{
5421        bfa_trc(phy, BFI_PHY_H2I_READ_REQ);
5422        bfa_trc(phy, instance);
5423        bfa_trc(phy, len);
5424        bfa_trc(phy, offset);
5425
5426        if (!bfa_phy_present(phy))
5427                return BFA_STATUS_PHY_NOT_PRESENT;
5428
5429        if (!bfa_ioc_is_operational(phy->ioc))
5430                return BFA_STATUS_IOC_NON_OP;
5431
5432        /* 'len' must be in word (4-byte) boundary */
5433        if (!len || (len & 0x03))
5434                return BFA_STATUS_FAILED;
5435
5436        if (phy->op_busy || bfa_phy_busy(phy->ioc)) {
5437                bfa_trc(phy, phy->op_busy);
5438                return BFA_STATUS_DEVBUSY;
5439        }
5440
5441        phy->op_busy = 1;
5442        phy->cbfn = cbfn;
5443        phy->cbarg = cbarg;
5444        phy->instance = instance;
5445        phy->residue = len;
5446        phy->offset = 0;
5447        phy->addr_off = offset;
5448        phy->ubuf = buf;
5449        bfa_phy_read_send(phy);
5450
5451        return BFA_STATUS_OK;
5452}
5453
5454/*
5455 * Process phy response messages upon receiving interrupts.
5456 *
5457 * @param[in] phyarg - phy structure
5458 * @param[in] msg - message structure
5459 */
5460void
5461bfa_phy_intr(void *phyarg, struct bfi_mbmsg_s *msg)
5462{
5463        struct bfa_phy_s *phy = phyarg;
5464        u32     status;
5465
5466        union {
5467                struct bfi_phy_query_rsp_s *query;
5468                struct bfi_phy_stats_rsp_s *stats;
5469                struct bfi_phy_write_rsp_s *write;
5470                struct bfi_phy_read_rsp_s *read;
5471                struct bfi_mbmsg_s   *msg;
5472        } m;
5473
5474        m.msg = msg;
5475        bfa_trc(phy, msg->mh.msg_id);
5476
5477        if (!phy->op_busy) {
5478                /* receiving response after ioc failure */
5479                bfa_trc(phy, 0x9999);
5480                return;
5481        }
5482
5483        switch (msg->mh.msg_id) {
5484        case BFI_PHY_I2H_QUERY_RSP:
5485                status = be32_to_cpu(m.query->status);
5486                bfa_trc(phy, status);
5487
5488                if (status == BFA_STATUS_OK) {
5489                        struct bfa_phy_attr_s *attr =
5490                                (struct bfa_phy_attr_s *) phy->ubuf;
5491                        bfa_phy_ntoh32((u32 *)attr, (u32 *)phy->dbuf_kva,
5492                                        sizeof(struct bfa_phy_attr_s));
5493                        bfa_trc(phy, attr->status);
5494                        bfa_trc(phy, attr->length);
5495                }
5496
5497                phy->status = status;
5498                phy->op_busy = 0;
5499                if (phy->cbfn)
5500                        phy->cbfn(phy->cbarg, phy->status);
5501                break;
5502        case BFI_PHY_I2H_STATS_RSP:
5503                status = be32_to_cpu(m.stats->status);
5504                bfa_trc(phy, status);
5505
5506                if (status == BFA_STATUS_OK) {
5507                        struct bfa_phy_stats_s *stats =
5508                                (struct bfa_phy_stats_s *) phy->ubuf;
5509                        bfa_phy_ntoh32((u32 *)stats, (u32 *)phy->dbuf_kva,
5510                                sizeof(struct bfa_phy_stats_s));
5511                                bfa_trc(phy, stats->status);
5512                }
5513
5514                phy->status = status;
5515                phy->op_busy = 0;
5516                if (phy->cbfn)
5517                        phy->cbfn(phy->cbarg, phy->status);
5518                break;
5519        case BFI_PHY_I2H_WRITE_RSP:
5520                status = be32_to_cpu(m.write->status);
5521                bfa_trc(phy, status);
5522
5523                if (status != BFA_STATUS_OK || phy->residue == 0) {
5524                        phy->status = status;
5525                        phy->op_busy = 0;
5526                        if (phy->cbfn)
5527                                phy->cbfn(phy->cbarg, phy->status);
5528                } else {
5529                        bfa_trc(phy, phy->offset);
5530                        bfa_phy_write_send(phy);
5531                }
5532                break;
5533        case BFI_PHY_I2H_READ_RSP:
5534                status = be32_to_cpu(m.read->status);
5535                bfa_trc(phy, status);
5536
5537                if (status != BFA_STATUS_OK) {
5538                        phy->status = status;
5539                        phy->op_busy = 0;
5540                        if (phy->cbfn)
5541                                phy->cbfn(phy->cbarg, phy->status);
5542                } else {
5543                        u32 len = be32_to_cpu(m.read->length);
5544                        u16 *buf = (u16 *)(phy->ubuf + phy->offset);
5545                        u16 *dbuf = (u16 *)phy->dbuf_kva;
5546                        int i, sz = len >> 1;
5547
5548                        bfa_trc(phy, phy->offset);
5549                        bfa_trc(phy, len);
5550
5551                        for (i = 0; i < sz; i++)
5552                                buf[i] = be16_to_cpu(dbuf[i]);
5553
5554                        phy->residue -= len;
5555                        phy->offset += len;
5556
5557                        if (phy->residue == 0) {
5558                                phy->status = status;
5559                                phy->op_busy = 0;
5560                                if (phy->cbfn)
5561                                        phy->cbfn(phy->cbarg, phy->status);
5562                        } else
5563                                bfa_phy_read_send(phy);
5564                }
5565                break;
5566        default:
5567                WARN_ON(1);
5568        }
5569}
5570
5571/*
5572 *      DCONF module specific
5573 */
5574
5575BFA_MODULE(dconf);
5576
5577/*
5578 * DCONF state machine events
5579 */
5580enum bfa_dconf_event {
5581        BFA_DCONF_SM_INIT               = 1,    /* dconf Init */
5582        BFA_DCONF_SM_FLASH_COMP         = 2,    /* read/write to flash */
5583        BFA_DCONF_SM_WR                 = 3,    /* binding change, map */
5584        BFA_DCONF_SM_TIMEOUT            = 4,    /* Start timer */
5585        BFA_DCONF_SM_EXIT               = 5,    /* exit dconf module */
5586        BFA_DCONF_SM_IOCDISABLE         = 6,    /* IOC disable event */
5587};
5588
5589/* forward declaration of DCONF state machine */
5590static void bfa_dconf_sm_uninit(struct bfa_dconf_mod_s *dconf,
5591                                enum bfa_dconf_event event);
5592static void bfa_dconf_sm_flash_read(struct bfa_dconf_mod_s *dconf,
5593                                enum bfa_dconf_event event);
5594static void bfa_dconf_sm_ready(struct bfa_dconf_mod_s *dconf,
5595                                enum bfa_dconf_event event);
5596static void bfa_dconf_sm_dirty(struct bfa_dconf_mod_s *dconf,
5597                                enum bfa_dconf_event event);
5598static void bfa_dconf_sm_sync(struct bfa_dconf_mod_s *dconf,
5599                                enum bfa_dconf_event event);
5600static void bfa_dconf_sm_final_sync(struct bfa_dconf_mod_s *dconf,
5601                                enum bfa_dconf_event event);
5602static void bfa_dconf_sm_iocdown_dirty(struct bfa_dconf_mod_s *dconf,
5603                                enum bfa_dconf_event event);
5604
5605static void bfa_dconf_cbfn(void *dconf, bfa_status_t status);
5606static void bfa_dconf_timer(void *cbarg);
5607static bfa_status_t bfa_dconf_flash_write(struct bfa_dconf_mod_s *dconf);
5608static void bfa_dconf_init_cb(void *arg, bfa_status_t status);
5609
5610/*
5611 * Beginning state of dconf module. Waiting for an event to start.
5612 */
5613static void
5614bfa_dconf_sm_uninit(struct bfa_dconf_mod_s *dconf, enum bfa_dconf_event event)
5615{
5616        bfa_status_t bfa_status;
5617        bfa_trc(dconf->bfa, event);
5618
5619        switch (event) {
5620        case BFA_DCONF_SM_INIT:
5621                if (dconf->min_cfg) {
5622                        bfa_trc(dconf->bfa, dconf->min_cfg);
5623                        bfa_fsm_send_event(&dconf->bfa->iocfc,
5624                                        IOCFC_E_DCONF_DONE);
5625                        return;
5626                }
5627                bfa_sm_set_state(dconf, bfa_dconf_sm_flash_read);
5628                bfa_timer_start(dconf->bfa, &dconf->timer,
5629                        bfa_dconf_timer, dconf, 2 * BFA_DCONF_UPDATE_TOV);
5630                bfa_status = bfa_flash_read_part(BFA_FLASH(dconf->bfa),
5631                                        BFA_FLASH_PART_DRV, dconf->instance,
5632                                        dconf->dconf,
5633                                        sizeof(struct bfa_dconf_s), 0,
5634                                        bfa_dconf_init_cb, dconf->bfa);
5635                if (bfa_status != BFA_STATUS_OK) {
5636                        bfa_timer_stop(&dconf->timer);
5637                        bfa_dconf_init_cb(dconf->bfa, BFA_STATUS_FAILED);
5638                        bfa_sm_set_state(dconf, bfa_dconf_sm_uninit);
5639                        return;
5640                }
5641                break;
5642        case BFA_DCONF_SM_EXIT:
5643                bfa_fsm_send_event(&dconf->bfa->iocfc, IOCFC_E_DCONF_DONE);
5644        case BFA_DCONF_SM_IOCDISABLE:
5645        case BFA_DCONF_SM_WR:
5646        case BFA_DCONF_SM_FLASH_COMP:
5647                break;
5648        default:
5649                bfa_sm_fault(dconf->bfa, event);
5650        }
5651}
5652
5653/*
5654 * Read flash for dconf entries and make a call back to the driver once done.
5655 */
5656static void
5657bfa_dconf_sm_flash_read(struct bfa_dconf_mod_s *dconf,
5658                        enum bfa_dconf_event event)
5659{
5660        bfa_trc(dconf->bfa, event);
5661
5662        switch (event) {
5663        case BFA_DCONF_SM_FLASH_COMP:
5664                bfa_timer_stop(&dconf->timer);
5665                bfa_sm_set_state(dconf, bfa_dconf_sm_ready);
5666                break;
5667        case BFA_DCONF_SM_TIMEOUT:
5668                bfa_sm_set_state(dconf, bfa_dconf_sm_ready);
5669                bfa_ioc_suspend(&dconf->bfa->ioc);
5670                break;
5671        case BFA_DCONF_SM_EXIT:
5672                bfa_timer_stop(&dconf->timer);
5673                bfa_sm_set_state(dconf, bfa_dconf_sm_uninit);
5674                bfa_fsm_send_event(&dconf->bfa->iocfc, IOCFC_E_DCONF_DONE);
5675                break;
5676        case BFA_DCONF_SM_IOCDISABLE:
5677                bfa_timer_stop(&dconf->timer);
5678                bfa_sm_set_state(dconf, bfa_dconf_sm_uninit);
5679                break;
5680        default:
5681                bfa_sm_fault(dconf->bfa, event);
5682        }
5683}
5684
5685/*
5686 * DCONF Module is in ready state. Has completed the initialization.
5687 */
5688static void
5689bfa_dconf_sm_ready(struct bfa_dconf_mod_s *dconf, enum bfa_dconf_event event)
5690{
5691        bfa_trc(dconf->bfa, event);
5692
5693        switch (event) {
5694        case BFA_DCONF_SM_WR:
5695                bfa_timer_start(dconf->bfa, &dconf->timer,
5696                        bfa_dconf_timer, dconf, BFA_DCONF_UPDATE_TOV);
5697                bfa_sm_set_state(dconf, bfa_dconf_sm_dirty);
5698                break;
5699        case BFA_DCONF_SM_EXIT:
5700                bfa_sm_set_state(dconf, bfa_dconf_sm_uninit);
5701                bfa_fsm_send_event(&dconf->bfa->iocfc, IOCFC_E_DCONF_DONE);
5702                break;
5703        case BFA_DCONF_SM_INIT:
5704        case BFA_DCONF_SM_IOCDISABLE:
5705                break;
5706        default:
5707                bfa_sm_fault(dconf->bfa, event);
5708        }
5709}
5710
5711/*
5712 * entries are dirty, write back to the flash.
5713 */
5714
5715static void
5716bfa_dconf_sm_dirty(struct bfa_dconf_mod_s *dconf, enum bfa_dconf_event event)
5717{
5718        bfa_trc(dconf->bfa, event);
5719
5720        switch (event) {
5721        case BFA_DCONF_SM_TIMEOUT:
5722                bfa_sm_set_state(dconf, bfa_dconf_sm_sync);
5723                bfa_dconf_flash_write(dconf);
5724                break;
5725        case BFA_DCONF_SM_WR:
5726                bfa_timer_stop(&dconf->timer);
5727                bfa_timer_start(dconf->bfa, &dconf->timer,
5728                        bfa_dconf_timer, dconf, BFA_DCONF_UPDATE_TOV);
5729                break;
5730        case BFA_DCONF_SM_EXIT:
5731                bfa_timer_stop(&dconf->timer);
5732                bfa_timer_start(dconf->bfa, &dconf->timer,
5733                        bfa_dconf_timer, dconf, BFA_DCONF_UPDATE_TOV);
5734                bfa_sm_set_state(dconf, bfa_dconf_sm_final_sync);
5735                bfa_dconf_flash_write(dconf);
5736                break;
5737        case BFA_DCONF_SM_FLASH_COMP:
5738                break;
5739        case BFA_DCONF_SM_IOCDISABLE:
5740                bfa_timer_stop(&dconf->timer);
5741                bfa_sm_set_state(dconf, bfa_dconf_sm_iocdown_dirty);
5742                break;
5743        default:
5744                bfa_sm_fault(dconf->bfa, event);
5745        }
5746}
5747
5748/*
5749 * Sync the dconf entries to the flash.
5750 */
5751static void
5752bfa_dconf_sm_final_sync(struct bfa_dconf_mod_s *dconf,
5753                        enum bfa_dconf_event event)
5754{
5755        bfa_trc(dconf->bfa, event);
5756
5757        switch (event) {
5758        case BFA_DCONF_SM_IOCDISABLE:
5759        case BFA_DCONF_SM_FLASH_COMP:
5760                bfa_timer_stop(&dconf->timer);
5761        case BFA_DCONF_SM_TIMEOUT:
5762                bfa_sm_set_state(dconf, bfa_dconf_sm_uninit);
5763                bfa_fsm_send_event(&dconf->bfa->iocfc, IOCFC_E_DCONF_DONE);
5764                break;
5765        default:
5766                bfa_sm_fault(dconf->bfa, event);
5767        }
5768}
5769
5770static void
5771bfa_dconf_sm_sync(struct bfa_dconf_mod_s *dconf, enum bfa_dconf_event event)
5772{
5773        bfa_trc(dconf->bfa, event);
5774
5775        switch (event) {
5776        case BFA_DCONF_SM_FLASH_COMP:
5777                bfa_sm_set_state(dconf, bfa_dconf_sm_ready);
5778                break;
5779        case BFA_DCONF_SM_WR:
5780                bfa_timer_start(dconf->bfa, &dconf->timer,
5781                        bfa_dconf_timer, dconf, BFA_DCONF_UPDATE_TOV);
5782                bfa_sm_set_state(dconf, bfa_dconf_sm_dirty);
5783                break;
5784        case BFA_DCONF_SM_EXIT:
5785                bfa_timer_start(dconf->bfa, &dconf->timer,
5786                        bfa_dconf_timer, dconf, BFA_DCONF_UPDATE_TOV);
5787                bfa_sm_set_state(dconf, bfa_dconf_sm_final_sync);
5788                break;
5789        case BFA_DCONF_SM_IOCDISABLE:
5790                bfa_sm_set_state(dconf, bfa_dconf_sm_iocdown_dirty);
5791                break;
5792        default:
5793                bfa_sm_fault(dconf->bfa, event);
5794        }
5795}
5796
5797static void
5798bfa_dconf_sm_iocdown_dirty(struct bfa_dconf_mod_s *dconf,
5799                        enum bfa_dconf_event event)
5800{
5801        bfa_trc(dconf->bfa, event);
5802
5803        switch (event) {
5804        case BFA_DCONF_SM_INIT:
5805                bfa_timer_start(dconf->bfa, &dconf->timer,
5806                        bfa_dconf_timer, dconf, BFA_DCONF_UPDATE_TOV);
5807                bfa_sm_set_state(dconf, bfa_dconf_sm_dirty);
5808                break;
5809        case BFA_DCONF_SM_EXIT:
5810                bfa_sm_set_state(dconf, bfa_dconf_sm_uninit);
5811                bfa_fsm_send_event(&dconf->bfa->iocfc, IOCFC_E_DCONF_DONE);
5812                break;
5813        case BFA_DCONF_SM_IOCDISABLE:
5814                break;
5815        default:
5816                bfa_sm_fault(dconf->bfa, event);
5817        }
5818}
5819
5820/*
5821 * Compute and return memory needed by DRV_CFG module.
5822 */
5823static void
5824bfa_dconf_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *meminfo,
5825                  struct bfa_s *bfa)
5826{
5827        struct bfa_mem_kva_s *dconf_kva = BFA_MEM_DCONF_KVA(bfa);
5828
5829        if (cfg->drvcfg.min_cfg)
5830                bfa_mem_kva_setup(meminfo, dconf_kva,
5831                                sizeof(struct bfa_dconf_hdr_s));
5832        else
5833                bfa_mem_kva_setup(meminfo, dconf_kva,
5834                                sizeof(struct bfa_dconf_s));
5835}
5836
5837static void
5838bfa_dconf_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
5839                struct bfa_pcidev_s *pcidev)
5840{
5841        struct bfa_dconf_mod_s *dconf = BFA_DCONF_MOD(bfa);
5842
5843        dconf->bfad = bfad;
5844        dconf->bfa = bfa;
5845        dconf->instance = bfa->ioc.port_id;
5846        bfa_trc(bfa, dconf->instance);
5847
5848        dconf->dconf = (struct bfa_dconf_s *) bfa_mem_kva_curp(dconf);
5849        if (cfg->drvcfg.min_cfg) {
5850                bfa_mem_kva_curp(dconf) += sizeof(struct bfa_dconf_hdr_s);
5851                dconf->min_cfg = BFA_TRUE;
5852        } else {
5853                dconf->min_cfg = BFA_FALSE;
5854                bfa_mem_kva_curp(dconf) += sizeof(struct bfa_dconf_s);
5855        }
5856
5857        bfa_dconf_read_data_valid(bfa) = BFA_FALSE;
5858        bfa_sm_set_state(dconf, bfa_dconf_sm_uninit);
5859}
5860
5861static void
5862bfa_dconf_init_cb(void *arg, bfa_status_t status)
5863{
5864        struct bfa_s *bfa = arg;
5865        struct bfa_dconf_mod_s *dconf = BFA_DCONF_MOD(bfa);
5866
5867        if (status == BFA_STATUS_OK) {
5868                bfa_dconf_read_data_valid(bfa) = BFA_TRUE;
5869                if (dconf->dconf->hdr.signature != BFI_DCONF_SIGNATURE)
5870                        dconf->dconf->hdr.signature = BFI_DCONF_SIGNATURE;
5871                if (dconf->dconf->hdr.version != BFI_DCONF_VERSION)
5872                        dconf->dconf->hdr.version = BFI_DCONF_VERSION;
5873        }
5874        bfa_sm_send_event(dconf, BFA_DCONF_SM_FLASH_COMP);
5875        bfa_fsm_send_event(&bfa->iocfc, IOCFC_E_DCONF_DONE);
5876}
5877
5878void
5879bfa_dconf_modinit(struct bfa_s *bfa)
5880{
5881        struct bfa_dconf_mod_s *dconf = BFA_DCONF_MOD(bfa);
5882        bfa_sm_send_event(dconf, BFA_DCONF_SM_INIT);
5883}
5884static void
5885bfa_dconf_start(struct bfa_s *bfa)
5886{
5887}
5888
5889static void
5890bfa_dconf_stop(struct bfa_s *bfa)
5891{
5892}
5893
5894static void bfa_dconf_timer(void *cbarg)
5895{
5896        struct bfa_dconf_mod_s *dconf = cbarg;
5897        bfa_sm_send_event(dconf, BFA_DCONF_SM_TIMEOUT);
5898}
5899static void
5900bfa_dconf_iocdisable(struct bfa_s *bfa)
5901{
5902        struct bfa_dconf_mod_s *dconf = BFA_DCONF_MOD(bfa);
5903        bfa_sm_send_event(dconf, BFA_DCONF_SM_IOCDISABLE);
5904}
5905
5906static void
5907bfa_dconf_detach(struct bfa_s *bfa)
5908{
5909}
5910
5911static bfa_status_t
5912bfa_dconf_flash_write(struct bfa_dconf_mod_s *dconf)
5913{
5914        bfa_status_t bfa_status;
5915        bfa_trc(dconf->bfa, 0);
5916
5917        bfa_status = bfa_flash_update_part(BFA_FLASH(dconf->bfa),
5918                                BFA_FLASH_PART_DRV, dconf->instance,
5919                                dconf->dconf,  sizeof(struct bfa_dconf_s), 0,
5920                                bfa_dconf_cbfn, dconf);
5921        if (bfa_status != BFA_STATUS_OK)
5922                WARN_ON(bfa_status);
5923        bfa_trc(dconf->bfa, bfa_status);
5924
5925        return bfa_status;
5926}
5927
5928bfa_status_t
5929bfa_dconf_update(struct bfa_s *bfa)
5930{
5931        struct bfa_dconf_mod_s *dconf = BFA_DCONF_MOD(bfa);
5932        bfa_trc(dconf->bfa, 0);
5933        if (bfa_sm_cmp_state(dconf, bfa_dconf_sm_iocdown_dirty))
5934                return BFA_STATUS_FAILED;
5935
5936        if (dconf->min_cfg) {
5937                bfa_trc(dconf->bfa, dconf->min_cfg);
5938                return BFA_STATUS_FAILED;
5939        }
5940
5941        bfa_sm_send_event(dconf, BFA_DCONF_SM_WR);
5942        return BFA_STATUS_OK;
5943}
5944
5945static void
5946bfa_dconf_cbfn(void *arg, bfa_status_t status)
5947{
5948        struct bfa_dconf_mod_s *dconf = arg;
5949        WARN_ON(status);
5950        bfa_sm_send_event(dconf, BFA_DCONF_SM_FLASH_COMP);
5951}
5952
5953void
5954bfa_dconf_modexit(struct bfa_s *bfa)
5955{
5956        struct bfa_dconf_mod_s *dconf = BFA_DCONF_MOD(bfa);
5957        bfa_sm_send_event(dconf, BFA_DCONF_SM_EXIT);
5958}
5959
5960/*
5961 * FRU specific functions
5962 */
5963
5964#define BFA_FRU_DMA_BUF_SZ      0x02000         /* 8k dma buffer */
5965#define BFA_FRU_CHINOOK_MAX_SIZE 0x10000
5966#define BFA_FRU_LIGHTNING_MAX_SIZE 0x200
5967
5968static void
5969bfa_fru_notify(void *cbarg, enum bfa_ioc_event_e event)
5970{
5971        struct bfa_fru_s *fru = cbarg;
5972
5973        bfa_trc(fru, event);
5974
5975        switch (event) {
5976        case BFA_IOC_E_DISABLED:
5977        case BFA_IOC_E_FAILED:
5978                if (fru->op_busy) {
5979                        fru->status = BFA_STATUS_IOC_FAILURE;
5980                        fru->cbfn(fru->cbarg, fru->status);
5981                        fru->op_busy = 0;
5982                }
5983                break;
5984
5985        default:
5986                break;
5987        }
5988}
5989
5990/*
5991 * Send fru write request.
5992 *
5993 * @param[in] cbarg - callback argument
5994 */
5995static void
5996bfa_fru_write_send(void *cbarg, enum bfi_fru_h2i_msgs msg_type)
5997{
5998        struct bfa_fru_s *fru = cbarg;
5999        struct bfi_fru_write_req_s *msg =
6000                        (struct bfi_fru_write_req_s *) fru->mb.msg;
6001        u32 len;
6002
6003        msg->offset = cpu_to_be32(fru->addr_off + fru->offset);
6004        len = (fru->residue < BFA_FRU_DMA_BUF_SZ) ?
6005                                fru->residue : BFA_FRU_DMA_BUF_SZ;
6006        msg->length = cpu_to_be32(len);
6007
6008        /*
6009         * indicate if it's the last msg of the whole write operation
6010         */
6011        msg->last = (len == fru->residue) ? 1 : 0;
6012
6013        bfi_h2i_set(msg->mh, BFI_MC_FRU, msg_type, bfa_ioc_portid(fru->ioc));
6014        bfa_alen_set(&msg->alen, len, fru->dbuf_pa);
6015
6016        memcpy(fru->dbuf_kva, fru->ubuf + fru->offset, len);
6017        bfa_ioc_mbox_queue(fru->ioc, &fru->mb);
6018
6019        fru->residue -= len;
6020        fru->offset += len;
6021}
6022
6023/*
6024 * Send fru read request.
6025 *
6026 * @param[in] cbarg - callback argument
6027 */
6028static void
6029bfa_fru_read_send(void *cbarg, enum bfi_fru_h2i_msgs msg_type)
6030{
6031        struct bfa_fru_s *fru = cbarg;
6032        struct bfi_fru_read_req_s *msg =
6033                        (struct bfi_fru_read_req_s *) fru->mb.msg;
6034        u32 len;
6035
6036        msg->offset = cpu_to_be32(fru->addr_off + fru->offset);
6037        len = (fru->residue < BFA_FRU_DMA_BUF_SZ) ?
6038                                fru->residue : BFA_FRU_DMA_BUF_SZ;
6039        msg->length = cpu_to_be32(len);
6040        bfi_h2i_set(msg->mh, BFI_MC_FRU, msg_type, bfa_ioc_portid(fru->ioc));
6041        bfa_alen_set(&msg->alen, len, fru->dbuf_pa);
6042        bfa_ioc_mbox_queue(fru->ioc, &fru->mb);
6043}
6044
6045/*
6046 * Flash memory info API.
6047 *
6048 * @param[in] mincfg - minimal cfg variable
6049 */
6050u32
6051bfa_fru_meminfo(bfa_boolean_t mincfg)
6052{
6053        /* min driver doesn't need fru */
6054        if (mincfg)
6055                return 0;
6056
6057        return BFA_ROUNDUP(BFA_FRU_DMA_BUF_SZ, BFA_DMA_ALIGN_SZ);
6058}
6059
6060/*
6061 * Flash attach API.
6062 *
6063 * @param[in] fru - fru structure
6064 * @param[in] ioc  - ioc structure
6065 * @param[in] dev  - device structure
6066 * @param[in] trcmod - trace module
6067 * @param[in] logmod - log module
6068 */
6069void
6070bfa_fru_attach(struct bfa_fru_s *fru, struct bfa_ioc_s *ioc, void *dev,
6071        struct bfa_trc_mod_s *trcmod, bfa_boolean_t mincfg)
6072{
6073        fru->ioc = ioc;
6074        fru->trcmod = trcmod;
6075        fru->cbfn = NULL;
6076        fru->cbarg = NULL;
6077        fru->op_busy = 0;
6078
6079        bfa_ioc_mbox_regisr(fru->ioc, BFI_MC_FRU, bfa_fru_intr, fru);
6080        bfa_q_qe_init(&fru->ioc_notify);
6081        bfa_ioc_notify_init(&fru->ioc_notify, bfa_fru_notify, fru);
6082        list_add_tail(&fru->ioc_notify.qe, &fru->ioc->notify_q);
6083
6084        /* min driver doesn't need fru */
6085        if (mincfg) {
6086                fru->dbuf_kva = NULL;
6087                fru->dbuf_pa = 0;
6088        }
6089}
6090
6091/*
6092 * Claim memory for fru
6093 *
6094 * @param[in] fru - fru structure
6095 * @param[in] dm_kva - pointer to virtual memory address
6096 * @param[in] dm_pa - frusical memory address
6097 * @param[in] mincfg - minimal cfg variable
6098 */
6099void
6100bfa_fru_memclaim(struct bfa_fru_s *fru, u8 *dm_kva, u64 dm_pa,
6101        bfa_boolean_t mincfg)
6102{
6103        if (mincfg)
6104                return;
6105
6106        fru->dbuf_kva = dm_kva;
6107        fru->dbuf_pa = dm_pa;
6108        memset(fru->dbuf_kva, 0, BFA_FRU_DMA_BUF_SZ);
6109        dm_kva += BFA_ROUNDUP(BFA_FRU_DMA_BUF_SZ, BFA_DMA_ALIGN_SZ);
6110        dm_pa += BFA_ROUNDUP(BFA_FRU_DMA_BUF_SZ, BFA_DMA_ALIGN_SZ);
6111}
6112
6113/*
6114 * Update fru vpd image.
6115 *
6116 * @param[in] fru - fru structure
6117 * @param[in] buf - update data buffer
6118 * @param[in] len - data buffer length
6119 * @param[in] offset - offset relative to starting address
6120 * @param[in] cbfn - callback function
6121 * @param[in] cbarg - callback argument
6122 *
6123 * Return status.
6124 */
6125bfa_status_t
6126bfa_fruvpd_update(struct bfa_fru_s *fru, void *buf, u32 len, u32 offset,
6127                  bfa_cb_fru_t cbfn, void *cbarg)
6128{
6129        bfa_trc(fru, BFI_FRUVPD_H2I_WRITE_REQ);
6130        bfa_trc(fru, len);
6131        bfa_trc(fru, offset);
6132
6133        if (fru->ioc->asic_gen != BFI_ASIC_GEN_CT2)
6134                return BFA_STATUS_FRU_NOT_PRESENT;
6135
6136        if (fru->ioc->attr->card_type != BFA_MFG_TYPE_CHINOOK)
6137                return BFA_STATUS_CMD_NOTSUPP;
6138
6139        if (!bfa_ioc_is_operational(fru->ioc))
6140                return BFA_STATUS_IOC_NON_OP;
6141
6142        if (fru->op_busy) {
6143                bfa_trc(fru, fru->op_busy);
6144                return BFA_STATUS_DEVBUSY;
6145        }
6146
6147        fru->op_busy = 1;
6148
6149        fru->cbfn = cbfn;
6150        fru->cbarg = cbarg;
6151        fru->residue = len;
6152        fru->offset = 0;
6153        fru->addr_off = offset;
6154        fru->ubuf = buf;
6155
6156        bfa_fru_write_send(fru, BFI_FRUVPD_H2I_WRITE_REQ);
6157
6158        return BFA_STATUS_OK;
6159}
6160
6161/*
6162 * Read fru vpd image.
6163 *
6164 * @param[in] fru - fru structure
6165 * @param[in] buf - read data buffer
6166 * @param[in] len - data buffer length
6167 * @param[in] offset - offset relative to starting address
6168 * @param[in] cbfn - callback function
6169 * @param[in] cbarg - callback argument
6170 *
6171 * Return status.
6172 */
6173bfa_status_t
6174bfa_fruvpd_read(struct bfa_fru_s *fru, void *buf, u32 len, u32 offset,
6175                bfa_cb_fru_t cbfn, void *cbarg)
6176{
6177        bfa_trc(fru, BFI_FRUVPD_H2I_READ_REQ);
6178        bfa_trc(fru, len);
6179        bfa_trc(fru, offset);
6180
6181        if (fru->ioc->asic_gen != BFI_ASIC_GEN_CT2)
6182                return BFA_STATUS_FRU_NOT_PRESENT;
6183
6184        if (fru->ioc->attr->card_type != BFA_MFG_TYPE_CHINOOK)
6185                return BFA_STATUS_CMD_NOTSUPP;
6186
6187        if (!bfa_ioc_is_operational(fru->ioc))
6188                return BFA_STATUS_IOC_NON_OP;
6189
6190        if (fru->op_busy) {
6191                bfa_trc(fru, fru->op_busy);
6192                return BFA_STATUS_DEVBUSY;
6193        }
6194
6195        fru->op_busy = 1;
6196
6197        fru->cbfn = cbfn;
6198        fru->cbarg = cbarg;
6199        fru->residue = len;
6200        fru->offset = 0;
6201        fru->addr_off = offset;
6202        fru->ubuf = buf;
6203        bfa_fru_read_send(fru, BFI_FRUVPD_H2I_READ_REQ);
6204
6205        return BFA_STATUS_OK;
6206}
6207
6208/*
6209 * Get maximum size fru vpd image.
6210 *
6211 * @param[in] fru - fru structure
6212 * @param[out] size - maximum size of fru vpd data
6213 *
6214 * Return status.
6215 */
6216bfa_status_t
6217bfa_fruvpd_get_max_size(struct bfa_fru_s *fru, u32 *max_size)
6218{
6219        if (fru->ioc->asic_gen != BFI_ASIC_GEN_CT2)
6220                return BFA_STATUS_FRU_NOT_PRESENT;
6221
6222        if (!bfa_ioc_is_operational(fru->ioc))
6223                return BFA_STATUS_IOC_NON_OP;
6224
6225        if (fru->ioc->attr->card_type == BFA_MFG_TYPE_CHINOOK)
6226                *max_size = BFA_FRU_CHINOOK_MAX_SIZE;
6227        else
6228                return BFA_STATUS_CMD_NOTSUPP;
6229        return BFA_STATUS_OK;
6230}
6231/*
6232 * tfru write.
6233 *
6234 * @param[in] fru - fru structure
6235 * @param[in] buf - update data buffer
6236 * @param[in] len - data buffer length
6237 * @param[in] offset - offset relative to starting address
6238 * @param[in] cbfn - callback function
6239 * @param[in] cbarg - callback argument
6240 *
6241 * Return status.
6242 */
6243bfa_status_t
6244bfa_tfru_write(struct bfa_fru_s *fru, void *buf, u32 len, u32 offset,
6245               bfa_cb_fru_t cbfn, void *cbarg)
6246{
6247        bfa_trc(fru, BFI_TFRU_H2I_WRITE_REQ);
6248        bfa_trc(fru, len);
6249        bfa_trc(fru, offset);
6250        bfa_trc(fru, *((u8 *) buf));
6251
6252        if (fru->ioc->asic_gen != BFI_ASIC_GEN_CT2)
6253                return BFA_STATUS_FRU_NOT_PRESENT;
6254
6255        if (!bfa_ioc_is_operational(fru->ioc))
6256                return BFA_STATUS_IOC_NON_OP;
6257
6258        if (fru->op_busy) {
6259                bfa_trc(fru, fru->op_busy);
6260                return BFA_STATUS_DEVBUSY;
6261        }
6262
6263        fru->op_busy = 1;
6264
6265        fru->cbfn = cbfn;
6266        fru->cbarg = cbarg;
6267        fru->residue = len;
6268        fru->offset = 0;
6269        fru->addr_off = offset;
6270        fru->ubuf = buf;
6271
6272        bfa_fru_write_send(fru, BFI_TFRU_H2I_WRITE_REQ);
6273
6274        return BFA_STATUS_OK;
6275}
6276
6277/*
6278 * tfru read.
6279 *
6280 * @param[in] fru - fru structure
6281 * @param[in] buf - read data buffer
6282 * @param[in] len - data buffer length
6283 * @param[in] offset - offset relative to starting address
6284 * @param[in] cbfn - callback function
6285 * @param[in] cbarg - callback argument
6286 *
6287 * Return status.
6288 */
6289bfa_status_t
6290bfa_tfru_read(struct bfa_fru_s *fru, void *buf, u32 len, u32 offset,
6291              bfa_cb_fru_t cbfn, void *cbarg)
6292{
6293        bfa_trc(fru, BFI_TFRU_H2I_READ_REQ);
6294        bfa_trc(fru, len);
6295        bfa_trc(fru, offset);
6296
6297        if (fru->ioc->asic_gen != BFI_ASIC_GEN_CT2)
6298                return BFA_STATUS_FRU_NOT_PRESENT;
6299
6300        if (!bfa_ioc_is_operational(fru->ioc))
6301                return BFA_STATUS_IOC_NON_OP;
6302
6303        if (fru->op_busy) {
6304                bfa_trc(fru, fru->op_busy);
6305                return BFA_STATUS_DEVBUSY;
6306        }
6307
6308        fru->op_busy = 1;
6309
6310        fru->cbfn = cbfn;
6311        fru->cbarg = cbarg;
6312        fru->residue = len;
6313        fru->offset = 0;
6314        fru->addr_off = offset;
6315        fru->ubuf = buf;
6316        bfa_fru_read_send(fru, BFI_TFRU_H2I_READ_REQ);
6317
6318        return BFA_STATUS_OK;
6319}
6320
6321/*
6322 * Process fru response messages upon receiving interrupts.
6323 *
6324 * @param[in] fruarg - fru structure
6325 * @param[in] msg - message structure
6326 */
6327void
6328bfa_fru_intr(void *fruarg, struct bfi_mbmsg_s *msg)
6329{
6330        struct bfa_fru_s *fru = fruarg;
6331        struct bfi_fru_rsp_s *rsp = (struct bfi_fru_rsp_s *)msg;
6332        u32 status;
6333
6334        bfa_trc(fru, msg->mh.msg_id);
6335
6336        if (!fru->op_busy) {
6337                /*
6338                 * receiving response after ioc failure
6339                 */
6340                bfa_trc(fru, 0x9999);
6341                return;
6342        }
6343
6344        switch (msg->mh.msg_id) {
6345        case BFI_FRUVPD_I2H_WRITE_RSP:
6346        case BFI_TFRU_I2H_WRITE_RSP:
6347                status = be32_to_cpu(rsp->status);
6348                bfa_trc(fru, status);
6349
6350                if (status != BFA_STATUS_OK || fru->residue == 0) {
6351                        fru->status = status;
6352                        fru->op_busy = 0;
6353                        if (fru->cbfn)
6354                                fru->cbfn(fru->cbarg, fru->status);
6355                } else {
6356                        bfa_trc(fru, fru->offset);
6357                        if (msg->mh.msg_id == BFI_FRUVPD_I2H_WRITE_RSP)
6358                                bfa_fru_write_send(fru,
6359                                        BFI_FRUVPD_H2I_WRITE_REQ);
6360                        else
6361                                bfa_fru_write_send(fru,
6362                                        BFI_TFRU_H2I_WRITE_REQ);
6363                }
6364                break;
6365        case BFI_FRUVPD_I2H_READ_RSP:
6366        case BFI_TFRU_I2H_READ_RSP:
6367                status = be32_to_cpu(rsp->status);
6368                bfa_trc(fru, status);
6369
6370                if (status != BFA_STATUS_OK) {
6371                        fru->status = status;
6372                        fru->op_busy = 0;
6373                        if (fru->cbfn)
6374                                fru->cbfn(fru->cbarg, fru->status);
6375                } else {
6376                        u32 len = be32_to_cpu(rsp->length);
6377
6378                        bfa_trc(fru, fru->offset);
6379                        bfa_trc(fru, len);
6380
6381                        memcpy(fru->ubuf + fru->offset, fru->dbuf_kva, len);
6382                        fru->residue -= len;
6383                        fru->offset += len;
6384
6385                        if (fru->residue == 0) {
6386                                fru->status = status;
6387                                fru->op_busy = 0;
6388                                if (fru->cbfn)
6389                                        fru->cbfn(fru->cbarg, fru->status);
6390                        } else {
6391                                if (msg->mh.msg_id == BFI_FRUVPD_I2H_READ_RSP)
6392                                        bfa_fru_read_send(fru,
6393                                                BFI_FRUVPD_H2I_READ_REQ);
6394                                else
6395                                        bfa_fru_read_send(fru,
6396                                                BFI_TFRU_H2I_READ_REQ);
6397                        }
6398                }
6399                break;
6400        default:
6401                WARN_ON(1);
6402        }
6403}
6404