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