aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/bfa/bfa_ioc.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/bfa/bfa_ioc.c')
-rw-r--r--drivers/scsi/bfa/bfa_ioc.c494
1 files changed, 475 insertions, 19 deletions
diff --git a/drivers/scsi/bfa/bfa_ioc.c b/drivers/scsi/bfa/bfa_ioc.c
index 75ca8752b9f4..0116c1032e25 100644
--- a/drivers/scsi/bfa/bfa_ioc.c
+++ b/drivers/scsi/bfa/bfa_ioc.c
@@ -731,8 +731,7 @@ bfa_iocpf_sm_fwcheck_entry(struct bfa_iocpf_s *iocpf)
731 /* 731 /*
732 * Unlock the hw semaphore. Should be here only once per boot. 732 * Unlock the hw semaphore. Should be here only once per boot.
733 */ 733 */
734 readl(iocpf->ioc->ioc_regs.ioc_sem_reg); 734 bfa_ioc_ownership_reset(iocpf->ioc);
735 writel(1, iocpf->ioc->ioc_regs.ioc_sem_reg);
736 735
737 /* 736 /*
738 * unlock init semaphore. 737 * unlock init semaphore.
@@ -1751,6 +1750,7 @@ bfa_ioc_getattr_reply(struct bfa_ioc_s *ioc)
1751 attr->card_type = be32_to_cpu(attr->card_type); 1750 attr->card_type = be32_to_cpu(attr->card_type);
1752 attr->maxfrsize = be16_to_cpu(attr->maxfrsize); 1751 attr->maxfrsize = be16_to_cpu(attr->maxfrsize);
1753 ioc->fcmode = (attr->port_mode == BFI_PORT_MODE_FC); 1752 ioc->fcmode = (attr->port_mode == BFI_PORT_MODE_FC);
1753 attr->mfg_year = be16_to_cpu(attr->mfg_year);
1754 1754
1755 bfa_fsm_send_event(ioc, IOC_E_FWRSP_GETATTR); 1755 bfa_fsm_send_event(ioc, IOC_E_FWRSP_GETATTR);
1756} 1756}
@@ -2497,6 +2497,9 @@ bfa_ioc_get_adapter_attr(struct bfa_ioc_s *ioc,
2497 ad_attr->cna_capable = bfa_ioc_is_cna(ioc); 2497 ad_attr->cna_capable = bfa_ioc_is_cna(ioc);
2498 ad_attr->trunk_capable = (ad_attr->nports > 1) && 2498 ad_attr->trunk_capable = (ad_attr->nports > 1) &&
2499 !bfa_ioc_is_cna(ioc) && !ad_attr->is_mezz; 2499 !bfa_ioc_is_cna(ioc) && !ad_attr->is_mezz;
2500 ad_attr->mfg_day = ioc_attr->mfg_day;
2501 ad_attr->mfg_month = ioc_attr->mfg_month;
2502 ad_attr->mfg_year = ioc_attr->mfg_year;
2500} 2503}
2501 2504
2502enum bfa_ioc_type_e 2505enum bfa_ioc_type_e
@@ -2923,7 +2926,7 @@ bfa_ioc_poll_fwinit(struct bfa_ioc_s *ioc)
2923 return; 2926 return;
2924 } 2927 }
2925 2928
2926 if (ioc->iocpf.poll_time >= BFA_IOC_TOV) 2929 if (ioc->iocpf.poll_time >= (3 * BFA_IOC_TOV))
2927 bfa_iocpf_timeout(ioc); 2930 bfa_iocpf_timeout(ioc);
2928 else { 2931 else {
2929 ioc->iocpf.poll_time += BFA_IOC_POLL_TOV; 2932 ioc->iocpf.poll_time += BFA_IOC_POLL_TOV;
@@ -3016,7 +3019,6 @@ bfa_ablk_config_swap(struct bfa_ablk_cfg_s *cfg)
3016 struct bfa_ablk_cfg_inst_s *cfg_inst; 3019 struct bfa_ablk_cfg_inst_s *cfg_inst;
3017 int i, j; 3020 int i, j;
3018 u16 be16; 3021 u16 be16;
3019 u32 be32;
3020 3022
3021 for (i = 0; i < BFA_ABLK_MAX; i++) { 3023 for (i = 0; i < BFA_ABLK_MAX; i++) {
3022 cfg_inst = &cfg->inst[i]; 3024 cfg_inst = &cfg->inst[i];
@@ -3027,8 +3029,10 @@ bfa_ablk_config_swap(struct bfa_ablk_cfg_s *cfg)
3027 cfg_inst->pf_cfg[j].num_qpairs = be16_to_cpu(be16); 3029 cfg_inst->pf_cfg[j].num_qpairs = be16_to_cpu(be16);
3028 be16 = cfg_inst->pf_cfg[j].num_vectors; 3030 be16 = cfg_inst->pf_cfg[j].num_vectors;
3029 cfg_inst->pf_cfg[j].num_vectors = be16_to_cpu(be16); 3031 cfg_inst->pf_cfg[j].num_vectors = be16_to_cpu(be16);
3030 be32 = cfg_inst->pf_cfg[j].bw; 3032 be16 = cfg_inst->pf_cfg[j].bw_min;
3031 cfg_inst->pf_cfg[j].bw = be16_to_cpu(be32); 3033 cfg_inst->pf_cfg[j].bw_min = be16_to_cpu(be16);
3034 be16 = cfg_inst->pf_cfg[j].bw_max;
3035 cfg_inst->pf_cfg[j].bw_max = be16_to_cpu(be16);
3032 } 3036 }
3033 } 3037 }
3034} 3038}
@@ -3170,7 +3174,8 @@ bfa_ablk_query(struct bfa_ablk_s *ablk, struct bfa_ablk_cfg_s *ablk_cfg,
3170 3174
3171bfa_status_t 3175bfa_status_t
3172bfa_ablk_pf_create(struct bfa_ablk_s *ablk, u16 *pcifn, 3176bfa_ablk_pf_create(struct bfa_ablk_s *ablk, u16 *pcifn,
3173 u8 port, enum bfi_pcifn_class personality, int bw, 3177 u8 port, enum bfi_pcifn_class personality,
3178 u16 bw_min, u16 bw_max,
3174 bfa_ablk_cbfn_t cbfn, void *cbarg) 3179 bfa_ablk_cbfn_t cbfn, void *cbarg)
3175{ 3180{
3176 struct bfi_ablk_h2i_pf_req_s *m; 3181 struct bfi_ablk_h2i_pf_req_s *m;
@@ -3194,7 +3199,8 @@ bfa_ablk_pf_create(struct bfa_ablk_s *ablk, u16 *pcifn,
3194 bfi_h2i_set(m->mh, BFI_MC_ABLK, BFI_ABLK_H2I_PF_CREATE, 3199 bfi_h2i_set(m->mh, BFI_MC_ABLK, BFI_ABLK_H2I_PF_CREATE,
3195 bfa_ioc_portid(ablk->ioc)); 3200 bfa_ioc_portid(ablk->ioc));
3196 m->pers = cpu_to_be16((u16)personality); 3201 m->pers = cpu_to_be16((u16)personality);
3197 m->bw = cpu_to_be32(bw); 3202 m->bw_min = cpu_to_be16(bw_min);
3203 m->bw_max = cpu_to_be16(bw_max);
3198 m->port = port; 3204 m->port = port;
3199 bfa_ioc_mbox_queue(ablk->ioc, &ablk->mb); 3205 bfa_ioc_mbox_queue(ablk->ioc, &ablk->mb);
3200 3206
@@ -3294,8 +3300,8 @@ bfa_ablk_port_config(struct bfa_ablk_s *ablk, int port, enum bfa_mode_s mode,
3294} 3300}
3295 3301
3296bfa_status_t 3302bfa_status_t
3297bfa_ablk_pf_update(struct bfa_ablk_s *ablk, int pcifn, int bw, 3303bfa_ablk_pf_update(struct bfa_ablk_s *ablk, int pcifn, u16 bw_min,
3298 bfa_ablk_cbfn_t cbfn, void *cbarg) 3304 u16 bw_max, bfa_ablk_cbfn_t cbfn, void *cbarg)
3299{ 3305{
3300 struct bfi_ablk_h2i_pf_req_s *m; 3306 struct bfi_ablk_h2i_pf_req_s *m;
3301 3307
@@ -3317,7 +3323,8 @@ bfa_ablk_pf_update(struct bfa_ablk_s *ablk, int pcifn, int bw,
3317 bfi_h2i_set(m->mh, BFI_MC_ABLK, BFI_ABLK_H2I_PF_UPDATE, 3323 bfi_h2i_set(m->mh, BFI_MC_ABLK, BFI_ABLK_H2I_PF_UPDATE,
3318 bfa_ioc_portid(ablk->ioc)); 3324 bfa_ioc_portid(ablk->ioc));
3319 m->pcifn = (u8)pcifn; 3325 m->pcifn = (u8)pcifn;
3320 m->bw = cpu_to_be32(bw); 3326 m->bw_min = cpu_to_be16(bw_min);
3327 m->bw_max = cpu_to_be16(bw_max);
3321 bfa_ioc_mbox_queue(ablk->ioc, &ablk->mb); 3328 bfa_ioc_mbox_queue(ablk->ioc, &ablk->mb);
3322 3329
3323 return BFA_STATUS_OK; 3330 return BFA_STATUS_OK;
@@ -4680,22 +4687,25 @@ diag_tempsensor_comp(struct bfa_diag_s *diag, bfi_diag_ts_rsp_t *rsp)
4680 diag->tsensor.temp->temp = be16_to_cpu(rsp->temp); 4687 diag->tsensor.temp->temp = be16_to_cpu(rsp->temp);
4681 diag->tsensor.temp->ts_junc = rsp->ts_junc; 4688 diag->tsensor.temp->ts_junc = rsp->ts_junc;
4682 diag->tsensor.temp->ts_brd = rsp->ts_brd; 4689 diag->tsensor.temp->ts_brd = rsp->ts_brd;
4683 diag->tsensor.temp->status = BFA_STATUS_OK;
4684 4690
4685 if (rsp->ts_brd) { 4691 if (rsp->ts_brd) {
4692 /* tsensor.temp->status is brd_temp status */
4693 diag->tsensor.temp->status = rsp->status;
4686 if (rsp->status == BFA_STATUS_OK) { 4694 if (rsp->status == BFA_STATUS_OK) {
4687 diag->tsensor.temp->brd_temp = 4695 diag->tsensor.temp->brd_temp =
4688 be16_to_cpu(rsp->brd_temp); 4696 be16_to_cpu(rsp->brd_temp);
4689 } else { 4697 } else
4690 bfa_trc(diag, rsp->status);
4691 diag->tsensor.temp->brd_temp = 0; 4698 diag->tsensor.temp->brd_temp = 0;
4692 diag->tsensor.temp->status = BFA_STATUS_DEVBUSY;
4693 }
4694 } 4699 }
4700
4701 bfa_trc(diag, rsp->status);
4695 bfa_trc(diag, rsp->ts_junc); 4702 bfa_trc(diag, rsp->ts_junc);
4696 bfa_trc(diag, rsp->temp); 4703 bfa_trc(diag, rsp->temp);
4697 bfa_trc(diag, rsp->ts_brd); 4704 bfa_trc(diag, rsp->ts_brd);
4698 bfa_trc(diag, rsp->brd_temp); 4705 bfa_trc(diag, rsp->brd_temp);
4706
4707 /* tsensor status is always good bcos we always have junction temp */
4708 diag->tsensor.status = BFA_STATUS_OK;
4699 diag->tsensor.cbfn(diag->tsensor.cbarg, diag->tsensor.status); 4709 diag->tsensor.cbfn(diag->tsensor.cbarg, diag->tsensor.status);
4700 diag->tsensor.lock = 0; 4710 diag->tsensor.lock = 0;
4701} 4711}
@@ -4924,6 +4934,7 @@ bfa_diag_tsensor_query(struct bfa_diag_s *diag,
4924 diag->tsensor.temp = result; 4934 diag->tsensor.temp = result;
4925 diag->tsensor.cbfn = cbfn; 4935 diag->tsensor.cbfn = cbfn;
4926 diag->tsensor.cbarg = cbarg; 4936 diag->tsensor.cbarg = cbarg;
4937 diag->tsensor.status = BFA_STATUS_OK;
4927 4938
4928 /* Send msg to fw */ 4939 /* Send msg to fw */
4929 diag_tempsensor_send(diag); 4940 diag_tempsensor_send(diag);
@@ -5615,7 +5626,7 @@ bfa_dconf_sm_uninit(struct bfa_dconf_mod_s *dconf, enum bfa_dconf_event event)
5615 } 5626 }
5616 bfa_sm_set_state(dconf, bfa_dconf_sm_flash_read); 5627 bfa_sm_set_state(dconf, bfa_dconf_sm_flash_read);
5617 bfa_timer_start(dconf->bfa, &dconf->timer, 5628 bfa_timer_start(dconf->bfa, &dconf->timer,
5618 bfa_dconf_timer, dconf, BFA_DCONF_UPDATE_TOV); 5629 bfa_dconf_timer, dconf, 2 * BFA_DCONF_UPDATE_TOV);
5619 bfa_status = bfa_flash_read_part(BFA_FLASH(dconf->bfa), 5630 bfa_status = bfa_flash_read_part(BFA_FLASH(dconf->bfa),
5620 BFA_FLASH_PART_DRV, dconf->instance, 5631 BFA_FLASH_PART_DRV, dconf->instance,
5621 dconf->dconf, 5632 dconf->dconf,
@@ -5655,7 +5666,7 @@ bfa_dconf_sm_flash_read(struct bfa_dconf_mod_s *dconf,
5655 break; 5666 break;
5656 case BFA_DCONF_SM_TIMEOUT: 5667 case BFA_DCONF_SM_TIMEOUT:
5657 bfa_sm_set_state(dconf, bfa_dconf_sm_ready); 5668 bfa_sm_set_state(dconf, bfa_dconf_sm_ready);
5658 bfa_fsm_send_event(&dconf->bfa->iocfc, IOCFC_E_IOC_FAILED); 5669 bfa_ioc_suspend(&dconf->bfa->ioc);
5659 break; 5670 break;
5660 case BFA_DCONF_SM_EXIT: 5671 case BFA_DCONF_SM_EXIT:
5661 bfa_timer_stop(&dconf->timer); 5672 bfa_timer_stop(&dconf->timer);
@@ -5853,7 +5864,6 @@ bfa_dconf_init_cb(void *arg, bfa_status_t status)
5853 struct bfa_s *bfa = arg; 5864 struct bfa_s *bfa = arg;
5854 struct bfa_dconf_mod_s *dconf = BFA_DCONF_MOD(bfa); 5865 struct bfa_dconf_mod_s *dconf = BFA_DCONF_MOD(bfa);
5855 5866
5856 bfa_sm_send_event(dconf, BFA_DCONF_SM_FLASH_COMP);
5857 if (status == BFA_STATUS_OK) { 5867 if (status == BFA_STATUS_OK) {
5858 bfa_dconf_read_data_valid(bfa) = BFA_TRUE; 5868 bfa_dconf_read_data_valid(bfa) = BFA_TRUE;
5859 if (dconf->dconf->hdr.signature != BFI_DCONF_SIGNATURE) 5869 if (dconf->dconf->hdr.signature != BFI_DCONF_SIGNATURE)
@@ -5861,6 +5871,7 @@ bfa_dconf_init_cb(void *arg, bfa_status_t status)
5861 if (dconf->dconf->hdr.version != BFI_DCONF_VERSION) 5871 if (dconf->dconf->hdr.version != BFI_DCONF_VERSION)
5862 dconf->dconf->hdr.version = BFI_DCONF_VERSION; 5872 dconf->dconf->hdr.version = BFI_DCONF_VERSION;
5863 } 5873 }
5874 bfa_sm_send_event(dconf, BFA_DCONF_SM_FLASH_COMP);
5864 bfa_fsm_send_event(&bfa->iocfc, IOCFC_E_DCONF_DONE); 5875 bfa_fsm_send_event(&bfa->iocfc, IOCFC_E_DCONF_DONE);
5865} 5876}
5866 5877
@@ -5945,3 +5956,448 @@ bfa_dconf_modexit(struct bfa_s *bfa)
5945 struct bfa_dconf_mod_s *dconf = BFA_DCONF_MOD(bfa); 5956 struct bfa_dconf_mod_s *dconf = BFA_DCONF_MOD(bfa);
5946 bfa_sm_send_event(dconf, BFA_DCONF_SM_EXIT); 5957 bfa_sm_send_event(dconf, BFA_DCONF_SM_EXIT);
5947} 5958}
5959
5960/*
5961 * FRU specific functions
5962 */
5963
5964#define BFA_FRU_DMA_BUF_SZ 0x02000 /* 8k dma buffer */
5965#define BFA_FRU_CHINOOK_MAX_SIZE 0x10000
5966#define BFA_FRU_LIGHTNING_MAX_SIZE 0x200
5967
5968static void
5969bfa_fru_notify(void *cbarg, enum bfa_ioc_event_e event)
5970{
5971 struct bfa_fru_s *fru = cbarg;
5972
5973 bfa_trc(fru, event);
5974
5975 switch (event) {
5976 case BFA_IOC_E_DISABLED:
5977 case BFA_IOC_E_FAILED:
5978 if (fru->op_busy) {
5979 fru->status = BFA_STATUS_IOC_FAILURE;
5980 fru->cbfn(fru->cbarg, fru->status);
5981 fru->op_busy = 0;
5982 }
5983 break;
5984
5985 default:
5986 break;
5987 }
5988}
5989
5990/*
5991 * Send fru write request.
5992 *
5993 * @param[in] cbarg - callback argument
5994 */
5995static void
5996bfa_fru_write_send(void *cbarg, enum bfi_fru_h2i_msgs msg_type)
5997{
5998 struct bfa_fru_s *fru = cbarg;
5999 struct bfi_fru_write_req_s *msg =
6000 (struct bfi_fru_write_req_s *) fru->mb.msg;
6001 u32 len;
6002
6003 msg->offset = cpu_to_be32(fru->addr_off + fru->offset);
6004 len = (fru->residue < BFA_FRU_DMA_BUF_SZ) ?
6005 fru->residue : BFA_FRU_DMA_BUF_SZ;
6006 msg->length = cpu_to_be32(len);
6007
6008 /*
6009 * indicate if it's the last msg of the whole write operation
6010 */
6011 msg->last = (len == fru->residue) ? 1 : 0;
6012
6013 bfi_h2i_set(msg->mh, BFI_MC_FRU, msg_type, bfa_ioc_portid(fru->ioc));
6014 bfa_alen_set(&msg->alen, len, fru->dbuf_pa);
6015
6016 memcpy(fru->dbuf_kva, fru->ubuf + fru->offset, len);
6017 bfa_ioc_mbox_queue(fru->ioc, &fru->mb);
6018
6019 fru->residue -= len;
6020 fru->offset += len;
6021}
6022
6023/*
6024 * Send fru read request.
6025 *
6026 * @param[in] cbarg - callback argument
6027 */
6028static void
6029bfa_fru_read_send(void *cbarg, enum bfi_fru_h2i_msgs msg_type)
6030{
6031 struct bfa_fru_s *fru = cbarg;
6032 struct bfi_fru_read_req_s *msg =
6033 (struct bfi_fru_read_req_s *) fru->mb.msg;
6034 u32 len;
6035
6036 msg->offset = cpu_to_be32(fru->addr_off + fru->offset);
6037 len = (fru->residue < BFA_FRU_DMA_BUF_SZ) ?
6038 fru->residue : BFA_FRU_DMA_BUF_SZ;
6039 msg->length = cpu_to_be32(len);
6040 bfi_h2i_set(msg->mh, BFI_MC_FRU, msg_type, bfa_ioc_portid(fru->ioc));
6041 bfa_alen_set(&msg->alen, len, fru->dbuf_pa);
6042 bfa_ioc_mbox_queue(fru->ioc, &fru->mb);
6043}
6044
6045/*
6046 * Flash memory info API.
6047 *
6048 * @param[in] mincfg - minimal cfg variable
6049 */
6050u32
6051bfa_fru_meminfo(bfa_boolean_t mincfg)
6052{
6053 /* min driver doesn't need fru */
6054 if (mincfg)
6055 return 0;
6056
6057 return BFA_ROUNDUP(BFA_FRU_DMA_BUF_SZ, BFA_DMA_ALIGN_SZ);
6058}
6059
6060/*
6061 * Flash attach API.
6062 *
6063 * @param[in] fru - fru structure
6064 * @param[in] ioc - ioc structure
6065 * @param[in] dev - device structure
6066 * @param[in] trcmod - trace module
6067 * @param[in] logmod - log module
6068 */
6069void
6070bfa_fru_attach(struct bfa_fru_s *fru, struct bfa_ioc_s *ioc, void *dev,
6071 struct bfa_trc_mod_s *trcmod, bfa_boolean_t mincfg)
6072{
6073 fru->ioc = ioc;
6074 fru->trcmod = trcmod;
6075 fru->cbfn = NULL;
6076 fru->cbarg = NULL;
6077 fru->op_busy = 0;
6078
6079 bfa_ioc_mbox_regisr(fru->ioc, BFI_MC_FRU, bfa_fru_intr, fru);
6080 bfa_q_qe_init(&fru->ioc_notify);
6081 bfa_ioc_notify_init(&fru->ioc_notify, bfa_fru_notify, fru);
6082 list_add_tail(&fru->ioc_notify.qe, &fru->ioc->notify_q);
6083
6084 /* min driver doesn't need fru */
6085 if (mincfg) {
6086 fru->dbuf_kva = NULL;
6087 fru->dbuf_pa = 0;
6088 }
6089}
6090
6091/*
6092 * Claim memory for fru
6093 *
6094 * @param[in] fru - fru structure
6095 * @param[in] dm_kva - pointer to virtual memory address
6096 * @param[in] dm_pa - frusical memory address
6097 * @param[in] mincfg - minimal cfg variable
6098 */
6099void
6100bfa_fru_memclaim(struct bfa_fru_s *fru, u8 *dm_kva, u64 dm_pa,
6101 bfa_boolean_t mincfg)
6102{
6103 if (mincfg)
6104 return;
6105
6106 fru->dbuf_kva = dm_kva;
6107 fru->dbuf_pa = dm_pa;
6108 memset(fru->dbuf_kva, 0, BFA_FRU_DMA_BUF_SZ);
6109 dm_kva += BFA_ROUNDUP(BFA_FRU_DMA_BUF_SZ, BFA_DMA_ALIGN_SZ);
6110 dm_pa += BFA_ROUNDUP(BFA_FRU_DMA_BUF_SZ, BFA_DMA_ALIGN_SZ);
6111}
6112
6113/*
6114 * Update fru vpd image.
6115 *
6116 * @param[in] fru - fru structure
6117 * @param[in] buf - update data buffer
6118 * @param[in] len - data buffer length
6119 * @param[in] offset - offset relative to starting address
6120 * @param[in] cbfn - callback function
6121 * @param[in] cbarg - callback argument
6122 *
6123 * Return status.
6124 */
6125bfa_status_t
6126bfa_fruvpd_update(struct bfa_fru_s *fru, void *buf, u32 len, u32 offset,
6127 bfa_cb_fru_t cbfn, void *cbarg)
6128{
6129 bfa_trc(fru, BFI_FRUVPD_H2I_WRITE_REQ);
6130 bfa_trc(fru, len);
6131 bfa_trc(fru, offset);
6132
6133 if (fru->ioc->asic_gen != BFI_ASIC_GEN_CT2)
6134 return BFA_STATUS_FRU_NOT_PRESENT;
6135
6136 if (fru->ioc->attr->card_type != BFA_MFG_TYPE_CHINOOK)
6137 return BFA_STATUS_CMD_NOTSUPP;
6138
6139 if (!bfa_ioc_is_operational(fru->ioc))
6140 return BFA_STATUS_IOC_NON_OP;
6141
6142 if (fru->op_busy) {
6143 bfa_trc(fru, fru->op_busy);
6144 return BFA_STATUS_DEVBUSY;
6145 }
6146
6147 fru->op_busy = 1;
6148
6149 fru->cbfn = cbfn;
6150 fru->cbarg = cbarg;
6151 fru->residue = len;
6152 fru->offset = 0;
6153 fru->addr_off = offset;
6154 fru->ubuf = buf;
6155
6156 bfa_fru_write_send(fru, BFI_FRUVPD_H2I_WRITE_REQ);
6157
6158 return BFA_STATUS_OK;
6159}
6160
6161/*
6162 * Read fru vpd image.
6163 *
6164 * @param[in] fru - fru structure
6165 * @param[in] buf - read data buffer
6166 * @param[in] len - data buffer length
6167 * @param[in] offset - offset relative to starting address
6168 * @param[in] cbfn - callback function
6169 * @param[in] cbarg - callback argument
6170 *
6171 * Return status.
6172 */
6173bfa_status_t
6174bfa_fruvpd_read(struct bfa_fru_s *fru, void *buf, u32 len, u32 offset,
6175 bfa_cb_fru_t cbfn, void *cbarg)
6176{
6177 bfa_trc(fru, BFI_FRUVPD_H2I_READ_REQ);
6178 bfa_trc(fru, len);
6179 bfa_trc(fru, offset);
6180
6181 if (fru->ioc->asic_gen != BFI_ASIC_GEN_CT2)
6182 return BFA_STATUS_FRU_NOT_PRESENT;
6183
6184 if (fru->ioc->attr->card_type != BFA_MFG_TYPE_CHINOOK)
6185 return BFA_STATUS_CMD_NOTSUPP;
6186
6187 if (!bfa_ioc_is_operational(fru->ioc))
6188 return BFA_STATUS_IOC_NON_OP;
6189
6190 if (fru->op_busy) {
6191 bfa_trc(fru, fru->op_busy);
6192 return BFA_STATUS_DEVBUSY;
6193 }
6194
6195 fru->op_busy = 1;
6196
6197 fru->cbfn = cbfn;
6198 fru->cbarg = cbarg;
6199 fru->residue = len;
6200 fru->offset = 0;
6201 fru->addr_off = offset;
6202 fru->ubuf = buf;
6203 bfa_fru_read_send(fru, BFI_FRUVPD_H2I_READ_REQ);
6204
6205 return BFA_STATUS_OK;
6206}
6207
6208/*
6209 * Get maximum size fru vpd image.
6210 *
6211 * @param[in] fru - fru structure
6212 * @param[out] size - maximum size of fru vpd data
6213 *
6214 * Return status.
6215 */
6216bfa_status_t
6217bfa_fruvpd_get_max_size(struct bfa_fru_s *fru, u32 *max_size)
6218{
6219 if (fru->ioc->asic_gen != BFI_ASIC_GEN_CT2)
6220 return BFA_STATUS_FRU_NOT_PRESENT;
6221
6222 if (!bfa_ioc_is_operational(fru->ioc))
6223 return BFA_STATUS_IOC_NON_OP;
6224
6225 if (fru->ioc->attr->card_type == BFA_MFG_TYPE_CHINOOK)
6226 *max_size = BFA_FRU_CHINOOK_MAX_SIZE;
6227 else
6228 return BFA_STATUS_CMD_NOTSUPP;
6229 return BFA_STATUS_OK;
6230}
6231/*
6232 * tfru write.
6233 *
6234 * @param[in] fru - fru structure
6235 * @param[in] buf - update data buffer
6236 * @param[in] len - data buffer length
6237 * @param[in] offset - offset relative to starting address
6238 * @param[in] cbfn - callback function
6239 * @param[in] cbarg - callback argument
6240 *
6241 * Return status.
6242 */
6243bfa_status_t
6244bfa_tfru_write(struct bfa_fru_s *fru, void *buf, u32 len, u32 offset,
6245 bfa_cb_fru_t cbfn, void *cbarg)
6246{
6247 bfa_trc(fru, BFI_TFRU_H2I_WRITE_REQ);
6248 bfa_trc(fru, len);
6249 bfa_trc(fru, offset);
6250 bfa_trc(fru, *((u8 *) buf));
6251
6252 if (fru->ioc->asic_gen != BFI_ASIC_GEN_CT2)
6253 return BFA_STATUS_FRU_NOT_PRESENT;
6254
6255 if (!bfa_ioc_is_operational(fru->ioc))
6256 return BFA_STATUS_IOC_NON_OP;
6257
6258 if (fru->op_busy) {
6259 bfa_trc(fru, fru->op_busy);
6260 return BFA_STATUS_DEVBUSY;
6261 }
6262
6263 fru->op_busy = 1;
6264
6265 fru->cbfn = cbfn;
6266 fru->cbarg = cbarg;
6267 fru->residue = len;
6268 fru->offset = 0;
6269 fru->addr_off = offset;
6270 fru->ubuf = buf;
6271
6272 bfa_fru_write_send(fru, BFI_TFRU_H2I_WRITE_REQ);
6273
6274 return BFA_STATUS_OK;
6275}
6276
6277/*
6278 * tfru read.
6279 *
6280 * @param[in] fru - fru structure
6281 * @param[in] buf - read data buffer
6282 * @param[in] len - data buffer length
6283 * @param[in] offset - offset relative to starting address
6284 * @param[in] cbfn - callback function
6285 * @param[in] cbarg - callback argument
6286 *
6287 * Return status.
6288 */
6289bfa_status_t
6290bfa_tfru_read(struct bfa_fru_s *fru, void *buf, u32 len, u32 offset,
6291 bfa_cb_fru_t cbfn, void *cbarg)
6292{
6293 bfa_trc(fru, BFI_TFRU_H2I_READ_REQ);
6294 bfa_trc(fru, len);
6295 bfa_trc(fru, offset);
6296
6297 if (fru->ioc->asic_gen != BFI_ASIC_GEN_CT2)
6298 return BFA_STATUS_FRU_NOT_PRESENT;
6299
6300 if (!bfa_ioc_is_operational(fru->ioc))
6301 return BFA_STATUS_IOC_NON_OP;
6302
6303 if (fru->op_busy) {
6304 bfa_trc(fru, fru->op_busy);
6305 return BFA_STATUS_DEVBUSY;
6306 }
6307
6308 fru->op_busy = 1;
6309
6310 fru->cbfn = cbfn;
6311 fru->cbarg = cbarg;
6312 fru->residue = len;
6313 fru->offset = 0;
6314 fru->addr_off = offset;
6315 fru->ubuf = buf;
6316 bfa_fru_read_send(fru, BFI_TFRU_H2I_READ_REQ);
6317
6318 return BFA_STATUS_OK;
6319}
6320
6321/*
6322 * Process fru response messages upon receiving interrupts.
6323 *
6324 * @param[in] fruarg - fru structure
6325 * @param[in] msg - message structure
6326 */
6327void
6328bfa_fru_intr(void *fruarg, struct bfi_mbmsg_s *msg)
6329{
6330 struct bfa_fru_s *fru = fruarg;
6331 struct bfi_fru_rsp_s *rsp = (struct bfi_fru_rsp_s *)msg;
6332 u32 status;
6333
6334 bfa_trc(fru, msg->mh.msg_id);
6335
6336 if (!fru->op_busy) {
6337 /*
6338 * receiving response after ioc failure
6339 */
6340 bfa_trc(fru, 0x9999);
6341 return;
6342 }
6343
6344 switch (msg->mh.msg_id) {
6345 case BFI_FRUVPD_I2H_WRITE_RSP:
6346 case BFI_TFRU_I2H_WRITE_RSP:
6347 status = be32_to_cpu(rsp->status);
6348 bfa_trc(fru, status);
6349
6350 if (status != BFA_STATUS_OK || fru->residue == 0) {
6351 fru->status = status;
6352 fru->op_busy = 0;
6353 if (fru->cbfn)
6354 fru->cbfn(fru->cbarg, fru->status);
6355 } else {
6356 bfa_trc(fru, fru->offset);
6357 if (msg->mh.msg_id == BFI_FRUVPD_I2H_WRITE_RSP)
6358 bfa_fru_write_send(fru,
6359 BFI_FRUVPD_H2I_WRITE_REQ);
6360 else
6361 bfa_fru_write_send(fru,
6362 BFI_TFRU_H2I_WRITE_REQ);
6363 }
6364 break;
6365 case BFI_FRUVPD_I2H_READ_RSP:
6366 case BFI_TFRU_I2H_READ_RSP:
6367 status = be32_to_cpu(rsp->status);
6368 bfa_trc(fru, status);
6369
6370 if (status != BFA_STATUS_OK) {
6371 fru->status = status;
6372 fru->op_busy = 0;
6373 if (fru->cbfn)
6374 fru->cbfn(fru->cbarg, fru->status);
6375 } else {
6376 u32 len = be32_to_cpu(rsp->length);
6377
6378 bfa_trc(fru, fru->offset);
6379 bfa_trc(fru, len);
6380
6381 memcpy(fru->ubuf + fru->offset, fru->dbuf_kva, len);
6382 fru->residue -= len;
6383 fru->offset += len;
6384
6385 if (fru->residue == 0) {
6386 fru->status = status;
6387 fru->op_busy = 0;
6388 if (fru->cbfn)
6389 fru->cbfn(fru->cbarg, fru->status);
6390 } else {
6391 if (msg->mh.msg_id == BFI_FRUVPD_I2H_READ_RSP)
6392 bfa_fru_read_send(fru,
6393 BFI_FRUVPD_H2I_READ_REQ);
6394 else
6395 bfa_fru_read_send(fru,
6396 BFI_TFRU_H2I_READ_REQ);
6397 }
6398 }
6399 break;
6400 default:
6401 WARN_ON(1);
6402 }
6403}