Back to home page

OSCL-LXR

 
 

    


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