root/drivers/scsi/bfa/bfa_ioc.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. bfa_ioc_sm_uninit_entry
  2. bfa_ioc_sm_uninit
  3. bfa_ioc_sm_reset_entry
  4. bfa_ioc_sm_reset
  5. bfa_ioc_sm_enabling_entry
  6. bfa_ioc_sm_enabling
  7. bfa_ioc_sm_getattr_entry
  8. bfa_ioc_sm_getattr
  9. bfa_ioc_sm_op_entry
  10. bfa_ioc_sm_op
  11. bfa_ioc_sm_disabling_entry
  12. bfa_ioc_sm_disabling
  13. bfa_ioc_sm_disabled_entry
  14. bfa_ioc_sm_disabled
  15. bfa_ioc_sm_fail_retry_entry
  16. bfa_ioc_sm_fail_retry
  17. bfa_ioc_sm_fail_entry
  18. bfa_ioc_sm_fail
  19. bfa_ioc_sm_hwfail_entry
  20. bfa_ioc_sm_hwfail
  21. bfa_iocpf_sm_reset_entry
  22. bfa_iocpf_sm_reset
  23. bfa_iocpf_sm_fwcheck_entry
  24. bfa_iocpf_sm_fwcheck
  25. bfa_iocpf_sm_mismatch_entry
  26. bfa_iocpf_sm_mismatch
  27. bfa_iocpf_sm_semwait_entry
  28. bfa_iocpf_sm_semwait
  29. bfa_iocpf_sm_hwinit_entry
  30. bfa_iocpf_sm_hwinit
  31. bfa_iocpf_sm_enabling_entry
  32. bfa_iocpf_sm_enabling
  33. bfa_iocpf_sm_ready_entry
  34. bfa_iocpf_sm_ready
  35. bfa_iocpf_sm_disabling_entry
  36. bfa_iocpf_sm_disabling
  37. bfa_iocpf_sm_disabling_sync_entry
  38. bfa_iocpf_sm_disabling_sync
  39. bfa_iocpf_sm_disabled_entry
  40. bfa_iocpf_sm_disabled
  41. bfa_iocpf_sm_initfail_sync_entry
  42. bfa_iocpf_sm_initfail_sync
  43. bfa_iocpf_sm_initfail_entry
  44. bfa_iocpf_sm_initfail
  45. bfa_iocpf_sm_fail_sync_entry
  46. bfa_iocpf_sm_fail_sync
  47. bfa_iocpf_sm_fail_entry
  48. bfa_iocpf_sm_fail
  49. bfa_ioc_event_notify
  50. bfa_ioc_disable_comp
  51. bfa_ioc_sem_get
  52. bfa_ioc_hw_sem_get
  53. bfa_ioc_lmem_init
  54. bfa_ioc_lpu_start
  55. bfa_ioc_lpu_stop
  56. bfa_ioc_fwver_get
  57. bfa_ioc_fwver_cmp
  58. bfa_ioc_fwver_valid
  59. bfa_ioc_fwver_md5_check
  60. bfa_ioc_fw_ver_compatible
  61. bfa_ioc_flash_fwver_valid
  62. fwhdr_is_ga
  63. bfa_ioc_fw_ver_patch_cmp
  64. bfa_ioc_flash_img_get_chnk
  65. bfa_ioc_flash_fwver_cmp
  66. bfa_ioc_fwsig_invalidate
  67. bfa_ioc_msgflush
  68. bfa_ioc_hwinit
  69. bfa_ioc_timeout
  70. bfa_ioc_mbox_send
  71. bfa_ioc_send_enable
  72. bfa_ioc_send_disable
  73. bfa_ioc_send_getattr
  74. bfa_ioc_hb_check
  75. bfa_ioc_hb_monitor
  76. bfa_ioc_download_fw
  77. bfa_ioc_getattr_reply
  78. bfa_ioc_mbox_attach
  79. bfa_ioc_mbox_poll
  80. bfa_ioc_mbox_flush
  81. bfa_ioc_smem_read
  82. bfa_ioc_smem_clr
  83. bfa_ioc_fail_notify
  84. bfa_ioc_pf_fwmismatch
  85. bfa_ioc_pll_init
  86. bfa_ioc_boot
  87. bfa_ioc_auto_recover
  88. bfa_ioc_is_operational
  89. bfa_ioc_is_initialized
  90. bfa_ioc_msgget
  91. bfa_ioc_isr
  92. bfa_ioc_attach
  93. bfa_ioc_detach
  94. bfa_ioc_pci_init
  95. bfa_ioc_mem_claim
  96. bfa_ioc_enable
  97. bfa_ioc_disable
  98. bfa_ioc_suspend
  99. bfa_ioc_debug_memclaim
  100. bfa_ioc_mbox_register
  101. bfa_ioc_mbox_regisr
  102. bfa_ioc_mbox_queue
  103. bfa_ioc_mbox_isr
  104. bfa_ioc_error_isr
  105. bfa_ioc_is_disabled
  106. bfa_ioc_fw_mismatch
  107. bfa_ioc_adapter_is_disabled
  108. bfa_ioc_reset_fwstate
  109. bfa_ioc_get_adapter_attr
  110. bfa_ioc_get_type
  111. bfa_ioc_get_adapter_serial_num
  112. bfa_ioc_get_adapter_fw_ver
  113. bfa_ioc_get_pci_chip_rev
  114. bfa_ioc_get_adapter_optrom_ver
  115. bfa_ioc_get_adapter_manufacturer
  116. bfa_ioc_get_adapter_model
  117. bfa_ioc_get_state
  118. bfa_ioc_get_attr
  119. bfa_ioc_get_mac
  120. bfa_ioc_get_mfg_mac
  121. bfa_ioc_aen_post
  122. bfa_ioc_debug_fwsave
  123. bfa_ioc_debug_fwtrc
  124. bfa_ioc_send_fwsync
  125. bfa_ioc_fwsync
  126. bfa_ioc_debug_fwcore
  127. bfa_ioc_fw_stats_get
  128. bfa_ioc_fw_stats_clear
  129. bfa_ioc_debug_save_ftrc
  130. bfa_ioc_recover
  131. bfa_iocpf_timeout
  132. bfa_iocpf_sem_timeout
  133. bfa_ioc_poll_fwinit
  134. bfa_iocpf_poll_timeout
  135. bfa_timer_beat
  136. bfa_timer_begin
  137. bfa_timer_stop
  138. bfa_ablk_config_swap
  139. bfa_ablk_isr
  140. bfa_ablk_notify
  141. bfa_ablk_meminfo
  142. bfa_ablk_memclaim
  143. bfa_ablk_attach
  144. bfa_ablk_query
  145. bfa_ablk_pf_create
  146. bfa_ablk_pf_delete
  147. bfa_ablk_adapter_config
  148. bfa_ablk_port_config
  149. bfa_ablk_pf_update
  150. bfa_ablk_optrom_en
  151. bfa_ablk_optrom_dis
  152. bfa_cb_sfp_show
  153. bfa_cb_sfp_state_query
  154. bfa_sfp_notify
  155. bfa_sfp_scn_aen_post
  156. bfa_sfp_getdata_send
  157. bfa_sfp_getdata
  158. bfa_sfp_scn
  159. bfa_sfp_show_comp
  160. bfa_sfp_state_query
  161. bfa_sfp_media_get
  162. bfa_sfp_speed_valid
  163. bfa_sfp_intr
  164. bfa_sfp_meminfo
  165. bfa_sfp_attach
  166. bfa_sfp_memclaim
  167. bfa_sfp_show
  168. bfa_sfp_media
  169. bfa_sfp_speed
  170. bfa_flash_aen_audit_post
  171. bfa_flash_cb
  172. bfa_flash_notify
  173. bfa_flash_query_send
  174. bfa_flash_write_send
  175. bfa_flash_read_send
  176. bfa_flash_erase_send
  177. bfa_flash_intr
  178. bfa_flash_meminfo
  179. bfa_flash_attach
  180. bfa_flash_memclaim
  181. bfa_flash_get_attr
  182. bfa_flash_erase_part
  183. bfa_flash_update_part
  184. bfa_flash_read_part
  185. bfa_diag_notify
  186. bfa_diag_memtest_done
  187. diag_fwping_send
  188. diag_fwping_comp
  189. diag_tempsensor_send
  190. diag_tempsensor_comp
  191. diag_ledtest_send
  192. diag_ledtest_comp
  193. diag_portbeacon_send
  194. diag_portbeacon_comp
  195. bfa_diag_intr
  196. bfa_diag_memtest
  197. bfa_diag_fwping
  198. bfa_diag_tsensor_query
  199. bfa_diag_ledtest
  200. bfa_diag_beacon_port
  201. bfa_diag_meminfo
  202. bfa_diag_attach
  203. bfa_diag_memclaim
  204. bfa_phy_ntoh32
  205. bfa_phy_present
  206. bfa_phy_notify
  207. bfa_phy_query_send
  208. bfa_phy_write_send
  209. bfa_phy_read_send
  210. bfa_phy_stats_send
  211. bfa_phy_meminfo
  212. bfa_phy_attach
  213. bfa_phy_memclaim
  214. bfa_phy_busy
  215. bfa_phy_get_attr
  216. bfa_phy_get_stats
  217. bfa_phy_update
  218. bfa_phy_read
  219. bfa_phy_intr
  220. bfa_dconf_sm_uninit
  221. bfa_dconf_sm_flash_read
  222. bfa_dconf_sm_ready
  223. bfa_dconf_sm_dirty
  224. bfa_dconf_sm_final_sync
  225. bfa_dconf_sm_sync
  226. bfa_dconf_sm_iocdown_dirty
  227. bfa_dconf_meminfo
  228. bfa_dconf_attach
  229. bfa_dconf_init_cb
  230. bfa_dconf_modinit
  231. bfa_dconf_timer
  232. bfa_dconf_iocdisable
  233. bfa_dconf_flash_write
  234. bfa_dconf_update
  235. bfa_dconf_cbfn
  236. bfa_dconf_modexit
  237. bfa_fru_notify
  238. bfa_fru_write_send
  239. bfa_fru_read_send
  240. bfa_fru_meminfo
  241. bfa_fru_attach
  242. bfa_fru_memclaim
  243. bfa_fruvpd_update
  244. bfa_fruvpd_read
  245. bfa_fruvpd_get_max_size
  246. bfa_tfru_write
  247. bfa_tfru_read
  248. bfa_fru_intr
  249. bfa_flash_set_cmd
  250. bfa_flash_set_addr
  251. bfa_flash_cmd_act_check
  252. bfa_flash_fifo_flush
  253. bfa_flash_status_read
  254. bfa_flash_read_start
  255. bfa_flash_read_check
  256. bfa_flash_read_end
  257. bfa_raw_sem_get
  258. bfa_flash_sem_get
  259. bfa_flash_sem_put
  260. bfa_flash_raw_read

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

/* [<][>][^][v][top][bottom][index][help] */