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