aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKrishna Gudipati <kgudipat@brocade.com>2012-09-21 20:27:14 -0400
committerJames Bottomley <JBottomley@Parallels.com>2012-10-07 06:26:53 -0400
commite6826c96ced7ea8161b2bae52686c99f6fbf8643 (patch)
tree9e95a4e581f2a854b2cfb88d3a6fc26a867d953f
parent4a49b044487dd04e41019b0c8c2aeec3ab090029 (diff)
[SCSI] bfa: Add support to read/update the FRU data.
- Add FRU sub-module to support FRU read/write/update. - Add support to read/write from the temp FRU module. [jejb: fix checkpatch issues] Signed-off-by: Krishna Gudipati <kgudipat@brocade.com> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
-rw-r--r--drivers/scsi/bfa/bfa_core.c14
-rw-r--r--drivers/scsi/bfa/bfa_defs.h1
-rw-r--r--drivers/scsi/bfa/bfa_ioc.c445
-rw-r--r--drivers/scsi/bfa/bfa_ioc.h49
-rw-r--r--drivers/scsi/bfa/bfa_modules.h1
-rw-r--r--drivers/scsi/bfa/bfad_bsg.c127
-rw-r--r--drivers/scsi/bfa/bfad_bsg.h35
-rw-r--r--drivers/scsi/bfa/bfi.h47
-rw-r--r--drivers/scsi/bfa/bfi_ms.h1
9 files changed, 715 insertions, 5 deletions
diff --git a/drivers/scsi/bfa/bfa_core.c b/drivers/scsi/bfa/bfa_core.c
index 89ebd4459bfc..342d7d9c0997 100644
--- a/drivers/scsi/bfa/bfa_core.c
+++ b/drivers/scsi/bfa/bfa_core.c
@@ -165,6 +165,16 @@ bfa_com_phy_attach(struct bfa_s *bfa, bfa_boolean_t mincfg)
165 bfa_phy_memclaim(phy, phy_dma->kva_curp, phy_dma->dma_curp, mincfg); 165 bfa_phy_memclaim(phy, phy_dma->kva_curp, phy_dma->dma_curp, mincfg);
166} 166}
167 167
168static void
169bfa_com_fru_attach(struct bfa_s *bfa, bfa_boolean_t mincfg)
170{
171 struct bfa_fru_s *fru = BFA_FRU(bfa);
172 struct bfa_mem_dma_s *fru_dma = BFA_MEM_FRU_DMA(bfa);
173
174 bfa_fru_attach(fru, &bfa->ioc, bfa, bfa->trcmod, mincfg);
175 bfa_fru_memclaim(fru, fru_dma->kva_curp, fru_dma->dma_curp, mincfg);
176}
177
168/* 178/*
169 * BFA IOC FC related definitions 179 * BFA IOC FC related definitions
170 */ 180 */
@@ -1752,6 +1762,7 @@ bfa_cfg_get_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *meminfo,
1752 struct bfa_mem_dma_s *flash_dma = BFA_MEM_FLASH_DMA(bfa); 1762 struct bfa_mem_dma_s *flash_dma = BFA_MEM_FLASH_DMA(bfa);
1753 struct bfa_mem_dma_s *diag_dma = BFA_MEM_DIAG_DMA(bfa); 1763 struct bfa_mem_dma_s *diag_dma = BFA_MEM_DIAG_DMA(bfa);
1754 struct bfa_mem_dma_s *phy_dma = BFA_MEM_PHY_DMA(bfa); 1764 struct bfa_mem_dma_s *phy_dma = BFA_MEM_PHY_DMA(bfa);
1765 struct bfa_mem_dma_s *fru_dma = BFA_MEM_FRU_DMA(bfa);
1755 1766
1756 WARN_ON((cfg == NULL) || (meminfo == NULL)); 1767 WARN_ON((cfg == NULL) || (meminfo == NULL));
1757 1768
@@ -1776,6 +1787,8 @@ bfa_cfg_get_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *meminfo,
1776 bfa_mem_dma_setup(meminfo, diag_dma, bfa_diag_meminfo()); 1787 bfa_mem_dma_setup(meminfo, diag_dma, bfa_diag_meminfo());
1777 bfa_mem_dma_setup(meminfo, phy_dma, 1788 bfa_mem_dma_setup(meminfo, phy_dma,
1778 bfa_phy_meminfo(cfg->drvcfg.min_cfg)); 1789 bfa_phy_meminfo(cfg->drvcfg.min_cfg));
1790 bfa_mem_dma_setup(meminfo, fru_dma,
1791 bfa_fru_meminfo(cfg->drvcfg.min_cfg));
1779} 1792}
1780 1793
1781/* 1794/*
@@ -1848,6 +1861,7 @@ bfa_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
1848 bfa_com_flash_attach(bfa, cfg->drvcfg.min_cfg); 1861 bfa_com_flash_attach(bfa, cfg->drvcfg.min_cfg);
1849 bfa_com_diag_attach(bfa); 1862 bfa_com_diag_attach(bfa);
1850 bfa_com_phy_attach(bfa, cfg->drvcfg.min_cfg); 1863 bfa_com_phy_attach(bfa, cfg->drvcfg.min_cfg);
1864 bfa_com_fru_attach(bfa, cfg->drvcfg.min_cfg);
1851} 1865}
1852 1866
1853/* 1867/*
diff --git a/drivers/scsi/bfa/bfa_defs.h b/drivers/scsi/bfa/bfa_defs.h
index daf7314d2eea..0efdf312b42c 100644
--- a/drivers/scsi/bfa/bfa_defs.h
+++ b/drivers/scsi/bfa/bfa_defs.h
@@ -196,6 +196,7 @@ enum bfa_status {
196 BFA_STATUS_DPORT_ENABLED = 235, /* D-port mode is already enabled */ 196 BFA_STATUS_DPORT_ENABLED = 235, /* D-port mode is already enabled */
197 BFA_STATUS_DPORT_DISABLED = 236, /* D-port mode is already disabled */ 197 BFA_STATUS_DPORT_DISABLED = 236, /* D-port mode is already disabled */
198 BFA_STATUS_CMD_NOTSUPP_MEZZ = 239, /* Cmd not supported for MEZZ card */ 198 BFA_STATUS_CMD_NOTSUPP_MEZZ = 239, /* Cmd not supported for MEZZ card */
199 BFA_STATUS_FRU_NOT_PRESENT = 240, /* fru module not present */
199 BFA_STATUS_DPORT_ERR = 245, /* D-port mode is enabled */ 200 BFA_STATUS_DPORT_ERR = 245, /* D-port mode is enabled */
200 BFA_STATUS_MAX_VAL /* Unknown error code */ 201 BFA_STATUS_MAX_VAL /* Unknown error code */
201}; 202};
diff --git a/drivers/scsi/bfa/bfa_ioc.c b/drivers/scsi/bfa/bfa_ioc.c
index dea6a5e86776..0116c1032e25 100644
--- a/drivers/scsi/bfa/bfa_ioc.c
+++ b/drivers/scsi/bfa/bfa_ioc.c
@@ -5956,3 +5956,448 @@ bfa_dconf_modexit(struct bfa_s *bfa)
5956 struct bfa_dconf_mod_s *dconf = BFA_DCONF_MOD(bfa); 5956 struct bfa_dconf_mod_s *dconf = BFA_DCONF_MOD(bfa);
5957 bfa_sm_send_event(dconf, BFA_DCONF_SM_EXIT); 5957 bfa_sm_send_event(dconf, BFA_DCONF_SM_EXIT);
5958} 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}
diff --git a/drivers/scsi/bfa/bfa_ioc.h b/drivers/scsi/bfa/bfa_ioc.h
index 0ad221abfc8f..23a90e7b7107 100644
--- a/drivers/scsi/bfa/bfa_ioc.h
+++ b/drivers/scsi/bfa/bfa_ioc.h
@@ -702,6 +702,55 @@ void bfa_phy_memclaim(struct bfa_phy_s *phy,
702void bfa_phy_intr(void *phyarg, struct bfi_mbmsg_s *msg); 702void bfa_phy_intr(void *phyarg, struct bfi_mbmsg_s *msg);
703 703
704/* 704/*
705 * FRU module specific
706 */
707typedef void (*bfa_cb_fru_t) (void *cbarg, bfa_status_t status);
708
709struct bfa_fru_s {
710 struct bfa_ioc_s *ioc; /* back pointer to ioc */
711 struct bfa_trc_mod_s *trcmod; /* trace module */
712 u8 op_busy; /* operation busy flag */
713 u8 rsv[3];
714 u32 residue; /* residual length */
715 u32 offset; /* offset */
716 bfa_status_t status; /* status */
717 u8 *dbuf_kva; /* dma buf virtual address */
718 u64 dbuf_pa; /* dma buf physical address */
719 struct bfa_reqq_wait_s reqq_wait; /* to wait for room in reqq */
720 bfa_cb_fru_t cbfn; /* user callback function */
721 void *cbarg; /* user callback arg */
722 u8 *ubuf; /* user supplied buffer */
723 struct bfa_cb_qe_s hcb_qe; /* comp: BFA callback qelem */
724 u32 addr_off; /* fru address offset */
725 struct bfa_mbox_cmd_s mb; /* mailbox */
726 struct bfa_ioc_notify_s ioc_notify; /* ioc event notify */
727 struct bfa_mem_dma_s fru_dma;
728};
729
730#define BFA_FRU(__bfa) (&(__bfa)->modules.fru)
731#define BFA_MEM_FRU_DMA(__bfa) (&(BFA_FRU(__bfa)->fru_dma))
732
733bfa_status_t bfa_fruvpd_update(struct bfa_fru_s *fru,
734 void *buf, u32 len, u32 offset,
735 bfa_cb_fru_t cbfn, void *cbarg);
736bfa_status_t bfa_fruvpd_read(struct bfa_fru_s *fru,
737 void *buf, u32 len, u32 offset,
738 bfa_cb_fru_t cbfn, void *cbarg);
739bfa_status_t bfa_fruvpd_get_max_size(struct bfa_fru_s *fru, u32 *max_size);
740bfa_status_t bfa_tfru_write(struct bfa_fru_s *fru,
741 void *buf, u32 len, u32 offset,
742 bfa_cb_fru_t cbfn, void *cbarg);
743bfa_status_t bfa_tfru_read(struct bfa_fru_s *fru,
744 void *buf, u32 len, u32 offset,
745 bfa_cb_fru_t cbfn, void *cbarg);
746u32 bfa_fru_meminfo(bfa_boolean_t mincfg);
747void bfa_fru_attach(struct bfa_fru_s *fru, struct bfa_ioc_s *ioc,
748 void *dev, struct bfa_trc_mod_s *trcmod, bfa_boolean_t mincfg);
749void bfa_fru_memclaim(struct bfa_fru_s *fru,
750 u8 *dm_kva, u64 dm_pa, bfa_boolean_t mincfg);
751void bfa_fru_intr(void *fruarg, struct bfi_mbmsg_s *msg);
752
753/*
705 * Driver Config( dconf) specific 754 * Driver Config( dconf) specific
706 */ 755 */
707#define BFI_DCONF_SIGNATURE 0xabcdabcd 756#define BFI_DCONF_SIGNATURE 0xabcdabcd
diff --git a/drivers/scsi/bfa/bfa_modules.h b/drivers/scsi/bfa/bfa_modules.h
index 189fff71e3c2..a14c784ff3fc 100644
--- a/drivers/scsi/bfa/bfa_modules.h
+++ b/drivers/scsi/bfa/bfa_modules.h
@@ -45,6 +45,7 @@ struct bfa_modules_s {
45 struct bfa_diag_s diag_mod; /* diagnostics module */ 45 struct bfa_diag_s diag_mod; /* diagnostics module */
46 struct bfa_phy_s phy; /* phy module */ 46 struct bfa_phy_s phy; /* phy module */
47 struct bfa_dconf_mod_s dconf_mod; /* DCONF common module */ 47 struct bfa_dconf_mod_s dconf_mod; /* DCONF common module */
48 struct bfa_fru_s fru; /* fru module */
48}; 49};
49 50
50/* 51/*
diff --git a/drivers/scsi/bfa/bfad_bsg.c b/drivers/scsi/bfa/bfad_bsg.c
index 0ab1d400ac33..555e7db94a1c 100644
--- a/drivers/scsi/bfa/bfad_bsg.c
+++ b/drivers/scsi/bfa/bfad_bsg.c
@@ -107,9 +107,10 @@ bfad_iocmd_ioc_get_info(struct bfad_s *bfad, void *cmd)
107 107
108 /* set adapter hw path */ 108 /* set adapter hw path */
109 strcpy(iocmd->adapter_hwpath, bfad->pci_name); 109 strcpy(iocmd->adapter_hwpath, bfad->pci_name);
110 i = strlen(iocmd->adapter_hwpath) - 1; 110 for (i = 0; iocmd->adapter_hwpath[i] != ':' && i < BFA_STRING_32; i++)
111 while (iocmd->adapter_hwpath[i] != '.') 111 ;
112 i--; 112 for (; iocmd->adapter_hwpath[++i] != ':' && i < BFA_STRING_32; )
113 ;
113 iocmd->adapter_hwpath[i] = '\0'; 114 iocmd->adapter_hwpath[i] = '\0';
114 iocmd->status = BFA_STATUS_OK; 115 iocmd->status = BFA_STATUS_OK;
115 return 0; 116 return 0;
@@ -2583,6 +2584,109 @@ bfad_iocmd_fcpim_throttle_set(struct bfad_s *bfad, void *cmd)
2583 return 0; 2584 return 0;
2584} 2585}
2585 2586
2587int
2588bfad_iocmd_tfru_read(struct bfad_s *bfad, void *cmd)
2589{
2590 struct bfa_bsg_tfru_s *iocmd =
2591 (struct bfa_bsg_tfru_s *)cmd;
2592 struct bfad_hal_comp fcomp;
2593 unsigned long flags = 0;
2594
2595 init_completion(&fcomp.comp);
2596 spin_lock_irqsave(&bfad->bfad_lock, flags);
2597 iocmd->status = bfa_tfru_read(BFA_FRU(&bfad->bfa),
2598 &iocmd->data, iocmd->len, iocmd->offset,
2599 bfad_hcb_comp, &fcomp);
2600 spin_unlock_irqrestore(&bfad->bfad_lock, flags);
2601 if (iocmd->status == BFA_STATUS_OK) {
2602 wait_for_completion(&fcomp.comp);
2603 iocmd->status = fcomp.status;
2604 }
2605
2606 return 0;
2607}
2608
2609int
2610bfad_iocmd_tfru_write(struct bfad_s *bfad, void *cmd)
2611{
2612 struct bfa_bsg_tfru_s *iocmd =
2613 (struct bfa_bsg_tfru_s *)cmd;
2614 struct bfad_hal_comp fcomp;
2615 unsigned long flags = 0;
2616
2617 init_completion(&fcomp.comp);
2618 spin_lock_irqsave(&bfad->bfad_lock, flags);
2619 iocmd->status = bfa_tfru_write(BFA_FRU(&bfad->bfa),
2620 &iocmd->data, iocmd->len, iocmd->offset,
2621 bfad_hcb_comp, &fcomp);
2622 spin_unlock_irqrestore(&bfad->bfad_lock, flags);
2623 if (iocmd->status == BFA_STATUS_OK) {
2624 wait_for_completion(&fcomp.comp);
2625 iocmd->status = fcomp.status;
2626 }
2627
2628 return 0;
2629}
2630
2631int
2632bfad_iocmd_fruvpd_read(struct bfad_s *bfad, void *cmd)
2633{
2634 struct bfa_bsg_fruvpd_s *iocmd =
2635 (struct bfa_bsg_fruvpd_s *)cmd;
2636 struct bfad_hal_comp fcomp;
2637 unsigned long flags = 0;
2638
2639 init_completion(&fcomp.comp);
2640 spin_lock_irqsave(&bfad->bfad_lock, flags);
2641 iocmd->status = bfa_fruvpd_read(BFA_FRU(&bfad->bfa),
2642 &iocmd->data, iocmd->len, iocmd->offset,
2643 bfad_hcb_comp, &fcomp);
2644 spin_unlock_irqrestore(&bfad->bfad_lock, flags);
2645 if (iocmd->status == BFA_STATUS_OK) {
2646 wait_for_completion(&fcomp.comp);
2647 iocmd->status = fcomp.status;
2648 }
2649
2650 return 0;
2651}
2652
2653int
2654bfad_iocmd_fruvpd_update(struct bfad_s *bfad, void *cmd)
2655{
2656 struct bfa_bsg_fruvpd_s *iocmd =
2657 (struct bfa_bsg_fruvpd_s *)cmd;
2658 struct bfad_hal_comp fcomp;
2659 unsigned long flags = 0;
2660
2661 init_completion(&fcomp.comp);
2662 spin_lock_irqsave(&bfad->bfad_lock, flags);
2663 iocmd->status = bfa_fruvpd_update(BFA_FRU(&bfad->bfa),
2664 &iocmd->data, iocmd->len, iocmd->offset,
2665 bfad_hcb_comp, &fcomp);
2666 spin_unlock_irqrestore(&bfad->bfad_lock, flags);
2667 if (iocmd->status == BFA_STATUS_OK) {
2668 wait_for_completion(&fcomp.comp);
2669 iocmd->status = fcomp.status;
2670 }
2671
2672 return 0;
2673}
2674
2675int
2676bfad_iocmd_fruvpd_get_max_size(struct bfad_s *bfad, void *cmd)
2677{
2678 struct bfa_bsg_fruvpd_max_size_s *iocmd =
2679 (struct bfa_bsg_fruvpd_max_size_s *)cmd;
2680 unsigned long flags = 0;
2681
2682 spin_lock_irqsave(&bfad->bfad_lock, flags);
2683 iocmd->status = bfa_fruvpd_get_max_size(BFA_FRU(&bfad->bfa),
2684 &iocmd->max_size);
2685 spin_unlock_irqrestore(&bfad->bfad_lock, flags);
2686
2687 return 0;
2688}
2689
2586static int 2690static int
2587bfad_iocmd_handler(struct bfad_s *bfad, unsigned int cmd, void *iocmd, 2691bfad_iocmd_handler(struct bfad_s *bfad, unsigned int cmd, void *iocmd,
2588 unsigned int payload_len) 2692 unsigned int payload_len)
@@ -2923,6 +3027,23 @@ bfad_iocmd_handler(struct bfad_s *bfad, unsigned int cmd, void *iocmd,
2923 case IOCMD_FCPIM_THROTTLE_SET: 3027 case IOCMD_FCPIM_THROTTLE_SET:
2924 rc = bfad_iocmd_fcpim_throttle_set(bfad, iocmd); 3028 rc = bfad_iocmd_fcpim_throttle_set(bfad, iocmd);
2925 break; 3029 break;
3030 /* TFRU */
3031 case IOCMD_TFRU_READ:
3032 rc = bfad_iocmd_tfru_read(bfad, iocmd);
3033 break;
3034 case IOCMD_TFRU_WRITE:
3035 rc = bfad_iocmd_tfru_write(bfad, iocmd);
3036 break;
3037 /* FRU */
3038 case IOCMD_FRUVPD_READ:
3039 rc = bfad_iocmd_fruvpd_read(bfad, iocmd);
3040 break;
3041 case IOCMD_FRUVPD_UPDATE:
3042 rc = bfad_iocmd_fruvpd_update(bfad, iocmd);
3043 break;
3044 case IOCMD_FRUVPD_GET_MAX_SIZE:
3045 rc = bfad_iocmd_fruvpd_get_max_size(bfad, iocmd);
3046 break;
2926 default: 3047 default:
2927 rc = -EINVAL; 3048 rc = -EINVAL;
2928 break; 3049 break;
diff --git a/drivers/scsi/bfa/bfad_bsg.h b/drivers/scsi/bfa/bfad_bsg.h
index e48dcca0d7fa..15e1fc8e796b 100644
--- a/drivers/scsi/bfa/bfad_bsg.h
+++ b/drivers/scsi/bfa/bfad_bsg.h
@@ -146,7 +146,12 @@ enum {
146 IOCMD_DIAG_DPORT_GET_STATE, 146 IOCMD_DIAG_DPORT_GET_STATE,
147 IOCMD_QOS_SET_BW, 147 IOCMD_QOS_SET_BW,
148 IOCMD_FCPIM_THROTTLE_QUERY, 148 IOCMD_FCPIM_THROTTLE_QUERY,
149 IOCMD_FCPIM_THROTTLE_SET 149 IOCMD_FCPIM_THROTTLE_SET,
150 IOCMD_TFRU_READ,
151 IOCMD_TFRU_WRITE,
152 IOCMD_FRUVPD_READ,
153 IOCMD_FRUVPD_UPDATE,
154 IOCMD_FRUVPD_GET_MAX_SIZE,
150}; 155};
151 156
152struct bfa_bsg_gen_s { 157struct bfa_bsg_gen_s {
@@ -750,6 +755,34 @@ struct bfa_bsg_fcpim_throttle_s {
750 struct bfa_defs_fcpim_throttle_s throttle; 755 struct bfa_defs_fcpim_throttle_s throttle;
751}; 756};
752 757
758#define BFA_TFRU_DATA_SIZE 64
759#define BFA_MAX_FRUVPD_TRANSFER_SIZE 0x1000
760
761struct bfa_bsg_tfru_s {
762 bfa_status_t status;
763 u16 bfad_num;
764 u16 rsvd;
765 u32 offset;
766 u32 len;
767 u8 data[BFA_TFRU_DATA_SIZE];
768};
769
770struct bfa_bsg_fruvpd_s {
771 bfa_status_t status;
772 u16 bfad_num;
773 u16 rsvd;
774 u32 offset;
775 u32 len;
776 u8 data[BFA_MAX_FRUVPD_TRANSFER_SIZE];
777};
778
779struct bfa_bsg_fruvpd_max_size_s {
780 bfa_status_t status;
781 u16 bfad_num;
782 u16 rsvd;
783 u32 max_size;
784};
785
753struct bfa_bsg_fcpt_s { 786struct bfa_bsg_fcpt_s {
754 bfa_status_t status; 787 bfa_status_t status;
755 u16 vf_id; 788 u16 vf_id;
diff --git a/drivers/scsi/bfa/bfi.h b/drivers/scsi/bfa/bfi.h
index 9c9861f8e6ce..57b146bca18c 100644
--- a/drivers/scsi/bfa/bfi.h
+++ b/drivers/scsi/bfa/bfi.h
@@ -210,7 +210,8 @@ enum bfi_mclass {
210 BFI_MC_PORT = 21, /* Physical port */ 210 BFI_MC_PORT = 21, /* Physical port */
211 BFI_MC_SFP = 22, /* SFP module */ 211 BFI_MC_SFP = 22, /* SFP module */
212 BFI_MC_PHY = 25, /* External PHY message class */ 212 BFI_MC_PHY = 25, /* External PHY message class */
213 BFI_MC_MAX = 32 213 BFI_MC_FRU = 34,
214 BFI_MC_MAX = 35
214}; 215};
215 216
216#define BFI_IOC_MAX_CQS 4 217#define BFI_IOC_MAX_CQS 4
@@ -1170,6 +1171,50 @@ struct bfi_phy_write_rsp_s {
1170 u32 length; 1171 u32 length;
1171}; 1172};
1172 1173
1174enum bfi_fru_h2i_msgs {
1175 BFI_FRUVPD_H2I_WRITE_REQ = 1,
1176 BFI_FRUVPD_H2I_READ_REQ = 2,
1177 BFI_TFRU_H2I_WRITE_REQ = 3,
1178 BFI_TFRU_H2I_READ_REQ = 4,
1179};
1180
1181enum bfi_fru_i2h_msgs {
1182 BFI_FRUVPD_I2H_WRITE_RSP = BFA_I2HM(1),
1183 BFI_FRUVPD_I2H_READ_RSP = BFA_I2HM(2),
1184 BFI_TFRU_I2H_WRITE_RSP = BFA_I2HM(3),
1185 BFI_TFRU_I2H_READ_RSP = BFA_I2HM(4),
1186};
1187
1188/*
1189 * FRU write request
1190 */
1191struct bfi_fru_write_req_s {
1192 struct bfi_mhdr_s mh; /* Common msg header */
1193 u8 last;
1194 u8 rsv[3];
1195 u32 offset;
1196 u32 length;
1197 struct bfi_alen_s alen;
1198};
1199
1200/*
1201 * FRU read request
1202 */
1203struct bfi_fru_read_req_s {
1204 struct bfi_mhdr_s mh; /* Common msg header */
1205 u32 offset;
1206 u32 length;
1207 struct bfi_alen_s alen;
1208};
1209
1210/*
1211 * FRU response
1212 */
1213struct bfi_fru_rsp_s {
1214 struct bfi_mhdr_s mh; /* Common msg header */
1215 u32 status;
1216 u32 length;
1217};
1173#pragma pack() 1218#pragma pack()
1174 1219
1175#endif /* __BFI_H__ */ 1220#endif /* __BFI_H__ */
diff --git a/drivers/scsi/bfa/bfi_ms.h b/drivers/scsi/bfa/bfi_ms.h
index c89defc9bb92..5ae2c167b2c8 100644
--- a/drivers/scsi/bfa/bfi_ms.h
+++ b/drivers/scsi/bfa/bfi_ms.h
@@ -426,6 +426,7 @@ struct bfi_lps_login_req_s {
426 u8 auth_en; 426 u8 auth_en;
427 u8 lps_role; 427 u8 lps_role;
428 u8 bb_scn; 428 u8 bb_scn;
429 u32 vvl_flag;
429}; 430};
430 431
431struct bfi_lps_login_rsp_s { 432struct bfi_lps_login_rsp_s {